Prefer std::string over std::wstring. (#179)

In the past, FTXUI switched from std::string to std::wstring to support
fullwidth characters. The reasons was that fullwidth characters can be
stored inside a single wchar_t.

Then FTXUI added support for combining characters. A single glygh
doesn't even fit a wchar_t. Instead, a glyph can be arbitrary large.

The usage of wstring doesn't really fit the new model and have several
drawbacks:
1. It doesn't simplify the implementation of FTXUI, because of combining
   characters.
2. It reduces drawing performance by 2x.
3. It increase Screen's memory allocation by 2x.

This patch converts FTXUI to use std::string internally. It now exposes
std::string based API. The std::wstring API remains, but is now
deprecated.

Tests and examples haven't been update to show the breakage is limited.
They will be updated in a second set of patches.

Bug: https://github.com/ArthurSonzogni/FTXUI/issues/153
Co-authored-by: Tushar Maheshwari <tushar27192@gmail.com>
This commit is contained in:
Arthur Sonzogni 2021-08-08 23:25:20 +02:00 committed by GitHub
parent 1ff894f6f5
commit 3b4ab618a3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
84 changed files with 1234 additions and 996 deletions

View File

@ -4,7 +4,7 @@ include(cmake/ftxui_git_version.cmake)
project(ftxui
LANGUAGES CXX
VERSION 0.7.${git_version}
VERSION 0.8.${git_version}
)
option(FTXUI_BUILD_DOCS "Set to ON to build tests" ON)
@ -31,7 +31,6 @@ add_library(screen STATIC
src/ftxui/screen/screen.cpp
src/ftxui/screen/string.cpp
src/ftxui/screen/terminal.cpp
src/ftxui/screen/wcwidth.cpp
include/ftxui/screen/box.hpp
include/ftxui/screen/color.hpp
include/ftxui/screen/color_info.hpp

View File

@ -23,6 +23,7 @@ add_executable(tests
src/ftxui/dom/hbox_test.cpp
src/ftxui/dom/text_test.cpp
src/ftxui/dom/vbox_test.cpp
src/ftxui/screen/string_test.cpp
)
target_link_libraries(tests

View File

@ -6,7 +6,8 @@
#include "ftxui/component/component_base.hpp" // for ComponentBase
#include "ftxui/component/component_options.hpp" // for ButtonOption
#include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive
#include "ftxui/dom/elements.hpp" // for separator, gauge, text, Element, operator|, vbox, border
#include "ftxui/dom/deprecated.hpp" // for text
#include "ftxui/dom/elements.hpp" // for separator, gauge, Element, operator|, vbox, border
using namespace ftxui;

View File

@ -6,7 +6,8 @@
#include "ftxui/component/component_base.hpp" // for ComponentBase
#include "ftxui/component/component_options.hpp" // for ButtonOption
#include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive
#include "ftxui/dom/elements.hpp" // for text, separator, Element, operator|, vbox, border
#include "ftxui/dom/deprecated.hpp" // for text
#include "ftxui/dom/elements.hpp" // for separator, Element, operator|, vbox, border
using namespace ftxui;

View File

@ -4,10 +4,12 @@
#include <vector> // for vector
#include "ftxui/component/captured_mouse.hpp" // for ftxui
#include "ftxui/component/component.hpp" // for Slider, Checkbox, Vertical, Renderer, Button, Input, Menu, Radiobox, Toggle
#include "ftxui/component/component.hpp" // for Slider, Checkbox, Vertical, Renderer, Button, Menu, Radiobox, Toggle
#include "ftxui/component/component_base.hpp" // for ComponentBase
#include "ftxui/component/deprecated.hpp" // for Input
#include "ftxui/component/screen_interactive.hpp" // for Component, ScreenInteractive
#include "ftxui/dom/elements.hpp" // for separator, Element, operator|, size, xflex, text, WIDTH, hbox, vbox, EQUAL, border, GREATER_THAN
#include "ftxui/dom/deprecated.hpp" // for text
#include "ftxui/dom/elements.hpp" // for separator, operator|, Element, size, xflex, WIDTH, hbox, vbox, EQUAL, border, GREATER_THAN
using namespace ftxui;

View File

@ -9,12 +9,14 @@
#include <vector> // for vector
#include "ftxui/component/captured_mouse.hpp" // for ftxui
#include "ftxui/component/component.hpp" // for Checkbox, Renderer, Horizontal, Vertical, Input, Menu, Radiobox, Tab, Toggle
#include "ftxui/component/component.hpp" // for Checkbox, Renderer, Horizontal, Vertical, Menu, Radiobox, Tab, Toggle
#include "ftxui/component/component_base.hpp" // for ComponentBase
#include "ftxui/component/component_options.hpp" // for InputOption
#include "ftxui/component/deprecated.hpp" // for Input
#include "ftxui/component/event.hpp" // for Event, Event::Custom
#include "ftxui/component/screen_interactive.hpp" // for Component, ScreenInteractive
#include "ftxui/dom/elements.hpp" // for text, operator|, color, bgcolor, filler, Element, size, vbox, flex, hbox, graph, separator, EQUAL, WIDTH, hcenter, bold, border, window, HEIGHT, Elements, hflow, flex_grow, frame, gauge, LESS_THAN, spinner, dim, GREATER_THAN
#include "ftxui/dom/deprecated.hpp" // for text
#include "ftxui/dom/elements.hpp" // for operator|, color, bgcolor, filler, Element, size, vbox, flex, hbox, graph, separator, EQUAL, WIDTH, hcenter, bold, border, window, HEIGHT, Elements, hflow, flex_grow, frame, gauge, LESS_THAN, spinner, dim, GREATER_THAN
#include "ftxui/screen/color.hpp" // for Color, Color::BlueLight, Color::RedLight, Color::Black, Color::Blue, Color::Cyan, Color::CyanLight, Color::GrayDark, Color::GrayLight, Color::Green, Color::GreenLight, Color::Magenta, Color::MagentaLight, Color::Red, Color::White, Color::Yellow, Color::YellowLight, Color::Default
using namespace ftxui;

View File

@ -2,11 +2,13 @@
#include <string> // for char_traits, operator+, wstring, basic_string
#include "ftxui/component/captured_mouse.hpp" // for ftxui
#include "ftxui/component/component.hpp" // for Input, Renderer, Vertical
#include "ftxui/component/component.hpp" // for Renderer, Vertical
#include "ftxui/component/component_base.hpp" // for ComponentBase
#include "ftxui/component/component_options.hpp" // for InputOption
#include "ftxui/component/deprecated.hpp" // for Input
#include "ftxui/component/screen_interactive.hpp" // for Component, ScreenInteractive
#include "ftxui/dom/elements.hpp" // for text, hbox, separator, Element, operator|, vbox, border
#include "ftxui/dom/deprecated.hpp" // for text
#include "ftxui/dom/elements.hpp" // for hbox, separator, Element, operator|, vbox, border
int main(int argc, const char* argv[]) {
using namespace ftxui;

View File

@ -8,7 +8,8 @@
#include "ftxui/component/component_base.hpp" // for ComponentBase
#include "ftxui/component/component_options.hpp" // for MenuOption
#include "ftxui/component/screen_interactive.hpp" // for Component, ScreenInteractive
#include "ftxui/dom/elements.hpp" // for text, separator, bold, hcenter, vbox, hbox, gauge, Element, operator|, border
#include "ftxui/dom/deprecated.hpp" // for text
#include "ftxui/dom/elements.hpp" // for separator, bold, hcenter, vbox, hbox, gauge, Element, operator|, border
#include "ftxui/screen/string.hpp" // for to_wstring
int main(int argc, const char* argv[]) {

View File

@ -1,13 +1,14 @@
#include <stdlib.h> // for EXIT_SUCCESS
#include <memory> // for __shared_ptr_access
#include <string> // for wstring, allocator, operator+, basic_string, char_traits
#include <memory> // for allocator, __shared_ptr_access
#include <string> // for wstring, operator+, basic_string, char_traits
#include <vector> // for vector, __alloc_traits<>::value_type
#include "ftxui/component/captured_mouse.hpp" // for ftxui
#include "ftxui/component/component.hpp" // for Menu, Renderer, Horizontal, Vertical
#include "ftxui/component/component_base.hpp" // for ComponentBase
#include "ftxui/component/screen_interactive.hpp" // for Component, ScreenInteractive
#include "ftxui/dom/elements.hpp" // for text, Element, operator|, window, flex, vbox
#include "ftxui/dom/deprecated.hpp" // for text
#include "ftxui/dom/elements.hpp" // for Element, operator|, window, flex, vbox
#include "ftxui/screen/string.hpp" // for to_wstring
using namespace ftxui;

View File

@ -1,12 +1,13 @@
#include <memory> // for allocator, __shared_ptr_access, shared_ptr
#include <string> // for wstring, operator+, basic_string, char_traits
#include <memory> // for allocator, shared_ptr, __shared_ptr_access
#include <string> // for wstring, basic_string, char_traits, operator+
#include <vector> // for vector
#include "ftxui/component/captured_mouse.hpp" // for ftxui
#include "ftxui/component/component.hpp" // for Button, Renderer, Horizontal, Tab
#include "ftxui/component/component_base.hpp" // for ComponentBase
#include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive
#include "ftxui/dom/elements.hpp" // for Element, operator|, filler, text, hbox, separator, center, vbox, bold, border, clear_under, dbox, size, GREATER_THAN, HEIGHT
#include "ftxui/dom/deprecated.hpp" // for text
#include "ftxui/dom/elements.hpp" // for operator|, Element, filler, hbox, separator, center, vbox, bold, border, clear_under, dbox, size, GREATER_THAN, HEIGHT
int main(int argc, const char* argv[]) {
using namespace ftxui;

View File

@ -4,8 +4,8 @@
#include <stddef.h> // for size_t
#include <algorithm> // for max
#include <memory> // for shared_ptr
#include <string> // for allocator, char_traits, operator+, wstring, basic_string, to_wstring, string
#include <memory> // for allocator, shared_ptr
#include <string> // for char_traits, operator+, string, basic_string, to_string
#include <utility> // for move
#include <vector> // for vector
@ -18,56 +18,56 @@
using namespace ftxui;
std::wstring Stringify(Event event) {
std::wstring out;
std::string Stringify(Event event) {
std::string out;
for (auto& it : event.input())
out += L" " + std::to_wstring((unsigned int)it);
out += " " + std::to_string((unsigned int)it);
out = L"(" + out + L" ) -> ";
out = "(" + out + " ) -> ";
if (event.is_character()) {
out += std::wstring(L"character(") + event.character() + L")";
out += "character(" + event.character() + ")";
} else if (event.is_mouse()) {
out += L"mouse";
out += "mouse";
switch (event.mouse().button) {
case Mouse::Left:
out += L"_left";
out += "_left";
break;
case Mouse::Middle:
out += L"_middle";
out += "_middle";
break;
case Mouse::Right:
out += L"_right";
out += "_right";
break;
case Mouse::None:
out += L"_none";
out += "_none";
break;
case Mouse::WheelUp:
out += L"_wheel_up";
out += "_wheel_up";
break;
case Mouse::WheelDown:
out += L"_wheel_down";
out += "_wheel_down";
break;
}
switch (event.mouse().motion) {
case Mouse::Pressed:
out += L"_pressed";
out += "_pressed";
break;
case Mouse::Released:
out += L"_released";
out += "_released";
break;
}
if (event.mouse().control)
out += L"_control";
out += "_control";
if (event.mouse().shift)
out += L"_shift";
out += "_shift";
if (event.mouse().meta)
out += L"_meta";
out += "_meta";
out += L"(" + //
std::to_wstring(event.mouse().x) + L"," +
std::to_wstring(event.mouse().y) + L")";
out += "(" + //
std::to_string(event.mouse().x) + "," +
std::to_string(event.mouse().y) + ")";
} else {
out += L"(special)";
out += "(special)";
}
return out;
}
@ -81,7 +81,7 @@ int main(int argc, const char* argv[]) {
Elements children;
for (size_t i = std::max(0, (int)keys.size() - 20); i < keys.size(); ++i)
children.push_back(text(Stringify(keys[i])));
return window(text(L"keys"), vbox(std::move(children)));
return window(text("keys"), vbox(std::move(children)));
});
component = CatchEvent(component, [&](Event event) {

View File

@ -4,7 +4,8 @@
#include "ftxui/component/component.hpp" // for Renderer, Button, Vertical
#include "ftxui/component/component_base.hpp" // for ComponentBase
#include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive
#include "ftxui/dom/elements.hpp" // for operator|, Element, text, bold, border, center, color
#include "ftxui/dom/deprecated.hpp" // for text
#include "ftxui/dom/elements.hpp" // for operator|, Element, bold, border, center, color
#include "ftxui/screen/color.hpp" // for Color, Color::Red
int main(int argc, const char* argv[]) {

View File

@ -4,7 +4,8 @@
#include "ftxui/component/component.hpp" // for Renderer, ResizableSplitBottom, ResizableSplitLeft, ResizableSplitRight, ResizableSplitTop
#include "ftxui/component/component_base.hpp" // for ComponentBase
#include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive
#include "ftxui/dom/elements.hpp" // for Element, operator|, text, center, border
#include "ftxui/dom/deprecated.hpp" // for text
#include "ftxui/dom/elements.hpp" // for Element, operator|, center, border
using namespace ftxui;

View File

@ -1,11 +1,12 @@
#include <memory> // for allocator, __shared_ptr_access, shared_ptr
#include <string> // for operator+, to_wstring, char_traits
#include <memory> // for allocator, shared_ptr, __shared_ptr_access
#include <string> // for char_traits, operator+, to_wstring
#include "ftxui/component/captured_mouse.hpp" // for ftxui
#include "ftxui/component/component.hpp" // for Slider, Renderer, Vertical
#include "ftxui/component/component_base.hpp" // for ComponentBase
#include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive
#include "ftxui/dom/elements.hpp" // for separator, Element, operator|, size, text, vbox, xflex, bgcolor, hbox, GREATER_THAN, WIDTH, border, HEIGHT, LESS_THAN
#include "ftxui/dom/deprecated.hpp" // for text
#include "ftxui/dom/elements.hpp" // for separator, operator|, Element, size, vbox, xflex, bgcolor, hbox, GREATER_THAN, WIDTH, border, HEIGHT, LESS_THAN
#include "ftxui/screen/color.hpp" // for Color
using namespace ftxui;

View File

@ -6,7 +6,8 @@
#include "ftxui/component/component.hpp" // for Toggle, Renderer, Vertical
#include "ftxui/component/component_base.hpp" // for ComponentBase
#include "ftxui/component/screen_interactive.hpp" // for Component, ScreenInteractive
#include "ftxui/dom/elements.hpp" // for text, hbox, vbox, Element
#include "ftxui/dom/deprecated.hpp" // for text
#include "ftxui/dom/elements.hpp" // for hbox, vbox, Element
using namespace ftxui;

View File

@ -1,9 +1,10 @@
#include <ftxui/dom/elements.hpp>
#include <ftxui/screen/screen.hpp>
#include <memory>
#include <ftxui/dom/elements.hpp> // for operator|, vbox, border, Element, hbox
#include <ftxui/screen/screen.hpp> // for Dimension, Screen
#include <memory> // for allocator
#include "ftxui/dom/node.hpp"
#include "ftxui/screen/box.hpp"
#include "ftxui/dom/deprecated.hpp" // for text
#include "ftxui/dom/node.hpp" // for Render
#include "ftxui/screen/box.hpp" // for ftxui
int main(int argc, const char* argv[]) {
using namespace ftxui;

View File

@ -7,7 +7,8 @@
using namespace ftxui;
#include "./color_info_sorted_2d.ipp" // for ColorInfoSorted2D
#include "ftxui/dom/elements.hpp" // for text, bgcolor, color, vbox, hbox, separator, operator|, Elements, Element, border
#include "ftxui/dom/deprecated.hpp" // for text
#include "ftxui/dom/elements.hpp" // for bgcolor, color, vbox, hbox, separator, operator|, Elements, Element, border
#include "ftxui/dom/node.hpp" // for Render
#include "ftxui/screen/color.hpp" // for Color, Color::Black, Color::Blue, Color::BlueLight, Color::Cyan, Color::CyanLight, Color::Default, Color::GrayDark, Color::GrayLight, Color::Green, Color::GreenLight, Color::Magenta, Color::MagentaLight, Color::Red, Color::RedLight, Color::White, Color::Yellow, Color::YellowLight, Color::Palette256, ftxui

View File

@ -1,17 +1,18 @@
#include <ftxui/dom/elements.hpp>
#include <ftxui/screen/color_info.hpp>
#include <ftxui/screen/screen.hpp>
#include <string>
#include <utility>
#include <vector>
#include <ftxui/dom/elements.hpp> // for bgcolor, hbox, operator|, Elements, vbox, Element
#include <ftxui/screen/color_info.hpp> // for ColorInfo
#include <ftxui/screen/screen.hpp> // for Dimension, Screen
#include <string> // for allocator, string
#include <utility> // for move
#include <vector> // for vector
#include "ftxui/dom/node.hpp"
#include "ftxui/screen/box.hpp"
#include "ftxui/screen/color.hpp"
#include "ftxui/screen/string.hpp"
#include "ftxui/dom/deprecated.hpp" // for text
#include "ftxui/dom/node.hpp" // for Render
#include "ftxui/screen/box.hpp" // for ftxui
#include "ftxui/screen/color.hpp" // for Color, Color::Palette256
#include "ftxui/screen/string.hpp" // for to_wstring
using namespace ftxui;
#include "./color_info_sorted_2d.ipp" // ColorInfoSorted2D.
#include "./color_info_sorted_2d.ipp" // for ColorInfoSorted2D
int main(int argc, const char* argv[]) {
std::vector<std::vector<ColorInfo>> info_columns = ColorInfoSorted2D();

View File

@ -1,11 +1,12 @@
#include <ftxui/dom/elements.hpp>
#include <ftxui/screen/screen.hpp>
#include <memory>
#include <utility>
#include <ftxui/dom/elements.hpp> // for operator|, Elements, bgcolor, color, hbox, vbox, Element
#include <ftxui/screen/screen.hpp> // for Dimension, Screen
#include <memory> // for allocator
#include <utility> // for move
#include "ftxui/dom/node.hpp"
#include "ftxui/screen/box.hpp"
#include "ftxui/screen/color.hpp"
#include "ftxui/dom/deprecated.hpp" // for text
#include "ftxui/dom/node.hpp" // for Render
#include "ftxui/screen/box.hpp" // for ftxui
#include "ftxui/screen/color.hpp" // for Color
int main(int argc, const char* argv[]) {
using namespace ftxui;

View File

@ -1,11 +1,12 @@
#include <ftxui/dom/elements.hpp>
#include <ftxui/screen/screen.hpp>
#include <memory>
#include <utility>
#include <ftxui/dom/elements.hpp> // for hbox, bgcolor, operator|, vbox, Elements, window, Element
#include <ftxui/screen/screen.hpp> // for Dimension, Screen
#include <memory> // for allocator
#include <utility> // for move
#include "ftxui/dom/node.hpp"
#include "ftxui/screen/box.hpp"
#include "ftxui/screen/color.hpp"
#include "ftxui/dom/deprecated.hpp" // for text
#include "ftxui/dom/node.hpp" // for Render
#include "ftxui/screen/box.hpp" // for ftxui
#include "ftxui/screen/color.hpp" // for Color
int main(int argc, const char* argv[]) {
using namespace ftxui;

View File

@ -1,9 +1,10 @@
#include <ftxui/dom/elements.hpp>
#include <ftxui/screen/screen.hpp>
#include <memory>
#include <ftxui/dom/elements.hpp> // for operator|, border, Element, vbox, center, dbox
#include <ftxui/screen/screen.hpp> // for Dimension, Screen
#include <memory> // for allocator
#include "ftxui/dom/node.hpp"
#include "ftxui/screen/box.hpp"
#include "ftxui/dom/deprecated.hpp" // for text
#include "ftxui/dom/node.hpp" // for Render
#include "ftxui/screen/box.hpp" // for ftxui
int main(int argc, const char* argv[]) {
using namespace ftxui;

View File

@ -1,12 +1,13 @@
#include <chrono>
#include <ftxui/dom/elements.hpp>
#include <ftxui/screen/screen.hpp>
#include <iostream>
#include <string>
#include <thread>
#include <chrono> // for operator""s, chrono_literals
#include <ftxui/dom/elements.hpp> // for gauge, operator|, flex, hbox, Element
#include <ftxui/screen/screen.hpp> // for Screen
#include <iostream> // for cout, endl, ostream
#include <string> // for allocator, operator+, char_traits, operator<<, to_wstring, basic_string, string, wstring
#include <thread> // for sleep_for
#include "ftxui/dom/node.hpp"
#include "ftxui/screen/box.hpp"
#include "ftxui/dom/deprecated.hpp" // for text
#include "ftxui/dom/node.hpp" // for Render
#include "ftxui/screen/box.hpp" // for ftxui
int main(int argc, const char* argv[]) {
using namespace ftxui;

View File

@ -1,10 +1,11 @@
#include <stddef.h> // for size_t
#include <ftxui/dom/elements.hpp> // for operator|, size, Element, text, hcenter, Decorator, WIDTH, hflow, window, EQUAL, GREATER_THAN, HEIGHT, bold, border, dim, LESS_THAN
#include <ftxui/dom/elements.hpp> // for operator|, size, Element, hcenter, Decorator, WIDTH, hflow, window, EQUAL, GREATER_THAN, HEIGHT, bold, border, dim, LESS_THAN
#include <ftxui/screen/screen.hpp> // for Dimension, Screen
#include <ftxui/screen/string.hpp> // for to_wstring
#include <memory> // for shared_ptr
#include <string> // for allocator, operator+, char_traits, wstring
#include <memory> // for allocator, shared_ptr
#include <string> // for operator+, char_traits, wstring
#include "ftxui/dom/deprecated.hpp" // for text
#include "ftxui/dom/node.hpp" // for Render
#include "ftxui/screen/box.hpp" // for ftxui

View File

@ -5,7 +5,8 @@
#include <string> // for operator<<, string
#include <thread> // for sleep_for
#include "ftxui/dom/elements.hpp" // for paragraph, text, operator|, Element, border, color, hflow, spinner, vbox, bold, dim, underlined
#include "ftxui/dom/deprecated.hpp" // for paragraph, text
#include "ftxui/dom/elements.hpp" // for operator|, Element, border, color, hflow, spinner, vbox, bold, dim, underlined
#include "ftxui/dom/node.hpp" // for Render
#include "ftxui/screen/box.hpp" // for ftxui
#include "ftxui/screen/color.hpp" // for Color, Color::Red

View File

@ -1,18 +1,19 @@
#include <chrono>
#include <ftxui/dom/elements.hpp>
#include <ftxui/screen/screen.hpp>
#include <ftxui/screen/string.hpp>
#include <iostream>
#include <list>
#include <memory>
#include <string>
#include <thread>
#include <utility>
#include <vector>
#include <chrono> // for operator""s, chrono_literals
#include <ftxui/dom/elements.hpp> // for operator|, Element, hbox, bold, color, filler, separator, vbox, window, gauge, size, dim, EQUAL, WIDTH
#include <ftxui/screen/screen.hpp> // for Screen, Dimension
#include <ftxui/screen/string.hpp> // for to_wstring
#include <iostream> // for cout, endl, ostream
#include <list> // for list, operator!=, _List_iterator, _List_iterator<>::_Self
#include <memory> // for allocator, shared_ptr, allocator_traits<>::value_type
#include <string> // for wstring, operator<<, string
#include <thread> // for sleep_for
#include <utility> // for move
#include <vector> // for vector
#include "ftxui/dom/node.hpp"
#include "ftxui/screen/box.hpp"
#include "ftxui/screen/color.hpp"
#include "ftxui/dom/deprecated.hpp" // for text
#include "ftxui/dom/node.hpp" // for Render
#include "ftxui/screen/box.hpp" // for ftxui
#include "ftxui/screen/color.hpp" // for Color, Color::Green, Color::Red, Color::RedLight
int main(int argc, const char* argv[]) {
using namespace ftxui;

View File

@ -1,10 +1,11 @@
#include <stdio.h>
#include <ftxui/dom/elements.hpp>
#include <ftxui/screen/screen.hpp>
#include <string>
#include <stdio.h> // for getchar
#include <ftxui/dom/elements.hpp> // for operator|, hflow, border, Element, hbox, flex, vbox
#include <ftxui/screen/screen.hpp> // for Dimension, Screen
#include <string> // for allocator, wstring
#include "ftxui/dom/node.hpp"
#include "ftxui/screen/box.hpp"
#include "ftxui/dom/deprecated.hpp" // for paragraph
#include "ftxui/dom/node.hpp" // for Render
#include "ftxui/screen/box.hpp" // for ftxui
int main(int argc, const char* argv[]) {
using namespace ftxui;

View File

@ -1,9 +1,10 @@
#include <ftxui/dom/elements.hpp>
#include <ftxui/screen/screen.hpp>
#include <memory>
#include <ftxui/dom/elements.hpp> // for center, separator, operator|, flex, Element, vbox, hbox, border
#include <ftxui/screen/screen.hpp> // for Dimension, Screen
#include <memory> // for allocator
#include "ftxui/dom/node.hpp"
#include "ftxui/screen/box.hpp"
#include "ftxui/dom/deprecated.hpp" // for text
#include "ftxui/dom/node.hpp" // for Render
#include "ftxui/screen/box.hpp" // for ftxui
int main(int argc, const char* argv[]) {
using namespace ftxui;

View File

@ -1,12 +1,13 @@
#include <ftxui/dom/elements.hpp>
#include <ftxui/screen/screen.hpp>
#include <ftxui/screen/string.hpp>
#include <memory>
#include <string>
#include <utility>
#include <ftxui/dom/elements.hpp> // for operator|, Element, hcenter, hbox, size, window, Elements, bold, dim, EQUAL, WIDTH
#include <ftxui/screen/screen.hpp> // for Screen, Dimension
#include <ftxui/screen/string.hpp> // for to_wstring
#include <memory> // for allocator, shared_ptr
#include <string> // for wstring
#include <utility> // for move
#include "ftxui/dom/node.hpp"
#include "ftxui/screen/box.hpp"
#include "ftxui/dom/deprecated.hpp" // for text
#include "ftxui/dom/node.hpp" // for Render
#include "ftxui/screen/box.hpp" // for ftxui
int main(int argc, const char* argv[]) {
using namespace ftxui;

View File

@ -1,15 +1,16 @@
#include <chrono>
#include <ftxui/dom/elements.hpp>
#include <ftxui/screen/screen.hpp>
#include <ftxui/screen/string.hpp>
#include <iostream>
#include <string>
#include <thread>
#include <utility>
#include <vector>
#include <chrono> // for operator""s, chrono_literals
#include <ftxui/dom/elements.hpp> // for Element, operator|, separator, filler, hbox, size, spinner, vbox, bold, border, EQUAL, WIDTH
#include <ftxui/screen/screen.hpp> // for Screen, Dimension
#include <ftxui/screen/string.hpp> // for to_wstring
#include <iostream> // for cout, endl, ostream
#include <string> // for operator<<, string
#include <thread> // for sleep_for
#include <utility> // for move
#include <vector> // for vector
#include "ftxui/dom/node.hpp"
#include "ftxui/screen/box.hpp"
#include "ftxui/dom/deprecated.hpp" // for text
#include "ftxui/dom/node.hpp" // for Render
#include "ftxui/screen/box.hpp" // for ftxui
int main(int argc, const char* argv[]) {
using namespace ftxui;

View File

@ -1,9 +1,10 @@
#include <ftxui/dom/elements.hpp>
#include <ftxui/screen/screen.hpp>
#include <memory>
#include <ftxui/dom/elements.hpp> // for operator|, blink, hbox, Element
#include <ftxui/screen/screen.hpp> // for Dimension, Screen
#include <memory> // for allocator
#include "ftxui/dom/node.hpp"
#include "ftxui/screen/box.hpp"
#include "ftxui/dom/deprecated.hpp" // for text
#include "ftxui/dom/node.hpp" // for Render
#include "ftxui/screen/box.hpp" // for ftxui
int main(int argc, const char* argv[]) {
using namespace ftxui;

View File

@ -1,9 +1,10 @@
#include <ftxui/dom/elements.hpp>
#include <ftxui/screen/screen.hpp>
#include <memory>
#include <ftxui/dom/elements.hpp> // for operator|, bold, hbox, Element
#include <ftxui/screen/screen.hpp> // for Dimension, Screen
#include <memory> // for allocator
#include "ftxui/dom/node.hpp"
#include "ftxui/screen/box.hpp"
#include "ftxui/dom/deprecated.hpp" // for text
#include "ftxui/dom/node.hpp" // for Render
#include "ftxui/screen/box.hpp" // for ftxui
int main(int argc, const char* argv[]) {
using namespace ftxui;

View File

@ -1,7 +1,8 @@
#include <ftxui/screen/screen.hpp> // for Dimension, Screen
#include <memory> // for allocator
#include "ftxui/dom/elements.hpp" // for text, bgcolor, color, vbox, filler, hbox
#include "ftxui/dom/deprecated.hpp" // for text
#include "ftxui/dom/elements.hpp" // for bgcolor, color, vbox, filler, hbox
#include "ftxui/dom/node.hpp" // for Render
#include "ftxui/screen/box.hpp" // for ftxui
#include "ftxui/screen/color.hpp" // for Color, Color::Black, Color::Blue, Color::BlueLight, Color::Cyan, Color::CyanLight, Color::Default, Color::GrayDark, Color::GrayLight, Color::Green, Color::GreenLight, Color::Magenta, Color::MagentaLight, Color::Red, Color::RedLight, Color::White, Color::Yellow, Color::YellowLight

View File

@ -1,9 +1,10 @@
#include <ftxui/dom/elements.hpp>
#include <ftxui/screen/screen.hpp>
#include <memory>
#include <ftxui/dom/elements.hpp> // for operator|, dim, hbox, Element
#include <ftxui/screen/screen.hpp> // for Dimension, Screen
#include <memory> // for allocator
#include "ftxui/dom/node.hpp"
#include "ftxui/screen/box.hpp"
#include "ftxui/dom/deprecated.hpp" // for text
#include "ftxui/dom/node.hpp" // for Render
#include "ftxui/screen/box.hpp" // for ftxui
int main(int argc, const char* argv[]) {
using namespace ftxui;

View File

@ -1,10 +1,11 @@
#include <ftxui/dom/elements.hpp>
#include <ftxui/screen/screen.hpp>
#include <memory>
#include <ftxui/dom/elements.hpp> // for operator|, Element, bgcolor, color, blink, bold, dim, inverted, underlined, hbox
#include <ftxui/screen/screen.hpp> // for Dimension, Screen
#include <memory> // for allocator
#include "ftxui/dom/node.hpp"
#include "ftxui/screen/box.hpp"
#include "ftxui/screen/color.hpp"
#include "ftxui/dom/deprecated.hpp" // for text
#include "ftxui/dom/node.hpp" // for Render
#include "ftxui/screen/box.hpp" // for ftxui
#include "ftxui/screen/color.hpp" // for Color, Color::Blue
int main(int argc, const char* argv[]) {
using namespace ftxui;

View File

@ -1,9 +1,10 @@
#include <ftxui/dom/elements.hpp>
#include <ftxui/screen/screen.hpp>
#include <memory>
#include <ftxui/dom/elements.hpp> // for operator|, inverted, hbox, Element
#include <ftxui/screen/screen.hpp> // for Dimension, Screen
#include <memory> // for allocator
#include "ftxui/dom/node.hpp"
#include "ftxui/screen/box.hpp"
#include "ftxui/dom/deprecated.hpp" // for text
#include "ftxui/dom/node.hpp" // for Render
#include "ftxui/screen/box.hpp" // for ftxui
int main(int argc, const char* argv[]) {
using namespace ftxui;

View File

@ -1,9 +1,10 @@
#include <ftxui/dom/elements.hpp>
#include <ftxui/screen/screen.hpp>
#include <memory>
#include <ftxui/dom/elements.hpp> // for operator|, underlined, hbox, Element
#include <ftxui/screen/screen.hpp> // for Dimension, Screen
#include <memory> // for allocator
#include "ftxui/dom/node.hpp"
#include "ftxui/screen/box.hpp"
#include "ftxui/dom/deprecated.hpp" // for text
#include "ftxui/dom/node.hpp" // for Render
#include "ftxui/screen/box.hpp" // for ftxui
int main(int argc, const char* argv[]) {
using namespace ftxui;

View File

@ -1,10 +1,11 @@
#include <stdio.h>
#include <ftxui/dom/elements.hpp>
#include <ftxui/screen/screen.hpp>
#include <memory>
#include <stdio.h> // for getchar
#include <ftxui/dom/elements.hpp> // for filler, hbox, vbox
#include <ftxui/screen/screen.hpp> // for Screen, Dimension
#include <memory> // for allocator
#include "ftxui/dom/node.hpp"
#include "ftxui/screen/box.hpp"
#include "ftxui/dom/deprecated.hpp" // for text
#include "ftxui/dom/node.hpp" // for Render
#include "ftxui/screen/box.hpp" // for ftxui
int main(int argc, const char* argv[]) {
using namespace ftxui;

View File

@ -9,7 +9,7 @@
#include "ftxui/component/component_base.hpp" // for Component, Components
#include "ftxui/component/component_options.hpp" // for ButtonOption, CheckboxOption, InputOption, MenuOption, RadioboxOption, ToggleOption
#include "ftxui/dom/elements.hpp" // for Element
#include "ftxui/util/ref.hpp" // for Ref, ConstStringRef, StringRef
#include "ftxui/util/ref.hpp" // for Ref, ConstStringRef, ConstStringListRef, StringRef
namespace ftxui {
struct ButtonOption;
@ -34,17 +34,17 @@ Component Checkbox(ConstStringRef label,
Component Input(StringRef content,
ConstStringRef placeholder,
Ref<InputOption> option = {});
Component Menu(const std::vector<std::wstring>* entries,
Component Menu(ConstStringListRef entries,
int* selected_,
Ref<MenuOption> = {});
Component Radiobox(const std::vector<std::wstring>* entries,
Component Radiobox(ConstStringListRef entries,
int* selected_,
Ref<RadioboxOption> option = {});
Component Toggle(const std::vector<std::wstring>* entries,
Component Toggle(ConstStringListRef entries,
int* selected,
Ref<ToggleOption> option = {});
template <class T> // T = {int, float, long}
Component Slider(StringRef label, T* value, T min, T max, T increment);
Component Slider(ConstStringRef label, T* value, T min, T max, T increment);
Component ResizableSplitLeft(Component main, Component back, int* main_size);
Component ResizableSplitRight(Component main, Component back, int* main_size);
Component ResizableSplitTop(Component main, Component back, int* main_size);
@ -65,6 +65,9 @@ Component Tab(Components children, int* selector);
} // namespace ftxui
// Include component using the old deprecated wstring.
#include "ftxui/component/deprecated.hpp"
#endif /* end of include guard: FTXUI_COMPONENT_HPP */
// Copyright 2021 Arthur Sonzogni. All rights reserved.

View File

@ -33,8 +33,8 @@ struct ButtonOption {
/// @brief Option for the Checkbox component.
/// @ingroup component
struct CheckboxOption {
std::wstring style_checked = L""; ///< Prefix for a "checked" state.
std::wstring style_unchecked = L""; ///< Prefix for a "unchecked" state.
std::string style_checked = ""; ///< Prefix for a "checked" state.
std::string style_unchecked = ""; ///< Prefix for a "unchecked" state.
Decorator style_focused = inverted; ///< Decorator used when focused.
Decorator style_unfocused = nothing; ///< Decorator used when unfocused.
@ -59,8 +59,8 @@ struct InputOption {
/// @brief Option for the Radiobox component.
/// @ingroup component
struct RadioboxOption {
std::wstring style_checked = L""; ///< Prefix for a "checked" state.
std::wstring style_unchecked = L""; ///< Prefix for a "unchecked" state.
std::string style_checked = ""; ///< Prefix for a "checked" state.
std::string style_unchecked = ""; ///< Prefix for a "unchecked" state.
Decorator style_focused = inverted; ///< Decorator used when focused.
Decorator style_unfocused = nothing; ///< Decorator used when unfocused.

View File

@ -0,0 +1,17 @@
#ifndef FTXUI_COMPONENT_DEPRECATED_HPP
#define FTXUI_COMPONENT_DEPRECATED_HPP
#include "ftxui/component/component.hpp"
namespace ftxui {
Component Input(WideStringRef content,
ConstStringRef placeholder,
Ref<InputOption> option = {});
} // namespace ftxui
#endif /* FTXUI_COMPONENT_DEPRECATED_HPP */
// Copyright 2021 Arthur Sonzogni. All rights reserved.
// Use of this source code is governed by the MIT license that can be found in
// the LICENSE file.

View File

@ -24,10 +24,9 @@ class ComponentBase;
/// https://invisible-island.net/xterm/ctlseqs/ctlseqs.html
struct Event {
// --- Constructor section ---------------------------------------------------
static Event Character(std::string);
static Event Character(char);
static Event Character(wchar_t);
static Event Character(std::string);
static Event Special(std::string);
static Event Mouse(std::string, Mouse mouse);
static Event CursorReporting(std::string, int x, int y);
@ -58,7 +57,7 @@ struct Event {
//--- Method section ---------------------------------------------------------
bool is_character() const { return type_ == Type::Character; }
wchar_t character() const { return character_; }
std::string character() const { return input_; }
bool is_mouse() const { return type_ == Type::Mouse; }
struct Mouse& mouse() {
@ -92,7 +91,6 @@ struct Event {
};
union {
wchar_t character_ = U'?';
struct Mouse mouse_;
struct Cursor cursor_;
};

View File

@ -0,0 +1,16 @@
#ifndef FTXUI_DOM_DEPRECRATED_HPP
#define FTXUI_DOM_DEPRECRATED_HPP
#include "ftxui/dom/elements.hpp"
namespace ftxui {
Element text(std::wstring text);
Element vtext(std::wstring text);
Elements paragraph(std::wstring text);
} // namespace ftxui
#endif /* end of include guard: FTXUI_DOM_DEPRECRATED_HPP */
// Copyright 2021 Arthur Sonzogni. All rights reserved.
// Use of this source code is governed by the MIT license that can be found in
// the LICENSE file.

View File

@ -26,8 +26,8 @@ Elements operator|(Elements, Decorator);
Decorator operator|(Decorator, Decorator);
// --- Widget ---
Element text(std::wstring text);
Element vtext(std::wstring text);
Element text(std::string text);
Element vtext(std::string text);
Element separator(void);
Element separator(Pixel);
Element gauge(float ratio);
@ -35,7 +35,7 @@ Element border(Element);
Decorator borderWith(Pixel);
Element window(Element title, Element content);
Element spinner(int charset_index, size_t image_index);
Elements paragraph(std::wstring text); // Use inside hflow(). Split by space.
Elements paragraph(std::string text); // Use inside hflow(). Split by space.
Element graph(GraphFunction);
// -- Decorator ---
@ -112,6 +112,8 @@ Dimensions Fit(Element&);
// Make container able to take any number of children as input.
#include "ftxui/dom/take_any_args.hpp"
// Include old definitions using wstring.
#include "ftxui/dom/deprecated.hpp"
#endif /* end of include guard: FTXUI_DOM_ELEMENTS_HPP */
// Copyright 2020 Arthur Sonzogni. All rights reserved.

View File

@ -303,7 +303,7 @@ class Color {
bool operator==(const Color& rhs) const;
bool operator!=(const Color& rhs) const;
std::wstring Print(bool is_background_color) const;
std::string Print(bool is_background_color) const;
private:
enum class ColorType : uint8_t {

View File

@ -2,7 +2,7 @@
#define FTXUI_SCREEN_SCREEN
#include <memory>
#include <string> // for allocator, wstring, string, basic_string
#include <string> // for string, allocator, basic_string
#include <vector> // for vector
#include "ftxui/screen/box.hpp" // for Box
@ -16,8 +16,7 @@ namespace ftxui {
struct Pixel {
// The graphemes stored into the pixel. To support combining characters,
// like: a⃦, this can potentially contains multiple codepoitns.
// Required: character.size() >= 1;
std::wstring character = L" ";
std::string character = " ";
// Colors:
Color background_color = Color::Default;
@ -55,7 +54,7 @@ class Screen {
static Screen Create(Dimensions width, Dimensions height);
// Node write into the screen using Screen::at.
wchar_t& at(int x, int y);
std::string& at(int x, int y);
Pixel& PixelAt(int x, int y);
// Convert the screen into a printable string in the terminal.

View File

@ -2,6 +2,7 @@
#define FTXUI_SCREEN_STRING_HPP
#include <string>
#include <vector>
namespace ftxui {
std::string to_string(const std::wstring& s);
@ -12,12 +13,10 @@ std::wstring to_wstring(T s) {
return to_wstring(std::to_string(s));
}
int wchar_width(char32_t);
int wchar_width(wchar_t);
int wchar_width_cjk(char32_t);
int wchar_width_cjk(wchar_t);
int wstring_width(const std::wstring&);
int wstring_width_cjk(const std::wstring&);
int string_width(const std::string&);
std::vector<std::string> Utf8ToGlyphs(const std::string& input);
} // namespace ftxui

View File

@ -42,11 +42,27 @@ class Ref {
/// class convert multiple mutable string toward a shared representation.
class StringRef {
public:
StringRef(std::wstring* ref) : address_(ref) {}
StringRef(std::wstring ref) : owned_(std::move(ref)) {}
StringRef(const wchar_t* ref) : StringRef(std::wstring(ref)) {}
StringRef(const char* ref) : StringRef(to_wstring(std::string(ref))) {}
StringRef(std::string ref) : StringRef(to_wstring(std::move(ref))) {}
StringRef(std::string* ref) : address_(ref) {}
StringRef(std::string ref) : owned_(std::move(ref)) {}
StringRef(const wchar_t* ref) : StringRef(to_string(std::wstring(ref))) {}
StringRef(const char* ref) : StringRef(std::string(ref)) {}
std::string& operator*() { return address_ ? *address_ : owned_; }
std::string* operator->() { return address_ ? address_ : &owned_; }
private:
std::string owned_;
std::string* address_ = nullptr;
};
/// @brief An adapter. Own or reference a constant string. For convenience, this
/// class convert multiple mutable string toward a shared representation.
class WideStringRef {
public:
WideStringRef(std::wstring* ref) : address_(ref) {}
WideStringRef(std::wstring ref) : owned_(std::move(ref)) {}
WideStringRef(const wchar_t* ref) : WideStringRef(std::wstring(ref)) {}
WideStringRef(const char* ref)
: WideStringRef(to_wstring(std::string(ref))) {}
std::wstring& operator*() { return address_ ? *address_ : owned_; }
std::wstring* operator->() { return address_ ? address_ : &owned_; }
@ -59,19 +75,35 @@ class StringRef {
/// class convert multiple immutable string toward a shared representation.
class ConstStringRef {
public:
ConstStringRef(const std::wstring* ref) : address_(ref) {}
ConstStringRef(std::wstring ref) : owned_(std::move(ref)) {}
ConstStringRef(const std::string* ref) : address_(ref) {}
ConstStringRef(const std::wstring* ref) : ConstStringRef(to_string(*ref)) {}
ConstStringRef(std::string ref) : owned_(std::move(ref)) {}
ConstStringRef(std::wstring ref) : ConstStringRef(to_string(ref)) {}
ConstStringRef(const wchar_t* ref) : ConstStringRef(std::wstring(ref)) {}
ConstStringRef(const char* ref)
: ConstStringRef(to_wstring(std::string(ref))) {}
ConstStringRef(std::string ref)
: ConstStringRef(to_wstring(std::move(ref))) {}
const std::wstring& operator*() { return address_ ? *address_ : owned_; }
const std::wstring* operator->() { return address_ ? address_ : &owned_; }
const std::string& operator*() { return address_ ? *address_ : owned_; }
const std::string* operator->() { return address_ ? address_ : &owned_; }
private:
const std::wstring owned_;
const std::wstring* address_ = nullptr;
const std::string owned_;
const std::string* address_ = nullptr;
};
/// @brief An adapter. Reference a list of strings.
class ConstStringListRef {
public:
ConstStringListRef(const std::vector<std::string>* ref) : ref_(ref) {}
ConstStringListRef(const std::vector<std::wstring>* ref) : ref_wide_(ref) {}
size_t size() const { return ref_ ? ref_->size() : ref_wide_->size(); }
std::string operator[](size_t i) const {
return ref_ ? (*ref_)[i] : to_string((*ref_wide_)[i]);
}
private:
const std::vector<std::string>* ref_ = nullptr;
const std::vector<std::wstring>* ref_wide_ = nullptr;
};
} // namespace ftxui

View File

@ -75,7 +75,7 @@ class ButtonBase : public ComponentBase {
///
/// ```cpp
/// auto screen = ScreenInteractive::FitComponent();
/// std::wstring label = L"Click to quit";
/// std::string label = "Click to quit";
/// Component button = Button(&label, screen.ExitLoopClosure());
/// screen.Loop(button)
/// ```

View File

@ -37,7 +37,7 @@ class CatchEventBase : public ComponentBase {
/// ```cpp
/// auto screen = ScreenInteractive::TerminalOutput();
/// auto renderer = Renderer([] {
/// return text(L"My interface");
/// return text("My interface");
/// });
/// screen.Loop(renderer);
/// ```

View File

@ -22,10 +22,10 @@ class CheckboxBase : public ComponentBase {
#if defined(FTXUI_MICROSOFT_TERMINAL_FALLBACK)
// Microsoft terminal do not use fonts able to render properly the default
// radiobox glyph.
if (option_->style_checked == L"")
option_->style_checked = L"[X]";
if (option_->style_unchecked == L"")
option_->style_unchecked = L"[ ]";
if (option_->style_checked == "")
option_->style_checked = "[X]";
if (option_->style_unchecked == "")
option_->style_unchecked = "[ ]";
#endif
}
@ -91,7 +91,7 @@ class CheckboxBase : public ComponentBase {
///
/// ```cpp
/// auto screen = ScreenInteractive::FitComponent();
/// std::wstring label = L"Make a sandwidth";
/// std::string label = "Make a sandwidth";
/// bool checked = false;
/// Component checkbox = Checkbox(&label, &checked);
/// screen.Loop(checkbox)

View File

@ -3,6 +3,7 @@
#include <cassert> // for assert
#include <iterator> // for begin, end
#include <utility> // for move
#include <vector> // for vector, __alloc_traits<>::value_type
#include "ftxui/component/captured_mouse.hpp" // for CapturedMouse, CapturedMouseInterface
#include "ftxui/component/component.hpp"
@ -82,7 +83,7 @@ Element ComponentBase::Render() {
if (children_.size() == 1)
return children_.front()->Render();
return text(L"Not implemented component");
return text("Not implemented component");
}
/// @brief Called in response to an event.

View File

@ -93,7 +93,7 @@ class VerticalContainer : public ContainerBase {
for (auto& it : children_)
elements.push_back(it->Render());
if (elements.size() == 0)
return text(L"Empty container");
return text("Empty container");
return vbox(std::move(elements));
}
@ -122,7 +122,7 @@ class HorizontalContainer : public ContainerBase {
for (auto& it : children_)
elements.push_back(it->Render());
if (elements.size() == 0)
return text(L"Empty container");
return text("Empty container");
return hbox(std::move(elements));
}
@ -150,7 +150,7 @@ class TabContainer : public ContainerBase {
Component active_child = ActiveChild();
if (active_child)
return active_child->Render();
return text(L"Empty container");
return text("Empty container");
}
bool OnMouseEvent(Event event) override {

View File

@ -9,7 +9,6 @@ namespace ftxui {
// static
Event Event::Character(std::string input) {
Event event;
event.character_ = to_wstring(input)[0];
event.input_ = std::move(input);
event.type_ = Type::Character;
return event;
@ -17,16 +16,12 @@ Event Event::Character(std::string input) {
// static
Event Event::Character(char c) {
return Character(wchar_t(c));
return Event::Character(std::string{c});
}
// static
Event Event::Character(wchar_t c) {
Event event;
event.input_ = {(char)c};
event.type_ = Type::Character;
event.character_ = c;
return event;
return Event::Character(to_string(std::wstring{c}));
}
// static

View File

@ -8,19 +8,22 @@
#include "ftxui/component/component.hpp" // for Make, Input
#include "ftxui/component/component_base.hpp" // for ComponentBase
#include "ftxui/component/component_options.hpp" // for InputOption
#include "ftxui/component/deprecated.hpp" // for Input
#include "ftxui/component/event.hpp" // for Event, Event::ArrowLeft, Event::ArrowRight, Event::Backspace, Event::Custom, Event::Delete, Event::End, Event::Home, Event::Return
#include "ftxui/component/mouse.hpp" // for Mouse, Mouse::Left, Mouse::Pressed
#include "ftxui/component/screen_interactive.hpp" // for Component
#include "ftxui/dom/elements.hpp" // for operator|, Element, text, reflect, dim, flex, focus, inverted, hbox, size, frame, select, underlined, Decorator, EQUAL, HEIGHT
#include "ftxui/dom/deprecated.hpp" // for text
#include "ftxui/dom/elements.hpp" // for operator|, Element, reflect, text, dim, flex, focus, inverted, hbox, size, frame, select, underlined, Decorator, EQUAL, HEIGHT
#include "ftxui/screen/box.hpp" // for Box
#include "ftxui/util/ref.hpp" // for StringRef, Ref, ConstStringRef
#include "ftxui/screen/string.hpp" // for to_wstring, to_string
#include "ftxui/util/ref.hpp" // for WideStringRef, Ref, ConstStringRef, StringRef
namespace ftxui {
// An input box. The user can type text into it.
class InputBase : public ComponentBase {
class WideInputBase : public ComponentBase {
public:
InputBase(StringRef content,
WideInputBase(WideStringRef content,
ConstStringRef placeholder,
Ref<InputOption> option)
: content_(content), placeholder_(placeholder), option_(option) {}
@ -132,7 +135,7 @@ class InputBase : public ComponentBase {
// Content
if (event.is_character()) {
content_->insert(cursor_position(), 1, event.character());
content_->insert(cursor_position(), 1, to_wstring(event.character())[0]);
cursor_position()++;
option_->on_change();
return true;
@ -165,7 +168,7 @@ class InputBase : public ComponentBase {
bool Focusable() const final { return true; }
StringRef content_;
WideStringRef content_;
ConstStringRef placeholder_;
Box input_box_;
@ -173,6 +176,43 @@ class InputBase : public ComponentBase {
Ref<InputOption> option_;
};
// An input box. The user can type text into it.
// For convenience, the std::string version of Input simply wrap a
// WideInputBase.
// TODO(arthursonzogni): Provide an implementation handling std::string natively
// and adds better support for combining characters.
class InputBase : public ComponentBase {
public:
InputBase(StringRef content,
ConstStringRef placeholder,
Ref<InputOption> option)
: content_(std::move(content)),
wrapped_content_(to_wstring(*content_)),
wrapped_input_(&wrapped_content_,
std::move(placeholder),
std::move(option)) {}
Element Render() override {
wrapped_content_ = to_wstring(*content_);
return wrapped_input_.Render();
}
bool OnEvent(Event event) override {
wrapped_content_ = to_wstring(*content_);
if (wrapped_input_.OnEvent(event)) {
content_ = to_string(wrapped_content_);
return true;
}
return false;
}
bool Focusable() const final { return true; }
StringRef content_;
std::wstring wrapped_content_;
WideInputBase wrapped_input_;
};
/// @brief An input box for editing text.
/// @param content The editable content.
/// @param placeholder The text displayed when content is still empty.
@ -184,8 +224,8 @@ class InputBase : public ComponentBase {
///
/// ```cpp
/// auto screen = ScreenInteractive::FitComponent();
/// std::wstring content= L"";
/// std::wstring placeholder = L"placeholder";
/// std::string content= "";
/// std::string placeholder = "placeholder";
/// Component input = Input(&content, &placeholder);
/// screen.Loop(input);
/// ```
@ -201,6 +241,34 @@ Component Input(StringRef content,
return Make<InputBase>(content, placeholder, std::move(option));
}
/// @brief . An input box for editing text.
/// @param content The editable content.
/// @param placeholder The text displayed when content is still empty.
/// @param option Additional optional parameters.
/// @ingroup component
/// @see InputBase
///
/// ### Example
///
/// ```cpp
/// auto screen = ScreenInteractive::FitComponent();
/// std::string content= "";
/// std::string placeholder = "placeholder";
/// Component input = Input(&content, &placeholder);
/// screen.Loop(input);
/// ```
///
/// ### Output
///
/// ```bash
/// placeholder
/// ```
Component Input(WideStringRef content,
ConstStringRef placeholder,
Ref<InputOption> option) {
return Make<WideInputBase>(content, placeholder, std::move(option));
}
} // namespace ftxui
// Copyright 2020 Arthur Sonzogni. All rights reserved.

View File

@ -4,9 +4,9 @@
#include <string> // for wstring
#include "ftxui/component/captured_mouse.hpp" // for ftxui
#include "ftxui/component/component.hpp" // for Input
#include "ftxui/component/component_base.hpp" // for ComponentBase, Component
#include "ftxui/component/component_options.hpp" // for InputOption
#include "ftxui/component/deprecated.hpp" // for Input
#include "ftxui/component/event.hpp" // for Event, Event::ArrowLeft, Event::ArrowRight, Event::Backspace, Event::Delete, Event::End, Event::Home
#include "ftxui/dom/elements.hpp" // for Fit
#include "ftxui/dom/node.hpp" // for Render
@ -42,8 +42,8 @@ TEST(InputTest, Type) {
auto document = input->Render();
auto screen = Screen::Create(Dimension::Fit(document));
Render(screen, document);
EXPECT_EQ(screen.PixelAt(0, 0).character, L"a");
EXPECT_EQ(screen.PixelAt(1, 0).character, L"b");
EXPECT_EQ(screen.PixelAt(0, 0).character, "a");
EXPECT_EQ(screen.PixelAt(1, 0).character, "b");
}
TEST(InputTest, TypePassword) {
@ -64,8 +64,8 @@ TEST(InputTest, TypePassword) {
auto document = input->Render();
auto screen = Screen::Create(Dimension::Fit(document));
Render(screen, document);
EXPECT_EQ(screen.PixelAt(0, 0).character, L"");
EXPECT_EQ(screen.PixelAt(1, 0).character, L"");
EXPECT_EQ(screen.PixelAt(0, 0).character, "");
EXPECT_EQ(screen.PixelAt(1, 0).character, "");
}
TEST(InputTest, Arrow) {

View File

@ -2,7 +2,7 @@
#include <algorithm> // for max, min
#include <functional> // for function
#include <memory> // for shared_ptr, allocator_traits<>::value_type
#include <string> // for operator+, wstring
#include <string> // for operator+, string
#include <utility> // for move
#include <vector> // for vector, __alloc_traits<>::value_type
@ -23,16 +23,14 @@ namespace ftxui {
/// @ingroup component
class MenuBase : public ComponentBase {
public:
MenuBase(const std::vector<std::wstring>* entries,
int* selected,
Ref<MenuOption> option)
MenuBase(ConstStringListRef entries, int* selected, Ref<MenuOption> option)
: entries_(entries), selected_(selected), option_(option) {}
Element Render() {
Elements elements;
bool is_menu_focused = Focused();
boxes_.resize(entries_->size());
for (size_t i = 0; i < entries_->size(); ++i) {
boxes_.resize(entries_.size());
for (size_t i = 0; i < entries_.size(); ++i) {
bool is_focused = (focused_entry() == int(i)) && is_menu_focused;
bool is_selected = (*selected_ == int(i));
@ -43,9 +41,9 @@ class MenuBase : public ComponentBase {
auto focus_management = !is_selected ? nothing
: is_menu_focused ? focus
: select;
auto icon = is_selected ? L"> " : L" ";
elements.push_back(text(icon + entries_->at(i)) | style |
focus_management | reflect(boxes_[i]));
auto icon = is_selected ? "> " : " ";
elements.push_back(text(icon + entries_[i]) | style | focus_management |
reflect(boxes_[i]));
}
return vbox(std::move(elements));
}
@ -64,12 +62,12 @@ class MenuBase : public ComponentBase {
(*selected_)--;
if (event == Event::ArrowDown || event == Event::Character('j'))
(*selected_)++;
if (event == Event::Tab && entries_->size())
*selected_ = (*selected_ + 1) % entries_->size();
if (event == Event::TabReverse && entries_->size())
*selected_ = (*selected_ + entries_->size() - 1) % entries_->size();
if (event == Event::Tab && entries_.size())
*selected_ = (*selected_ + 1) % entries_.size();
if (event == Event::TabReverse && entries_.size())
*selected_ = (*selected_ + entries_.size() - 1) % entries_.size();
*selected_ = std::max(0, std::min(int(entries_->size()) - 1, *selected_));
*selected_ = std::max(0, std::min(int(entries_.size()) - 1, *selected_));
if (*selected_ != old_selected) {
focused_entry() = *selected_;
@ -106,12 +104,11 @@ class MenuBase : public ComponentBase {
return false;
}
bool Focusable() const final { return entries_->size(); }
bool Focusable() const final { return entries_.size(); }
int& focused_entry() { return option_->focused_entry(); }
protected:
const std::vector<std::wstring>* const entries_;
ConstStringListRef entries_;
int* selected_ = 0;
Ref<MenuOption> option_;
@ -129,10 +126,10 @@ class MenuBase : public ComponentBase {
///
/// ```cpp
/// auto screen = ScreenInteractive::TerminalOutput();
/// std::vector<std::wstring> entries = {
/// L"entry 1",
/// L"entry 2",
/// L"entry 3",
/// std::vector<std::string> entries = {
/// "entry 1",
/// "entry 2",
/// "entry 3",
/// };
/// int selected = 0;
/// auto menu = Menu(&entries, &selected);
@ -146,7 +143,7 @@ class MenuBase : public ComponentBase {
/// entry 2
/// entry 3
/// ```
Component Menu(const std::vector<std::wstring>* entries,
Component Menu(ConstStringListRef entries,
int* selected,
Ref<MenuOption> option) {
return Make<MenuBase>(entries, selected, std::move(option));

View File

@ -2,7 +2,7 @@
#include <algorithm> // for max, min
#include <functional> // for function
#include <memory> // for shared_ptr, allocator_traits<>::value_type
#include <string> // for wstring
#include <string> // for string
#include <utility> // for move
#include <vector> // for vector
@ -25,26 +25,26 @@ namespace {
/// @ingroup component
class RadioboxBase : public ComponentBase {
public:
RadioboxBase(const std::vector<std::wstring>* entries,
RadioboxBase(ConstStringListRef entries,
int* selected,
Ref<RadioboxOption> option)
: entries_(entries), selected_(selected), option_(std::move(option)) {
#if defined(FTXUI_MICROSOFT_TERMINAL_FALLBACK)
// Microsoft terminal do not use fonts able to render properly the default
// radiobox glyph.
if (option_->style_checked == L"")
option_->style_checked = L"(*)";
if (option_->style_unchecked == L"")
option_->style_unchecked = L"( )";
if (option_->style_checked == "")
option_->style_checked = "(*)";
if (option_->style_unchecked == "")
option_->style_unchecked = "( )";
#endif
}
private:
Element Render() override {
std::vector<Element> elements;
Elements elements;
bool is_focused = Focused();
boxes_.resize(entries_->size());
for (size_t i = 0; i < entries_->size(); ++i) {
boxes_.resize(entries_.size());
for (size_t i = 0; i < entries_.size(); ++i) {
auto style = (focused_entry() == int(i) && is_focused)
? option_->style_focused
: option_->style_unfocused;
@ -52,10 +52,10 @@ class RadioboxBase : public ComponentBase {
: is_focused ? focus
: select;
const std::wstring& symbol = *selected_ == int(i)
const std::string& symbol = *selected_ == int(i)
? option_->style_checked
: option_->style_unchecked;
elements.push_back(hbox(text(symbol), text(entries_->at(i)) | style) |
elements.push_back(hbox(text(symbol), text(entries_[i]) | style) |
focus_management | reflect(boxes_[i]));
}
return vbox(std::move(elements));
@ -75,12 +75,12 @@ class RadioboxBase : public ComponentBase {
new_focused--;
if (event == Event::ArrowDown || event == Event::Character('j'))
new_focused++;
if (event == Event::Tab && entries_->size())
new_focused = (new_focused + 1) % entries_->size();
if (event == Event::TabReverse && entries_->size())
new_focused = (new_focused + entries_->size() - 1) % entries_->size();
if (event == Event::Tab && entries_.size())
new_focused = (new_focused + 1) % entries_.size();
if (event == Event::TabReverse && entries_.size())
new_focused = (new_focused + entries_.size() - 1) % entries_.size();
new_focused = std::max(0, std::min(int(entries_->size()) - 1, new_focused));
new_focused = std::max(0, std::min(int(entries_.size()) - 1, new_focused));
if (focused_entry() != new_focused) {
focused_entry() = new_focused;
@ -119,11 +119,10 @@ class RadioboxBase : public ComponentBase {
return false;
}
bool Focusable() const final { return entries_->size(); }
bool Focusable() const final { return entries_.size(); }
int& focused_entry() { return option_->focused_entry(); }
const std::vector<std::wstring>* const entries_;
ConstStringListRef entries_;
int* const selected_;
int cursor_position = 0;
@ -144,10 +143,10 @@ class RadioboxBase : public ComponentBase {
///
/// ```cpp
/// auto screen = ScreenInteractive::TerminalOutput();
/// std::vector<std::wstring> entries = {
/// L"entry 1",
/// L"entry 2",
/// L"entry 3",
/// std::vector<std::string> entries = {
/// "entry 1",
/// "entry 2",
/// "entry 3",
/// };
/// int selected = 0;
/// auto menu = Radiobox(&entries, &selected);
@ -161,7 +160,7 @@ class RadioboxBase : public ComponentBase {
/// ○ entry 2
/// ○ entry 3
/// ```
Component Radiobox(const std::vector<std::wstring>* entries,
Component Radiobox(ConstStringListRef entries,
int* selected,
Ref<RadioboxOption> option) {
return Make<RadioboxBase>(entries, selected, std::move(option));

View File

@ -21,7 +21,7 @@ namespace ftxui {
/// ```cpp
/// auto screen = ScreenInteractive::TerminalOutput();
/// auto renderer = Renderer([] {
/// return text(L"My interface");
/// return text("My interface");
/// });
/// screen.Loop(renderer);
/// ```
@ -46,7 +46,7 @@ Component Renderer(std::function<Element()> render) {
///
/// ```cpp
/// auto screen = ScreenInteractive::TerminalOutput();
/// std::wstring label = "Click to quit";
/// std::string label = "Click to quit";
/// auto button = Button(&label, screen.ExitLoopClosure());
/// auto renderer = Renderer(button, [&] {
/// return hbox({

View File

@ -250,8 +250,8 @@ class ResizableSplitBottomBase : public ComponentBase {
/// ```cpp
/// auto screen = ScreenInteractive::Fullscreen();
/// int left_size = 10;
/// auto left = Renderer([] { return text(L"Left") | center;});
/// auto right = Renderer([] { return text(L"right") | center;});
/// auto left = Renderer([] { return text("Left") | center;});
/// auto right = Renderer([] { return text("right") | center;});
/// auto split = ResizableSplitLeft(left, right, &left_size);
/// screen.Loop(split);
/// ```
@ -280,8 +280,8 @@ Component ResizableSplitLeft(Component main, Component back, int* main_size) {
/// ```cpp
/// auto screen = ScreenInteractive::Fullscreen();
/// int right_size = 10;
/// auto left = Renderer([] { return text(L"Left") | center;});
/// auto right = Renderer([] { return text(L"right") | center;});
/// auto left = Renderer([] { return text("Left") | center;});
/// auto right = Renderer([] { return text("right") | center;});
/// auto split = ResizableSplitRight(right, left, &right_size);
/// screen.Loop(split);
/// ```
@ -310,8 +310,8 @@ Component ResizableSplitRight(Component main, Component back, int* main_size) {
/// ```cpp
/// auto screen = ScreenInteractive::Fullscreen();
/// int top_size = 1;
/// auto top = Renderer([] { return text(L"Top") | center;});
/// auto bottom = Renderer([] { return text(L"Bottom") | center;});
/// auto top = Renderer([] { return text("Top") | center;});
/// auto bottom = Renderer([] { return text("Bottom") | center;});
/// auto split = ResizableSplitTop(top, bottom, &top_size);
/// screen.Loop(split);
/// ```
@ -340,8 +340,8 @@ Component ResizableSplitTop(Component main, Component back, int* main_size) {
/// ```cpp
/// auto screen = ScreenInteractive::Fullscreen();
/// int bottom_size = 1;
/// auto top = Renderer([] { return text(L"Top") | center;});
/// auto bottom = Renderer([] { return text(L"Bottom") | center;});
/// auto top = Renderer([] { return text("Top") | center;});
/// auto bottom = Renderer([] { return text("Bottom") | center;});
/// auto split = ResizableSplit::Bottom(bottom, top, &bottom_size);
/// screen.Loop(split);
/// ```

View File

@ -1,11 +1,12 @@
#include <gtest/gtest-message.h> // for Message
#include <gtest/gtest-test-part.h> // for TestPartResult
#include <csignal>
#include <gtest/gtest-test-part.h> // for SuiteApiResolver, TestFactoryImpl, TestPartResult
#include <csignal> // for raise, SIGABRT, SIGFPE, SIGILL, SIGINT, SIGSEGV, SIGTERM
#include "ftxui/component/component.hpp"
#include "ftxui/component/component.hpp" // for Renderer
#include "ftxui/component/screen_interactive.hpp"
#include "ftxui/dom/elements.hpp"
#include "gtest/gtest_pred_impl.h" // for AssertionResult, Test, EXPECT_EQ
#include "ftxui/dom/deprecated.hpp" // for text
#include "ftxui/dom/elements.hpp" // for Element
#include "gtest/gtest_pred_impl.h" // for Test, TEST, EXPECT_EQ
using namespace ftxui;

View File

@ -17,7 +17,7 @@ namespace ftxui {
template <class T>
class SliderBase : public ComponentBase {
public:
SliderBase(StringRef label, T* value, T min, T max, T increment)
SliderBase(ConstStringRef label, T* value, T min, T max, T increment)
: label_(label),
value_(value),
min_(min),
@ -31,9 +31,9 @@ class SliderBase : public ComponentBase {
return hbox({
text(*label_) | dim | vcenter,
hbox({
text(L"["),
text("["),
gauge(percent) | underlined | xflex | reflect(gauge_box_),
text(L"]"),
text("]"),
}) | xflex,
}) |
gauge_color | xflex | reflect(box_);
@ -87,7 +87,7 @@ class SliderBase : public ComponentBase {
bool Focusable() const final { return true; }
private:
StringRef label_;
ConstStringRef label_;
T* value_;
T min_;
T max_;
@ -110,7 +110,7 @@ class SliderBase : public ComponentBase {
/// ```cpp
/// auto screen = ScreenInteractive::TerminalOutput();
/// int value = 50;
/// auto slider = Slider(L"Value:", &value, 0, 100, 1);
/// auto slider = Slider("Value:", &value, 0, 100, 1);
/// screen.Loop(slider);
/// ```
///
@ -120,23 +120,23 @@ class SliderBase : public ComponentBase {
/// Value:[██████████████████████████ ]
/// ```
template <class T>
Component Slider(StringRef label, T* value, T min, T max, T increment) {
Component Slider(ConstStringRef label, T* value, T min, T max, T increment) {
return Make<SliderBase<T>>(std::move(label), value, min, max, increment);
}
template Component Slider(StringRef label,
template Component Slider(ConstStringRef label,
int* value,
int min,
int max,
int increment);
template Component Slider(StringRef label,
template Component Slider(ConstStringRef label,
float* value,
float min,
float max,
float increment);
template Component Slider(StringRef label,
template Component Slider(ConstStringRef label,
long* value,
long min,
long max,

View File

@ -29,7 +29,7 @@ TEST(Event, Character) {
for (char c : basic_char) {
EXPECT_TRUE(event_receiver->Receive(&received));
EXPECT_TRUE(received.is_character());
EXPECT_EQ(c, received.character());
EXPECT_EQ(c, received.character()[0]);
}
EXPECT_FALSE(event_receiver->Receive(&received));
}

View File

@ -2,19 +2,18 @@
#include <algorithm> // for max, min
#include <functional> // for function
#include <memory> // for shared_ptr, allocator_traits<>::value_type
#include <string> // for wstring
#include <utility> // for move
#include <vector> // for vector
#include "ftxui/component/captured_mouse.hpp" // for CapturedMouse
#include "ftxui/component/component.hpp" // for Make, Component, Toggle
#include "ftxui/component/component_base.hpp" // for ComponentBase
#include "ftxui/component/component.hpp" // for Make, Toggle
#include "ftxui/component/component_base.hpp" // for Component, ComponentBase
#include "ftxui/component/component_options.hpp" // for ToggleOption
#include "ftxui/component/event.hpp" // for Event, Event::ArrowLeft, Event::ArrowRight, Event::Return, Event::Tab, Event::TabReverse
#include "ftxui/component/mouse.hpp" // for Mouse, Mouse::Left, Mouse::Pressed
#include "ftxui/dom/elements.hpp" // for operator|, Element, Elements, hbox, reflect, separator, text, focus, nothing, select
#include "ftxui/screen/box.hpp" // for Box
#include "ftxui/util/ref.hpp" // for Ref
#include "ftxui/util/ref.hpp" // for ConstStringListRef, Ref
namespace ftxui {
@ -24,7 +23,7 @@ namespace {
/// @ingroup component
class ToggleBase : public ComponentBase {
public:
ToggleBase(const std::vector<std::wstring>* entries,
ToggleBase(ConstStringListRef entries,
int* selected,
Ref<ToggleOption> option)
: entries_(entries), selected_(selected), option_(std::move(option)) {}
@ -33,8 +32,8 @@ class ToggleBase : public ComponentBase {
Element Render() override {
Elements children;
bool is_toggle_focused = Focused();
boxes_.resize(entries_->size());
for (size_t i = 0; i < entries_->size(); ++i) {
boxes_.resize(entries_.size());
for (size_t i = 0; i < entries_.size(); ++i) {
// Separator.
if (i != 0)
children.push_back(separator());
@ -49,7 +48,7 @@ class ToggleBase : public ComponentBase {
auto focus_management = !is_selected ? nothing
: is_toggle_focused ? focus
: select;
children.push_back(text(entries_->at(i)) | style | focus_management |
children.push_back(text(entries_[i]) | style | focus_management |
reflect(boxes_[i]));
}
return hbox(std::move(children));
@ -64,12 +63,12 @@ class ToggleBase : public ComponentBase {
(*selected_)--;
if (event == Event::ArrowRight || event == Event::Character('l'))
(*selected_)++;
if (event == Event::Tab && entries_->size())
*selected_ = (*selected_ + 1) % entries_->size();
if (event == Event::TabReverse && entries_->size())
*selected_ = (*selected_ + entries_->size() - 1) % entries_->size();
if (event == Event::Tab && entries_.size())
*selected_ = (*selected_ + 1) % entries_.size();
if (event == Event::TabReverse && entries_.size())
*selected_ = (*selected_ + entries_.size() - 1) % entries_.size();
*selected_ = std::max(0, std::min(int(entries_->size()) - 1, *selected_));
*selected_ = std::max(0, std::min(int(entries_.size()) - 1, *selected_));
if (old_selected != *selected_) {
focused_entry() = *selected_;
@ -107,11 +106,10 @@ class ToggleBase : public ComponentBase {
return false;
}
bool Focusable() const final { return entries_->size(); }
bool Focusable() const final { return entries_.size(); }
int& focused_entry() { return option_->focused_entry(); }
const std::vector<std::wstring>* const entries_;
ConstStringListRef entries_;
int* selected_ = 0;
std::vector<Box> boxes_;
@ -125,7 +123,7 @@ class ToggleBase : public ComponentBase {
/// @param selected Reference the selected entry.
/// @param option Additional optional parameters.
/// @ingroup component
Component Toggle(const std::vector<std::wstring>* entries,
Component Toggle(ConstStringListRef entries,
int* selected,
Ref<ToggleOption> option) {
return Make<ToggleBase>(entries, selected, std::move(option));

View File

@ -10,7 +10,7 @@ using namespace ftxui;
static void BencharkBasic(benchmark::State& state) {
while (state.KeepRunning()) {
auto document = vbox({
text(L"Test"),
text("Test"),
separator(),
hbox({
gauge(0.9),
@ -20,7 +20,7 @@ static void BencharkBasic(benchmark::State& state) {
gauge(0.1),
separator(),
}),
text(L"Test"),
text("Test"),
}) |
border;
auto root = gauge(1.0);

View File

@ -1,6 +1,7 @@
#include <algorithm> // for max
#include <iterator> // for begin, end
#include <memory> // for make_shared, __shared_ptr_access
#include <memory> // for allocator, make_shared, __shared_ptr_access
#include <string> // for basic_string, string
#include <utility> // for move
#include <vector> // for vector, __alloc_traits<>::value_type
@ -12,10 +13,11 @@
namespace ftxui {
static wchar_t simple_border_charset[] = L"╭╮╰╯─│┬┴┤├";
static std::string simple_border_charset[] = {"", "", "", "", "",
"", "", "", "", ""};
// For reference, here is the charset for normal border:
// L"┌┐└┘─│┬┴┤├";
// {"┌", "┐", "└", "┘", "─", "│", "┬", "┴", "┤", "├"};
// TODO(arthursonzogni): Consider adding options to choose the kind of borders
// to use.
@ -29,7 +31,7 @@ class Border : public Node {
: Node(std::move(children)), charset_pixel(10, pixel) {}
std::vector<Pixel> charset_pixel;
std::vector<wchar_t> charset;
std::vector<std::string> charset;
void ComputeRequirement() override {
Node::ComputeRequirement();
@ -120,10 +122,10 @@ class Border : public Node {
///
/// ```cpp
/// // Use 'border' as a function...
/// Element document = border(text(L"The element"));
/// Element document = border(text("The element"));
///
/// // ...Or as a 'pipe'.
/// Element document = text(L"The element") | border;
/// Element document = text("The element") | border;
/// ```
///
/// ### Output
@ -146,8 +148,8 @@ Element border(Element child) {
/// ### Example
///
/// ```cpp
/// Element document = window(text(L"Title"),
/// text(L"content")
/// Element document = window(text("Title"),
/// text("content")
/// );
/// ```
///

View File

@ -52,7 +52,7 @@ class FgColor : public NodeDecorator {
/// ### Example
///
/// ```cpp
/// Element document = color(Color::Green, text(L"Success")),
/// Element document = color(Color::Green, text("Success")),
/// ```
Element color(Color color, Element child) {
return std::make_shared<FgColor>(std::move(child), color);
@ -67,7 +67,7 @@ Element color(Color color, Element child) {
/// ### Example
///
/// ```cpp
/// Element document = bgcolor(Color::Green, text(L"Success")),
/// Element document = bgcolor(Color::Green, text("Success")),
/// ```
Element bgcolor(Color color, Element child) {
return std::make_shared<BgColor>(std::move(child), color);
@ -81,7 +81,7 @@ Element bgcolor(Color color, Element child) {
/// ### Example
///
/// ```cpp
/// Element document = text(L"red") | color(Color::Red);
/// Element document = text("red") | color(Color::Red);
/// ```
Decorator color(Color c) {
return [c](Element child) { return color(c, std::move(child)); };
@ -95,7 +95,7 @@ Decorator color(Color c) {
/// ### Example
///
/// ```cpp
/// Element document = text(L"red") | bgcolor(Color::Red);
/// Element document = text("red") | bgcolor(Color::Red);
/// ```
Decorator bgcolor(Color color) {
return [color](Element child) { return bgcolor(color, std::move(child)); };

View File

@ -103,9 +103,9 @@ Element filler() {
///
/// ~~~cpp
/// hbox({
/// text(L"left") | border ,
/// text(L"middle") | border | flex,
/// text(L"right") | border,
/// text("left") | border ,
/// text("middle") | border | flex,
/// text("right") | border,
/// });
/// ~~~
///

View File

@ -1,4 +1,5 @@
#include <memory> // for make_shared
#include <memory> // for allocator, make_shared
#include <string> // for string
#include "ftxui/dom/elements.hpp" // for Element, gauge
#include "ftxui/dom/node.hpp" // for Node
@ -8,12 +9,13 @@
namespace ftxui {
static std::string charset[] =
#if defined(FTXUI_MICROSOFT_TERMINAL_FALLBACK)
// Microsoft's terminals often use fonts not handling the 8 unicode characters
// for representing the whole gauge. Fallback with less.
static wchar_t charset[] = L" ▌▌▌███";
// Microsoft's terminals often use fonts not handling the 8 unicode
// characters for representing the whole gauge. Fallback with less.
{" ", " ", " ", " ", "", "", "", "", "", ""};
#else
static wchar_t charset[] = L" ▏▎▍▌▋▊▉█";
{" ", " ", "", "", "", "", "", "", "", ""};
#endif
class Gauge : public Node {

View File

@ -1,5 +1,6 @@
#include <functional> // for function
#include <memory> // for make_shared
#include <memory> // for allocator, make_shared
#include <string> // for string
#include <vector> // for vector
#include "ftxui/dom/elements.hpp" // for GraphFunction, Element, graph
@ -10,12 +11,13 @@
namespace ftxui {
// Microsoft's terminals often use fonts not handling the 8 unicode characters
// for representing the whole gauge. Fallback with less.
static std::string charset[] =
#if defined(FTXUI_MICROSOFT_TERMINAL_FALLBACK)
const wchar_t charset[] = L" █ █████";
// Microsoft's terminals often use fonts not handling the 8 unicode
// characters for representing the whole graph. Fallback with less.
{" ", " ", "", " ", "", "", "", "", ""};
#else
const wchar_t charset[] = L" ▗▐▖▄▟▌▙█";
{" ", "", "", "", "", "", "", "", ""};
#endif
class Graph : public Node {
@ -43,8 +45,7 @@ class Graph : public Node {
int yy = 2 * y;
int i_1 = yy < height_1 ? 0 : yy == height_1 ? 3 : 6;
int i_2 = yy < height_2 ? 0 : yy == height_2 ? 1 : 2;
wchar_t pix = charset[i_1 + i_2];
screen.at(x, y) = pix;
screen.at(x, y) = charset[i_1 + i_2];
}
}
}

View File

@ -136,8 +136,8 @@ class HBox : public Node {
///
/// ```cpp
/// hbox({
/// text(L"Left"),
/// text(L"Right"),
/// text("Left"),
/// text("Right"),
/// });
/// ```
Element hbox(Elements children) {

View File

@ -1,13 +1,14 @@
#include <gtest/gtest-message.h> // for Message
#include <gtest/gtest-test-part.h> // for TestPartResult
#include <gtest/gtest-test-part.h> // for SuiteApiResolver, TestFactoryImpl, TestPartResult
#include <string> // for allocator, basic_string, string
#include <vector> // for vector
#include "ftxui/dom/elements.hpp" // for text, operator|, Element, flex_grow
#include "ftxui/dom/deprecated.hpp" // for text
#include "ftxui/dom/elements.hpp" // for operator|, Element, flex_grow, flex_shrink, hbox
#include "ftxui/dom/node.hpp" // for Render
#include "ftxui/screen/box.hpp" // for ftxui
#include "ftxui/screen/screen.hpp" // for Screen
#include "gtest/gtest_pred_impl.h" // for Test, SuiteApiResolver, EXPECT_EQ
#include "gtest/gtest_pred_impl.h" // for Test, EXPECT_EQ, TEST
using namespace ftxui;
using namespace ftxui;

View File

@ -1,7 +1,8 @@
#include <sstream>
#include <string>
#include <sstream> // for basic_istream, wstringstream
#include <string> // for allocator, char_traits, getline, operator+, wstring, basic_string
#include "ftxui/dom/elements.hpp"
#include "ftxui/dom/deprecated.hpp" // for text, paragraph
#include "ftxui/dom/elements.hpp" // for Elements
namespace ftxui {
@ -14,9 +15,22 @@ Elements paragraph(std::wstring the_text) {
Elements output;
std::wstringstream ss(the_text);
std::wstring word;
while (std::getline(ss, word, L' ')) {
while (std::getline(ss, word, L' '))
output.push_back(text(word + L' '));
}
return output;
}
/// @brief Return a vector of ftxui::text for every word of the string. This is
/// useful combined with ftxui::hflow.
/// @param the_text The string to be splitted.
/// @ingroup dom
/// @see hflow.
Elements paragraph(std::string the_text) {
Elements output;
std::stringstream ss(the_text);
std::string word;
while (std::getline(ss, word, ' '))
output.push_back(text(word + ' '));
return output;
}

View File

@ -1,5 +1,5 @@
#include <memory> // for make_shared
#include <string> // for wstring
#include <string> // for string
#include "ftxui/dom/elements.hpp" // for Element, separator
#include "ftxui/dom/node.hpp" // for Node
@ -22,11 +22,11 @@ class Separator : public Node {
bool is_column = (box_.x_max == box_.x_min);
bool is_line = (box_.y_min == box_.y_max);
wchar_t c = U'+';
std::string c = "+";
if (is_line && !is_column)
c = U'';
c = "";
else
c = U'';
c = "";
for (int y = box_.y_min; y <= box_.y_max; ++y) {
for (int x = box_.x_min; x <= box_.x_max; ++x) {

View File

@ -1,6 +1,6 @@
#include <stddef.h> // for size_t
#include <memory> // for allocator, allocator_traits<>::value_type
#include <string> // for basic_string, wstring
#include <string> // for string
#include <utility> // for move
#include <vector> // for vector, __alloc_traits<>::value_type
@ -8,242 +8,242 @@
namespace ftxui {
static const std::vector<std::vector<std::vector<std::wstring>>> elements = {
static const std::vector<std::vector<std::vector<std::string>>> elements = {
{
{L"Replaced by the gauge"},
{"Replaced by the gauge"},
},
{
{L". "},
{L".. "},
{L"..."},
{". "},
{".. "},
{"..."},
},
{
{L"|"},
{L"/"},
{L"-"},
{L"\\"},
{"|"},
{"/"},
{"-"},
{"\\"},
},
{
{L"+"},
{L"x"},
{"+"},
{"x"},
},
{
{L"| "},
{L"|| "},
{L"|||"},
{"| "},
{"|| "},
{"|||"},
},
{
{L""},
{L""},
{L""},
{L""},
{L""},
{L""},
{L""},
{L""},
{""},
{""},
{""},
{""},
{""},
{""},
{""},
{""},
},
{
{L""},
{L""},
{L""},
{L""},
{L""},
{L""},
{L""},
{L""},
{L""},
{L""},
{L""},
{L""},
{L""},
{L""},
{""},
{""},
{""},
{""},
{""},
{""},
{""},
{""},
{""},
{""},
{""},
{""},
{""},
{""},
},
{
{L""},
{L""},
{L""},
{L""},
{L""},
{L""},
{L""},
{L""},
{L""},
{L""},
{L""},
{L""},
{""},
{""},
{""},
{""},
{""},
{""},
{""},
{""},
{""},
{""},
{""},
{""},
},
{
{L""},
{L""},
{L""},
{L""},
{""},
{""},
{""},
{""},
},
{
{L""},
{L""},
{L""},
{L""},
{""},
{""},
{""},
{""},
},
{
{L""},
{L""},
{L""},
{L""},
{""},
{""},
{""},
{""},
},
{
{L""},
{L""},
{L""},
{L""},
{""},
{""},
{""},
{""},
},
{
{L""},
{L""},
{L""},
{L""},
{""},
{""},
{""},
{""},
},
{
{L""},
{L""},
{L""},
{""},
{""},
{""},
},
{
{L""},
{L""},
{L""},
{L""},
{L""},
{L""},
{L""},
{L""},
{""},
{""},
{""},
{""},
{""},
{""},
{""},
{""},
},
{
{L""},
{L""},
{L""},
{L""},
{L""},
{L""},
{L""},
{L""},
{L""},
{L""},
{""},
{""},
{""},
{""},
{""},
{""},
{""},
{""},
{""},
{""},
},
{
{L"(*----------)"}, {L"(-*---------)"}, {L"(--*--------)"},
{L"(---*-------)"}, {L"(----*------)"}, {L"(-----*-----)"},
{L"(------*----)"}, {L"(-------*---)"}, {L"(--------*--)"},
{L"(---------*-)"}, {L"(----------*)"}, {L"(---------*-)"},
{L"(--------*--)"}, {L"(-------*---)"}, {L"(------*----)"},
{L"(-----*-----)"}, {L"(----*------)"}, {L"(---*-------)"},
{L"(--*--------)"}, {L"(-*---------)"},
{"(*----------)"}, {"(-*---------)"}, {"(--*--------)"},
{"(---*-------)"}, {"(----*------)"}, {"(-----*-----)"},
{"(------*----)"}, {"(-------*---)"}, {"(--------*--)"},
{"(---------*-)"}, {"(----------*)"}, {"(---------*-)"},
{"(--------*--)"}, {"(-------*---)"}, {"(------*----)"},
{"(-----*-----)"}, {"(----*------)"}, {"(---*-------)"},
{"(--*--------)"}, {"(-*---------)"},
},
{
{L"[ ]"},
{L"[= ]"},
{L"[== ]"},
{L"[=== ]"},
{L"[==== ]"},
{L"[===== ]"},
{L"[======]"},
{L"[===== ]"},
{L"[==== ]"},
{L"[=== ]"},
{L"[== ]"},
{L"[= ]"},
{"[ ]"},
{"[= ]"},
{"[== ]"},
{"[=== ]"},
{"[==== ]"},
{"[===== ]"},
{"[======]"},
{"[===== ]"},
{"[==== ]"},
{"[=== ]"},
{"[== ]"},
{"[= ]"},
},
{
{L"[ ]"},
{L"[= ]"},
{L"[== ]"},
{L"[=== ]"},
{L"[==== ]"},
{L"[===== ]"},
{L"[======]"},
{L"[ =====]"},
{L"[ ====]"},
{L"[ ===]"},
{L"[ ==]"},
{L"[ =]"},
{"[ ]"},
{"[= ]"},
{"[== ]"},
{"[=== ]"},
{"[==== ]"},
{"[===== ]"},
{"[======]"},
{"[ =====]"},
{"[ ====]"},
{"[ ===]"},
{"[ ==]"},
{"[ =]"},
},
{
{L"[== ]"},
{L"[== ]"},
{L"[== ]"},
{L"[== ]"},
{L"[== ]"},
{L" [== ]"},
{L"[ == ]"},
{L"[ == ]"},
{L"[ ==]"},
{L"[ ==]"},
{L"[ ==]"},
{L"[ ==]"},
{L"[ ==]"},
{L"[ ==] "},
{L"[ == ]"},
{L"[ == ]"},
{"[== ]"},
{"[== ]"},
{"[== ]"},
{"[== ]"},
{"[== ]"},
{" [== ]"},
{"[ == ]"},
{"[ == ]"},
{"[ ==]"},
{"[ ==]"},
{"[ ==]"},
{"[ ==]"},
{"[ ==]"},
{"[ ==] "},
{"[ == ]"},
{"[ == ]"},
},
{{
L" ─╮",
L"",
L" ",
" ─╮",
"",
" ",
},
{
L"",
L"",
L"",
"",
"",
"",
},
{
L" ",
L"",
L" ─╯",
" ",
"",
" ─╯",
},
{
L" ",
L" ",
L"╰─╯",
" ",
" ",
"╰─╯",
},
{
L" ",
L"",
L"╰─ ",
" ",
"",
"╰─ ",
},
{
L"",
L"",
L"",
"",
"",
"",
},
{
L"╭─ ",
L"",
L" ",
"╭─ ",
"",
" ",
},
{
L"╭─╮",
L" ",
L" ",
"╭─╮",
" ",
" ",
}},
{{
L" /\\O ",
L" /\\/ ",
L" /\\ ",
L" / \\ ",
L"LOL LOL",
" /\\O ",
" /\\/ ",
" /\\ ",
" / \\ ",
"LOL LOL ",
},
{
L" _O ",
L" //|_ ",
L" | ",
L" /| ",
L" LLOL ",
" _O ",
" //|_ ",
" | ",
" /| ",
" LLOL ",
},
{
L" O ",
L" /_ ",
L" |\\ ",
L" / | ",
L" LOLLOL ",
" O ",
" /_ ",
" |\\ ",
" / | ",
" LOLLOL ",
}}};
/// @brief Useful to represent the effect of time and/or events. This display an

View File

@ -1,13 +1,14 @@
#include <algorithm> // for max
#include <memory> // for make_shared
#include <string> // for wstring
#include <string> // for string
#include <vector> // for vector
#include "ftxui/dom/deprecated.hpp" // for text, vtext
#include "ftxui/dom/elements.hpp" // for Element, text, vtext
#include "ftxui/dom/node.hpp" // for Node
#include "ftxui/dom/requirement.hpp" // for Requirement
#include "ftxui/screen/box.hpp" // for Box
#include "ftxui/screen/screen.hpp" // for Screen
#include "ftxui/screen/string.hpp" // for wchar_width, wstring_width
#include "ftxui/screen/screen.hpp" // for Pixel, Screen
#include "ftxui/screen/string.hpp" // for string_width, Utf8ToGlyphs, to_string
namespace ftxui {
@ -15,10 +16,10 @@ using ftxui::Screen;
class Text : public Node {
public:
Text(std::wstring text) : text_(text) {}
Text(std::string text) : text_(text) {}
void ComputeRequirement() override {
requirement_.min_x = wstring_width(text_);
requirement_.min_x = string_width(text_);
requirement_.min_y = 1;
}
@ -27,33 +28,26 @@ class Text : public Node {
int y = box_.y_min;
if (y > box_.y_max)
return;
for (wchar_t c : text_) {
const int width = wchar_width(c);
if (width >= 1) {
for (const auto& cell : Utf8ToGlyphs(text_)) {
if (x > box_.x_max)
return;
screen.PixelAt(x, y).character = c;
} else {
screen.PixelAt(x - 1, y).character += c;
}
x += std::max(width, 0);
screen.PixelAt(x, y).character = cell;
++x;
}
}
private:
std::wstring text_;
std::string text_;
};
class VText : public Node {
public:
VText(std::wstring text) : text_(text) {
for (auto& c : text_)
width_ = std::max(width_, wchar_width(c));
}
VText(std::string text)
: text_(text), width_{std::min(string_width(text_), 1)} {}
void ComputeRequirement() override {
requirement_.min_x = width_;
requirement_.min_y = text_.size();
requirement_.min_y = string_width(text_);
}
void Render(Screen& screen) override {
@ -61,20 +55,39 @@ class VText : public Node {
int y = box_.y_min;
if (x + width_ - 1 > box_.x_max)
return;
for (wchar_t c : text_) {
for (const auto& it : Utf8ToGlyphs(text_)) {
if (y > box_.y_max)
return;
screen.at(x, y) = c;
screen.PixelAt(x, y).character = it;
y += 1;
}
}
private:
std::wstring text_;
std::string text_;
int width_ = 1;
};
/// @brief Display a pieve of unicode text.
/// @brief Display a piece of UTF8 encoded unicode text.
/// @ingroup dom
/// @see ftxui::to_wstring
///
/// ### Example
///
/// ```cpp
/// Element document = text("Hello world!");
/// ```
///
/// ### Output
///
/// ```bash
/// Hello world!
/// ```
Element text(std::string text) {
return std::make_shared<Text>(text);
}
/// @brief Display a piece of UTF16 encoded unicode text.
/// @ingroup dom
/// @see ftxui::to_wstring
///
@ -90,10 +103,40 @@ class VText : public Node {
/// Hello world!
/// ```
Element text(std::wstring text) {
return std::make_shared<Text>(text);
return std::make_shared<Text>(to_string(text));
}
/// @brief Display a pieve of unicode text vertically.
/// @brief Display a piece of unicode text vertically.
/// @ingroup dom
/// @see ftxui::to_wstring
///
/// ### Example
///
/// ```cpp
/// Element document = vtext("Hello world!");
/// ```
///
/// ### Output
///
/// ```bash
/// H
/// e
/// l
/// l
/// o
///
/// w
/// o
/// r
/// l
/// d
/// !
/// ```
Element vtext(std::string text) {
return std::make_shared<VText>(text);
}
/// @brief Display a piece of UTF16 encoded unicode text vertically.
/// @ingroup dom
/// @see ftxui::to_wstring
///
@ -120,7 +163,7 @@ Element text(std::wstring text) {
/// !
/// ```
Element vtext(std::wstring text) {
return std::make_shared<VText>(text);
return std::make_shared<VText>(to_string(text));
}
} // namespace ftxui

View File

@ -2,7 +2,8 @@
#include <gtest/gtest-test-part.h> // for SuiteApiResolver, TestFactoryImpl, TestPartResult
#include <string> // for allocator, wstring
#include "ftxui/dom/elements.hpp" // for text, operator|, border, Element
#include "ftxui/dom/deprecated.hpp" // for text
#include "ftxui/dom/elements.hpp" // for operator|, border, Element
#include "ftxui/dom/node.hpp" // for Render
#include "ftxui/screen/box.hpp" // for ftxui
#include "ftxui/screen/screen.hpp" // for Screen

View File

@ -56,10 +56,10 @@ Elements operator|(Elements elements, Decorator decorator) {
///
/// Both of these are equivalent:
/// ```cpp
/// bold(text(L"Hello"));
/// bold(text("Hello"));
/// ```
/// ```cpp
/// text(L"Hello") | bold;
/// text("Hello") | bold;
/// ```
Element operator|(Element element, Decorator decorator) {
return decorator(std::move(element));

View File

@ -137,8 +137,8 @@ class VBox : public Node {
///
/// ```cpp
/// vbox({
/// text(L"Up"),
/// text(L"Down"),
/// text("Up"),
/// text("Down"),
/// });
/// ```
Element vbox(Elements children) {

View File

@ -1,14 +1,15 @@
#include <gtest/gtest-message.h> // for Message
#include <gtest/gtest-test-part.h> // for TestPartResult
#include <gtest/gtest-test-part.h> // for SuiteApiResolver, TestFactoryImpl, TestPartResult
#include <algorithm> // for remove
#include <string> // for allocator, basic_string, string
#include <vector> // for vector
#include "ftxui/dom/elements.hpp" // for vtext, operator|, Element, flex_grow
#include "ftxui/dom/deprecated.hpp" // for vtext
#include "ftxui/dom/elements.hpp" // for operator|, Element, flex_grow, flex_shrink, vbox
#include "ftxui/dom/node.hpp" // for Render
#include "ftxui/screen/box.hpp" // for ftxui
#include "ftxui/screen/screen.hpp" // for Screen
#include "gtest/gtest_pred_impl.h" // for Test, SuiteApiResolver, EXPECT_EQ
#include "gtest/gtest_pred_impl.h" // for Test, EXPECT_EQ, TEST
using namespace ftxui;
using namespace ftxui;

View File

@ -1,19 +1,16 @@
#include "ftxui/screen/color.hpp"
#include "ftxui/screen/color_info.hpp"
#include "ftxui/screen/string.hpp"
#include "ftxui/screen/terminal.hpp"
#include "ftxui/screen/color_info.hpp" // for GetColorInfo, ColorInfo
#include "ftxui/screen/terminal.hpp" // for Terminal, Terminal::Color, Terminal::Palette256, Terminal::TrueColor
namespace ftxui {
namespace {
const wchar_t* palette16code[16][2] = {
{L"30", L"40"}, {L"31", L"41"}, {L"32", L"42"}, {L"33", L"43"},
{L"34", L"44"},
{L"35", L"45"}, {L"36", L"46"}, {L"37", L"47"},
{L"90", L"100"}, {L"91", L"101"}, {L"92", L"102"}, {L"93", L"103"},
{L"94", L"104"}, {L"95", L"105"}, {L"96", L"106"}, {L"97", L"107"},
const char* palette16code[16][2] = {
{"30", "40"}, {"31", "41"}, {"32", "42"}, {"33", "43"},
{"34", "44"}, {"35", "45"}, {"36", "46"}, {"37", "47"},
{"90", "100"}, {"91", "101"}, {"92", "102"}, {"93", "103"},
{"94", "104"}, {"95", "105"}, {"96", "106"}, {"97", "107"},
};
}
@ -26,24 +23,24 @@ bool Color::operator!=(const Color& rhs) const {
return !operator==(rhs);
}
std::wstring Color::Print(bool is_background_color) const {
std::string Color::Print(bool is_background_color) const {
switch (type_) {
case ColorType::Palette1:
return is_background_color ? L"49" : L"39";
return is_background_color ? "49" : "39";
case ColorType::Palette16:
return palette16code[index_][is_background_color];
case ColorType::Palette256:
return (is_background_color ? L"48;5;" : L"38;5;") + to_wstring(index_);
return (is_background_color ? "48;5;" : "38;5;") + std::to_string(index_);
case ColorType::TrueColor:
return (is_background_color ? L"48;2;" : L"38;2;") //
+ to_wstring(red_) + L";" //
+ to_wstring(green_) + L";" //
+ to_wstring(blue_); //
return (is_background_color ? "48;2;" : "38;2;") //
+ std::to_string(red_) + ";" //
+ std::to_string(green_) + ";" //
+ std::to_string(blue_); //
}
return L"";
return "";
}
/// @brief Build a transparent color.

View File

@ -1,10 +1,9 @@
#include <algorithm> // for max
#include <iostream> // for operator<<, basic_ostream, wstringstream, stringstream, flush, cout, ostream
#include <iostream> // for operator<<, stringstream, basic_ostream, flush, cout, ostream
#include <memory> // for allocator
#include <sstream> // IWYU pragma: keep
#include "ftxui/screen/screen.hpp"
#include "ftxui/screen/string.hpp" // for to_string, wchar_width
#include "ftxui/screen/string.hpp" // for string_width
#include "ftxui/screen/terminal.hpp" // for Dimensions, Size
#if defined(_WIN32)
@ -18,24 +17,24 @@
namespace ftxui {
namespace {
static const wchar_t* BOLD_SET = L"\x1B[1m";
static const wchar_t* BOLD_RESET = L"\x1B[22m"; // Can't use 21 here.
static const char BOLD_SET[] = "\x1B[1m";
static const char BOLD_RESET[] = "\x1B[22m"; // Can't use 21 here.
static const wchar_t* DIM_SET = L"\x1B[2m";
static const wchar_t* DIM_RESET = L"\x1B[22m";
static const char DIM_SET[] = "\x1B[2m";
static const char DIM_RESET[] = "\x1B[22m";
static const wchar_t* UNDERLINED_SET = L"\x1B[4m";
static const wchar_t* UNDERLINED_RESET = L"\x1B[24m";
static const char UNDERLINED_SET[] = "\x1B[4m";
static const char UNDERLINED_RESET[] = "\x1B[24m";
static const wchar_t* BLINK_SET = L"\x1B[5m";
static const wchar_t* BLINK_RESET = L"\x1B[25m";
static const char BLINK_SET[] = "\x1B[5m";
static const char BLINK_RESET[] = "\x1B[25m";
static const wchar_t* INVERTED_SET = L"\x1B[7m";
static const wchar_t* INVERTED_RESET = L"\x1B[27m";
static const char INVERTED_SET[] = "\x1B[7m";
static const char INVERTED_RESET[] = "\x1B[27m";
static const char* MOVE_LEFT = "\r";
static const char* MOVE_UP = "\x1B[1A";
static const char* CLEAR_LINE = "\x1B[2K";
static const char MOVE_LEFT[] = "\r";
static const char MOVE_UP[] = "\x1B[1A";
static const char CLEAR_LINE[] = "\x1B[2K";
Pixel dev_null_pixel;
@ -62,7 +61,9 @@ void WindowsEmulateVT100Terminal() {
}
#endif
void UpdatePixelStyle(std::wstringstream& ss, Pixel& previous, Pixel& next) {
void UpdatePixelStyle(std::stringstream& ss,
Pixel& previous,
const Pixel& next) {
if (next.bold != previous.bold)
ss << (next.bold ? BOLD_SET : BOLD_RESET);
@ -80,8 +81,8 @@ void UpdatePixelStyle(std::wstringstream& ss, Pixel& previous, Pixel& next) {
if (next.foreground_color != previous.foreground_color ||
next.background_color != previous.background_color) {
ss << L"\x1B[" + next.foreground_color.Print(false) + L"m";
ss << L"\x1B[" + next.background_color.Print(true) + L"m";
ss << "\x1B[" + next.foreground_color.Print(false) + "m";
ss << "\x1B[" + next.background_color.Print(true) + "m";
}
previous = next;
@ -135,7 +136,7 @@ Screen::Screen(int dimx, int dimy)
/// Produce a std::string that can be used to print the Screen on the terminal.
/// Don't forget to flush stdout. Alternatively, you can use Screen::Print();
std::string Screen::ToString() {
std::wstringstream ss;
std::stringstream ss;
Pixel previous_pixel;
Pixel final_pixel;
@ -143,24 +144,21 @@ std::string Screen::ToString() {
for (int y = 0; y < dimy_; ++y) {
if (y != 0) {
UpdatePixelStyle(ss, previous_pixel, final_pixel);
ss << L"\r\n";
ss << "\r\n";
}
for (int x = 0; x < dimx_;) {
auto& pixel = pixels_[y][x];
bool previous_fullwidth = false;
for (const auto& pixel : pixels_[y]) {
if (!previous_fullwidth) {
UpdatePixelStyle(ss, previous_pixel, pixel);
int x_inc = 0;
for (auto& c : pixel.character) {
ss << c;
x_inc += wchar_width(c);
ss << pixel.character;
}
x += std::max(x_inc, 1);
previous_fullwidth = (string_width(pixel.character) == 2);
}
}
UpdatePixelStyle(ss, previous_pixel, final_pixel);
return to_string(ss.str());
return ss.str();
}
void Screen::Print() {
@ -170,8 +168,8 @@ void Screen::Print() {
/// @brief Access a character a given position.
/// @param x The character position along the x-axis.
/// @param y The character position along the y-axis.
wchar_t& Screen::at(int x, int y) {
return PixelAt(x, y).character[0];
std::string& Screen::at(int x, int y) {
return PixelAt(x, y).character;
}
/// @brief Access a Pixel at a given position.
@ -229,21 +227,21 @@ void Screen::ApplyShader() {
// Merge box characters togethers.
for (int y = 1; y < dimy_; ++y) {
for (int x = 1; x < dimx_; ++x) {
wchar_t& left = at(x - 1, y);
wchar_t& top = at(x, y - 1);
wchar_t& cur = at(x, y);
std::string& left = at(x - 1, y);
std::string& top = at(x, y - 1);
std::string& cur = at(x, y);
// Left vs current
if (cur == U'' && left == U'') cur = U'';
if (cur == U'' && left == U'') left = U'';
if (cur == U'' && left == U'') cur = U'';
if (cur == U'' && left == U'') left = U'';
if (cur == "" && left == "") cur = "";
if (cur == "" && left == "") left = "";
if (cur == "" && left == "") cur = "";
if (cur == "" && left == "") left = "";
// Top vs current
if (cur == U'' && top == U'') cur = U'';
if (cur == U'' && top == U'') top = U'';
if (cur == U'' && top == U'') cur = U'';
if (cur == U'' && top == U'') top = U'';
if (cur == "" && top == "") cur = "";
if (cur == "" && top == "") top = "";
if (cur == "" && top == "") cur = "";
if (cur == "" && top == "") top = "";
}
}
}

View File

@ -1,9 +1,291 @@
// Most of this code is borrowed from:
// Markus Kuhn -- 2007-05-26 (Unicode 5.0)
// Latest version: http://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c
// Thanks you!
//
// Modified by Arthur Sonzogni for FTXUI.
#include "ftxui/screen/string.hpp"
#include <stddef.h> // for size_t
#include <stdint.h> // for uint32_t, uint8_t
#include <codecvt> // for codecvt_utf8_utf16
#include <locale> // for wstring_convert
#include <string> // for string, basic_string, wstring, allocator
namespace {
struct Interval {
uint32_t first;
uint32_t last;
};
// Sorted list of non-overlapping intervals of non-spacing characters
// generated by "uniset +cat=Me +cat=Mn +cat=Cf -00AD +1160-11FF +200B c"
static const Interval g_combining_characters[] = {
{0x0300, 0x036F}, {0x0483, 0x0486}, {0x0488, 0x0489},
{0x0591, 0x05BD}, {0x05BF, 0x05BF}, {0x05C1, 0x05C2},
{0x05C4, 0x05C5}, {0x05C7, 0x05C7}, {0x0600, 0x0603},
{0x0610, 0x0615}, {0x064B, 0x065E}, {0x0670, 0x0670},
{0x06D6, 0x06E4}, {0x06E7, 0x06E8}, {0x06EA, 0x06ED},
{0x070F, 0x070F}, {0x0711, 0x0711}, {0x0730, 0x074A},
{0x07A6, 0x07B0}, {0x07EB, 0x07F3}, {0x0901, 0x0902},
{0x093C, 0x093C}, {0x0941, 0x0948}, {0x094D, 0x094D},
{0x0951, 0x0954}, {0x0962, 0x0963}, {0x0981, 0x0981},
{0x09BC, 0x09BC}, {0x09C1, 0x09C4}, {0x09CD, 0x09CD},
{0x09E2, 0x09E3}, {0x0A01, 0x0A02}, {0x0A3C, 0x0A3C},
{0x0A41, 0x0A42}, {0x0A47, 0x0A48}, {0x0A4B, 0x0A4D},
{0x0A70, 0x0A71}, {0x0A81, 0x0A82}, {0x0ABC, 0x0ABC},
{0x0AC1, 0x0AC5}, {0x0AC7, 0x0AC8}, {0x0ACD, 0x0ACD},
{0x0AE2, 0x0AE3}, {0x0B01, 0x0B01}, {0x0B3C, 0x0B3C},
{0x0B3F, 0x0B3F}, {0x0B41, 0x0B43}, {0x0B4D, 0x0B4D},
{0x0B56, 0x0B56}, {0x0B82, 0x0B82}, {0x0BC0, 0x0BC0},
{0x0BCD, 0x0BCD}, {0x0C3E, 0x0C40}, {0x0C46, 0x0C48},
{0x0C4A, 0x0C4D}, {0x0C55, 0x0C56}, {0x0CBC, 0x0CBC},
{0x0CBF, 0x0CBF}, {0x0CC6, 0x0CC6}, {0x0CCC, 0x0CCD},
{0x0CE2, 0x0CE3}, {0x0D41, 0x0D43}, {0x0D4D, 0x0D4D},
{0x0DCA, 0x0DCA}, {0x0DD2, 0x0DD4}, {0x0DD6, 0x0DD6},
{0x0E31, 0x0E31}, {0x0E34, 0x0E3A}, {0x0E47, 0x0E4E},
{0x0EB1, 0x0EB1}, {0x0EB4, 0x0EB9}, {0x0EBB, 0x0EBC},
{0x0EC8, 0x0ECD}, {0x0F18, 0x0F19}, {0x0F35, 0x0F35},
{0x0F37, 0x0F37}, {0x0F39, 0x0F39}, {0x0F71, 0x0F7E},
{0x0F80, 0x0F84}, {0x0F86, 0x0F87}, {0x0F90, 0x0F97},
{0x0F99, 0x0FBC}, {0x0FC6, 0x0FC6}, {0x102D, 0x1030},
{0x1032, 0x1032}, {0x1036, 0x1037}, {0x1039, 0x1039},
{0x1058, 0x1059}, {0x1160, 0x11FF}, {0x135F, 0x135F},
{0x1712, 0x1714}, {0x1732, 0x1734}, {0x1752, 0x1753},
{0x1772, 0x1773}, {0x17B4, 0x17B5}, {0x17B7, 0x17BD},
{0x17C6, 0x17C6}, {0x17C9, 0x17D3}, {0x17DD, 0x17DD},
{0x180B, 0x180D}, {0x18A9, 0x18A9}, {0x1920, 0x1922},
{0x1927, 0x1928}, {0x1932, 0x1932}, {0x1939, 0x193B},
{0x1A17, 0x1A18}, {0x1B00, 0x1B03}, {0x1B34, 0x1B34},
{0x1B36, 0x1B3A}, {0x1B3C, 0x1B3C}, {0x1B42, 0x1B42},
{0x1B6B, 0x1B73}, {0x1DC0, 0x1DCA}, {0x1DFE, 0x1DFF},
{0x200B, 0x200F}, {0x202A, 0x202E}, {0x2060, 0x2063},
{0x206A, 0x206F}, {0x20D0, 0x20EF}, {0x302A, 0x302F},
{0x3099, 0x309A}, {0xA806, 0xA806}, {0xA80B, 0xA80B},
{0xA825, 0xA826}, {0xFB1E, 0xFB1E}, {0xFE00, 0xFE0F},
{0xFE20, 0xFE23}, {0xFEFF, 0xFEFF}, {0xFFF9, 0xFFFB},
{0x10A01, 0x10A03}, {0x10A05, 0x10A06}, {0x10A0C, 0x10A0F},
{0x10A38, 0x10A3A}, {0x10A3F, 0x10A3F}, {0x1D167, 0x1D169},
{0x1D173, 0x1D182}, {0x1D185, 0x1D18B}, {0x1D1AA, 0x1D1AD},
{0x1D242, 0x1D244}, {0xE0001, 0xE0001}, {0xE0020, 0xE007F},
{0xE0100, 0xE01EF},
};
static const Interval g_full_width_characters[] = {
{0x1100, 0x115f}, {0x2329, 0x2329}, {0x232a, 0x232a}, {0x2e80, 0x303e},
{0x3040, 0xa4cf}, {0xac00, 0xd7a3}, {0xf900, 0xfaff}, {0xfe10, 0xfe19},
{0xfe30, 0xfe6f}, {0xff00, 0xff60}, {0xffe0, 0xffe6}, {0x20000, 0x2fffd},
{0x30000, 0x3fffd},
};
// Find a codepoint inside a sorted list of Interval.
int Bisearch(uint32_t ucs, const Interval* table, int max) {
if (ucs < table[0].first || ucs > table[max].last)
return 0;
int min = 0;
while (max >= min) {
int mid = (min + max) / 2;
if (ucs > table[mid].last)
min = mid + 1;
else if (ucs < table[mid].first)
max = mid - 1;
else
return 1;
}
return 0;
}
bool IsCombining(uint32_t ucs) {
return Bisearch(ucs, g_combining_characters,
sizeof(g_combining_characters) / sizeof(Interval) - 1);
}
bool IsFullWidth(uint32_t ucs) {
if (ucs < 0x0300) // Quick path:
return false;
return Bisearch(ucs, g_full_width_characters,
sizeof(g_full_width_characters) / sizeof(Interval) - 1);
}
bool IsControl(uint32_t ucs) {
if (ucs == 0)
return true;
if (ucs < 32)
return true;
if (ucs >= 0x7f && ucs < 0xa0)
return true;
return false;
}
int codepoint_width(uint32_t ucs) {
if (IsControl(ucs))
return -1;
if (IsCombining(ucs))
return 0;
if (IsFullWidth(ucs))
return 2;
return 1;
}
// From UTF8 encoded string |input|, eat in between 1 and 4 byte representing
// one codepoint. Put the codepoint into |ucs|. Start at |start| and update
// |end| to represent the beginning of the next byte to eat for consecutive
// executions.
bool EatCodePoint(const std::string& input,
size_t start,
size_t* end,
uint32_t* ucs) {
if (start >= input.size()) {
*end = start + 1;
return false;
}
uint8_t byte_1 = input[start];
// 1 byte string.
if ((byte_1 & 0b1000'0000) == 0b0000'0000) {
*ucs = byte_1 & 0b0111'1111;
*end = start + 1;
return true;
}
// 2 byte string.
if ((byte_1 & 0b1110'0000) == 0b1100'0000 && start + 1 < input.size()) {
uint8_t byte_2 = input[start + 1];
*ucs = 0;
*ucs += byte_1 & 0b0001'1111;
*ucs <<= 6;
*ucs += byte_2 & 0b0011'1111;
*end = start + 2;
return true;
}
// 3 byte string.
if ((byte_1 & 0b1111'0000) == 0b1110'0000 && start + 2 < input.size()) {
uint8_t byte_2 = input[start + 1];
uint8_t byte_3 = input[start + 2];
*ucs = 0;
*ucs += byte_1 & 0b0000'1111;
*ucs <<= 6;
*ucs += byte_2 & 0b0011'1111;
*ucs <<= 6;
*ucs += byte_3 & 0b0011'1111;
*end = start + 3;
return true;
}
// 4 byte string.
if ((byte_1 & 0b1111'1000) == 0b1111'0000 && start + 3 < input.size()) {
uint8_t byte_2 = input[start + 1];
uint8_t byte_3 = input[start + 2];
uint8_t byte_4 = input[start + 3];
*ucs = 0;
*ucs += byte_1 & 0b0000'0111;
*ucs <<= 6;
*ucs += byte_2 & 0b0011'1111;
*ucs <<= 6;
*ucs += byte_3 & 0b0011'1111;
*ucs <<= 6;
*ucs += byte_4 & 0b0011'1111;
*end = start + 4;
return true;
}
*end = start + 1;
return false;
}
} // namespace
namespace ftxui {
int wchar_width(wchar_t ucs) {
return codepoint_width(uint32_t(ucs));
}
int wstring_width(const std::wstring& text) {
int width = 0;
for (const wchar_t& it : text) {
int w = wchar_width(it);
if (w < 0)
return -1;
width += w;
}
return width;
}
int string_width(const std::string& input) {
int width = 0;
size_t start = 0;
while (start < input.size()) {
uint32_t codepoint = 0;
if (!EatCodePoint(input, start, &start, &codepoint))
continue;
if (IsControl(codepoint))
continue;
if (IsCombining(codepoint))
continue;
if (IsFullWidth(codepoint)) {
width += 2;
continue;
}
width += 1;
}
return width;
}
std::vector<std::string> Utf8ToGlyphs(const std::string& input) {
std::vector<std::string> out;
std::string current;
out.reserve(input.size());
size_t start = 0;
size_t end = 0;
while (start < input.size()) {
uint32_t codepoint;
if (!EatCodePoint(input, start, &end, &codepoint)) {
start = end;
continue;
}
std::string append = input.substr(start, end - start);
start = end;
// Ignore control characters.
if (IsControl(codepoint))
continue;
// Combining characters are put with the previous glyph they are modifying.
if (IsCombining(codepoint)) {
if (out.size() != 0)
out.back() += append;
continue;
}
// Fullwidth characters take two cells. The second is made of the empty
// string to reserve the space the first is taking.
if (IsFullWidth(codepoint)) {
out.push_back(append);
out.push_back("");
continue;
}
// Normal characters:
out.push_back(append);
}
return out;
}
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable : 4996) // codecvt_utf8_utf16 is deprecated

View File

@ -0,0 +1,47 @@
#include <gtest/gtest-message.h> // for Message
#include <gtest/gtest-test-part.h> // for TestPartResult, SuiteApiResolver, TestFactoryImpl
#include <string> // for allocator, string
#include "ftxui/screen/string.hpp"
#include "gtest/gtest_pred_impl.h" // for EXPECT_EQ, Test, TEST
using namespace ftxui;
TEST(StringTest, StringWidth) {
// Basic:
EXPECT_EQ(0, string_width(""));
EXPECT_EQ(1, string_width("a"));
EXPECT_EQ(2, string_width("ab"));
// Fullwidth glyphs:
EXPECT_EQ(2, string_width(""));
EXPECT_EQ(4, string_width("测试"));
// Combining characters:
EXPECT_EQ(1, string_width(""));
EXPECT_EQ(1, string_width("a⃒"));
EXPECT_EQ(1, string_width(""));
// Control characters:
EXPECT_EQ(0, string_width("\1"));
EXPECT_EQ(2, string_width("a\1a"));
}
TEST(StringTest, Utf8ToGlyphs) {
using T = std::vector<std::string>;
// Basic:
EXPECT_EQ(Utf8ToGlyphs(""), T({}));
EXPECT_EQ(Utf8ToGlyphs("a"), T({"a"}));
EXPECT_EQ(Utf8ToGlyphs("ab"), T({"a", "b"}));
// Fullwidth glyphs:
EXPECT_EQ(Utf8ToGlyphs(""), T({"", ""}));
EXPECT_EQ(Utf8ToGlyphs("测试"), T({"", "", "", ""}));
// Combining characters:
EXPECT_EQ(Utf8ToGlyphs(""), T({""}));
EXPECT_EQ(Utf8ToGlyphs("a⃒"), T({"a⃒"}));
EXPECT_EQ(Utf8ToGlyphs(""), T({""}));
// Control characters:
EXPECT_EQ(Utf8ToGlyphs("\1"), T({}));
EXPECT_EQ(Utf8ToGlyphs("a\1a"), T({"a", "a"}));
}
// Copyright 2020 Arthur Sonzogni. All rights reserved.
// Use of this source code is governed by the MIT license that can be found in
// the LICENSE file.

View File

@ -1,317 +1,4 @@
/*
* This is an implementation of wcwidth() and wcswidth() (defined in
* IEEE Std 1002.1-2001) for Unicode.
*
* http://www.opengroup.org/onlinepubs/007904975/functions/wcwidth.html
* http://www.opengroup.org/onlinepubs/007904975/functions/wcswidth.html
*
* In fixed-width output devices, Latin characters all occupy a single
* "cell" position of equal width, whereas ideographic CJK characters
* occupy two such cells. Interoperability between terminal-line
* applications and (teletype-style) character terminals using the
* UTF-8 encoding requires agreement on which character should advance
* the cursor by how many cell positions. No established formal
* standards exist at present on which Unicode character shall occupy
* how many cell positions on character terminals. These routines are
* a first attempt of defining such behavior based on simple rules
* applied to data provided by the Unicode Consortium.
*
* For some graphical characters, the Unicode standard explicitly
* defines a character-cell width via the definition of the East Asian
* FullWidth (F), Wide (W), Half-width (H), and Narrow (Na) classes.
* In all these cases, there is no ambiguity about which width a
* terminal shall use. For characters in the East Asian Ambiguous (A)
* class, the width choice depends purely on a preference of backward
* compatibility with either historic CJK or Western practice.
* Choosing single-width for these characters is easy to justify as
* the appropriate long-term solution, as the CJK practice of
* displaying these characters as double-width comes from historic
* implementation simplicity (8-bit encoded characters were displayed
* single-width and 16-bit ones double-width, even for Greek,
* Cyrillic, etc.) and not any typographic considerations.
*
* Much less clear is the choice of width for the Not East Asian
* (Neutral) class. Existing practice does not dictate a width for any
* of these characters. It would nevertheless make sense
* typographically to allocate two character cells to characters such
* as for instance EM SPACE or VOLUME INTEGRAL, which cannot be
* represented adequately with a single-width glyph. The following
* routines at present merely assign a single-cell width to all
* neutral characters, in the interest of simplicity. This is not
* entirely satisfactory and should be reconsidered before
* establishing a formal standard in this area. At the moment, the
* decision which Not East Asian (Neutral) characters should be
* represented by double-width glyphs cannot yet be answered by
* applying a simple rule from the Unicode database content. Setting
* up a proper standard for the behavior of UTF-8 character terminals
* will require a careful analysis not only of each Unicode character,
* but also of each presentation form, something the author of these
* routines has avoided to do so far.
*
* http://www.unicode.org/unicode/reports/tr11/
*
* Markus Kuhn -- 2007-05-26 (Unicode 5.0)
*
* Permission to use, copy, modify, and distribute this software
* for any purpose and without fee is hereby granted. The author
* disclaims all warranties with regard to this software.
*
* Latest version: http://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c
*/
#include <string>
#include "ftxui/screen/string.hpp"
namespace ftxui {
namespace {
struct interval {
char32_t first;
char32_t last;
};
/* auxiliary function for binary search in interval table */
int bisearch(char32_t ucs, const struct interval* table, int max) {
int min = 0;
int mid;
if (ucs < table[0].first || ucs > table[max].last)
return 0;
while (max >= min) {
mid = (min + max) / 2;
if (ucs > table[mid].last)
min = mid + 1;
else if (ucs < table[mid].first)
max = mid - 1;
else
return 1;
}
return 0;
}
} // namespace
/* The following two functions define the column width of an ISO 10646
* character as follows:
*
* - The null character (U+0000) has a column width of 0.
*
* - Other C0/C1 control characters and DEL will lead to a return
* value of -1.
*
* - Non-spacing and enclosing combining characters (general
* category code Mn or Me in the Unicode database) have a
* column width of 0.
*
* - SOFT HYPHEN (U+00AD) has a column width of 1.
*
* - Other format characters (general category code Cf in the Unicode
* database) and ZERO WIDTH SPACE (U+200B) have a column width of 0.
*
* - Hangul Jamo medial vowels and final consonants (U+1160-U+11FF)
* have a column width of 0.
*
* - Spacing characters in the East Asian Wide (W) or East Asian
* Full-width (F) category as defined in Unicode Technical
* Report #11 have a column width of 2.
*
* - All remaining characters (including all printable
* ISO 8859-1 and WGL4 characters, Unicode control characters,
* etc.) have a column width of 1.
*
* This implementation assumes that char32_t characters are encoded
* in ISO 10646.
*/
int wchar_width(char32_t ucs) {
/* sorted list of non-overlapping intervals of non-spacing characters */
/* generated by "uniset +cat=Me +cat=Mn +cat=Cf -00AD +1160-11FF +200B c" */
static const struct interval combining[] = {
{0x0300, 0x036F}, {0x0483, 0x0486}, {0x0488, 0x0489},
{0x0591, 0x05BD}, {0x05BF, 0x05BF}, {0x05C1, 0x05C2},
{0x05C4, 0x05C5}, {0x05C7, 0x05C7}, {0x0600, 0x0603},
{0x0610, 0x0615}, {0x064B, 0x065E}, {0x0670, 0x0670},
{0x06D6, 0x06E4}, {0x06E7, 0x06E8}, {0x06EA, 0x06ED},
{0x070F, 0x070F}, {0x0711, 0x0711}, {0x0730, 0x074A},
{0x07A6, 0x07B0}, {0x07EB, 0x07F3}, {0x0901, 0x0902},
{0x093C, 0x093C}, {0x0941, 0x0948}, {0x094D, 0x094D},
{0x0951, 0x0954}, {0x0962, 0x0963}, {0x0981, 0x0981},
{0x09BC, 0x09BC}, {0x09C1, 0x09C4}, {0x09CD, 0x09CD},
{0x09E2, 0x09E3}, {0x0A01, 0x0A02}, {0x0A3C, 0x0A3C},
{0x0A41, 0x0A42}, {0x0A47, 0x0A48}, {0x0A4B, 0x0A4D},
{0x0A70, 0x0A71}, {0x0A81, 0x0A82}, {0x0ABC, 0x0ABC},
{0x0AC1, 0x0AC5}, {0x0AC7, 0x0AC8}, {0x0ACD, 0x0ACD},
{0x0AE2, 0x0AE3}, {0x0B01, 0x0B01}, {0x0B3C, 0x0B3C},
{0x0B3F, 0x0B3F}, {0x0B41, 0x0B43}, {0x0B4D, 0x0B4D},
{0x0B56, 0x0B56}, {0x0B82, 0x0B82}, {0x0BC0, 0x0BC0},
{0x0BCD, 0x0BCD}, {0x0C3E, 0x0C40}, {0x0C46, 0x0C48},
{0x0C4A, 0x0C4D}, {0x0C55, 0x0C56}, {0x0CBC, 0x0CBC},
{0x0CBF, 0x0CBF}, {0x0CC6, 0x0CC6}, {0x0CCC, 0x0CCD},
{0x0CE2, 0x0CE3}, {0x0D41, 0x0D43}, {0x0D4D, 0x0D4D},
{0x0DCA, 0x0DCA}, {0x0DD2, 0x0DD4}, {0x0DD6, 0x0DD6},
{0x0E31, 0x0E31}, {0x0E34, 0x0E3A}, {0x0E47, 0x0E4E},
{0x0EB1, 0x0EB1}, {0x0EB4, 0x0EB9}, {0x0EBB, 0x0EBC},
{0x0EC8, 0x0ECD}, {0x0F18, 0x0F19}, {0x0F35, 0x0F35},
{0x0F37, 0x0F37}, {0x0F39, 0x0F39}, {0x0F71, 0x0F7E},
{0x0F80, 0x0F84}, {0x0F86, 0x0F87}, {0x0F90, 0x0F97},
{0x0F99, 0x0FBC}, {0x0FC6, 0x0FC6}, {0x102D, 0x1030},
{0x1032, 0x1032}, {0x1036, 0x1037}, {0x1039, 0x1039},
{0x1058, 0x1059}, {0x1160, 0x11FF}, {0x135F, 0x135F},
{0x1712, 0x1714}, {0x1732, 0x1734}, {0x1752, 0x1753},
{0x1772, 0x1773}, {0x17B4, 0x17B5}, {0x17B7, 0x17BD},
{0x17C6, 0x17C6}, {0x17C9, 0x17D3}, {0x17DD, 0x17DD},
{0x180B, 0x180D}, {0x18A9, 0x18A9}, {0x1920, 0x1922},
{0x1927, 0x1928}, {0x1932, 0x1932}, {0x1939, 0x193B},
{0x1A17, 0x1A18}, {0x1B00, 0x1B03}, {0x1B34, 0x1B34},
{0x1B36, 0x1B3A}, {0x1B3C, 0x1B3C}, {0x1B42, 0x1B42},
{0x1B6B, 0x1B73}, {0x1DC0, 0x1DCA}, {0x1DFE, 0x1DFF},
{0x200B, 0x200F}, {0x202A, 0x202E}, {0x2060, 0x2063},
{0x206A, 0x206F}, {0x20D0, 0x20EF}, {0x302A, 0x302F},
{0x3099, 0x309A}, {0xA806, 0xA806}, {0xA80B, 0xA80B},
{0xA825, 0xA826}, {0xFB1E, 0xFB1E}, {0xFE00, 0xFE0F},
{0xFE20, 0xFE23}, {0xFEFF, 0xFEFF}, {0xFFF9, 0xFFFB},
{0x10A01, 0x10A03}, {0x10A05, 0x10A06}, {0x10A0C, 0x10A0F},
{0x10A38, 0x10A3A}, {0x10A3F, 0x10A3F}, {0x1D167, 0x1D169},
{0x1D173, 0x1D182}, {0x1D185, 0x1D18B}, {0x1D1AA, 0x1D1AD},
{0x1D242, 0x1D244}, {0xE0001, 0xE0001}, {0xE0020, 0xE007F},
{0xE0100, 0xE01EF}};
/* test for 8-bit control characters */
if (ucs == 0)
return 0;
if (ucs < 32 || (ucs >= 0x7f && ucs < 0xa0))
return -1;
/* binary search in table of non-spacing characters */
if (bisearch(ucs, combining, sizeof(combining) / sizeof(struct interval) - 1))
return 0;
/* if we arrive here, ucs is not a combining or C0/C1 control character */
return 1 +
(ucs >= 0x1100 &&
(ucs <= 0x115f || /* Hangul Jamo init. consonants */
ucs == 0x2329 || ucs == 0x232a ||
(ucs >= 0x2e80 && ucs <= 0xa4cf && ucs != 0x303f) || /* CJK ... Yi */
(ucs >= 0xac00 && ucs <= 0xd7a3) || /* Hangul Syllables */
(ucs >= 0xf900 &&
ucs <= 0xfaff) || /* CJK Compatibility Ideographs */
(ucs >= 0xfe10 && ucs <= 0xfe19) || /* Vertical forms */
(ucs >= 0xfe30 && ucs <= 0xfe6f) || /* CJK Compatibility Forms */
(ucs >= 0xff00 && ucs <= 0xff60) || /* Fullwidth Forms */
(ucs >= 0xffe0 && ucs <= 0xffe6) ||
(ucs >= 0x20000 && ucs <= 0x2fffd) ||
(ucs >= 0x30000 && ucs <= 0x3fffd)));
}
/*
* The following functions are the same as mk_wcwidth() and
* mk_wcswidth(), except that spacing characters in the East Asian
* Ambiguous (A) category as defined in Unicode Technical Report #11
* have a column width of 2. This variant might be useful for users of
* CJK legacy encodings who want to migrate to UCS without changing
* the traditional terminal character-width behaviour. It is not
* otherwise recommended for general use.
*/
int wchar_width_cjk(char32_t ucs) {
/* sorted list of non-overlapping intervals of East Asian Ambiguous
* characters, generated by "uniset +WIDTH-A -cat=Me -cat=Mn -cat=Cf c" */
static const struct interval ambiguous[] = {
{0x00A1, 0x00A1}, {0x00A4, 0x00A4}, {0x00A7, 0x00A8},
{0x00AA, 0x00AA}, {0x00AE, 0x00AE}, {0x00B0, 0x00B4},
{0x00B6, 0x00BA}, {0x00BC, 0x00BF}, {0x00C6, 0x00C6},
{0x00D0, 0x00D0}, {0x00D7, 0x00D8}, {0x00DE, 0x00E1},
{0x00E6, 0x00E6}, {0x00E8, 0x00EA}, {0x00EC, 0x00ED},
{0x00F0, 0x00F0}, {0x00F2, 0x00F3}, {0x00F7, 0x00FA},
{0x00FC, 0x00FC}, {0x00FE, 0x00FE}, {0x0101, 0x0101},
{0x0111, 0x0111}, {0x0113, 0x0113}, {0x011B, 0x011B},
{0x0126, 0x0127}, {0x012B, 0x012B}, {0x0131, 0x0133},
{0x0138, 0x0138}, {0x013F, 0x0142}, {0x0144, 0x0144},
{0x0148, 0x014B}, {0x014D, 0x014D}, {0x0152, 0x0153},
{0x0166, 0x0167}, {0x016B, 0x016B}, {0x01CE, 0x01CE},
{0x01D0, 0x01D0}, {0x01D2, 0x01D2}, {0x01D4, 0x01D4},
{0x01D6, 0x01D6}, {0x01D8, 0x01D8}, {0x01DA, 0x01DA},
{0x01DC, 0x01DC}, {0x0251, 0x0251}, {0x0261, 0x0261},
{0x02C4, 0x02C4}, {0x02C7, 0x02C7}, {0x02C9, 0x02CB},
{0x02CD, 0x02CD}, {0x02D0, 0x02D0}, {0x02D8, 0x02DB},
{0x02DD, 0x02DD}, {0x02DF, 0x02DF}, {0x0391, 0x03A1},
{0x03A3, 0x03A9}, {0x03B1, 0x03C1}, {0x03C3, 0x03C9},
{0x0401, 0x0401}, {0x0410, 0x044F}, {0x0451, 0x0451},
{0x2010, 0x2010}, {0x2013, 0x2016}, {0x2018, 0x2019},
{0x201C, 0x201D}, {0x2020, 0x2022}, {0x2024, 0x2027},
{0x2030, 0x2030}, {0x2032, 0x2033}, {0x2035, 0x2035},
{0x203B, 0x203B}, {0x203E, 0x203E}, {0x2074, 0x2074},
{0x207F, 0x207F}, {0x2081, 0x2084}, {0x20AC, 0x20AC},
{0x2103, 0x2103}, {0x2105, 0x2105}, {0x2109, 0x2109},
{0x2113, 0x2113}, {0x2116, 0x2116}, {0x2121, 0x2122},
{0x2126, 0x2126}, {0x212B, 0x212B}, {0x2153, 0x2154},
{0x215B, 0x215E}, {0x2160, 0x216B}, {0x2170, 0x2179},
{0x2190, 0x2199}, {0x21B8, 0x21B9}, {0x21D2, 0x21D2},
{0x21D4, 0x21D4}, {0x21E7, 0x21E7}, {0x2200, 0x2200},
{0x2202, 0x2203}, {0x2207, 0x2208}, {0x220B, 0x220B},
{0x220F, 0x220F}, {0x2211, 0x2211}, {0x2215, 0x2215},
{0x221A, 0x221A}, {0x221D, 0x2220}, {0x2223, 0x2223},
{0x2225, 0x2225}, {0x2227, 0x222C}, {0x222E, 0x222E},
{0x2234, 0x2237}, {0x223C, 0x223D}, {0x2248, 0x2248},
{0x224C, 0x224C}, {0x2252, 0x2252}, {0x2260, 0x2261},
{0x2264, 0x2267}, {0x226A, 0x226B}, {0x226E, 0x226F},
{0x2282, 0x2283}, {0x2286, 0x2287}, {0x2295, 0x2295},
{0x2299, 0x2299}, {0x22A5, 0x22A5}, {0x22BF, 0x22BF},
{0x2312, 0x2312}, {0x2460, 0x24E9}, {0x24EB, 0x254B},
{0x2550, 0x2573}, {0x2580, 0x258F}, {0x2592, 0x2595},
{0x25A0, 0x25A1}, {0x25A3, 0x25A9}, {0x25B2, 0x25B3},
{0x25B6, 0x25B7}, {0x25BC, 0x25BD}, {0x25C0, 0x25C1},
{0x25C6, 0x25C8}, {0x25CB, 0x25CB}, {0x25CE, 0x25D1},
{0x25E2, 0x25E5}, {0x25EF, 0x25EF}, {0x2605, 0x2606},
{0x2609, 0x2609}, {0x260E, 0x260F}, {0x2614, 0x2615},
{0x261C, 0x261C}, {0x261E, 0x261E}, {0x2640, 0x2640},
{0x2642, 0x2642}, {0x2660, 0x2661}, {0x2663, 0x2665},
{0x2667, 0x266A}, {0x266C, 0x266D}, {0x266F, 0x266F},
{0x273D, 0x273D}, {0x2776, 0x277F}, {0xE000, 0xF8FF},
{0xFFFD, 0xFFFD}, {0xF0000, 0xFFFFD}, {0x100000, 0x10FFFD}};
/* binary search in table of non-spacing characters */
if (bisearch(ucs, ambiguous, sizeof(ambiguous) / sizeof(struct interval) - 1))
return 2;
return wchar_width(ucs);
}
int wchar_width(wchar_t ucs) {
return wchar_width(char32_t(ucs));
}
int wchar_width_cjk(wchar_t ucs) {
return wchar_width_cjk(char32_t(ucs));
}
int wstring_width(const std::wstring& text) {
int width = 0;
for (const wchar_t& it : text) {
int w = wchar_width(it);
if (w < 0)
return -1;
width += w;
}
return width;
}
int wstring_width_cjk(const std::wstring& text) {
int width = 0;
for (const wchar_t& it : text) {
int w = wchar_width_cjk(it);
if (w < 0)
return -1;
width += w;
}
return width;
}
} // namespace ftxui
// Copyright 2020 Arthur Sonzogni. All rights reserved.
// Copyright 2021 Arthur Sonzogni. All rights reserved.
// Use of this source code is governed by the MIT license that can be found in
// the LICENSE file.