diff --git a/src/lib/notcurses.c b/src/lib/notcurses.c index 18793d025..c20783ce6 100644 --- a/src/lib/notcurses.c +++ b/src/lib/notcurses.c @@ -2138,6 +2138,9 @@ int ncplane_erase_region(ncplane* n, int ystart, int xstart, int ylen, int xlen) return -1; } if(xlen < 0){ + if(xlen + 1 < -xstart){ + xlen = -xstart - 1; + } xstart = xstart + xlen + 1; xlen = -xlen; }else if(xlen == 0){ @@ -2148,6 +2151,9 @@ int ncplane_erase_region(ncplane* n, int ystart, int xstart, int ylen, int xlen) xlen = ncplane_dim_x(n) - xstart; } if(ylen < 0){ + if(ylen + 1 < -ystart){ + ylen = -ystart - 1; + } ystart = ystart + ylen + 1; ylen = -ylen; }else if(ylen == 0){ diff --git a/src/tests/erase.cpp b/src/tests/erase.cpp index 21cd502a4..86e726012 100644 --- a/src/tests/erase.cpp +++ b/src/tests/erase.cpp @@ -7,25 +7,171 @@ TEST_CASE("Erase") { if(!nc_){ return; } - struct ncplane* n_ = notcurses_stdplane(nc_); + int dimy, dimx; + struct ncplane* n_ = notcurses_stddim_yx(nc_, &dimy, &dimx); REQUIRE(n_); + // fill the standard plane with 'x's + nccell nc = CELL_CHAR_INITIALIZER('x'); + CHECK(0 < ncplane_polyfill_yx(n_, 0, 0, &nc)); + nccell_release(n_, &nc); + CHECK(0 == notcurses_render(nc_)); + CHECK(0 == ncplane_cursor_move_yx(n_, dimy / 2, dimx / 2)); + // clear all columns to the left of cursor, inclusive SUBCASE("EraseColumnsLeft") { + CHECK(0 == ncplane_erase_region(n_, -1, -1, 0, -INT_MAX)); + for(int y = 0 ; y < dimy ; ++y){ + for(int x = 0 ; x < dimx ; ++x){ + char* c = ncplane_at_yx(n_, y, x, nullptr, nullptr); + REQUIRE(nullptr != c); + if(x <= dimx / 2){ + CHECK(0 == strcmp(c, "")); + }else{ + CHECK(0 == strcmp(c, "x")); + } + free(c); + } + } } // clear all columns to the right of cursor, inclusive SUBCASE("EraseColumnsRight") { + CHECK(0 == ncplane_erase_region(n_, -1, -1, 0, INT_MAX)); + for(int y = 0 ; y < dimy ; ++y){ + for(int x = 0 ; x < dimx ; ++x){ + char* c = ncplane_at_yx(n_, y, x, nullptr, nullptr); + REQUIRE(nullptr != c); + if(x >= dimx / 2){ + CHECK(0 == strcmp(c, "")); + }else{ + CHECK(0 == strcmp(c, "x")); + } + free(c); + } + } } // clear all rows above cursor, inclusive - SUBCASE("EraseRowsLeft") { + SUBCASE("EraseRowsAbove") { + CHECK(0 == ncplane_erase_region(n_, -1, -1, -INT_MAX, 0)); + for(int y = 0 ; y < dimy ; ++y){ + for(int x = 0 ; x < dimx ; ++x){ + char* c = ncplane_at_yx(n_, y, x, nullptr, nullptr); + REQUIRE(nullptr != c); + if(y <= dimy / 2){ + CHECK(0 == strcmp(c, "")); + }else{ + CHECK(0 == strcmp(c, "x")); + } + free(c); + } + } } // clear all rows below cursor, inclusive SUBCASE("EraseRowsBelow") { + CHECK(0 == ncplane_erase_region(n_, -1, -1, INT_MAX, 0)); + for(int y = 0 ; y < dimy ; ++y){ + for(int x = 0 ; x < dimx ; ++x){ + char* c = ncplane_at_yx(n_, y, x, nullptr, nullptr); + REQUIRE(nullptr != c); + if(y >= dimy / 2){ + CHECK(0 == strcmp(c, "")); + }else{ + CHECK(0 == strcmp(c, "x")); + } + free(c); + } + } + } + + // current cursor to the end of the line + SUBCASE("EraseToEOL") { + CHECK(0 == ncplane_erase_region(n_, -1, -1, 1, INT_MAX)); + for(int y = 0 ; y < dimy ; ++y){ + for(int x = 0 ; x < dimx ; ++x){ + char* c = ncplane_at_yx(n_, y, x, nullptr, nullptr); + REQUIRE(nullptr != c); + if(y == dimy / 2 && x >= dimx / 2){ + CHECK(0 == strcmp(c, "")); + }else{ + CHECK(0 == strcmp(c, "x")); + } + free(c); + } + } + } + + // current cursor to the start of the line + SUBCASE("EraseToSOL") { + CHECK(0 == ncplane_erase_region(n_, -1, -1, 1, -INT_MAX)); + for(int y = 0 ; y < dimy ; ++y){ + for(int x = 0 ; x < dimx ; ++x){ + char* c = ncplane_at_yx(n_, y, x, nullptr, nullptr); + REQUIRE(nullptr != c); + if(y == dimy / 2 && x <= dimx / 2){ + CHECK(0 == strcmp(c, "")); + }else{ + CHECK(0 == strcmp(c, "x")); + } + free(c); + } + } + } + + // current cursor to the end of the line using -1 len + SUBCASE("EraseToEOLNeg") { + CHECK(0 == ncplane_erase_region(n_, -1, -1, -1, INT_MAX)); + for(int y = 0 ; y < dimy ; ++y){ + for(int x = 0 ; x < dimx ; ++x){ + char* c = ncplane_at_yx(n_, y, x, nullptr, nullptr); + REQUIRE(nullptr != c); + if(y == dimy / 2 && x >= dimx / 2){ + CHECK(0 == strcmp(c, "")); + }else{ + CHECK(0 == strcmp(c, "x")); + } + free(c); + } + } + } + + // current cursor to the start of the line using -1 len + SUBCASE("EraseToSOLNeg") { + CHECK(0 == ncplane_erase_region(n_, -1, -1, -1, -INT_MAX)); + for(int y = 0 ; y < dimy ; ++y){ + for(int x = 0 ; x < dimx ; ++x){ + char* c = ncplane_at_yx(n_, y, x, nullptr, nullptr); + REQUIRE(nullptr != c); + if(y == dimy / 2 && x <= dimx / 2){ + CHECK(0 == strcmp(c, "")); + }else{ + CHECK(0 == strcmp(c, "x")); + } + free(c); + } + } + } + + // current cursor only + SUBCASE("EraseCurrentCursor") { + CHECK(0 == ncplane_erase_region(n_, -1, -1, 1, 1)); + for(int y = 0 ; y < dimy ; ++y){ + for(int x = 0 ; x < dimx ; ++x){ + char* c = ncplane_at_yx(n_, y, x, nullptr, nullptr); + REQUIRE(nullptr != c); + if(y == dimy / 2 && x == dimx / 2){ + CHECK(0 == strcmp(c, "")); + }else{ + CHECK(0 == strcmp(c, "x")); + } + free(c); + } + } } + CHECK(0 == notcurses_render(nc_)); CHECK(0 == notcurses_stop(nc_)); } diff --git a/src/tests/main.cpp b/src/tests/main.cpp index d011fc585..693e8cf91 100644 --- a/src/tests/main.cpp +++ b/src/tests/main.cpp @@ -164,7 +164,9 @@ auto main(int argc, const char **argv) -> int { handle_opts(argv); int res = context.run(); // run reset_terminal(); - check_data_dir(); + if(res){ + check_data_dir(); + } if(context.shouldExit()){ // important - query flags (and --exit) rely on the user doing this return res; // propagate the result of the tests }