ncplane_reparent: extract from z-axis #1078

This commit is contained in:
nick black 2020-11-24 02:38:51 -05:00 committed by Nick Black
parent 43ddfd11c6
commit a6101d4fa2
3 changed files with 61 additions and 20 deletions

View File

@ -10,8 +10,8 @@ ncpile_debug(const ncpile* p, FILE* debugfp){
fprintf(debugfp, "%04d off y: %3d x: %3d geom y: %3d x: %3d curs y: %3d x: %3d %p %.8s\n",
planeidx, n->absy, n->absx, n->leny, n->lenx, n->y, n->x, n, n->name);
if(n->boundto || n->bnext || n->bprev || n->blist){
fprintf(debugfp, " bound %p → %p ← %p binds %p\n",
n->boundto, n->bnext, n->bprev, n->blist);
fprintf(debugfp, " bound %p ← %p → %p binds %p\n",
n->boundto, n->bprev, n->bnext, n->blist);
}
if(n->bprev && (*n->bprev != n)){
fprintf(stderr, " WARNING: expected *->bprev %p, got %p\n", n, *n->bprev);
@ -37,7 +37,11 @@ void notcurses_debug(notcurses* nc, FILE* debugfp){
const ncpile* p0 = p;
do{
ncpile_debug(p0, debugfp);
const ncpile* prev = p0;
p0 = p0->next;
if(p0->prev != prev){
fprintf(stderr, "WARNING: expected ->prev %p, got %p\n", prev, p0->prev);
}
}while(p != p0);
fprintf(debugfp, " ******************************************************************************\n");
}

View File

@ -1148,6 +1148,7 @@ err:
// updates *pile to point at (*pile)->next, frees all but standard pile/plane
static void
ncpile_drop(notcurses* nc, ncpile** pile){
ncpile* next = (*pile)->next;
ncplane* p = (*pile)->top;
while(p){
ncplane* tmp = p->below;
@ -1156,11 +1157,7 @@ ncpile_drop(notcurses* nc, ncpile** pile){
}
p = tmp;
}
ncpile* tmp = (*pile)->next;
if(*pile != ncplane_pile(nc->stdplane)){
ncpile_destroy(*pile);
}
*pile = tmp;
*pile = next;
}
// drop all piles and all planes, save the standard plane and its pile
@ -1980,10 +1977,16 @@ int ncplane_move_yx(ncplane* n, int y, int x){
}
int ncplane_y(const ncplane* n){
if(n->boundto == n){
return n->absy - ncplane_notcurses_const(n)->margin_t;
}
return n->absy - n->boundto->absy;
}
int ncplane_x(const ncplane* n){
if(n->boundto == n){
return n->absx - ncplane_notcurses_const(n)->margin_t;
}
return n->absx - n->boundto->absx;
}
@ -2174,9 +2177,8 @@ int ncplane_resize_realign(ncplane* n){
}
// The standard plane cannot be reparented; we return NULL in that case.
// If provided a NULL |newparent|, we are moving |n| to its own stack. If |n|
// is already root of its own stack in this case, we return NULL. If |n| is
// already bound to |newparent|, this is a no-op, and we return |n|.
// If provided |newparent|==|n|, we are moving |n| to its own stack. If |n|
// is already bound to |newparent|, this is a no-op, and we return |n|.
ncplane* ncplane_reparent(ncplane* n, ncplane* newparent){
if(n == ncplane_notcurses(n)->stdplane){
return NULL; // can't reparent standard plane
@ -2208,30 +2210,59 @@ ncplane* ncplane_reparent_family(ncplane* n, ncplane* newparent){
if(n->boundto == newparent){ // no-op
return n;
}
// are we the sole member of our current pile? if so, destroy it.
if(n->boundto == n && n->blist == NULL && n->bprev == NULL){
pthread_mutex_lock(&ncplane_notcurses(n)->pilelock);
ncpile_destroy(ncplane_pile(n));
pthread_mutex_unlock(&ncplane_notcurses(n)->pilelock);
// if we are not a root plane, adjust our origin
if(n->boundto != n){
n->absx -= n->boundto->absx;
n->absy -= n->boundto->absy;
}
if(n->bprev){ // extract from sibling list
if( (*n->bprev = n->bnext) ){
n->bnext->bprev = n->bprev;
}
}
// if leaving a pile, extract n from the old zaxis
if(n == newparent || ncplane_pile(n) != ncplane_pile(newparent)){
// FIXME need remove full family from z-axis, not just n!
if(ncplane_pile(n)->top == n){
ncplane_pile(n)->top = n->below;
}else{
n->above->below = n->below;
}
if(ncplane_pile(n)->bottom == n){
ncplane_pile(n)->bottom = n->above;
}else{
n->below->above = n->above;
}
}
n->boundto = newparent;
if(n == n->boundto){ // we're a new root plane
n->bnext = NULL;
n->bprev = NULL;
pthread_mutex_lock(&ncplane_notcurses(n)->pilelock);
if(ncplane_pile(n)->top == NULL){ // did we just empty our pile?
ncpile_destroy(ncplane_pile(n));
}
make_ncpile(ncplane_notcurses(n), n);
pthread_mutex_unlock(&ncplane_notcurses(n)->pilelock);
}else{ // establish ourselves as a sibling of new parent's children
n->absx += n->boundto->absx;
n->absy += n->boundto->absy;
if( (n->bnext = newparent->blist) ){
n->bnext->bprev = &n->bnext;
}
n->bprev = &newparent->blist;
newparent->blist = n;
// place it immediately above the new binding plane if crossing piles
if(n->pile != ncplane_pile(n->boundto)){
n->pile = ncplane_pile(n->boundto);
if((n->above = n->boundto->above) == NULL){
n->pile->top = n;
}else{
n->boundto->above->below = n;
}
n->below = n->boundto;
n->boundto->above = n;
}
}
return n;
}

View File

@ -551,6 +551,7 @@ TEST_CASE("NCPlane") {
CHECK(0 == testcell.gcluster);
CHECK(0 == testcell.stylemask);
CHECK(0 == testcell.channels);
cell_release(n_, &testcell);
int dimy, dimx;
ncplane_dim_yx(n_, &dimy, &dimx);
REQUIRE(0 == ncplane_cursor_move_yx(n_, 1, dimx - strlen(STR2)));
@ -588,6 +589,7 @@ TEST_CASE("NCPlane") {
CHECK(0 == testcell.gcluster);
CHECK(0 == testcell.stylemask);
CHECK(0 == testcell.channels);
cell_release(n_, &testcell);
int dimy, dimx;
ncplane_dim_yx(n_, &dimy, &dimx);
REQUIRE(0 == ncplane_cursor_move_yx(n_, 1, dimx - mbstowcs(nullptr, STR2, 0)));
@ -897,11 +899,14 @@ TEST_CASE("NCPlane") {
.x = 1,
.rows = 2,
.cols = 2,
nullptr, nullptr, nullptr, 0,
nullptr, "ndom", nullptr, 0,
};
struct ncplane* ndom = ncplane_create(n_, &nopts);
CHECK(ncplane_pile(ndom) == ncplane_pile(n_));
REQUIRE(ndom);
nopts.name = "sub";
struct ncplane* nsub = ncplane_create(ndom, &nopts);
CHECK(ncplane_pile(nsub) == ncplane_pile(ndom));
REQUIRE(nsub);
int absy, absx;
CHECK(0 == notcurses_render(nc_));
@ -909,13 +914,14 @@ TEST_CASE("NCPlane") {
CHECK(1 == absy); // actually at 2, 2
CHECK(1 == absx);
ncplane_reparent(nsub, nsub);
CHECK(ncplane_pile(nsub) != ncplane_pile(ndom));
ncplane_yx(nsub, &absy, &absx);
CHECK(2 == absy); // now we recognize 2, 2
CHECK(2 == absx);
CHECK(1 == absy); // now truly at 1, 1
CHECK(1 == absx);
CHECK(0 == ncplane_move_yx(ndom, 0, 0));
ncplane_yx(nsub, &absy, &absx);
CHECK(2 == absy); // still at 2, 2
CHECK(2 == absx);
CHECK(1 == absy); // still at 1, 1
CHECK(1 == absx);
}
SUBCASE("NoReparentStdPlane") {