retain stdscr across a resize #28

pull/44/head
nick black 5 years ago
parent fb07becc16
commit 6b877f89a9
No known key found for this signature in database
GPG Key ID: 5F43400C21CBFACC

@ -92,13 +92,12 @@ int notcurses_render(struct notcurses* nc);
// Refresh our idea of the terminal's dimensions, reshaping the standard plane // Refresh our idea of the terminal's dimensions, reshaping the standard plane
// if necessary. Without a call to this function following a terminal resize // if necessary. Without a call to this function following a terminal resize
// (as signaled via SIGWINCH), notcurses_render() might not function properly. // (as signaled via SIGWINCH), notcurses_render() might not function properly.
// Following a call to notcurses_resize(), any references to the standard plane // References to ncplanes remain valid following a resize operation, but the
// ought be considered invalidated. // cursor might have changed position.
int notcurses_resize(struct notcurses* n); int notcurses_resize(struct notcurses* n);
// Get a reference to the standard plane (one matching our current idea of the // Get a reference to the standard plane (one matching our current idea of the
// terminal size) for this terminal. Invalidated following a call to // terminal size) for this terminal.
// notcurses_resize().
struct ncplane* notcurses_stdplane(struct notcurses* nc); struct ncplane* notcurses_stdplane(struct notcurses* nc);
const struct ncplane* notcurses_stdplane_const(const struct notcurses* nc); const struct ncplane* notcurses_stdplane_const(const struct notcurses* nc);

