diff --git a/README.md b/README.md index fedd5ca2e..9887fb28c 100644 --- a/README.md +++ b/README.md @@ -730,8 +730,7 @@ memory. int ncplane_cursor_move_yx(struct ncplane* n, int y, int x); // Get the current position of the cursor within n. y and/or x may be NULL. -void ncplane_cursor_yx(const struct ncplane* n, int* RESTRICT y, - int* RESTRICT x); +void ncplane_cursor_yx(struct ncplane* n, int* RESTRICT y, int* RESTRICT x); // Replace the cell underneath the cursor with the provided cell 'c', and // advance the cursor by the width of the cell (but not past the end of the diff --git a/data/chunli1.bmp b/data/chunli1.bmp new file mode 100644 index 000000000..65eb54c8b Binary files /dev/null and b/data/chunli1.bmp differ diff --git a/data/chunli2.bmp b/data/chunli2.bmp new file mode 100644 index 000000000..382d4c2f8 Binary files /dev/null and b/data/chunli2.bmp differ diff --git a/data/chunli3.bmp b/data/chunli3.bmp new file mode 100644 index 000000000..94ba21334 Binary files /dev/null and b/data/chunli3.bmp differ diff --git a/data/chunli4.bmp b/data/chunli4.bmp new file mode 100644 index 000000000..de8c0278b Binary files /dev/null and b/data/chunli4.bmp differ diff --git a/data/chunli5.bmp b/data/chunli5.bmp new file mode 100644 index 000000000..6c085d74c Binary files /dev/null and b/data/chunli5.bmp differ diff --git a/data/chunli6.bmp b/data/chunli6.bmp new file mode 100644 index 000000000..b6603b7bb Binary files /dev/null and b/data/chunli6.bmp differ diff --git a/data/chunli7.bmp b/data/chunli7.bmp new file mode 100644 index 000000000..aa5c01821 Binary files /dev/null and b/data/chunli7.bmp differ diff --git a/data/chunli8.bmp b/data/chunli8.bmp new file mode 100644 index 000000000..641bb58b7 Binary files /dev/null and b/data/chunli8.bmp differ diff --git a/data/chunlivictory.png b/data/chunlivictory.png new file mode 100644 index 000000000..d8a3bdace Binary files /dev/null and b/data/chunlivictory.png differ diff --git a/doc/man/man1/notcurses-demo.1 b/doc/man/man1/notcurses-demo.1 index 2c11ef476..726e34e91 100644 --- a/doc/man/man1/notcurses-demo.1 +++ b/doc/man/man1/notcurses-demo.1 @@ -1,4 +1,4 @@ -.TH notcurses-demo 1 "2019-12-25" +.TH notcurses-demo 1 "v1.0.0" .SH NAME notcurses-demo \- Show off some notcurses features .SH SYNOPSIS @@ -17,6 +17,10 @@ Look in the specified path for data files. .BR \-d \fIdelaymult\fR Apply a (floating-point) multiplier to the standard delay of 1s. .TP +.BR \-H +Launch a HUD with running timers for each demo. This HUD can be moved or +closed with the mouse. +.TP .BR \-k Inhibit use of the alternate screen. Necessary if you want the output left on your terminal after the program exits. @@ -44,6 +48,8 @@ contains a set of text-based demonstrations of capabilities from the notcurses l .P (t)rans—an exploration of various transparencies .P +(c)hunli—the day Bison graced her village, it was Tuesday +.P (l)uigi-a dashing plumber of Apennine persuasion .P (u)niblocks—a series of blocks detailing Unicode pages diff --git a/doc/man/man1/notcurses-input.1 b/doc/man/man1/notcurses-input.1 index 0e3abaa97..90e2b1295 100644 --- a/doc/man/man1/notcurses-input.1 +++ b/doc/man/man1/notcurses-input.1 @@ -1,4 +1,4 @@ -.TH notcurses-input. 1 "2019-12-25" +.TH notcurses-input. 1 "v1.0.0" .SH NAME notcurses-input \- Display and decode input .SH SYNOPSIS diff --git a/doc/man/man1/notcurses-planereel.1 b/doc/man/man1/notcurses-planereel.1 index 13628bf54..e69aec336 100644 --- a/doc/man/man1/notcurses-planereel.1 +++ b/doc/man/man1/notcurses-planereel.1 @@ -1,4 +1,4 @@ -.TH notcurses-planereel 1 "2019-12-25" +.TH notcurses-planereel 1 "v1.0.0" .SH NAME notcurses-planereel \- Experiment with panelreels .SH SYNOPSIS diff --git a/doc/man/man1/notcurses-view.1 b/doc/man/man1/notcurses-view.1 index 96993150b..63ca2e9df 100644 --- a/doc/man/man1/notcurses-view.1 +++ b/doc/man/man1/notcurses-view.1 @@ -1,4 +1,4 @@ -.TH notcurses-view 1 "2019-12-25" +.TH notcurses-view 1 "v1.0.0" .SH NAME notcurses-view \- Render multimedia to the terminal .SH SYNOPSIS diff --git a/doc/man/man3/notcurses_ncplane.3.md b/doc/man/man3/notcurses_ncplane.3.md index 29c42d1b0..60e2ce89c 100644 --- a/doc/man/man3/notcurses_ncplane.3.md +++ b/doc/man/man3/notcurses_ncplane.3.md @@ -46,7 +46,11 @@ notcurses_ncplane - operations on notcurses planes **const void* ncplane_userptr_const(const struct ncplane* n);** -**void ncplane_dim_yx(const struct ncplane* n, int* restrict rows, int* restrict cols);** +**void ncplane_dim_yx(struct ncplane* n, int* restrict rows, int* restrict cols);** + +**static inline int ncplane_dim_y(struct ncplane* n);** + +**static inline int ncplane_dim_x(struct ncplane* n);** **int ncplane_cursor_move_yx(struct ncplane* n, int y, int x);** @@ -121,6 +125,11 @@ Functions returning **int** return 0 on success, and non-zero on error. All other functions either cannot fail (and return **void**). +# NOTES + +It would be reasonable to expect many of these functions to accept `const struct notcurses` +parameters. Alas, almost all must manipulate the mutex contained within the object. + # SEE ALSO **notcurses(3)**, **notcurses_cell(3)**, **notcurses_output(3)**, diff --git a/include/notcurses.h b/include/notcurses.h index 21ae8195a..2efc79b3c 100644 --- a/include/notcurses.h +++ b/include/notcurses.h @@ -535,8 +535,7 @@ ncplane_align(struct ncplane* n, ncalign_e align, int c){ if(align == NCALIGN_LEFT){ return 0; } - int cols; - ncplane_dim_yx(n, NULL, &cols); + int cols = ncplane_dim_x(n); if(align == NCALIGN_CENTER){ return (cols - c) / 2; }else if(align == NCALIGN_RIGHT){ diff --git a/src/demo/chunli.c b/src/demo/chunli.c new file mode 100644 index 000000000..363962daa --- /dev/null +++ b/src/demo/chunli.c @@ -0,0 +1,78 @@ +#include "demo.h" + +#define CHUNS 8 // 8-part sprite + +typedef struct chunli { + char* path; + struct ncvisual* ncv; + struct ncplane* n; +} chunli; + +// test of sprites from files +int chunli_demo(struct notcurses* nc){ + struct ncplane* stdn = notcurses_stdplane(nc); + cell c = CELL_SIMPLE_INITIALIZER(' '); + ncplane_set_base(stdn, &c); + struct timespec iterdelay; + timespec_div(&demodelay, 10, &iterdelay); + int averr, dimy, dimx; + chunli chuns[CHUNS]; + char file[PATH_MAX]; + for(int i = 0 ; i < CHUNS ; ++i){ + notcurses_resize(nc, &dimy, &dimx); + snprintf(file, sizeof(file), "chunli%d.bmp", i + 1); + chuns[i].path = find_data(file); + chuns[i].ncv = ncvisual_open_plane(nc, chuns[i].path, &averr, 0, 0, NCSCALE_NONE); + if(chuns[i].ncv == NULL){ + return -1; + } + if(ncvisual_decode(chuns[i].ncv, &averr) == NULL){ + return -1; + } + if(ncvisual_render(chuns[i].ncv, 0, 0, 0, 0)){ + return -1; + } + chuns[i].n = ncvisual_plane(chuns[i].ncv); + int thisx, thisy; + ncplane_dim_yx(chuns[i].n, &thisy, &thisx); + if(ncplane_move_yx(chuns[i].n, (dimy - thisy) / 2, (dimx - thisx) / 2)){ + return -1; + } + // xoff += thisx; + if(notcurses_render(nc)){ + return -1; + } + nanosleep(&iterdelay, NULL); + ncvisual_destroy(chuns[i].ncv); + free(chuns[i].path); + } + char* victory = find_data("chunlivictory.png"); + struct ncvisual* ncv = ncvisual_open_plane(nc, victory, &averr, 0, 0, NCSCALE_NONE); + if(ncv == NULL){ + return -1; + } + if(ncvisual_decode(ncv, &averr) == NULL){ + return -1; + } + struct ncplane* ncp = ncvisual_plane(ncv); + cell b = CELL_TRIVIAL_INITIALIZER; + cell_set_fg_alpha(&b, CELL_ALPHA_TRANSPARENT); + cell_set_bg_alpha(&b, CELL_ALPHA_TRANSPARENT); + ncplane_set_base(ncp, &b); + const int offsets[] = { + 0, 50, 100, 154, 208, 260, 312, 368, 420, 479, 538, 588, 638, 688, 736, 786, 836, 888, 942 + }; + for(size_t i = 0u ; i < sizeof(offsets) / sizeof(*offsets) - 1 ; ++i){ + notcurses_resize(nc, &dimy, &dimx); + ncplane_erase(ncvisual_plane(ncv)); + if(ncvisual_render(ncv, 0, offsets[i], 0, offsets[i + 1] - offsets[i] + 1)){ + return -1; + } + if(notcurses_render(nc)){ + return -1; + } + nanosleep(&iterdelay, NULL); + } + ncvisual_destroy(ncv); + return 0; +} diff --git a/src/demo/demo.c b/src/demo/demo.c index 68a4e6ea7..ff4d3590f 100644 --- a/src/demo/demo.c +++ b/src/demo/demo.c @@ -19,7 +19,7 @@ static int democount; static demoresult* results; static atomic_bool interrupted = ATOMIC_VAR_INIT(false); -static const char DEFAULT_DEMO[] = "ixetlubgswvpo"; +static const char DEFAULT_DEMO[] = "ixetclubgswvpo"; static char datadir[PATH_MAX] = "/usr/share/notcurses"; // FIXME void interrupt_demo(void){ @@ -77,6 +77,7 @@ usage(const char* exe, int status){ fprintf(out, " -c: constant PRNG seed, useful for benchmarking\n"); fprintf(out, "all demos are run if no specification is provided\n"); fprintf(out, " b: run box\n"); + fprintf(out, " c: run chunli\n"); fprintf(out, " e: run eagles\n"); fprintf(out, " g: run grid\n"); fprintf(out, " i: run intro\n"); @@ -253,6 +254,7 @@ ext_demos(struct notcurses* nc, const char* demos){ case 'u': ret = unicodeblocks_demo(nc); break; case 't': ret = trans_demo(nc); break; case 'b': ret = box_demo(nc); break; + case 'c': ret = chunli_demo(nc); break; case 'g': ret = grid_demo(nc); break; case 'l': ret = luigi_demo(nc); break; case 'v': ret = view_demo(nc); break; diff --git a/src/demo/demo.h b/src/demo/demo.h index 1a44325e0..fde1bb1a1 100644 --- a/src/demo/demo.h +++ b/src/demo/demo.h @@ -20,6 +20,7 @@ int unicodeblocks_demo(struct notcurses* nc); int witherworm_demo(struct notcurses* nc); int box_demo(struct notcurses* nc); int trans_demo(struct notcurses* nc); +int chunli_demo(struct notcurses* nc); int grid_demo(struct notcurses* nc); int sliding_puzzle_demo(struct notcurses* nc); int view_demo(struct notcurses* nc); diff --git a/src/demo/unicodeblocks.c b/src/demo/unicodeblocks.c index 47434e901..107f268be 100644 --- a/src/demo/unicodeblocks.c +++ b/src/demo/unicodeblocks.c @@ -67,7 +67,7 @@ draw_block(struct ncplane* nn, uint32_t blockstart){ }else{ // don't dump non-printing codepoints strcpy(utf8arr, " "); } - ncplane_set_fg_rgb(nn, 0xad + z * 2, 0xd8, 0xe6 - z * 2); + ncplane_set_fg_rgb(nn, 0xad + z * 2, 0xff, 0x2f - z * 2); ncplane_set_bg_rgb(nn, 8 * chunk, 8 * chunk + z, 8 * chunk); if(ncplane_putstr(nn, utf8arr) < 0){ return -1; diff --git a/src/lib/libav.c b/src/lib/libav.c index 84fdbdd11..a3d697fbd 100644 --- a/src/lib/libav.c +++ b/src/lib/libav.c @@ -89,6 +89,7 @@ print_frame_summary(const AVCodecContext* cctx, const AVFrame* f){ AVFrame* ncvisual_decode(ncvisual* nc, int* averr){ bool have_frame = false; bool unref = false; + av_freep(&nc->oframe->data[0]); do{ do{ if(nc->packet_outstanding){ @@ -370,7 +371,6 @@ int ncvisual_render(const ncvisual* ncv, int begy, int begx, int leny, int lenx) } } } - av_freep(&ncv->oframe->data[0]); //av_frame_unref(ncv->oframe); return 0; } @@ -381,7 +381,6 @@ int ncvisual_render(const ncvisual* ncv, int begy, int begx, int leny, int lenx) // up playback. int ncvisual_stream(notcurses* nc, ncvisual* ncv, int* averr, streamcb streamer, void* curry){ - ncplane* n = ncv->ncp; int frame = 1; AVFrame* avf; struct timespec begin; // time we started @@ -396,7 +395,6 @@ int ncvisual_stream(notcurses* nc, ncvisual* ncv, int* averr, if(frame == 1 && ts){ usets = true; } - ncplane_cursor_move_yx(n, 0, 0); if(ncvisual_render(ncv, 0, 0, 0, 0)){ return -1; }