Planereel exploration app, panelreel logic fixes (#188)

* planereels tester #180
* suppress_banner in all tests
* tabletcb: start passing back tablet
* properly initialize fbbytes stat
* panelreel: logic fixes #178
* install all testing data
pull/193/head
Nick Black 5 years ago committed by GitHub
parent b0b1679de6
commit 0e0925a84e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -114,6 +114,26 @@ target_compile_definitions(notcurses-input
FORTIFY_SOURCE=2
)
file(GLOB PLANEREELSRCS CONFIGURE_DEPENDS src/planereel/*.cpp)
add_executable(notcurses-planereel ${PLANEREELSRCS})
target_include_directories(notcurses-planereel
PRIVATE
include
"${PROJECT_BINARY_DIR}/include"
)
target_link_libraries(notcurses-planereel
PRIVATE
notcurses
)
target_compile_options(notcurses-planereel
PRIVATE
-Wall -Wextra -W -Wshadow
)
target_compile_definitions(notcurses-planereel
PRIVATE
FORTIFY_SOURCE=2
)
file(GLOB VIEWSRCS CONFIGURE_DEPENDS src/view/*.cpp)
add_executable(notcurses-view ${VIEWSRCS})
target_include_directories(notcurses-view
@ -192,7 +212,7 @@ install(FILES
DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig
)
file(GLOB TESTDATA CONFIGURE_DEPENDS tests/*.png tests/*.jpg tests/*.mkv)
file(GLOB TESTDATA CONFIGURE_DEPENDS tests/*.png tests/*.jpg tests/*.mkv tests/*.bmp)
install(FILES
${TESTDATA}
DESTINATION ${CMAKE_INSTALL_PREFIX}/share/notcurses
@ -212,6 +232,7 @@ install(FILES
install(TARGETS notcurses-demo DESTINATION bin)
install(TARGETS notcurses-view DESTINATION bin)
install(TARGETS notcurses-input DESTINATION bin)
install(TARGETS notcurses-planereel DESTINATION bin)
install(TARGETS notcurses
LIBRARY
DESTINATION ${CMAKE_INSTALL_LIBDIR}

@ -77,8 +77,8 @@ Why use this non-standard library?
`static inline` header-only code is used. This facilitates compiler
optimizations, and reduces loader time.
* All APIs natively suport UTF-8. The `cell` API is based around Unicode's
[Extended Grapheme Cluster](https://unicode.org/reports/tr29/) concept.
* All APIs natively (and exclusively) support UTF-8. The `cell` API is based
around Unicode's [Extended Grapheme Cluster](https://unicode.org/reports/tr29/) concept.
* Visual features including images, fonts, video, high-contrast text, sprites,
and transparent regions. All APIs natively support 24-bit color, quantized
@ -1389,6 +1389,145 @@ UI discontinuity when the tablets grow to fill the entire screen (or shrink to
not fill it). If it is not desired, however, scrolling of focus can be
configured instead.
```c
// A panelreel is an notcurses region devoted to displaying zero or more
// line-oriented, contained panels between which the user may navigate. If at
// least one panel exists, there is an active panel. As much of the active
// panel as is possible is always displayed. If there is space left over, other
// panels are included in the display. Panels can come and go at any time, and
// can grow or shrink at any time.
//
// This structure is amenable to line- and page-based navigation via keystrokes,
// scrolling gestures, trackballs, scrollwheels, touchpads, and verbal commands.
typedef struct panelreel_options {
// require this many rows and columns (including borders). otherwise, a
// message will be displayed stating that a larger terminal is necessary, and
// input will be queued. if 0, no minimum will be enforced. may not be
// negative. note that panelreel_create() does not return error if given a
// WINDOW smaller than these minima; it instead patiently waits for the
// screen to get bigger.
int min_supported_cols;
int min_supported_rows;
// use no more than this many rows and columns (including borders). may not be
// less than the corresponding minimum. 0 means no maximum.
int max_supported_cols;
int max_supported_rows;
// desired offsets within the surrounding WINDOW (top right bottom left) upon
// creation / resize. a panelreel_move() operation updates these.
int toff, roff, boff, loff;
// is scrolling infinite (can one move down or up forever, or is an end
// reached?). if true, 'circular' specifies how to handle the special case of
// an incompletely-filled reel.
bool infinitescroll;
// is navigation circular (does moving down from the last panel move to the
// first, and vice versa)? only meaningful when infinitescroll is true. if
// infinitescroll is false, this must be false.
bool circular;
// notcurses can draw a border around the panelreel, and also around the
// component tablets. inhibit borders by setting all valid bits in the masks.
// partially inhibit borders by setting individual bits in the masks. the
// appropriate attr and pair values will be used to style the borders.
// focused and non-focused tablets can have different styles. you can instead
// draw your own borders, or forgo borders entirely.
unsigned bordermask; // bitfield; 1s will not be drawn (see bordermaskbits)
uint64_t borderchan; // attributes used for panelreel border
unsigned tabletmask; // bitfield; same as bordermask but for tablet borders
uint64_t tabletchan; // tablet border styling channel
uint64_t focusedchan;// focused tablet border styling channel
uint64_t bgchannel; // background colors
} panelreel_options;
struct tablet;
struct panelreel;
// Create a panelreel according to the provided specifications. Returns NULL on
// failure. w must be a valid WINDOW*, to which offsets are relative. Note that
// there might not be enough room for the specified offsets, in which case the
// panelreel will be clipped on the bottom and right. A minimum number of rows
// and columns can be enforced via popts. efd, if non-negative, is an eventfd
// that ought be written to whenever panelreel_touch() updates a tablet (this
// is useful in the case of nonblocking input).
struct panelreel* panelreel_create(struct ncplane* nc,
const panelreel_options* popts, int efd);
// Returns the ncplane on which this panelreel lives.
struct ncplane* panelreel_plane(struct panelreel* pr);
// Tablet draw callback, provided a tablet (from which the ncplane and userptr
// may be extracted), the first column that may be used, the first row that may
// be used, the first column that may not be used, the first row that may not
// be used, and a bool indicating whether output ought be clipped at the top
// (true) or bottom (false). Rows and columns are zero-indexed, and both are
// relative to the tablet's plane.
//
// Regarding clipping: it is possible that the tablet is only partially
// displayed on the screen. If so, it is either partially present on the top of
// the screen, or partially present at the bottom. In the former case, the top
// is clipped (cliptop will be true), and output ought start from the end. In
// the latter case, cliptop is false, and output ought start from the beginning.
//
// Returns the number of lines of output, which ought be less than or equal to
// maxy - begy, and non-negative (negative values might be used in the future).
typedef int (*tabletcb)(struct tablet* t, int begx, int begy, int maxx,
int maxy, bool cliptop);
// Add a new tablet to the provided panelreel, having the callback object
// opaque. Neither, either, or both of after and before may be specified. If
// neither is specified, the new tablet can be added anywhere on the reel. If
// one or the other is specified, the tablet will be added before or after the
// specified tablet. If both are specifid, the tablet will be added to the
// resulting location, assuming it is valid (after->next == before->prev); if
// it is not valid, or there is any other error, NULL will be returned.
struct tablet* panelreel_add(struct panelreel* pr, struct tablet* after,
struct tablet *before, tabletcb cb, void* opaque);
// Return the number of tablets.
int panelreel_tabletcount(const struct panelreel* pr);
// Indicate that the specified tablet has been updated in a way that would
// change its display. This will trigger some non-negative number of callbacks
// (though not in the caller's context).
int panelreel_touch(struct panelreel* pr, struct tablet* t);
// Delete the tablet specified by t from the panelreel specified by pr. Returns
// -1 if the tablet cannot be found.
int panelreel_del(struct panelreel* pr, struct tablet* t);
// Delete the active tablet. Returns -1 if there are no tablets.
int panelreel_del_focused(struct panelreel* pr);
// Move to the specified location within the containing WINDOW.
int panelreel_move(struct panelreel* pr, int x, int y);
// Redraw the panelreel in its entirety, for instance after
// clearing the screen due to external corruption, or a SIGWINCH.
int panelreel_redraw(struct panelreel* pr);
// Return the focused tablet, if any tablets are present. This is not a copy;
// be careful to use it only for the duration of a critical section.
struct tablet* panelreel_focused(struct panelreel* pr);
// Change focus to the next tablet, if one exists
struct tablet* panelreel_next(struct panelreel* pr);
// Change focus to the previous tablet, if one exists
struct tablet* panelreel_prev(struct panelreel* pr);
// Destroy a panelreel allocated with panelreel_create(). Does not destroy the
// underlying WINDOW. Returns non-zero on failure.
int panelreel_destroy(struct panelreel* pr);
void* tablet_userptr(struct tablet* t);
const void* tablet_userptr_const(const struct tablet* t);
// Access the ncplane associated with this tablet, if one exists.
struct ncplane* tablet_ncplane(struct tablet* t);
const struct ncplane* tablet_ncplane_const(const struct tablet* t);
```
#### Panelreel examples
Let's say we have a screen of 11 lines, and 3 tablets of one line each. Both
@ -1861,6 +2000,7 @@ Four binaries are built as part of notcurses:
* `notcurses-demo`: some demonstration code
* `notcurses-view`: renders visual media (images/videos)
* `notcurses-input`: decode and print keypresses
* `notcurses-planereels`: play around with panelreels
* `notcurses-tester`: unit testing
## Differences from NCURSES

@ -1441,18 +1441,17 @@ typedef struct panelreel_options {
// first, and vice versa)? only meaningful when infinitescroll is true. if
// infinitescroll is false, this must be false.
bool circular;
// outcurses can draw a border around the panelreel, and also around the
// notcurses can draw a border around the panelreel, and also around the
// component tablets. inhibit borders by setting all valid bits in the masks.
// partially inhibit borders by setting individual bits in the masks. the
// appropriate attr and pair values will be used to style the borders.
// focused and non-focused tablets can have different styles. you can instead
// draw your own borders, or forgo borders entirely.
unsigned bordermask; // bitfield; 1s will not be drawn (see bordermaskbits)
cell borderattr; // attributes used for panelreel border
uint64_t borderchan; // attributes used for panelreel border
unsigned tabletmask; // bitfield; same as bordermask but for tablet borders
// FIXME should be attrword + channels, as we don't use gcluster here
cell tabletattr; // attributes used for tablet borders
cell focusedattr; // attributes used for focused tablet borders, no color!
uint64_t tabletchan; // tablet border styling channel
uint64_t focusedchan;// focused tablet border styling channel
uint64_t bgchannel; // background colors
} panelreel_options;
@ -1473,11 +1472,12 @@ API struct panelreel* panelreel_create(struct ncplane* nc,
// Returns the ncplane on which this panelreel lives.
API struct ncplane* panelreel_plane(struct panelreel* pr);
// Tablet draw callback, provided a ncplane the first column that may be used,
// the first row that may be used, the first column that may not be used, the
// first row that may not be used, and a bool indicating whether output ought
// be clipped at the top (true) or bottom (false). Rows and columns are
// zero-indexed, and both are relative to the panel.
// Tablet draw callback, provided a tablet (from which the ncplane and userptr
// may be extracted), the first column that may be used, the first row that may
// be used, the first column that may not be used, the first row that may not
// be used, and a bool indicating whether output ought be clipped at the top
// (true) or bottom (false). Rows and columns are zero-indexed, and both are
// relative to the tablet's plane.
//
// Regarding clipping: it is possible that the tablet is only partially
// displayed on the screen. If so, it is either partially present on the top of
@ -1487,8 +1487,8 @@ API struct ncplane* panelreel_plane(struct panelreel* pr);
//
// Returns the number of lines of output, which ought be less than or equal to
// maxy - begy, and non-negative (negative values might be used in the future).
typedef int (*tabletcb)(struct ncplane* p, int begx, int begy, int maxx,
int maxy, bool cliptop, void* curry);
typedef int (*tabletcb)(struct tablet* t, int begx, int begy, int maxx,
int maxy, bool cliptop);
// Add a new tablet to the provided panelreel, having the callback object
// opaque. Neither, either, or both of after and before may be specified. If
@ -1540,6 +1540,10 @@ API int panelreel_destroy(struct panelreel* pr);
API void* tablet_userptr(struct tablet* t);
API const void* tablet_userptr_const(const struct tablet* t);
// Access the ncplane associated with this tablet, if one exists.
API struct ncplane* tablet_ncplane(struct tablet* t);
API const struct ncplane* tablet_ncplane_const(const struct tablet* t);
#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

@ -14,7 +14,7 @@ static const char DEFAULT_DEMO[] = "iemlubgswvpo";
static char datadir[PATH_MAX] = "/usr/share/notcurses"; // FIXME
char* find_data(const char* datum){
char* path = malloc(strlen(datadir) + 1 + strlen(datum));
char* path = malloc(strlen(datadir) + 1 + strlen(datum) + 1);
strcpy(path, datadir);
strcat(path, "/");
strcat(path, datum);

@ -91,7 +91,9 @@ int outro(struct notcurses* nc){
ncplane_erase(ncp);
ncplane_dim_yx(ncp, &rows, &cols);
int averr = 0;
struct ncvisual* ncv = ncplane_visual_open(ncp, "../tests/changes.jpg", &averr);
char* path = find_data("changes.jpg");
struct ncvisual* ncv = ncplane_visual_open(ncp, path, &averr);
free(path);
if(ncv == NULL){
return -1;
}

@ -118,10 +118,10 @@ tabletdown(struct ncplane* w, int begx, int begy, int maxx, int maxy,
}
static int
tabletdraw(struct ncplane* p, int begx, int begy, int maxx, int maxy,
bool cliptop, void* vtabletctx){
tabletdraw(struct tablet* t, int begx, int begy, int maxx, int maxy, bool cliptop){
int err = 0;
tabletctx* tctx = vtabletctx;
struct ncplane* p = tablet_ncplane(t);
tabletctx* tctx = tablet_userptr(t);
pthread_mutex_lock(&tctx->lock);
unsigned rgb = tctx->rgb;
int ll;
@ -258,20 +258,20 @@ panelreel_demo_core(struct notcurses* nc, int efd, tabletctx** tctxs){
.min_supported_rows = 5,
.bordermask = NCBOXMASK_BOTTOM | NCBOXMASK_TOP |
NCBOXMASK_LEFT | NCBOXMASK_RIGHT,
.borderattr = CELL_TRIVIAL_INITIALIZER,
.tabletattr = CELL_TRIVIAL_INITIALIZER,
.focusedattr = CELL_TRIVIAL_INITIALIZER,
.borderchan = 0,
.tabletchan = 0,
.focusedchan = 0,
.toff = y,
.loff = x,
.roff = x,
.boff = y,
.bgchannel = 0,
};
cell_set_fg_rgb(&popts.focusedattr, 58, 150, 221);
cell_set_bg_rgb(&popts.focusedattr, 97, 214, 214);
cell_set_fg_rgb(&popts.tabletattr, 19, 161, 14);
cell_set_fg_rgb(&popts.borderattr, 136, 23, 152);
cell_set_bg_rgb(&popts.borderattr, 0, 0, 0);
channels_set_fg_rgb(&popts.focusedchan, 58, 150, 221);
channels_set_bg_rgb(&popts.focusedchan, 97, 214, 214);
channels_set_fg_rgb(&popts.tabletchan, 19, 161, 14);
channels_set_fg_rgb(&popts.borderchan, 136, 23, 152);
channels_set_bg_rgb(&popts.borderchan, 0, 0, 0);
if(channels_set_bg_alpha(&popts.bgchannel, CELL_ALPHA_TRANS)){
return NULL;
}

@ -165,7 +165,9 @@ int sliding_puzzle_demo(struct notcurses* nc){
struct ncplane* n = notcurses_stdplane(nc);
ncplane_erase(n);
int averr = 0;
struct ncvisual* ncv = ncplane_visual_open(n, "../tests/changes.jpg", &averr);
char* path = find_data("changes.jpg");
struct ncvisual* ncv = ncplane_visual_open(n, path, &averr);
free(path);
if(ncv == NULL){
return -1;
}

@ -715,6 +715,8 @@ notcurses* notcurses_init(const notcurses_options* opts, FILE* outfp){
free(ret);
return NULL;
}
ret->stats.fbbytes = 0;
ret->stashstats.fbbytes = 0;
reset_stats(&ret->stats);
reset_stats(&ret->stashstats);
ret->ttyfp = outfp;

@ -60,7 +60,7 @@ int wresize(ncplane* n, int leny, int lenx){
// bchrs: 6-element array of wide border characters + attributes FIXME
static int
draw_borders(ncplane* w, unsigned mask, const cell* attr,
draw_borders(ncplane* w, unsigned mask, uint64_t channel,
bool cliphead, bool clipfoot){
int begx, begy, lenx, leny;
int ret = 0;
@ -72,7 +72,7 @@ draw_borders(ncplane* w, unsigned mask, const cell* attr,
cell ul, ur, ll, lr, hl, vl;
cell_init(&ul); cell_init(&ur); cell_init(&hl);
cell_init(&ll); cell_init(&lr); cell_init(&vl);
if(cells_rounded_box(w, attr->attrword, attr->channels, &ul, &ur, &ll, &lr, &hl, &vl)){
if(cells_rounded_box(w, 0, channel, &ul, &ur, &ll, &lr, &hl, &vl)){
return -1;
}
/*fprintf(stderr, "drawing borders %p %d/%d->%d/%d, mask: %04x, clipping: %c%c\n",
@ -153,7 +153,7 @@ draw_panelreel_borders(const panelreel* pr){
if(begy >= maxy || maxy - begy + 1 < pr->popts.min_supported_cols){
return 0; // no room
}
return draw_borders(pr->p, pr->popts.bordermask, &pr->popts.borderattr, false, false);
return draw_borders(pr->p, pr->popts.bordermask, pr->popts.borderchan, false, false);
}
// Calculate the starting and ending coordinates available for occupation by
@ -167,12 +167,12 @@ tablet_columns(const panelreel* pr, int* begx, int* begy, int* lenx, int* leny,
window_coordinates(pr->p, begy, begx, leny, lenx);
int maxy = *leny + *begy - 1;
int begindraw = *begy + !(pr->popts.bordermask & NCBOXMASK_TOP);
// FIXME i think this fails to account for an absent panelreel bottom?
int enddraw = maxy - !(pr->popts.bordermask & NCBOXMASK_TOP);
if(direction){
if(direction <= 0){
if(frontiery < begindraw){
return -1;
}
}else{
if(frontiery > enddraw){
// fprintf(stderr, "FRONTIER: %d ENDDRAW: %d\n", frontiery, enddraw);
return -1;
@ -222,7 +222,7 @@ panelreel_draw_tablet(const panelreel* pr, tablet* t, int frontiery,
int lenx, leny, begy, begx;
ncplane* fp = t->p;
if(tablet_columns(pr, &begx, &begy, &lenx, &leny, frontiery, direction)){
//fprintf(stderr, "no room: %p:%p base %d/%d len %d/%d\n", t, fp, begx, begy, lenx, leny);
//fprintf(stderr, "no room: %p:%p base %d/%d len %d/%d dir %d\n", t, fp, begy, begx, leny, lenx, direction);
//fprintf(stderr, "FRONTIER DONE!!!!!!\n");
if(fp){
//fprintf(stderr, "HIDING %p at frontier %d (dir %d) with %d\n", t, frontiery, direction, leny);
@ -280,7 +280,7 @@ panelreel_draw_tablet(const panelreel* pr, tablet* t, int frontiery,
bool cbdir = direction < 0 ? true : false;
// fprintf(stderr, "calling! lenx/leny: %d/%d cbx/cby: %d/%d cbmaxx/cbmaxy: %d/%d dir: %d\n",
// lenx, leny, cbx, cby, cbmaxx, cbmaxy, direction);
int ll = t->cbfxn(fp, cbx, cby, cbmaxx, cbmaxy, cbdir, t->curry);
int ll = t->cbfxn(t, cbx, cby, cbmaxx, cbmaxy, cbdir);
//fprintf(stderr, "RETURNRETURNRETURN %p %d (%d, %d, %d) DIR %d\n",
// t, ll, cby, cbmaxy, leny, direction);
if(ll != leny){
@ -324,7 +324,7 @@ panelreel_draw_tablet(const panelreel* pr, tablet* t, int frontiery,
}
}
draw_borders(fp, pr->popts.tabletmask,
direction == 0 ? &pr->popts.focusedattr : &pr->popts.tabletattr,
direction == 0 ? pr->popts.focusedchan : pr->popts.tabletchan,
cliphead, clipfoot);
return cliphead || clipfoot;
}
@ -377,17 +377,22 @@ draw_following_tablets(const panelreel* pr, const tablet* otherend){
tablet* working = pr->tablets;
int frontiery;
// move down past the focused tablet, filling up the reel to the bottom
while(working->next != otherend || otherend->p == NULL){
do{
//fprintf(stderr, "following otherend: %p ->p: %p\n", otherend, otherend->p);
// modify frontier based off the one we're at
window_coordinates(working->p, &wbegy, &wbegx, &wleny, &wlenx);
wmaxy = wbegy + wleny - 1;
frontiery = wmaxy + 2;
//fprintf(stderr, "EASTBOUND AND DOWN: %d %d\n", frontiery, wmaxy + 2);
//fprintf(stderr, "EASTBOUND AND DOWN: %p->%p %d %d\n", working, working->next, frontiery, wmaxy + 2);
working = working->next;
panelreel_draw_tablet(pr, working, frontiery, 1);
if(working->p == NULL){ // FIXME might be more to hide
if(working == otherend && otherend->p){
break;
}
}
panelreel_draw_tablet(pr, working, frontiery, 1);
if(working == otherend){
otherend = otherend->next;
}
}while(working->p); // FIXME might be more to hide
// FIXME keep going forward, hiding those no longer visible
return working;
}
@ -396,13 +401,15 @@ draw_following_tablets(const panelreel* pr, const tablet* otherend){
// returns the last tablet drawn.
static tablet*
draw_previous_tablets(const panelreel* pr, const tablet* otherend){
//fprintf(stderr, "preceding otherend: %p ->p: %p\n", otherend, otherend->p);
int wbegy, wbegx, wlenx, wleny; // working tablet window coordinates
tablet* upworking = pr->tablets;
int frontiery;
// modify frontier based off the one we're at
window_coordinates(upworking->p, &wbegy, &wbegx, &wleny, &wlenx);
frontiery = wbegy - 2;
while(upworking->prev != otherend || otherend->p == NULL){
window_coordinates(upworking->p, &wbegy, &wbegx, &wleny, &wlenx);
frontiery = wbegy - 2;
//fprintf(stderr, "MOVIN' ON UP: %d %d\n", frontiery, wbegy - 2);
//fprintf(stderr, "MOVIN' ON UP: %p->%p %d %d\n", upworking, upworking->prev, frontiery, wbegy - 2);
upworking = upworking->prev;
panelreel_draw_tablet(pr, upworking, frontiery, -1);
if(upworking->p){
@ -559,6 +566,14 @@ validate_panelreel_opts(ncplane* w, const panelreel_options* popts){
return true;
}
ncplane* tablet_ncplane(tablet* t){
return t->p;
}
const ncplane* tablet_ncplane_const(const tablet* t){
return t->p;
}
ncplane* panelreel_plane(panelreel* pr){
return pr->p;
}

@ -0,0 +1,75 @@
#include <cstdlib>
#include <clocale>
#include <notcurses.h>
// FIXME ought be able to get pr from tablet, methinks?
static struct panelreel* PR;
int tabletfxn(struct tablet* t, int begx, int begy, int maxx, int maxy,
bool cliptop){
struct ncplane* p = tablet_ncplane(t);
cell c = CELL_SIMPLE_INITIALIZER(' ');
cell_set_bg(&c, (((uintptr_t)t) % 0x1000000) + cliptop + begx + maxx);
ncplane_set_default(p, &c);
cell_release(p, &c);
return 3 > maxy - begy ? maxy - begy : 3;
}
int main(void){
if(setlocale(LC_ALL, "") == nullptr){
return EXIT_FAILURE;
}
struct notcurses_options opts{};
struct notcurses* nc = notcurses_init(&opts, stdout);
if(!nc){
return EXIT_FAILURE;
}
struct ncplane* nstd = notcurses_stdplane(nc);
int dimy, dimx;
ncplane_dim_yx(nstd, &dimy, &dimx);
struct ncplane* n = notcurses_newplane(nc, dimy - 1, dimx, 1, 0, nullptr);
if(!n){
notcurses_stop(nc);
return EXIT_FAILURE;
}
if(ncplane_set_fg(nstd, 0xb11bb1)){
notcurses_stop(nc);
return EXIT_FAILURE;
}
if(ncplane_putstr_aligned(nstd, 0, "(a)dd (q)uit", NCALIGN_CENTER) <= 0){
notcurses_stop(nc);
return EXIT_FAILURE;
}
struct panelreel_options popts{};
channels_set_fg(&popts.focusedchan, 0xffffff);
channels_set_bg(&popts.focusedchan, 0x00c080);
struct panelreel* pr = panelreel_create(n, &popts, -1);
if(!pr || notcurses_render(nc)){
notcurses_stop(nc);
return EXIT_FAILURE;
}
PR = pr; // FIXME eliminate
char32_t key;
while((key = notcurses_getc_blocking(nc)) != (char32_t)-1){
switch(key){
case 'q':
return notcurses_stop(nc) ? EXIT_FAILURE : EXIT_SUCCESS;
case 'a':
panelreel_add(pr, nullptr, nullptr, tabletfxn, nullptr);
break;
case NCKEY_UP:
panelreel_prev(pr);
break;
case NCKEY_DOWN:
panelreel_next(pr);
break;
default:
break;
}
if(notcurses_render(nc)){
break;
}
}
notcurses_stop(nc);
return EXIT_FAILURE;
}

@ -11,6 +11,7 @@ class CellTest : public :: testing::Test {
}
notcurses_options nopts{};
nopts.inhibit_alternate_screen = true;
nopts.suppress_bannner = true;
outfp_ = fopen("/dev/tty", "wb");
ASSERT_NE(nullptr, outfp_);
nc_ = notcurses_init(&nopts, outfp_);

@ -10,6 +10,7 @@ class LibavTest : public :: testing::Test {
}
notcurses_options nopts{};
nopts.inhibit_alternate_screen = true;
nopts.suppress_bannner = true;
outfp_ = fopen("/dev/tty", "wb");
ASSERT_NE(nullptr, outfp_);
nc_ = notcurses_init(&nopts, outfp_);

@ -11,6 +11,7 @@ class NcplaneTest : public :: testing::Test {
}
notcurses_options nopts{};
nopts.inhibit_alternate_screen = true;
nopts.suppress_bannner = true;
outfp_ = fopen("/dev/tty", "wb");
ASSERT_NE(nullptr, outfp_);
nc_ = notcurses_init(&nopts, outfp_);

@ -13,6 +13,7 @@ class NotcursesTest : public :: testing::Test {
}
notcurses_options nopts{};
nopts.inhibit_alternate_screen = true;
nopts.suppress_bannner = true;
outfp_ = fopen("/dev/tty", "wb");
ASSERT_NE(nullptr, outfp_);
nc_ = notcurses_init(&nopts, outfp_);

@ -10,6 +10,7 @@ class PanelReelTest : public :: testing::Test {
}
notcurses_options nopts{};
nopts.inhibit_alternate_screen = true;
nopts.suppress_bannner = true;
outfp_ = fopen("/dev/tty", "wb");
ASSERT_NE(nullptr, outfp_);
nc_ = notcurses_init(&nopts, outfp_);
@ -78,12 +79,11 @@ TEST_F(PanelReelTest, MovementWithoutTablets) {
// EXPECT_EQ(0, panelreel_validate(n_, pr));
}
int panelcb(struct ncplane* p, int begx, int begy, int maxx, int maxy,
bool cliptop, void* curry){
EXPECT_NE(nullptr, p);
int panelcb(struct tablet* t, int begx, int begy, int maxx, int maxy, bool cliptop){
EXPECT_NE(nullptr, tablet_ncplane(t));
EXPECT_LT(begx, maxx);
EXPECT_LT(begy, maxy);
EXPECT_EQ(nullptr, curry);
EXPECT_EQ(nullptr, tablet_userptr(t));
EXPECT_FALSE(cliptop);
// FIXME verify geometry is as expected
return 0;

@ -11,6 +11,7 @@ class ZAxisTest : public :: testing::Test {
}
notcurses_options nopts{};
nopts.inhibit_alternate_screen = true;
nopts.suppress_bannner = true;
outfp_ = fopen("/dev/tty", "wb");
ASSERT_NE(nullptr, outfp_);
nc_ = notcurses_init(&nopts, outfp_);

Loading…
Cancel
Save