add ncplane_descendant_p(), unit test it #1192

This commit is contained in:
nick black 2020-12-09 00:18:47 -05:00
parent ec7bfea22d
commit a3220b8a73
No known key found for this signature in database
GPG Key ID: 5F43400C21CBFACC
5 changed files with 33 additions and 7 deletions

View File

@ -1,6 +1,9 @@
This document attempts to list user-visible changes and any major internal
rearrangements of Notcurses.
* 2.0.11 (not yet released)
* Added `ncplane_descendant_p()` predicate.
* 2.0.10 (2020-12-06)
* `ncpile_top()` and `ncpile_bottom()` have been added, returning the top
or bottommost plane, respectively, of the pile containing their argument.

View File

@ -41,6 +41,8 @@ typedef struct ncplane_options {
**struct ncplane* ncplane_reparent_family(struct ncplane* ***n***, struct ncplane* ***newparent***);**
**int ncplane_descendant_p(const struct ncplane* ***n***, const struct ncplane* ***ancestor***);**
**int ncplane_resize_realign(struct ncplane* ***n***);**
**void ncplane_set_resizecb(struct ncplane* ***n***, int(*resizecb)(struct ncplane*));**

View File

@ -1114,7 +1114,8 @@ API int (*ncplane_resizecb(const struct ncplane* n))(struct ncplane*);
API struct ncplane* ncplane_reparent(struct ncplane* n, struct ncplane* newparent);
// The same as ncplane_reparent(), except any planes bound to 'n' come along
// with it to its new destination. Their z-order is maintained.
// with it to its new destination. Their z-order is maintained. If 'newparent'
// is an ancestor of 'n', NULL is returned, and no changes are made.
API struct ncplane* ncplane_reparent_family(struct ncplane* n, struct ncplane* newparent);
// Duplicate an existing ncplane. The new plane will have the same geometry,
@ -1277,6 +1278,17 @@ API int ncplane_x(const struct ncplane* n);
API struct ncplane* ncplane_parent(struct ncplane* n);
API const struct ncplane* ncplane_parent_const(const struct ncplane* n);
// Return non-zero iff 'n' is a proper descendent of 'ancestor'.
static inline int
ncplane_descendant_p(const struct ncplane* n, const struct ncplane* ancestor){
for(const struct ncplane* parent = ncplane_parent_const(n) ; parent != ancestor ; parent = ncplane_parent_const(parent)){
if(ncplane_parent_const(parent) == parent){ // reached a root plane
return 0;
}
}
return 1;
}
// Splice ncplane 'n' out of the z-buffer, and reinsert it at the top or bottom.
API void ncplane_move_top(struct ncplane* n);
API void ncplane_move_bottom(struct ncplane* n);

View File

@ -2282,6 +2282,9 @@ ncplane* ncplane_reparent_family(ncplane* n, ncplane* newparent){
if(n == ncplane_notcurses(n)->stdplane){
return NULL; // can't reparent standard plane
}
if(ncplane_descendant_p(newparent, n)){
return NULL;
}
if(n->boundto == newparent){ // no-op
return n;
}

View File

@ -148,12 +148,18 @@ TEST_CASE("Piles") {
CHECK(&n3->bnext == n2->bprev);
CHECK(n2 == *n2->bprev);
CHECK(nullptr == n2->bnext);
// we now have n1 -> { n3, n2 }
// rotate n1's family under n2: n2 -> n1 -> n3
CHECK(nullptr != ncplane_reparent_family(n1, n2));
// FIXME CHECK(n2 == ncplane_parent_const(n2));
CHECK(n2 == ncplane_parent_const(n1));
CHECK(n1 == ncplane_parent_const(n3));
nopts.name = "new4";
auto n4 = ncplane_create(n2, &nopts);
REQUIRE(nullptr != n4);
CHECK(n2 == ncplane_parent_const(n4));
// we now have n1 -> { n3, n2 } -> n4
// n1 to any ought be refused
CHECK(nullptr == ncplane_reparent_family(n1, n2));
CHECK(nullptr == ncplane_reparent_family(n1, n3));
CHECK(nullptr == ncplane_reparent_family(n1, n4));
// n2 to n4 ought be refused
CHECK(nullptr == ncplane_reparent_family(n2, n4));
ncplane_destroy(n4);
ncplane_destroy(n3);
ncplane_destroy(n2);
ncplane_destroy(n1);