@ -42,7 +42,6 @@ typedef struct ncplane {
int absx, absy; // origin of the plane relative to the screen int absx, absy; // origin of the plane relative to the screen
int lenx, leny; // size of the plane, [0..len{x,y}) is addressable int lenx, leny; // size of the plane, [0..len{x,y}) is addressable
struct ncplane* z; // plane below us struct ncplane* z; // plane below us
struct notcurses* nc; // our parent nc, kinda lame waste of memory FIXME
egcpool pool; // attached storage pool for UTF-8 EGCs egcpool pool; // attached storage pool for UTF-8 EGCs
uint64_t channels; // works the same way as cells uint64_t channels; // works the same way as cells
uint32_t attrword; // same deal as in a cell uint32_t attrword; // same deal as in a cell
@ -122,7 +121,8 @@ void ncplane_dimyx(const ncplane* n, int* rows, int* cols){
} }
} }
// This should really only be called from within alloc_stdscr() // anyone calling this needs ensure the ncplane's framebuffer is updated
// to reflect changes in geometry.
static int static int
update_term_dimensions(notcurses* n, int* rows, int* cols){ update_term_dimensions(notcurses* n, int* rows, int* cols){
struct winsize ws; struct winsize ws;
@ -177,67 +177,49 @@ term_emit(const char* seq){
return 0; return 0;
} }
// Create an ncplane of the specified dimensions, but does not place it in // create an ncplane of the specified dimensions, but do not yet place it in
// the z-buffer. // the z-buffer. clear out all cells. this is for a wholly new context.
static ncplane* static ncplane*
create_ncplane(notcurses* nc, int rows, int cols){ create_initial_ncplane(notcurses* nc){
ncplane* p = NULL; int rows, cols;
if((p = malloc(sizeof(*p))) == NULL){ if(update_term_dimensions(nc, &rows, &cols)){
return NULL; return NULL;
} }
ncplane* p = malloc(sizeof(*p));
size_t fbsize = sizeof(*p->fb) * (rows * cols); size_t fbsize = sizeof(*p->fb) * (rows * cols);
if((p->fb = malloc(fbsize)) == NULL){ if((p->fb = malloc(fbsize)) == NULL){
free(p); free(p);
return NULL; return NULL;
} }
memset(p->fb, 0, fbsize);
p->leny = rows; p->leny = rows;
p->lenx = cols; p->lenx = cols;
p->nc = nc;
p->x = p->y = 0; p->x = p->y = 0;
p->absx = p->absy = 0; p->absx = p->absy = 0;
// framebuffer is initialized by calling function, might be copy p->attrword = 0;
p->channels = 0;
egcpool_init(&p->pool);
return p; return p;
} }
// Call this on initialization, or when the screen size changes. Takes a flat // Call this when the screen size changes. Takes a flat
// array of *rows * *cols cells (may be NULL if *rows == *cols == 0). Gets the // array of *rows * *cols cells (may be NULL if *rows == *cols == 0). Gets the
// new size, and copies what can be copied from the old stdscr. Assumes that // new size, and copies what can be copied from the old stdscr. Assumes that
// the screen is always anchored in the same place. // the screen is always anchored in the same place.
static ncplane* int notcurses_resize(notcurses* n){
alloc_stdscr(notcurses* nc){ int oldrows = n->stdscr->leny;
ncplane* p = NULL; int oldcols = n->stdscr->lenx;
int oldrows = 0;
int oldcols = 0;
if(nc->stdscr){
oldrows = nc->stdscr->leny;
oldcols = nc->stdscr->lenx;
}
int rows, cols; int rows, cols;
if(update_term_dimensions(nc, &rows, &cols)){ if(update_term_dimensions(n, &rows, &cols)){
goto err; return -1;
}
if((p = create_ncplane(nc, rows, cols)) == NULL){
goto err;
}
egcpool_init(&p->pool);
p->attrword = 0;
p->channels = 0;
ncplane** oldscr;
ncplane* preserve;
// if we ever make this a doubly-linked list, turn this into o(1)
// if nc->stdscr is NULL, we're all good -- there are no entries
for(oldscr = &nc->top ; *oldscr ; oldscr = &(*oldscr)->z){
if(*oldscr == nc->stdscr){
break;
}
} }
if( (preserve = *oldscr) ){ ncplane* p = n->stdscr;
p->z = preserve->z; cell* preserved = p->fb;
}else{ size_t fbsize = sizeof(*preserved) * (rows * cols);
p->z = NULL; if((p->fb = malloc(fbsize)) == NULL){
p->fb = preserved;
return -1;
} }
*oldscr = p;
nc->stdscr = p;
int y, idx; int y, idx;
idx = 0; idx = 0;
for(y = 0 ; y < p->leny ; ++y){ for(y = 0 ; y < p->leny ; ++y){
@ -251,24 +233,13 @@ alloc_stdscr(notcurses* nc){
if(oldcopy > p->lenx){ if(oldcopy > p->lenx){
oldcopy = p->lenx; oldcopy = p->lenx;
} }
memcpy(&p->fb[idx], &preserve->fb[y * oldcols], oldcopy * sizeof(*p->fb)); memcpy(&p->fb[idx], &preserved[y * oldcols], oldcopy * sizeof(*p->fb));
} }
if(p->lenx - oldcopy){ if(p->lenx - oldcopy){
memset(&p->fb[idx + oldcopy], 0, sizeof(*p->fb) * (p->lenx - oldcopy)); memset(&p->fb[idx + oldcopy], 0, sizeof(*p->fb) * (p->lenx - oldcopy));
} }
} }
free_plane(preserve); free(preserved);
return p;
err:
free_plane(p);
return NULL;
}
int notcurses_resize(notcurses* n){
if(alloc_stdscr(n) == NULL){
return -1;
}
return 0; return 0;
} }
@ -395,7 +366,7 @@ notcurses* notcurses_init(const notcurses_options* opts){
if(interrogate_terminfo(ret, opts)){ if(interrogate_terminfo(ret, opts)){
goto err; goto err;
} }
if(alloc_stdscr(ret) == NULL){ if((ret->top = create_initial_ncplane(ret)) == NULL){
goto err; goto err;
} }
ret->stdscr = ret->top; ret->stdscr = ret->top;

Loading…
Cancel
Save