Merge branch 'master' of github.com:dankamongmen/notcurses

This commit is contained in:
nick black 2021-10-05 03:41:08 -04:00
commit 4fa88efafe
No known key found for this signature in database
GPG Key ID: 5F43400C21CBFACC
5 changed files with 37 additions and 15 deletions

View File

@ -154,7 +154,7 @@ not itself perform any locking.
* It is **not** safe to add, delete, or reorder ncplanes within a single pile * It is **not** safe to add, delete, or reorder ncplanes within a single pile
from multiple threads. from multiple threads.
Only one thread may call **notcurses_getc** or any other input-related thread Only one thread may call **notcurses_get(3)** or any other input-related thread
at a time, but it **is** safe to call for input while another thread renders. at a time, but it **is** safe to call for input while another thread renders.
Since multiple threads can concurrently manipulate distinct ncplanes, peak Since multiple threads can concurrently manipulate distinct ncplanes, peak

View File

@ -396,9 +396,17 @@ When a plane is moved to a different pile (whether new or preexisting), any
planes which were bound to it are rebound to its previous parent. If the plane planes which were bound to it are rebound to its previous parent. If the plane
was a root plane of some pile, any bound planes become root planes. The new was a root plane of some pile, any bound planes become root planes. The new
plane is placed immediately atop its new parent on its new pile's z-axis. plane is placed immediately atop its new parent on its new pile's z-axis.
When `ncplane_reparent_family()` is used, all planes bound to the reparented When **ncplane_reparent_family** is used, all planes bound to the reparented
plane are moved along with it. Their relative z-order is maintained. plane are moved along with it. Their relative z-order is maintained.
## Binding
The planes of a pile make up a directed acyclic forest. Planes bound to
themselves make up the root planes of the pile. Every plane is either a
root plane, or bound to some other plane in its pile. A plane and its
descendants make up a family. When a plane is moved using **ncplane_move_yx**,
its family is moved along with it.
## Scrolling ## Scrolling
All planes, including the standard plane, are created with scrolling disabled. All planes, including the standard plane, are created with scrolling disabled.
@ -503,7 +511,7 @@ It should not be used in new code.
# BUGS # BUGS
**ncplane_at_yx** doesn't yet account for bitmap-based graphics (see **ncplane_at_yx** doesn't yet account for bitmap-based graphics (see
**notcurses_visual**). Whatever glyph-based contents existed on the plane when **notcurses_visual(3)**). Whatever glyph-based contents existed on the plane when
the bitmap was blitted will continue to be returned. the bitmap was blitted will continue to be returned.
When the alternate screen is not used (see **notcurses_init(3)**), the contents When the alternate screen is not used (see **notcurses_init(3)**), the contents

View File

@ -1244,11 +1244,13 @@ typedef struct ncplane_options {
// must both be positive. This plane is initially at the top of the z-buffer, // must both be positive. This plane is initially at the top of the z-buffer,
// as if ncplane_move_top() had been called on it. The void* 'userptr' can be // as if ncplane_move_top() had been called on it. The void* 'userptr' can be
// retrieved (and reset) later. A 'name' can be set, used in debugging. // retrieved (and reset) later. A 'name' can be set, used in debugging.
API ALLOC struct ncplane* ncplane_create(struct ncplane* n, const ncplane_options* nopts); API ALLOC struct ncplane* ncplane_create(struct ncplane* n, const ncplane_options* nopts)
__attribute__ ((nonnull (1, 2)));
// Same as ncplane_create(), but creates a new pile. The returned plane will // Same as ncplane_create(), but creates a new pile. The returned plane will
// be the top, bottom, and root of this new pile. // be the top, bottom, and root of this new pile.
API ALLOC struct ncplane* ncpile_create(struct notcurses* nc, const ncplane_options* nopts); API ALLOC struct ncplane* ncpile_create(struct notcurses* nc, const ncplane_options* nopts)
__attribute__ ((nonnull (1, 2)));
// Suitable for use as a 'resizecb', this will resize the plane to the visual // Suitable for use as a 'resizecb', this will resize the plane to the visual
// region's size. It is used for the standard plane. // region's size. It is used for the standard plane.
@ -1296,7 +1298,8 @@ API struct ncplane* ncplane_reparent_family(struct ncplane* n, struct ncplane* n
// Duplicate an existing ncplane. The new plane will have the same geometry, // Duplicate an existing ncplane. The new plane will have the same geometry,
// will duplicate all content, and will start with the same rendering state. // will duplicate all content, and will start with the same rendering state.
// The new plane will be immediately above the old one on the z axis, and will // The new plane will be immediately above the old one on the z axis, and will
// be bound to the same parent. Bound planes are *not* duplicated; the new // be bound to the same parent (unless 'n' is a root plane, in which case the
// new plane will be bound to it). Bound planes are *not* duplicated; the new
// plane is bound to the parent of 'n', but has no bound planes. // plane is bound to the parent of 'n', but has no bound planes.
API ALLOC struct ncplane* ncplane_dup(const struct ncplane* n, void* opaque) API ALLOC struct ncplane* ncplane_dup(const struct ncplane* n, void* opaque)
__attribute__ ((nonnull (1))); __attribute__ ((nonnull (1)));

View File

@ -197,7 +197,6 @@ link_kleene(automaton* a, esctrie* e, unsigned follow){
e->trie[follow] = esctrie_idx(a, term); e->trie[follow] = esctrie_idx(a, term);
}else if(e->trie[i] == 0){ }else if(e->trie[i] == 0){
e->trie[i] = esctrie_idx(a, targ); e->trie[i] = esctrie_idx(a, targ);
// FIXME travel to the ends and link targ there
} }
} }
targ->kleene = esctrie_idx(a, targ); targ->kleene = esctrie_idx(a, targ);

