From 15386d57ceeb96d93fb03b1c62147e40f8cb525b Mon Sep 17 00:00:00 2001 From: nick black Date: Fri, 8 Jan 2021 04:59:24 -0500 Subject: [PATCH] nontrivial stacking unit test #1068 --- NEWS.md | 5 ++++ USAGE.md | 2 +- include/notcurses/notcurses.h | 2 +- tests/stacking.cpp | 53 +++++++++++++++++++++++++++++++++++ 4 files changed, 60 insertions(+), 2 deletions(-) create mode 100644 tests/stacking.cpp diff --git a/NEWS.md b/NEWS.md index 1d1e029dec..eece7b1efd 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,6 +1,11 @@ This document attempts to list user-visible changes and any major internal rearrangements of Notcurses. +* 2.1.5 (not yet released): + * `ncplane_putstr_yx()`, `ncplane_putstr_stained()`, and + `ncplane_putnstr_yx()` now return the number of columns output, as + long documented (they were mistakenly returning the number of bytes). + * 2.1.4 (2021-01-03): * Direct mode now supports `NCDIRECT_OPTION_NO_QUIT_SIGHANDLERS`, and by default installs signal handlers similar to those of fullscreen mode. diff --git a/USAGE.md b/USAGE.md index fa41ae43b2..b89a25f043 100644 --- a/USAGE.md +++ b/USAGE.md @@ -996,7 +996,7 @@ int ncplane_putchar_stained(struct ncplane* n, char c); // Replace the nccell at the specified coordinates with the provided wide char // 'w'. Advance the cursor by the character's width as reported by wcwidth(). -// On success, returns 1. On failure, returns -1. +// On success, returns the number of columns written. On failure, returns -1. static inline int ncplane_putwc_yx(struct ncplane* n, int y, int x, wchar_t w){ wchar_t warr[2] = { w, L'\0' }; diff --git a/include/notcurses/notcurses.h b/include/notcurses/notcurses.h index 0fd29028da..13889b1318 100644 --- a/include/notcurses/notcurses.h +++ b/include/notcurses/notcurses.h @@ -1606,7 +1606,7 @@ ncplane_putwstr(struct ncplane* n, const wchar_t* gclustarr){ // Replace the cell at the specified coordinates with the provided wide char // 'w'. Advance the cursor by the character's width as reported by wcwidth(). -// On success, returns 1. On failure, returns -1. +// On success, returns the number of columns written. On failure, returns -1. static inline int ncplane_putwc_yx(struct ncplane* n, int y, int x, wchar_t w){ wchar_t warr[2] = { w, L'\0' }; diff --git a/tests/stacking.cpp b/tests/stacking.cpp new file mode 100644 index 0000000000..36743a9c05 --- /dev/null +++ b/tests/stacking.cpp @@ -0,0 +1,53 @@ +#include "main.h" + +// These tests address cases where box characters on two overlapping planes +// interact in non-trivial ways. A simple example is a U2580 UPPER HALF BLOCK +// (▀) with a white foreground and transparent background, above a U2584 LOWER +// HALF BLOCK (▄) with a white foreground and transparent background. One might +// expect the result to be an entirely white cell, but by typical Notcurses +// rendering rules, we would instead get a white upper half and transparent +// lower half: +// +// - after first cell, glyph is locked U2584, fg is locked white, bg transparent +// - second cell can't override glyph nor fg, and background remains transparent +// +// we will instead special-case block-drawing characters. +// see https://github.com/dankamongmen/notcurses/issues/1068 +TEST_CASE("Stacking") { + auto nc_ = testing_notcurses(); + if(!nc_){ + return; + } + if(!notcurses_canutf8(nc_)){ + CHECK(0 == notcurses_stop(nc_)); + return; + } + int dimy, dimx; + struct ncplane* n_ = notcurses_stddim_yx(nc_, &dimy, &dimx); + REQUIRE(nullptr != n_); + + + SUBCASE("UpperAtopLowerWhite") { + struct ncplane_options opts = { + 0, 0, 1, 1, nullptr, "top", nullptr, 0, + }; + auto top = ncplane_create(n_, &opts); + REQUIRE(nullptr != top); + CHECK(0 == ncplane_set_fg_rgb(top, 0xffffff)); + CHECK(0 == ncplane_set_fg_rgb(n_, 0xffffff)); + CHECK(1 == ncplane_putwc(top, L'\u2580')); + CHECK(1 == ncplane_putwc(n_, L'\u2584')); + CHECK(0 == notcurses_render(nc_)); + uint64_t channels; + auto egc = notcurses_at_yx(nc_, 0, 0, nullptr, &channels); + REQUIRE(nullptr != egc); + // ought yield space with white background + WARN(0 == strcmp(" ", egc)); + WARN(0xffffff == channels_fg_rgb(channels)); + WARN(0xffffff == channels_bg_rgb(channels)); + ncplane_destroy(top); + } + + // common teardown + CHECK(0 == notcurses_stop(nc_)); +}