Luigi in Mega Man world (#127)

* uniblock-demo: reset background to black
* warning about quantization
* some luigi love
* update cell documentation
* add unit test for move of stdplane
* MoveToLowerRight unit test
* ncplane_move_yx(): error to move stdscr
* better box permutations test
* luigi in megaman2 world
* stats: don't print 'em if we haven't got 'em
This commit is contained in:
Nick Black 2019-12-10 06:02:49 -05:00 committed by GitHub
parent fdc4325929
commit 0d2c43603b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 369 additions and 49 deletions

View File

@ -304,7 +304,7 @@ int ncplane_background(struct ncplane* ncp, cell* c);
// Move this plane relative to the standard plane. It is an error to attempt to // Move this plane relative to the standard plane. It is an error to attempt to
// move the standard plane. // move the standard plane.
void ncplane_move_yx(struct ncplane* n, int y, int x); int ncplane_move_yx(struct ncplane* n, int y, int x);
// Get the origin of this plane relative to the standard plane. // Get the origin of this plane relative to the standard plane.
void ncplane_yx(const struct ncplane* n, int* RESTRICT y, int* RESTRICT x); void ncplane_yx(const struct ncplane* n, int* RESTRICT y, int* RESTRICT x);
@ -503,7 +503,7 @@ ncplane_double_box_sized(struct ncplane* n, uint32_t attr, uint64_t channels,
// Erase every cell in the ncplane, resetting all attributes to normal, all // Erase every cell in the ncplane, resetting all attributes to normal, all
// colors to the default color, and all cells to undrawn. All cells associated // colors to the default color, and all cells to undrawn. All cells associated
// with this ncplane is invalidated, and must not be used after the call. // with this ncplane are invalidated, and must not be used after the call.
void ncplane_erase(struct ncplane* n); void ncplane_erase(struct ncplane* n);
// Set the current fore/background color using RGB specifications. If the // Set the current fore/background color using RGB specifications. If the
@ -571,18 +571,20 @@ available to the user:
// are unlikely in common use. // are unlikely in common use.
typedef struct cell { typedef struct cell {
// These 32 bits are either a single-byte, single-character grapheme cluster // These 32 bits are either a single-byte, single-character grapheme cluster
// (values 0--0x7f), or a pointer into a per-ncplane attached pool of // (values 0--0x7f), or an offset into a per-ncplane attached pool of
// varying-length UTF-8 grapheme clusters. This pool may thus be up to 16MB. // varying-length UTF-8 grapheme clusters. This pool may thus be up to 32MB.
uint32_t gcluster; // 1 * 4b -> 4b uint32_t gcluster; // 1 * 4b -> 4b
// The classic NCURSES WA_* attributes (16 bits), plus 16 bits of alpha. // CELL_STYLE_* attributes (16 bits) + 16 reserved bits
uint32_t attrword; // + 4b -> 8b uint32_t attrword; // + 4b -> 8b
// (channels & 0x8000000000000000ull): inherit styling from prior cell // (channels & 0x8000000000000000ull): wide character (left or right side)
// (channels & 0x4000000000000000ull): foreground is *not* "default color" // (channels & 0x4000000000000000ull): foreground is *not* "default color"
// (channels & 0x3f00000000000000ull): reserved, must be 0 // (channels & 0x3000000000000000ull): foreground alpha (2 bits)
// (channels & 0x0f00000000000000ull): reserved, must be 0
// (channels & 0x00ffffff00000000ull): foreground in 3x8 RGB (rrggbb) // (channels & 0x00ffffff00000000ull): foreground in 3x8 RGB (rrggbb)
// (channels & 0x0000000080000000ull): in the middle of a multicolumn glyph // (channels & 0x0000000080000000ull): reserved, must be 0
// (channels & 0x0000000040000000ull): background is *not* "default color" // (channels & 0x0000000040000000ull): background is *not* "default color"
// (channels & 0x000000003f000000ull): reserved, must be 0 // (channels & 0x0000000030000000ull): background alpha (2 bits)
// (channels & 0x000000000f000000ull): reserved, must be 0
// (channels & 0x0000000000ffffffull): background in 3x8 RGB (rrggbb) // (channels & 0x0000000000ffffffull): background in 3x8 RGB (rrggbb)
// At render time, these 24-bit values are quantized down to terminal // At render time, these 24-bit values are quantized down to terminal
// capabilities, if necessary. There's a clear path to 10-bit support should // capabilities, if necessary. There's a clear path to 10-bit support should

View File

@ -20,7 +20,7 @@ on your terminal after the program exits.
Print a usage message, and exit with success. Print a usage message, and exit with success.
.TP .TP
.IR demospec .IR demospec
Select which demos to run, and what order to run them in. The default is "imbgsuwvpo". See below for a list of demos. Select which demos to run, and what order to run them in. The default is "imlbgsuwvpo". See below for a list of demos.
.SH DESCRIPTION .SH DESCRIPTION
.B notcurses-demo .B notcurses-demo
contains a set of text-based demonstrations of capabilities from the notcurses library. The demonstrations include: contains a set of text-based demonstrations of capabilities from the notcurses library. The demonstrations include:
@ -33,6 +33,8 @@ contains a set of text-based demonstrations of capabilities from the notcurses l
.P .P
(m)axcolors—smoothly changing colors (m)axcolors—smoothly changing colors
.P .P
(l)uigi-a dashing plumber of Apennine persuasion
.P
(b)oxes—pulsating boxes with a transparent center (b)oxes—pulsating boxes with a transparent center
.P .P
(g)rid—a gradient of color lain atop a great grid (g)rid—a gradient of color lain atop a great grid

60
include/enmetric.h Normal file
View File

@ -0,0 +1,60 @@
#ifndef NOTCURSES_ENMETRIC
#define NOTCURSES_ENMETRIC
#ifdef __cplusplus
extern "C" {
#else
#define RESTRICT restrict
#endif
#define PREFIXSTRLEN 7 // Does not include a '\0' (xxx.xxU)
#define IPREFIXSTRLEN 8 // Does not include a '\0' (xxxx.xxU)
#define BPREFIXSTRLEN 9 // Does not include a '\0' (xxxx.xxUi), i == prefix
// A bit of the nasties here to stringize our preprocessor tokens just now
// #defined, making them usable as printf(3) specifiers.
#define STRHACK1(x) #x
#define STRHACK2(x) STRHACK1(x)
#define PREFIXFMT "%" STRHACK2(PREFIXSTRLEN) "s"
#define IPREFIXFMT "%" STRHACK2(IPREFIXSTRLEN) "s"
#define BPREFIXFMT "%" STRHACK2(BPREFIXSTRLEN) "s"
// Takes an arbitrarily large number, and prints it into a fixed-size buffer by
// adding the necessary SI suffix. Usually, pass a |[B]PREFIXSTRLEN+1|-sized
// buffer to generate up to [B]PREFIXSTRLEN characters. The characteristic can
// occupy up through |mult-1| characters (3 for 1000, 4 for 1024). The mantissa
// can occupy either zero or two characters.
//
// Floating-point is never used, because an IEEE758 double can only losslessly
// represent integers through 2^53-1.
//
// 2^64-1 is 18446744073709551615, 18.45E(xa). KMGTPEZY thus suffice to handle
// a 89-bit uintmax_t. Beyond Z(etta) and Y(otta) lie lands unspecified by SI.
//
// val: value to print
// decimal: scaling. '1' if none has taken place.
// buf: buffer in which string will be generated
// omitdec: inhibit printing of all-0 decimal portions
// mult: base of suffix system (almost always 1000 or 1024)
// uprefix: character to print following suffix ('i' for kibibytes basically).
// only printed if suffix is actually printed (input >= mult).
const char *enmetric(uintmax_t val, unsigned decimal, char *buf, int omitdec,
unsigned mult, int uprefix);
// Mega, kilo, gigabytes. Use PREFIXSTRLEN + 1.
static inline const char *
qprefix(uintmax_t val, unsigned decimal, char *buf, int omitdec){
return enmetric(val, decimal, buf, omitdec, 1000, '\0');
}
// Mibi, kebi, gibibytes. Use BPREFIXSTRLEN + 1.
static inline const char *
bprefix(uintmax_t val, unsigned decimal, char *buf, int omitdec){
return enmetric(val, decimal, buf, omitdec, 1024, 'i');
}
#ifdef __cplusplus
} // extern "C"
#endif
#endif

View File

@ -303,7 +303,7 @@ API int ncplane_background(struct ncplane* ncp, cell* c);
// Move this plane relative to the standard plane. It is an error to attempt to // Move this plane relative to the standard plane. It is an error to attempt to
// move the standard plane. // move the standard plane.
API void ncplane_move_yx(struct ncplane* n, int y, int x); API int ncplane_move_yx(struct ncplane* n, int y, int x);
// Get the origin of this plane relative to the standard plane. // Get the origin of this plane relative to the standard plane.
API void ncplane_yx(const struct ncplane* n, int* RESTRICT y, int* RESTRICT x); API void ncplane_yx(const struct ncplane* n, int* RESTRICT y, int* RESTRICT x);

View File

@ -9,7 +9,7 @@
#include <notcurses.h> #include <notcurses.h>
#include "demo.h" #include "demo.h"
static const char DEFAULT_DEMO[] = "imbgswuvpo"; static const char DEFAULT_DEMO[] = "imlbgswuvpo";
int timespec_subtract(struct timespec *result, const struct timespec *time0, int timespec_subtract(struct timespec *result, const struct timespec *time0,
struct timespec *time1){ struct timespec *time1){
@ -45,6 +45,7 @@ usage(const char* exe, int status){
fprintf(out, " b: run box\n"); fprintf(out, " b: run box\n");
fprintf(out, " g: run grid\n"); fprintf(out, " g: run grid\n");
fprintf(out, " i: run intro\n"); fprintf(out, " i: run intro\n");
fprintf(out, " l: run luigi\n");
fprintf(out, " m: run maxcolor\n"); fprintf(out, " m: run maxcolor\n");
fprintf(out, " o: run outro\n"); fprintf(out, " o: run outro\n");
fprintf(out, " p: run panelreels\n"); fprintf(out, " p: run panelreels\n");
@ -145,6 +146,7 @@ ext_demos(struct notcurses* nc, const char* demos){
case 'm': ret = maxcolor_demo(nc); break; case 'm': ret = maxcolor_demo(nc); break;
case 'b': ret = box_demo(nc); break; case 'b': ret = box_demo(nc); break;
case 'g': ret = grid_demo(nc); break; case 'g': ret = grid_demo(nc); break;
case 'l': ret = luigi_demo(nc); break;
case 'v': ret = view_demo(nc); break; case 'v': ret = view_demo(nc); break;
case 'w': ret = widecolor_demo(nc); break; case 'w': ret = widecolor_demo(nc); break;
case 'p': ret = panelreel_demo(nc); break; case 'p': ret = panelreel_demo(nc); break;

View File

@ -19,6 +19,7 @@ int grid_demo(struct notcurses* nc);
int sliding_puzzle_demo(struct notcurses* nc); int sliding_puzzle_demo(struct notcurses* nc);
int view_demo(struct notcurses* nc); int view_demo(struct notcurses* nc);
int panelreel_demo(struct notcurses* nc); int panelreel_demo(struct notcurses* nc);
int luigi_demo(struct notcurses* nc);
int outro(struct notcurses* nc); int outro(struct notcurses* nc);
int timespec_subtract(struct timespec *result, const struct timespec *time1, int timespec_subtract(struct timespec *result, const struct timespec *time1,

193
src/demo/luigi.c Normal file
View File

@ -0,0 +1,193 @@
#include "demo.h"
//0 = trans
//1 = white
//2 = yellow
//3 = green
static const char luigi1[] = "0000000000000000"
"0000000000000000"
"0000000111110000"
"0000011111120000"
"0000111111220000"
"0000111111111110"
"0000333223222000"
"0003223223322220"
"0003223322222222"
"0033223322232222"
"0033222223333330"
"0003322222333330"
"0000032222222200"
"0000311122200000"
"0003133313000000"
"0003133331300000"
"0033133333112200"
"0031133333332222"
"0031113333332222"
"0001113333333222"
"0001111333333222"
"0001111113331000"
"0001111111111000"
"0001111111113000"
"3333111111131100"
"3333111113311100"
"3333111131111000"
"3333111001111000"
"3333000003333000"
"3300000003333000"
"3000000003333330"
"0000000003333330";
static const char luigi2[] = "0000000000000000"
"0000001111100000"
"0000111111200000"
"0001111112200000"
"0001111111111100"
"0003332232220000"
"0032232233222200"
"0032233222222220"
"0332233222322220"
"0332222233333300"
"0033222223333300"
"0003322222222000"
"0000111122000000"
"0003133113300000"
"0031333311300000"
"0031333311330000"
"0031333311130000"
"0031333332230000"
"0031333322220000"
"0011133322221000"
"0011133322221100"
"0011113322211100"
"0011111133111100"
"0001111133311000"
"0000111333333000"
"0000113333330000"
"0000011333300000"
"0000031113330000"
"0000033330330000"
"0000333330000000"
"0000333333300000"
"0000003333300000";
static const char luigi3[] = "0000001111100000"
"0000111111200000"
"0001111112200000"
"0001111111111100"
"0003332232220000"
"0032232233222200"
"0032233222222220"
"0332233222322220"
"0332222233333300"
"0333222223333300"
"0003322222222000"
"0000033322000000"
"0000111133100020"
"0003333113310222"
"0033333311313222"
"0333333311331222"
"0333333311331323"
"0333333111331330"
"3333331112132300"
"3333111111111000"
"2222211111111000"
"2222211111111003"
"2222111111111033"
"0222111111133333"
"0001311111133333"
"0031131111133333"
"3331113311133333"
"3333111100033333"
"3333310000000000"
"0333000000000000"
"0333000000000000"
"0033300000000000";
static int
draw_luigi(struct ncplane* n, const char* sprite){
cell bgc = CELL_TRIVIAL_INITIALIZER;
cell_bg_set_alpha(&bgc, 3);
ncplane_set_background(n, &bgc);
cell_release(n, &bgc);
size_t s;
int sbytes;
uint64_t channels = 0;
for(s = 0 ; s < strlen(sprite) ; ++s){
switch(sprite[s]){
case '0':
ncplane_cursor_move_yx(n, (s + 1) / 16, (s + 1) % 16);
break;
case '1':
notcurses_fg_prep(&channels, 255, 255, 255);
break;
case '2':
notcurses_fg_prep(&channels, 0xe3, 0x9d, 0x25);
break;
case '3':
notcurses_fg_prep(&channels, 0x3a, 0x84, 0x00);
break;
}
if(sprite[s] != '0'){
if(ncplane_putegc(n, "\u2588", 0, channels, &sbytes) != 1){
return -1;
}
}
}
return 0;
}
int luigi_demo(struct notcurses* nc){
struct ncplane* n = notcurses_stdplane(nc);
int averr = 0;
struct ncvisual* nv = ncplane_visual_open(n, "../tests/megaman2.bmp", &averr);
if(nv == NULL){
return -1;
}
if(ncvisual_decode(nv, &averr) == NULL){
return -1;
}
if(ncvisual_render(nv)){
return -1;
}
int rows, cols;
ncplane_dim_yx(n, &rows, &cols);
// he should be walking on the platform ~4/5 of the way down
const int height = 32;
int yoff = rows * 4 / 5 - height + 1; // tuned
struct ncplane* lns[3];
int i;
for(i = 0 ; i < 3 ; ++i){
lns[i] = notcurses_newplane(nc, height, 16, yoff, -16, NULL);
if(lns[i] == NULL){
while(--i){
ncplane_destroy(lns[i]);
}
return -1;
}
}
draw_luigi(lns[0], luigi1);
draw_luigi(lns[1], luigi2);
draw_luigi(lns[2], luigi3);
struct ncplane* lastseen = NULL;
struct timespec stepdelay;
ns_to_timespec(timespec_to_ns(&demodelay) / (cols - 16 - 1), &stepdelay);
for(i = 0 ; i < cols - 16 - 1 ; ++i){
if(lastseen){ // hide the previous sprite
ncplane_move_yx(lastseen, yoff, -16);
}
if(i % 4 == 3){
lastseen = lns[1];
}else{
lastseen = lns[i % 4];
}
ncplane_move_yx(lastseen, yoff, i);
notcurses_render(nc);
nanosleep(&stepdelay, NULL);
}
for(i = 0 ; i < 3 ; ++i){
ncplane_destroy(lns[i]);
}
ncvisual_destroy(nv);
return 0;
}

View File

@ -180,8 +180,9 @@ int unicodeblocks_demo(struct notcurses* nc){
// we don't want a full delay period for each one, urk...or do we? // we don't want a full delay period for each one, urk...or do we?
struct timespec subdelay; struct timespec subdelay;
uint64_t nstotal = timespec_to_ns(&demodelay); uint64_t nstotal = timespec_to_ns(&demodelay);
ns_to_timespec(nstotal, &subdelay); ns_to_timespec(nstotal / 5, &subdelay);
for(sindex = 0 ; sindex < sizeof(blocks) / sizeof(*blocks) ; ++sindex){ for(sindex = 0 ; sindex < sizeof(blocks) / sizeof(*blocks) ; ++sindex){
ncplane_set_bg_rgb(n, 0, 0, 0);
//ncplane_erase(n); //ncplane_erase(n);
uint32_t blockstart = blocks[sindex].start; uint32_t blockstart = blocks[sindex].start;
const char* description = blocks[sindex].name; const char* description = blocks[sindex].name;
@ -204,7 +205,6 @@ int unicodeblocks_demo(struct notcurses* nc){
return -1; return -1;
} }
ncplane_set_fg_rgb(n, 0x40, 0xc0, 0x40); ncplane_set_fg_rgb(n, 0x40, 0xc0, 0x40);
ncplane_set_bg_rgb(n, 0, 0, 0);
if(ncplane_cursor_move_yx(n, 6 + BLOCKSIZE / CHUNKSIZE, 0)){ if(ncplane_cursor_move_yx(n, 6 + BLOCKSIZE / CHUNKSIZE, 0)){
return -1; return -1;
} }

View File

@ -357,8 +357,6 @@ ncplane* notcurses_newplane(notcurses* nc, int rows, int cols,
if(n == NULL){ if(n == NULL){
return n; return n;
} }
n->absx = xoff;
n->absy = yoff;
n->userptr = opaque; n->userptr = opaque;
return n; return n;
} }
@ -680,6 +678,15 @@ notcurses* notcurses_init(const notcurses_options* opts){
ret->top->leny, ret->top->lenx, ret->top->leny, ret->top->lenx,
ret->top->lenx * ret->top->leny * sizeof(*ret->top->fb), ret->top->lenx * ret->top->leny * sizeof(*ret->top->fb),
ret->colors, ret->RGBflag ? "direct" : "palette"); ret->colors, ret->RGBflag ? "direct" : "palette");
if(!ret->RGBflag){ // FIXME
if(ret->colors > 16){
putp(tiparm(ret->setaf, 207));
}else{
putp(tiparm(ret->setaf, 9));
}
fprintf(ret->ttyfp, "\nWarning: you will not have colors until this is resolved:\n");
fprintf(ret->ttyfp, " https://github.com/dankamongmen/notcurses/issues/4\n");
}
return ret; return ret;
err: err:
@ -700,20 +707,21 @@ int notcurses_stop(notcurses* nc){
ret = -1; ret = -1;
} }
ret |= tcsetattr(nc->ttyfd, TCSANOW, &nc->tpreserved); ret |= tcsetattr(nc->ttyfd, TCSANOW, &nc->tpreserved);
double avg = nc->stats.renders ? if(nc->stats.renders){
nc->stats.render_ns / (double)nc->stats.renders : 0; double avg = nc->stats.render_ns / (double)nc->stats.renders;
fprintf(stderr, "%ju renders, %.03gs total (%.03gs min, %.03gs max, %.02gs avg)\n", fprintf(stderr, "%ju renders, %.03gs total (%.03gs min, %.03gs max, %.02gs avg)\n",
nc->stats.renders, nc->stats.renders,
nc->stats.render_ns / 1000000000.0, nc->stats.render_ns / 1000000000.0,
nc->stats.render_min_ns / 1000000000.0, nc->stats.render_min_ns / 1000000000.0,
nc->stats.render_max_ns / 1000000000.0, nc->stats.render_max_ns / 1000000000.0,
avg / NANOSECS_IN_SEC); avg / NANOSECS_IN_SEC);
avg = nc->stats.renders ? nc->stats.render_bytes / (double)nc->stats.renders : 0; avg = nc->stats.render_bytes / (double)nc->stats.renders;
fprintf(stderr, "%.03fKB total (%.03fKB min, %.03fKB max, %.02fKB avg)\n", fprintf(stderr, "%.03fKB total (%.03fKB min, %.03fKB max, %.02fKB avg)\n",
nc->stats.render_bytes / 1024.0, nc->stats.render_bytes / 1024.0,
nc->stats.render_min_bytes / 1024.0, nc->stats.render_min_bytes / 1024.0,
nc->stats.render_max_bytes / 1024.0, nc->stats.render_max_bytes / 1024.0,
avg / 1024); avg / 1024);
}
fprintf(stderr, "Emits/elides: def %lu/%lu fg %lu/%lu bg %lu/%lu\n", fprintf(stderr, "Emits/elides: def %lu/%lu fg %lu/%lu bg %lu/%lu\n",
nc->stats.defaultemissions, nc->stats.defaultemissions,
nc->stats.defaultelisions, nc->stats.defaultelisions,
@ -1672,9 +1680,13 @@ int ncplane_box(ncplane* n, const cell* ul, const cell* ur,
return 0; return 0;
} }
void ncplane_move_yx(ncplane* n, int y, int x){ int ncplane_move_yx(ncplane* n, int y, int x){
if(n == n->nc->stdscr){
return -1;
}
n->absy = y; n->absy = y;
n->absx = x; n->absx = x;
return 0;
} }
void ncplane_yx(const ncplane* n, int* y, int* x){ void ncplane_yx(const ncplane* n, int* y, int* x){

BIN
tests/megaman2.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

View File

@ -214,28 +214,33 @@ TEST_F(NcplaneTest, BadlyPlacedBoxen) {
EXPECT_EQ(0, notcurses_render(nc_)); EXPECT_EQ(0, notcurses_render(nc_));
} }
TEST_F(NcplaneTest, BoxPermutations) { TEST_F(NcplaneTest, BoxPermutationsRounded) {
int dimx, dimy; int dimx, dimy;
ncplane_dim_yx(n_, &dimy, &dimx); ncplane_dim_yx(n_, &dimy, &dimx);
ASSERT_LT(12, dimy); ASSERT_LT(2, dimy);
ASSERT_LT(24, dimx); ASSERT_LT(47, dimx);
// we'll try all 16 boxmasks in 3x3 configurations in a 4x4 map // we'll try all 16 boxmasks in 3x3 configurations in a 1x16 map
unsigned boxmask = 0; unsigned boxmask = 0;
for(auto y0 = 0 ; y0 < 4 ; ++y0){ for(auto x0 = 0 ; x0 < 16 ; ++x0){
for(auto x0 = 0 ; x0 < 4 ; ++x0){ EXPECT_EQ(0, ncplane_cursor_move_yx(n_, 0, x0 * 3));
EXPECT_EQ(0, ncplane_cursor_move_yx(n_, y0 * 3, x0 * 3));
EXPECT_EQ(0, ncplane_rounded_box_sized(n_, 0, 0, 3, 3, boxmask)); EXPECT_EQ(0, ncplane_rounded_box_sized(n_, 0, 0, 3, 3, boxmask));
++boxmask; ++boxmask;
} }
EXPECT_EQ(0, notcurses_render(nc_));
} }
boxmask = 0;
for(auto y0 = 0 ; y0 < 4 ; ++y0){ TEST_F(NcplaneTest, BoxPermutationsDouble) {
for(auto x0 = 0 ; x0 < 4 ; ++x0){ int dimx, dimy;
EXPECT_EQ(0, ncplane_cursor_move_yx(n_, y0 * 3, x0 * 3 + 12)); ncplane_dim_yx(n_, &dimy, &dimx);
ASSERT_LT(2, dimx);
ASSERT_LT(47, dimx);
// we'll try all 16 boxmasks in 3x3 configurations in a 1x16 map
unsigned boxmask = 0;
for(auto x0 = 0 ; x0 < 16 ; ++x0){
EXPECT_EQ(0, ncplane_cursor_move_yx(n_, 0, x0 * 3));
EXPECT_EQ(0, ncplane_double_box_sized(n_, 0, 0, 3, 3, boxmask)); EXPECT_EQ(0, ncplane_double_box_sized(n_, 0, 0, 3, 3, boxmask));
++boxmask; ++boxmask;
} }
}
EXPECT_EQ(0, notcurses_render(nc_)); EXPECT_EQ(0, notcurses_render(nc_));
} }
@ -388,27 +393,32 @@ TEST_F(NcplaneTest, ShrinkPlane) {
notcurses_term_dim_yx(nc_, &maxy, &maxx); notcurses_term_dim_yx(nc_, &maxy, &maxx);
struct ncplane* newp = notcurses_newplane(nc_, maxy, maxx, y, x, nullptr); struct ncplane* newp = notcurses_newplane(nc_, maxy, maxx, y, x, nullptr);
ASSERT_NE(nullptr, newp); ASSERT_NE(nullptr, newp);
EXPECT_EQ(0, notcurses_render(nc_));
while(y > 4 && x > 4){ while(y > 4 && x > 4){
maxx -= 2; maxx -= 2;
maxy -= 2; maxy -= 2;
++x; ++x;
++y; ++y;
ASSERT_EQ(0, ncplane_resize(newp, 1, 1, maxy, maxx, 1, 1, maxy, maxx)); ASSERT_EQ(0, ncplane_resize(newp, 1, 1, maxy, maxx, 1, 1, maxy, maxx));
EXPECT_EQ(0, notcurses_render(nc_));
// FIXME check dims, pos // FIXME check dims, pos
} }
while(y > 4){ while(y > 4){
maxy -= 2; maxy -= 2;
++y; ++y;
ASSERT_EQ(0, ncplane_resize(newp, 1, 0, maxy, maxx, 1, 0, maxy, maxx)); ASSERT_EQ(0, ncplane_resize(newp, 1, 0, maxy, maxx, 1, 0, maxy, maxx));
EXPECT_EQ(0, notcurses_render(nc_));
// FIXME check dims, pos // FIXME check dims, pos
} }
while(x > 4){ while(x > 4){
maxx -= 2; maxx -= 2;
++x; ++x;
ASSERT_EQ(0, ncplane_resize(newp, 0, 1, maxy, maxx, 0, 1, maxy, maxx)); ASSERT_EQ(0, ncplane_resize(newp, 0, 1, maxy, maxx, 0, 1, maxy, maxx));
EXPECT_EQ(0, notcurses_render(nc_));
// FIXME check dims, pos // FIXME check dims, pos
} }
ASSERT_EQ(0, ncplane_resize(newp, 0, 0, 0, 0, 0, 0, 2, 2)); ASSERT_EQ(0, ncplane_resize(newp, 0, 0, 0, 0, 0, 0, 2, 2));
EXPECT_EQ(0, notcurses_render(nc_));
// FIXME check dims, pos // FIXME check dims, pos
ASSERT_EQ(0, ncplane_destroy(newp)); ASSERT_EQ(0, ncplane_destroy(newp));
} }
@ -686,3 +696,34 @@ TEST_F(NcplaneTest, RightToLeft) {
EXPECT_LT(0, ncplane_putstr(n_, "㉀㉁㉂㉃㉄㉅㉆㉇㉈㉉㉊㉋㉌㉍㉎㉏㉐㉑㉒㉓㉔㉕㉖㉗㉘㉙㉚㉛㉜㉝㉞㉟")); EXPECT_LT(0, ncplane_putstr(n_, "㉀㉁㉂㉃㉄㉅㉆㉇㉈㉉㉊㉋㉌㉍㉎㉏㉐㉑㉒㉓㉔㉕㉖㉗㉘㉙㉚㉛㉜㉝㉞㉟"));
EXPECT_EQ(0, notcurses_render(nc_)); EXPECT_EQ(0, notcurses_render(nc_));
} }
TEST_F(NcplaneTest, NewPlaneOnRight) {
int ncols, nrows;
ncplane_dim_yx(n_, &nrows, &ncols);
cell ul{}, ll{}, lr{}, ur{}, hl{}, vl{};
int y, x;
ncplane_yx(n_, &y, &x);
struct ncplane* ncp = notcurses_newplane(nc_, 2, 2, y, ncols - 3, nullptr);
ASSERT_NE(nullptr, ncp);
ASSERT_EQ(0, cells_rounded_box(ncp, 0, 0, &ul, &ur, &ll, &lr, &hl, &vl));
EXPECT_EQ(0, ncplane_box(ncp, &ul, &ur, &ll, &lr, &hl, &vl, y + 1, x + 1, 0));
EXPECT_EQ(0, notcurses_render(nc_));
// FIXME verify with ncplane_at_cursor()
EXPECT_EQ(0, ncplane_destroy(ncp));
}
TEST_F(NcplaneTest, MoveToLowerRight) {
int ncols, nrows;
ncplane_dim_yx(n_, &nrows, &ncols);
cell ul{}, ll{}, lr{}, ur{}, hl{}, vl{};
int y, x;
ncplane_yx(n_, &y, &x);
struct ncplane* ncp = notcurses_newplane(nc_, 2, 2, y, x, nullptr);
ASSERT_NE(nullptr, ncp);
ASSERT_EQ(0, cells_rounded_box(ncp, 0, 0, &ul, &ur, &ll, &lr, &hl, &vl));
EXPECT_EQ(0, ncplane_box(ncp, &ul, &ur, &ll, &lr, &hl, &vl, y + 1, x + 1, 0));
EXPECT_EQ(0, notcurses_render(nc_));
EXPECT_EQ(0, ncplane_move_yx(ncp, nrows - 3, ncols - 3));
EXPECT_EQ(0, notcurses_render(nc_));
EXPECT_EQ(0, ncplane_destroy(ncp));
// FIXME verify with ncplane_at_cursor()
}

View File

@ -76,6 +76,13 @@ TEST_F(NotcursesTest, RejectDestroyStdPlane) {
ASSERT_NE(0, ncplane_destroy(ncp)); ASSERT_NE(0, ncplane_destroy(ncp));
} }
// it is an error to attempt to move the standard plane
TEST_F(NotcursesTest, RejectMoveStdPlane) {
ncplane* ncp = notcurses_stdplane(nc_);
ASSERT_NE(nullptr, ncp);
ASSERT_NE(0, ncplane_move_yx(ncp, 1, 1));
}
// create planes partitioning the entirety of the screen, one at each coordinate // create planes partitioning the entirety of the screen, one at each coordinate
TEST_F(NotcursesTest, TileScreenWithPlanes) { TEST_F(NotcursesTest, TileScreenWithPlanes) {
int maxx, maxy; int maxx, maxy;