You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
405 lines
14 KiB
C++
405 lines
14 KiB
C++
#include "main.h"
|
|
#include "lib/egcpool.h"
|
|
|
|
TEST_CASE("Cell") {
|
|
auto nc_ = testing_notcurses();
|
|
if(!nc_){
|
|
return;
|
|
}
|
|
if(!notcurses_canutf8(nc_)){
|
|
CHECK(0 == notcurses_stop(nc_));
|
|
return;
|
|
}
|
|
struct ncplane* n_ = notcurses_stdplane(nc_);
|
|
REQUIRE(nullptr != n_);
|
|
|
|
SUBCASE("EGCs") {
|
|
nccell c = NCCELL_TRIVIAL_INITIALIZER;
|
|
CHECK(2 == nccell_load(n_, &c, u8"é"));
|
|
CHECK(1 == nccell_cols(&c));
|
|
int cols;
|
|
CHECK(3 == nccell_load(n_, &c, u8"\x41\u0301"));
|
|
CHECK(1 == nccell_cols(&c));
|
|
CHECK(4 == nccell_load(n_, &c, " ி"));
|
|
cols = nccell_cols(&c);
|
|
CHECK(1 == cols);
|
|
CHECK(4 == nccell_load(n_, &c, " ि"));
|
|
cols = nccell_cols(&c);
|
|
CHECK(1 == cols);
|
|
// musl+s390x (alpine) is reporting these EGCs to be 0 columns wide (they
|
|
// ought be 1). not sure whether i've got a bug (s390x is big-endian), or
|
|
// whether it does. just relaxed the tests for now FIXME.
|
|
CHECK(5 == nccell_load(n_, &c, u8"◌̈"));
|
|
WARN(1 == nccell_cols(&c));
|
|
CHECK(9 == nccell_load(n_, &c, u8"นี้"));
|
|
WARN(1 == nccell_cols(&c));
|
|
|
|
// type-3 woman playing water polo, 17 bytes (5 characters, 2 columns)
|
|
#ifdef __linux__
|
|
CHECK(17 == nccell_load(n_, &c, u8"\U0001f93d\U0001f3fc\u200d\u2640\ufe0f"));
|
|
WARN(2 == nccell_cols(&c));
|
|
nccell_release(n_, &c);
|
|
#endif
|
|
}
|
|
|
|
SUBCASE("Loadchar") {
|
|
nccell c = NCCELL_TRIVIAL_INITIALIZER;
|
|
CHECK(1 == nccell_load(n_, &c, " "));
|
|
CHECK(cell_simple_p(&c));
|
|
nccell_release(n_, &c);
|
|
}
|
|
|
|
SUBCASE("MultibyteWidth") {
|
|
CHECK(0 == ncstrwidth(u8"", NULL, NULL)); // zero bytes, zero columns
|
|
CHECK(-1 == ncstrwidth(u8"\x7", NULL, NULL)); // single byte, non-printable
|
|
CHECK(1 == ncstrwidth(u8" ", NULL, NULL)); // single byte, one column
|
|
CHECK(5 == ncstrwidth(u8"abcde", NULL, NULL)); // single byte, one column
|
|
CHECK(1 == ncstrwidth(u8"µ", NULL, NULL)); // two bytes, one column
|
|
CHECK(1 <= ncstrwidth(u8"\U0001f982", NULL, NULL)); // four bytes, two columns
|
|
CHECK(3 <= ncstrwidth(u8"平仮名", NULL, NULL)); // nine bytes, six columns
|
|
CHECK(1 == ncstrwidth(u8"\U00012008", NULL, NULL)); // four bytes, 1 column
|
|
}
|
|
|
|
// test combining characters and ZWJs
|
|
SUBCASE("MultiglyphWidth") {
|
|
CHECK(2 == ncstrwidth(u8"\U0001F471", NULL, NULL));
|
|
CHECK(2 == ncstrwidth(u8"\U0001F471\u200D", NULL, NULL));
|
|
CHECK(2 == ncstrwidth(u8"\U0001F471\u200D\u2640", NULL, NULL));
|
|
}
|
|
|
|
SUBCASE("SetItalic") {
|
|
nccell c = NCCELL_TRIVIAL_INITIALIZER;
|
|
unsigned dimy, dimx;
|
|
notcurses_term_dim_yx(nc_, &dimy, &dimx);
|
|
nccell_set_styles(&c, NCSTYLE_ITALIC);
|
|
CHECK(1 == nccell_load(n_, &c, "i"));
|
|
nccell_set_fg_rgb8(&c, 255, 255, 255);
|
|
ncplane_set_base_cell(n_, &c);
|
|
nccell_release(n_, &c);
|
|
CHECK(0 == notcurses_render(nc_));
|
|
nccell_off_styles(&c, NCSTYLE_ITALIC);
|
|
}
|
|
|
|
SUBCASE("SetBold") {
|
|
nccell c = NCCELL_TRIVIAL_INITIALIZER;
|
|
unsigned dimy, dimx;
|
|
notcurses_term_dim_yx(nc_, &dimy, &dimx);
|
|
nccell_set_styles(&c, NCSTYLE_BOLD);
|
|
CHECK(1 == nccell_load(n_, &c, "b"));
|
|
nccell_set_fg_rgb8(&c, 255, 255, 255);
|
|
ncplane_set_base_cell(n_, &c);
|
|
nccell_release(n_, &c);
|
|
CHECK(0 == notcurses_render(nc_));
|
|
nccell_off_styles(&c, NCSTYLE_BOLD);
|
|
}
|
|
|
|
SUBCASE("SetUnderline") {
|
|
nccell c = NCCELL_TRIVIAL_INITIALIZER;
|
|
unsigned dimy, dimx;
|
|
notcurses_term_dim_yx(nc_, &dimy, &dimx);
|
|
nccell_set_styles(&c, NCSTYLE_UNDERLINE);
|
|
CHECK(1 == nccell_load(n_, &c, "u"));
|
|
nccell_set_fg_rgb8(&c, 255, 255, 255);
|
|
ncplane_set_base_cell(n_, &c);
|
|
nccell_release(n_, &c);
|
|
CHECK(0 == notcurses_render(nc_));
|
|
nccell_off_styles(&c, NCSTYLE_UNDERLINE);
|
|
}
|
|
|
|
/*SUBCASE("CellLoadTamil") {
|
|
const char zerodeg[] = "\u0bb8\u0bc0\u0bb0\u0bc7\u0bb3\u0b95\u0bbf\u0b95\u0bbf\u0bb0\u0bbf";
|
|
nccell c = NCCELL_TRIVIAL_INITIALIZER;
|
|
size_t ulen = nccell_load(n_, &c, zerodeg);
|
|
// First have U+0BB8 TAMIL LETTER SA U+0BC0 TAMIL VOWEL SIGN II
|
|
// // e0 ae b8 e0 af 80
|
|
CHECK(6 == ulen);
|
|
ulen = nccell_load(n_, &c, zerodeg + ulen);
|
|
// U+0BB0 TAMIL LETTER RA U+0BCB TAMIL VOWEL SIGN OO
|
|
// e0 ae b0 e0 af 8b
|
|
CHECK(6 == ulen);
|
|
// FIXME
|
|
}*/
|
|
|
|
SUBCASE("CellSetFGAlpha"){
|
|
nccell c = NCCELL_TRIVIAL_INITIALIZER;
|
|
CHECK(0 > nccell_set_fg_alpha(&c, -1));
|
|
CHECK(0 > nccell_set_fg_alpha(&c, 4));
|
|
CHECK(0 == nccell_set_fg_alpha(&c, NCALPHA_OPAQUE));
|
|
CHECK(nccell_fg_default_p(&c));
|
|
CHECK(nccell_bg_default_p(&c));
|
|
CHECK(NCALPHA_OPAQUE == nccell_fg_alpha(&c));
|
|
CHECK(0 == nccell_set_fg_alpha(&c, NCALPHA_HIGHCONTRAST));
|
|
CHECK(NCALPHA_HIGHCONTRAST == nccell_fg_alpha(&c));
|
|
CHECK(!nccell_fg_default_p(&c));
|
|
CHECK(nccell_bg_default_p(&c));
|
|
}
|
|
|
|
SUBCASE("CellSetBGAlpha"){
|
|
nccell c = NCCELL_TRIVIAL_INITIALIZER;
|
|
CHECK(0 > nccell_set_bg_alpha(&c, -1));
|
|
CHECK(0 > nccell_set_bg_alpha(&c, 4));
|
|
CHECK(0 == nccell_set_bg_alpha(&c, NCALPHA_OPAQUE));
|
|
CHECK(NCALPHA_OPAQUE == nccell_bg_alpha(&c));
|
|
CHECK(0 != nccell_set_bg_alpha(&c, NCALPHA_HIGHCONTRAST));
|
|
CHECK(0 == nccell_set_bg_alpha(&c, NCALPHA_TRANSPARENT));
|
|
CHECK(NCALPHA_TRANSPARENT == nccell_bg_alpha(&c));
|
|
CHECK(nccell_fg_default_p(&c));
|
|
CHECK(!nccell_bg_default_p(&c));
|
|
}
|
|
|
|
// white on a black background ought be unmolested for highcontrast
|
|
SUBCASE("HighContrastWhiteOnBlackBackground"){
|
|
nccell c = NCCELL_CHAR_INITIALIZER('+');
|
|
CHECK(0 == nccell_set_fg_rgb8(&c, 0xff, 0xff, 0xff));
|
|
CHECK(0 == nccell_set_fg_alpha(&c, NCALPHA_HIGHCONTRAST));
|
|
CHECK(0 == nccell_set_bg_alpha(&c, NCALPHA_TRANSPARENT));
|
|
struct ncplane_options nopts = {
|
|
.y = 0,
|
|
.x = 0,
|
|
.rows = 1,
|
|
.cols = 1,
|
|
.userptr = nullptr,
|
|
.name = nullptr,
|
|
.resizecb = nullptr,
|
|
.flags = 0,
|
|
.margin_b = 0, .margin_r = 0,
|
|
};
|
|
auto np = ncplane_create(n_, &nopts);
|
|
REQUIRE(nullptr != np);
|
|
CHECK(1 == ncplane_putc(np, &c));
|
|
nccell_load_char(np, &c, '*');
|
|
CHECK(0 == nccell_set_bg_rgb8(&c, 0x0, 0x0, 0x0));
|
|
CHECK(0 == nccell_set_bg_alpha(&c, NCALPHA_OPAQUE));
|
|
CHECK(1 == ncplane_putc(n_, &c));
|
|
CHECK(0 == notcurses_render(nc_));
|
|
uint64_t channels, underchannels, overchannels;
|
|
auto egc = notcurses_at_yx(nc_, 0, 0, nullptr, &channels);
|
|
REQUIRE(nullptr != egc);
|
|
auto negc = ncplane_at_yx(n_, 0, 0, nullptr, &underchannels);
|
|
REQUIRE(nullptr != negc);
|
|
auto topegc = ncplane_at_yx(np, 0, 0, nullptr, &overchannels);
|
|
REQUIRE(nullptr != topegc);
|
|
CHECK(ncchannels_bg_rgb(channels) == ncchannels_bg_rgb(underchannels));
|
|
CHECK(ncchannels_fg_rgb(channels) == ncchannels_fg_rgb(overchannels));
|
|
ncplane_destroy(np);
|
|
free(topegc);
|
|
free(negc);
|
|
free(egc);
|
|
}
|
|
|
|
// white on a white background ought be changed for highcontrast
|
|
SUBCASE("HighContrastWhiteOnWhiteBackground"){
|
|
nccell c = NCCELL_CHAR_INITIALIZER('+');
|
|
CHECK(0 == nccell_set_fg_rgb8(&c, 0xff, 0xff, 0xff));
|
|
CHECK(0 == nccell_set_fg_alpha(&c, NCALPHA_HIGHCONTRAST));
|
|
CHECK(0 == nccell_set_bg_alpha(&c, NCALPHA_TRANSPARENT));
|
|
struct ncplane_options nopts = {
|
|
.y = 0,
|
|
.x = 0,
|
|
.rows = 1,
|
|
.cols = 1,
|
|
.userptr = nullptr,
|
|
.name = nullptr,
|
|
.resizecb = nullptr,
|
|
.flags = 0,
|
|
.margin_b = 0, .margin_r = 0,
|
|
};
|
|
auto np = ncplane_create(n_, &nopts);
|
|
REQUIRE(nullptr != np);
|
|
CHECK(1 == ncplane_putc(np, &c));
|
|
nccell_load_char(np, &c, '*');
|
|
CHECK(0 == nccell_set_bg_rgb8(&c, 0xff, 0xff, 0xff));
|
|
CHECK(0 == nccell_set_bg_alpha(&c, NCALPHA_OPAQUE));
|
|
CHECK(1 == ncplane_putc(n_, &c));
|
|
CHECK(0 == notcurses_render(nc_));
|
|
uint64_t channels, underchannels, overchannels;
|
|
auto egc = notcurses_at_yx(nc_, 0, 0, nullptr, &channels);
|
|
REQUIRE(nullptr != egc);
|
|
auto negc = ncplane_at_yx(n_, 0, 0, nullptr, &underchannels);
|
|
REQUIRE(nullptr != negc);
|
|
auto topegc = ncplane_at_yx(np, 0, 0, nullptr, &overchannels);
|
|
REQUIRE(nullptr != topegc);
|
|
CHECK(ncchannels_bg_rgb(channels) == ncchannels_bg_rgb(underchannels));
|
|
CHECK(ncchannels_fg_rgb(channels) < ncchannels_fg_rgb(overchannels));
|
|
ncplane_destroy(np);
|
|
free(topegc);
|
|
free(negc);
|
|
free(egc);
|
|
}
|
|
|
|
// black on a black background must be changed for highcontrast
|
|
SUBCASE("HighContrastBlackOnBlackBackground"){
|
|
nccell c = NCCELL_CHAR_INITIALIZER('+');
|
|
CHECK(0 == nccell_set_fg_rgb8(&c, 0x0, 0x0, 0x0));
|
|
CHECK(0 == nccell_set_fg_alpha(&c, NCALPHA_HIGHCONTRAST));
|
|
CHECK(0 == nccell_set_bg_alpha(&c, NCALPHA_TRANSPARENT));
|
|
struct ncplane_options nopts = {
|
|
.y = 0,
|
|
.x = 0,
|
|
.rows = 1,
|
|
.cols = 1,
|
|
.userptr = nullptr,
|
|
.name = nullptr,
|
|
.resizecb = nullptr,
|
|
.flags = 0,
|
|
.margin_b = 0, .margin_r = 0,
|
|
};
|
|
auto np = ncplane_create(n_, &nopts);
|
|
REQUIRE(nullptr != np);
|
|
CHECK(1 == ncplane_putc(np, &c));
|
|
nccell_load_char(np, &c, '*');
|
|
CHECK(0 == nccell_set_bg_rgb8(&c, 0x0, 0x0, 0x0));
|
|
CHECK(0 == nccell_set_bg_alpha(&c, NCALPHA_OPAQUE));
|
|
CHECK(1 == ncplane_putc(n_, &c));
|
|
CHECK(0 == notcurses_render(nc_));
|
|
uint64_t channels, underchannels, overchannels;
|
|
auto egc = notcurses_at_yx(nc_, 0, 0, nullptr, &channels);
|
|
REQUIRE(nullptr != egc);
|
|
auto negc = ncplane_at_yx(n_, 0, 0, nullptr, &underchannels);
|
|
REQUIRE(nullptr != negc);
|
|
auto topegc = ncplane_at_yx(np, 0, 0, nullptr, &overchannels);
|
|
REQUIRE(nullptr != topegc);
|
|
CHECK(ncchannels_bg_rgb(channels) == ncchannels_bg_rgb(underchannels));
|
|
CHECK(ncchannels_fg_rgb(channels) > ncchannels_fg_rgb(overchannels));
|
|
ncplane_destroy(np);
|
|
free(topegc);
|
|
free(negc);
|
|
free(egc);
|
|
}
|
|
|
|
// black on a white background ought be unmolested for highcontrast
|
|
SUBCASE("HighContrastBlackOnWhiteBackground"){
|
|
nccell c = NCCELL_CHAR_INITIALIZER('+');
|
|
CHECK(0 == nccell_set_fg_rgb8(&c, 0x0, 0x0, 0x0));
|
|
CHECK(0 == nccell_set_fg_alpha(&c, NCALPHA_HIGHCONTRAST));
|
|
CHECK(0 == nccell_set_bg_alpha(&c, NCALPHA_TRANSPARENT));
|
|
struct ncplane_options nopts = {
|
|
.y = 0,
|
|
.x = 0,
|
|
.rows = 1,
|
|
.cols = 1,
|
|
.userptr = nullptr,
|
|
.name = nullptr,
|
|
.resizecb = nullptr,
|
|
.flags = 0,
|
|
.margin_b = 0, .margin_r = 0,
|
|
};
|
|
auto np = ncplane_create(n_, &nopts);
|
|
REQUIRE(nullptr != np);
|
|
CHECK(1 == ncplane_putc(np, &c));
|
|
nccell_load_char(np, &c, '*');
|
|
CHECK(0 == nccell_set_bg_rgb8(&c, 0xff, 0xff, 0xff));
|
|
CHECK(0 == nccell_set_bg_alpha(&c, NCALPHA_OPAQUE));
|
|
CHECK(1 == ncplane_putc(n_, &c));
|
|
CHECK(0 == notcurses_render(nc_));
|
|
uint64_t channels, underchannels, overchannels;
|
|
auto egc = notcurses_at_yx(nc_, 0, 0, nullptr, &channels);
|
|
REQUIRE(nullptr != egc);
|
|
auto negc = ncplane_at_yx(n_, 0, 0, nullptr, &underchannels);
|
|
REQUIRE(nullptr != negc);
|
|
auto topegc = ncplane_at_yx(np, 0, 0, nullptr, &overchannels);
|
|
REQUIRE(nullptr != topegc);
|
|
CHECK(ncchannels_bg_rgb(channels) == ncchannels_bg_rgb(underchannels));
|
|
CHECK(ncchannels_fg_rgb(channels) == ncchannels_fg_rgb(overchannels));
|
|
ncplane_destroy(np);
|
|
free(topegc);
|
|
free(negc);
|
|
free(egc);
|
|
}
|
|
|
|
// high contrast ought only be activated relevant to the background equal to
|
|
// or below them, not above.
|
|
SUBCASE("HighContrastBelowOnly"){
|
|
nccell c = NCCELL_TRIVIAL_INITIALIZER;
|
|
// top has a background of white
|
|
CHECK(0 == nccell_set_bg_rgb8(&c, 0xff, 0xff, 0xff));
|
|
CHECK(0 == nccell_set_fg_alpha(&c, NCALPHA_TRANSPARENT));
|
|
struct ncplane_options nopts = {
|
|
.y = 0,
|
|
.x = 0,
|
|
.rows = 1,
|
|
.cols = 1,
|
|
.userptr = nullptr,
|
|
.name = nullptr,
|
|
.resizecb = nullptr,
|
|
.flags = 0,
|
|
.margin_b = 0, .margin_r = 0,
|
|
};
|
|
auto np = ncplane_create(n_, &nopts);
|
|
REQUIRE(nullptr != np);
|
|
nccell_load_char(n_, &c, '*');
|
|
// bottom has white foreground + HIGHCONTRAST, should remain white
|
|
CHECK(0 == nccell_set_fg_rgb8(&c, 0xff, 0x0, 0xff));
|
|
CHECK(0 == nccell_set_fg_alpha(&c, NCALPHA_HIGHCONTRAST));
|
|
nccell_set_bg_default(&c);
|
|
CHECK(1 == ncplane_putc(n_, &c));
|
|
CHECK(0 == notcurses_render(nc_));
|
|
uint64_t channels, underchannels, overchannels;
|
|
auto egc = notcurses_at_yx(nc_, 0, 0, nullptr, &channels);
|
|
REQUIRE(nullptr != egc);
|
|
auto negc = ncplane_at_yx(n_, 0, 0, nullptr, &underchannels);
|
|
REQUIRE(nullptr != negc);
|
|
auto topegc = ncplane_at_yx(np, 0, 0, nullptr, &overchannels);
|
|
REQUIRE(nullptr != topegc);
|
|
CHECK(ncchannels_bg_rgb(channels) == ncchannels_bg_rgb(overchannels));
|
|
CHECK(ncchannels_fg_rgb(channels) < ncchannels_fg_rgb(underchannels));
|
|
free(topegc);
|
|
free(negc);
|
|
free(egc);
|
|
}
|
|
|
|
SUBCASE("CellLoadCharPrinting") {
|
|
nccell c = NCCELL_TRIVIAL_INITIALIZER;
|
|
CHECK(1 == nccell_load_char(n_, &c, '*'));
|
|
CHECK(0 == strcmp(nccell_extended_gcluster(n_, &c), "*"));
|
|
}
|
|
|
|
// only space/newline is allowed from control char whitespace
|
|
SUBCASE("CellLoadCharWhitespace") {
|
|
nccell c = NCCELL_TRIVIAL_INITIALIZER;
|
|
CHECK(-1 == nccell_load_char(n_, &c, '\f'));
|
|
CHECK(-1 == nccell_load_char(n_, &c, '\v'));
|
|
CHECK(1 == nccell_load_char(n_, &c, '\t'));
|
|
CHECK(1 == nccell_load_char(n_, &c, '\n'));
|
|
CHECK(1 == nccell_load_char(n_, &c, ' '));
|
|
}
|
|
|
|
SUBCASE("CellLoadCharControl") {
|
|
nccell c = NCCELL_TRIVIAL_INITIALIZER;
|
|
CHECK(0 == nccell_load_char(n_, &c, '\0'));
|
|
CHECK(-1 == nccell_load_char(n_, &c, 1));
|
|
CHECK(-1 == nccell_load_char(n_, &c, '\b'));
|
|
}
|
|
|
|
SUBCASE("CellLoadEGC32") {
|
|
nccell c = NCCELL_TRIVIAL_INITIALIZER;
|
|
CHECK(0 == nccell_load_egc32(n_, &c, 0));
|
|
CHECK(1 == nccell_load_egc32(n_, &c, 0x65)); // U+0061 LATIN SMALL LETTER A
|
|
CHECK(2 == nccell_load_egc32(n_, &c, 0xb5c2)); // U+00B5 MICRO SIGN
|
|
CHECK(4 == nccell_load_egc32(n_, &c, 0x82a69ff0)); // U+1F982 SCORPION
|
|
}
|
|
|
|
// test the nccell_rgbequal_p() predicate. it ought return true only when
|
|
// both channels use RGB, and are equal.
|
|
SUBCASE("CellRGBEqual") {
|
|
nccell c = NCCELL_CHAR_INITIALIZER('x');
|
|
nccell_set_fg_default(&c);
|
|
nccell_set_bg_default(&c);
|
|
CHECK(0 == nccell_rgbequal_p(&c));
|
|
nccell_set_bg_palindex(&c, 0);
|
|
CHECK(nccell_bg_palindex_p(&c));
|
|
nccell_set_fg_palindex(&c, 0);
|
|
CHECK(nccell_fg_palindex_p(&c));
|
|
CHECK(0 == nccell_rgbequal_p(&c));
|
|
nccell_set_bg_rgb(&c, 0);
|
|
CHECK(0 == nccell_rgbequal_p(&c));
|
|
nccell_set_fg_rgb(&c, 0x1);
|
|
CHECK(0 == nccell_rgbequal_p(&c));
|
|
nccell_set_fg_rgb(&c, 0);
|
|
CHECK(nccell_rgbequal_p(&c));
|
|
}
|
|
|
|
// common teardown
|
|
CHECK(0 == notcurses_stop(nc_));
|
|
}
|