View File

@ -428,7 +428,7 @@ make_ncpile(notcurses* nc, ncplane* n){
// (as once more is n). // (as once more is n).
ncplane* ncplane_new_internal(notcurses* nc, ncplane* n, ncplane* ncplane_new_internal(notcurses* nc, ncplane* n,
const ncplane_options* nopts){ const ncplane_options* nopts){
if(nopts->flags >= (NCPLANE_OPTION_MARGINALIZED << 1u)){ if(nopts->flags >= (NCPLANE_OPTION_FIXED << 1u)){
logwarn("Provided unsupported flags %016jx\n", (uintmax_t)nopts->flags); logwarn("Provided unsupported flags %016jx\n", (uintmax_t)nopts->flags);
} }
if(nopts->flags & NCPLANE_OPTION_HORALIGNED || nopts->flags & NCPLANE_OPTION_VERALIGNED){ if(nopts->flags & NCPLANE_OPTION_HORALIGNED || nopts->flags & NCPLANE_OPTION_VERALIGNED){
@ -863,13 +863,16 @@ int ncplane_destroy(ncplane* ncp){
if( (*ncp->bprev = ncp->bnext) ){ if( (*ncp->bprev = ncp->bnext) ){
ncp->bnext->bprev = ncp->bprev; ncp->bnext->bprev = ncp->bprev;
} }
}else if(ncp->bnext){
ncp->bnext->bprev = NULL;
} }
// recursively reparent our children to the plane to which we are bound. // recursively reparent our children to the plane to which we are bound.
// this will extract each one from the sibling list. // this will extract each one from the sibling list.
struct ncplane* bound = ncp->blist; struct ncplane* bound = ncp->blist;
while(bound){ while(bound){
struct ncplane* tmp = bound->bnext; struct ncplane* tmp = bound->bnext;
if(ncplane_reparent_family(bound, ncp->boundto) == NULL){ ncplane* bindto = ((ncp == ncp->boundto) ? bound : ncp->boundto);
if(ncplane_reparent_family(bound, bindto) == NULL){
ret = -1; ret = -1;
} }
bound = tmp; bound = tmp;
@ -2568,19 +2571,21 @@ ncplane* ncplane_reparent(ncplane* n, ncplane* newparent){
// to be called before unbinding 'n' from old pile. // to be called before unbinding 'n' from old pile.
static void static void
unsplice_zaxis_recursive(ncplane* n){ unsplice_zaxis_recursive(ncplane* n){
// might already have been unspliced, in which case ->above/->below are NULL
if(ncplane_pile(n)->top == n){ if(ncplane_pile(n)->top == n){
ncplane_pile(n)->top = n->below; ncplane_pile(n)->top = n->below;
}else{ }else if(n->above){
n->above->below = n->below; n->above->below = n->below;
} }
if(ncplane_pile(n)->bottom == n){ if(ncplane_pile(n)->bottom == n){
ncplane_pile(n)->bottom = n->above; ncplane_pile(n)->bottom = n->above;
}else{ }else if(n->below){
n->below->above = n->above; n->below->above = n->above;
} }
for(ncplane* child = n->blist ; child ; child = child->bnext){ for(ncplane* child = n->blist ; child ; child = child->bnext){
unsplice_zaxis_recursive(child); unsplice_zaxis_recursive(child);
} }
n->below = n->above = NULL;
} }
// unsplice our sprixel from the pile's sprixellist, and then unsplice all // unsplice our sprixel from the pile's sprixellist, and then unsplice all
@ -2616,7 +2621,8 @@ unsplice_sprixels_recursive(ncplane* n, sprixel* prev){
// recursively splice 'n' and children into the z-axis, above 'n->boundto'. // recursively splice 'n' and children into the z-axis, above 'n->boundto'.
// handles 'n' == 'n->boundto'. to be called after binding 'n' into new pile. // handles 'n' == 'n->boundto'. to be called after binding 'n' into new pile.
static void static void
splice_zaxis_recursive(ncplane* n){ splice_zaxis_recursive(ncplane* n, ncpile* p){
n->pile = p;
if(n != n->boundto){ if(n != n->boundto){
if((n->above = n->boundto->above) == NULL){ if((n->above = n->boundto->above) == NULL){
n->pile->top = n; n->pile->top = n;
@ -2627,7 +2633,7 @@ splice_zaxis_recursive(ncplane* n){
n->boundto->above = n; n->boundto->above = n;
} }
for(ncplane* child = n->blist ; child ; child = child->bnext){ for(ncplane* child = n->blist ; child ; child = child->bnext){
splice_zaxis_recursive(child); splice_zaxis_recursive(child, p);
} }
} }
@ -2646,7 +2652,11 @@ ncplane* ncplane_reparent_family(ncplane* n, ncplane* newparent){
if( (*n->bprev = n->bnext) ){ if( (*n->bprev = n->bnext) ){
n->bnext->bprev = n->bprev; n->bnext->bprev = n->bprev;
} }
}else if(n->bnext){
n->bnext->bprev = NULL;
} }
n->bprev = NULL;
n->bnext = NULL;
// ncplane_notcurses() goes through ncplane_pile(). since we're possibly // ncplane_notcurses() goes through ncplane_pile(). since we're possibly
// destroying piles below, get the notcurses reference early on. // destroying piles below, get the notcurses reference early on.
notcurses* nc = ncplane_notcurses(n); notcurses* nc = ncplane_notcurses(n);
@ -2658,15 +2668,17 @@ ncplane* ncplane_reparent_family(ncplane* n, ncplane* newparent){
} }
n->boundto = newparent; n->boundto = newparent;
if(n == n->boundto){ // we're a new root plane if(n == n->boundto){ // we're a new root plane
logdebug("reparenting new root plane %p\n", n);
unsplice_zaxis_recursive(n);
n->bnext = NULL; n->bnext = NULL;
n->bprev = NULL; n->bprev = NULL;
splice_zaxis_recursive(n);
pthread_mutex_lock(&nc->pilelock); pthread_mutex_lock(&nc->pilelock);
if(ncplane_pile(n)->top == NULL){ // did we just empty our pile? if(ncplane_pile(n)->top == NULL){ // did we just empty our pile?
ncpile_destroy(ncplane_pile(n)); ncpile_destroy(ncplane_pile(n));
} }
make_ncpile(ncplane_notcurses(n), n); make_ncpile(ncplane_notcurses(n), n);
pthread_mutex_unlock(&nc->pilelock); pthread_mutex_unlock(&nc->pilelock);
splice_zaxis_recursive(n, ncplane_pile(n));
}else{ // establish ourselves as a sibling of new parent's children }else{ // establish ourselves as a sibling of new parent's children
if( (n->bnext = newparent->blist) ){ if( (n->bnext = newparent->blist) ){
n->bnext->bprev = &n->bnext; n->bnext->bprev = &n->bnext;
@ -2675,13 +2687,13 @@ ncplane* ncplane_reparent_family(ncplane* n, ncplane* newparent){
newparent->blist = n; newparent->blist = n;
// place it immediately above the new binding plane if crossing piles // place it immediately above the new binding plane if crossing piles
if(n->pile != ncplane_pile(n->boundto)){ if(n->pile != ncplane_pile(n->boundto)){
splice_zaxis_recursive(n);
pthread_mutex_lock(&nc->pilelock); pthread_mutex_lock(&nc->pilelock);
if(ncplane_pile(n)->top == NULL){ // did we just empty our pile? if(ncplane_pile(n)->top == NULL){ // did we just empty our pile?
ncpile_destroy(ncplane_pile(n)); ncpile_destroy(ncplane_pile(n));
} }
n->pile = ncplane_pile(n->boundto); n->pile = ncplane_pile(n->boundto);
pthread_mutex_unlock(&nc->pilelock); pthread_mutex_unlock(&nc->pilelock);
splice_zaxis_recursive(n, ncplane_pile(n));
} }
} }
if(s){ // must be on new plane, with sprixels to donate if(s){ // must be on new plane, with sprixels to donate