mirror of
https://github.com/dankamongmen/notcurses.git
synced 2024-11-18 03:25:55 +00:00
255 lines
7.8 KiB
C++
255 lines
7.8 KiB
C++
#include "main.h"
|
|
#include <array>
|
|
#include <cstdlib>
|
|
#include "internal.h"
|
|
|
|
TEST_CASE("Scrolling") {
|
|
auto nc_ = testing_notcurses();
|
|
if(!nc_){
|
|
return;
|
|
}
|
|
struct ncplane* n_ = notcurses_stdplane(nc_);
|
|
REQUIRE(n_);
|
|
|
|
// verify that the standard plane has scrolling disabled initially, and that
|
|
// we can enable it at runtime.
|
|
SUBCASE("ScollingDisabledStdplane") {
|
|
CHECK(!ncplane_set_scrolling(n_, true));
|
|
CHECK(ncplane_set_scrolling(n_, false));
|
|
}
|
|
|
|
SUBCASE("ScrollingStr") {
|
|
struct ncplane_options nopts = {
|
|
.y = 1,
|
|
.x = 1,
|
|
.rows = 2,
|
|
.cols = 20,
|
|
nullptr, nullptr, nullptr, 0,
|
|
};
|
|
struct ncplane* n = ncplane_create(n_, &nopts);
|
|
REQUIRE(n);
|
|
// verify that the new plane was started without scrolling
|
|
CHECK(!ncplane_set_scrolling(n, false));
|
|
// try to write 40 EGCs; it ought fail after 20
|
|
CHECK(-20 == ncplane_putstr(n, "0123456789012345678901234567890123456789"));
|
|
int y, x;
|
|
ncplane_cursor_yx(n, &y, &x);
|
|
CHECK(0 == y);
|
|
CHECK(20 == x);
|
|
CHECK(!ncplane_set_scrolling(n, true)); // enable scrolling
|
|
// try to write 40 EGCs from origin; it ought succeed
|
|
CHECK(40 == ncplane_putstr_yx(n, 0, 0, "0123456789012345678901234567890123456789"));
|
|
ncplane_cursor_yx(n, &y, &x);
|
|
CHECK(1 == y);
|
|
CHECK(20 == x);
|
|
CHECK(0 == notcurses_render(nc_));
|
|
}
|
|
|
|
// even when scrolling is enabled, you aren't allowed to move the cursor
|
|
// off-plane, or initiate output there
|
|
SUBCASE("NoScrollingManually") {
|
|
struct ncplane_options nopts = {
|
|
.y = 1,
|
|
.x = 1,
|
|
.rows = 2,
|
|
.cols = 20,
|
|
nullptr, nullptr, nullptr, 0,
|
|
};
|
|
struct ncplane* n = ncplane_create(n_, &nopts);
|
|
REQUIRE(n);
|
|
CHECK(!ncplane_set_scrolling(n, true)); // enable scrolling
|
|
CHECK(0 > ncplane_cursor_move_yx(n, 0, 20));
|
|
CHECK(0 > ncplane_cursor_move_yx(n, 1, 20));
|
|
CHECK(0 > ncplane_cursor_move_yx(n, 2, 2));
|
|
CHECK(0 > ncplane_putchar_yx(n, 0, 20, 'c'));
|
|
CHECK(0 > ncplane_putchar_yx(n, 1, 20, 'c'));
|
|
CHECK(0 > ncplane_putchar_yx(n, 2, 0, 'c'));
|
|
}
|
|
|
|
// verify that two strings, each the length of the plane, can be output when
|
|
// scrolling is enabled (the second ought get an error without scrolling)
|
|
SUBCASE("ScrollingSplitStr") {
|
|
struct ncplane_options nopts = {
|
|
.y = 1,
|
|
.x = 1,
|
|
.rows = 2,
|
|
.cols = 20,
|
|
nullptr, nullptr, nullptr, 0,
|
|
};
|
|
struct ncplane* n = ncplane_create(n_, &nopts);
|
|
REQUIRE(n);
|
|
CHECK(20 == ncplane_putstr(n, "01234567890123456789"));
|
|
int y, x;
|
|
ncplane_cursor_yx(n, &y, &x);
|
|
CHECK(0 == y);
|
|
CHECK(20 == x);
|
|
CHECK(0 == ncplane_putstr(n, "01234567890123456789"));
|
|
CHECK(!ncplane_set_scrolling(n, true)); // enable scrolling
|
|
CHECK(20 == ncplane_putstr(n, "01234567890123456789"));
|
|
ncplane_cursor_yx(n, &y, &x);
|
|
CHECK(1 == y);
|
|
CHECK(20 == x);
|
|
CHECK(0 == notcurses_render(nc_));
|
|
}
|
|
|
|
// verify that a single string the size of the plane can be output when
|
|
// scrolling is enabled (it ought be an error without scrolling)
|
|
SUBCASE("ScrollingEGC") {
|
|
const char* out = "0123456789012345678901234567890123456789";
|
|
struct ncplane_options nopts = {
|
|
.y = 1,
|
|
.x = 1,
|
|
.rows = 2,
|
|
.cols = 20,
|
|
nullptr, nullptr, nullptr, 0,
|
|
};
|
|
struct ncplane* n = ncplane_create(n_, &nopts);
|
|
REQUIRE(n);
|
|
// verify that the new plane was started without scrolling
|
|
CHECK(!ncplane_set_scrolling(n, false));
|
|
// try to write 40 EGCs; the last 20 ought fail
|
|
for(const char* c = out ; *c ; ++c){
|
|
int ret = ncplane_putchar(n, *c);
|
|
if(c - out < 20){
|
|
CHECK(1 == ret);
|
|
}else{
|
|
CHECK(0 > ret);
|
|
}
|
|
}
|
|
int y, x;
|
|
ncplane_cursor_yx(n, &y, &x);
|
|
CHECK(0 == y);
|
|
CHECK(20 == x);
|
|
CHECK(0 == ncplane_cursor_move_yx(n, 0, 0));
|
|
CHECK(!ncplane_set_scrolling(n, true)); // enable scrolling
|
|
// try to write 40 EGCs; all ought succeed
|
|
for(const char* c = out ; *c ; ++c){
|
|
CHECK(1 == ncplane_putchar(n, *c));
|
|
}
|
|
ncplane_cursor_yx(n, &y, &x);
|
|
CHECK(1 == y);
|
|
CHECK(20 == x);
|
|
CHECK(0 == notcurses_render(nc_));
|
|
}
|
|
|
|
// ensure that if we draw a box on a scrolling plane, it stops at the right
|
|
// side, as opposed to scrolling and making a horrible mess
|
|
SUBCASE("ScrollingBoxen") {
|
|
struct ncplane_options nopts = {
|
|
.y = 1,
|
|
.x = 1,
|
|
.rows = 4,
|
|
.cols = 20,
|
|
nullptr, nullptr, nullptr, 0,
|
|
};
|
|
struct ncplane* n = ncplane_create(n_, &nopts);
|
|
REQUIRE(n);
|
|
// verify that the new plane was started without scrolling
|
|
CHECK(!ncplane_set_scrolling(n, true));
|
|
nccell ul = CELL_TRIVIAL_INITIALIZER, ur = CELL_TRIVIAL_INITIALIZER;
|
|
nccell dl = CELL_TRIVIAL_INITIALIZER, dr = CELL_TRIVIAL_INITIALIZER;
|
|
nccell hl = CELL_TRIVIAL_INITIALIZER, vl = CELL_TRIVIAL_INITIALIZER;
|
|
CHECK(0 == cells_double_box(n, 0, 0, &ul, &ur, &dl, &dr, &hl, &vl));
|
|
CHECK(0 > ncplane_box_sized(n, &ul, &ur, &dl, &dr, &hl, &vl, 2, 25, 0));
|
|
CHECK(0 > ncplane_box_sized(n, &ul, &ur, &dl, &dr, &hl, &vl, 2, 21, 0));
|
|
CHECK(0 == notcurses_render(nc_));
|
|
}
|
|
|
|
SUBCASE("ScrollingOffBottom") {
|
|
const char* out = "0123456789012345678901234567890123456789";
|
|
const char* onext = "ABCDEFGHIJKLMNOPQRST";
|
|
const char* next2 = "UVWXYZabcd";
|
|
struct ncplane_options nopts = {
|
|
.y = 1,
|
|
.x = 1,
|
|
.rows = 2,
|
|
.cols = 20,
|
|
nullptr, nullptr, nullptr, 0,
|
|
};
|
|
struct ncplane* n = ncplane_create(n_, &nopts);
|
|
REQUIRE(n);
|
|
// verify that the new plane was started without scrolling
|
|
CHECK(!ncplane_set_scrolling(n, true));
|
|
CHECK(40 == ncplane_putstr(n, out)); // fill up the plane w/ numbers
|
|
CHECK(0 == notcurses_render(nc_));
|
|
int y, x;
|
|
ncplane_cursor_yx(n, &y, &x);
|
|
CHECK(1 == y);
|
|
CHECK(20 == x);
|
|
CHECK(20 == ncplane_putstr(n, onext)); // scroll off one line, fill new one
|
|
ncplane_cursor_yx(n, &y, &x);
|
|
CHECK(1 == y);
|
|
CHECK(20 == x);
|
|
CHECK(0 == notcurses_render(nc_));
|
|
for(int i = 1 ; i < 21 ; ++i){
|
|
uint16_t styles;
|
|
uint64_t channels;
|
|
char* egc = notcurses_at_yx(nc_, 2, i, &styles, &channels);
|
|
REQUIRE(egc);
|
|
CHECK(onext[i - 1] == *egc);
|
|
free(egc);
|
|
}
|
|
ncplane_cursor_yx(n, &y, &x);
|
|
CHECK(1 == y);
|
|
CHECK(20 == x);
|
|
CHECK(10 == ncplane_putstr(n, next2));
|
|
CHECK(0 == notcurses_render(nc_));
|
|
for(int i = 1 ; i < 21 ; ++i){
|
|
uint16_t styles;
|
|
uint64_t channels;
|
|
char* egc = notcurses_at_yx(nc_, 2, i, &styles, &channels);
|
|
REQUIRE(egc);
|
|
if(i < 11){
|
|
CHECK(next2[i - 1] == *egc);
|
|
}else{
|
|
CHECK('\0' == *egc);
|
|
}
|
|
free(egc);
|
|
}
|
|
ncplane_cursor_yx(n, &y, &x);
|
|
CHECK(1 == y);
|
|
CHECK(10 == x);
|
|
}
|
|
|
|
// make sure that, after scrolling a line up, our y specifications are
|
|
// correctly adjusted for scrolling.
|
|
SUBCASE("XYPostScroll") {
|
|
const char* out = "0123456789012345678901234567890123456789";
|
|
const char* onext = "ABCDEFGHIJ";
|
|
//const char* next2 = "KLMNOPQRST";
|
|
//const char* next3 = "UVWXYZ";
|
|
CHECK(0 == notcurses_render(nc_));
|
|
struct ncplane_options nopts = {
|
|
.y = 1,
|
|
.x = 1,
|
|
.rows = 2,
|
|
.cols = 20,
|
|
nullptr, nullptr, nullptr, 0,
|
|
};
|
|
struct ncplane* n = ncplane_create(n_, &nopts);
|
|
REQUIRE(n);
|
|
// verify that the new plane was started without scrolling
|
|
CHECK(!ncplane_set_scrolling(n, true));
|
|
CHECK(40 == ncplane_putstr(n, out));
|
|
CHECK(0 == notcurses_render(nc_));
|
|
CHECK(10 == ncplane_putstr(n, onext));
|
|
CHECK(0 == notcurses_render(nc_));
|
|
for(int i = 1 ; i < 21 ; ++i){
|
|
uint16_t styles;
|
|
uint64_t channels;
|
|
char* egc = notcurses_at_yx(nc_, 2, i, &styles, &channels);
|
|
REQUIRE(egc);
|
|
if(i < 11){
|
|
CHECK(onext[i - 1] == *egc);
|
|
}else{
|
|
CHECK('\0' == *egc);
|
|
}
|
|
free(egc);
|
|
}
|
|
// FIXME
|
|
}
|
|
|
|
CHECK(0 == notcurses_stop(nc_));
|
|
|
|
}
|