Fill out some API holes, improve some comments

- Disambiguate the docs for ncplane_erase()
- Add ncpile_top(), ncpile_bottom()
- Refuse attempts to modify the standard plane's resizecb
- Copy alignment and resizecb in ncplane_dup()
- Add cell_load_egc32()
This commit is contained in:
nick black 2020-12-03 00:25:29 -05:00 committed by Nick Black
parent 38bdc627a4
commit 6fb5c1e512
6 changed files with 75 additions and 10 deletions

View File

@ -1,6 +1,13 @@
This document attempts to list user-visible changes and any major internal
rearrangements of Notcurses.
* 2.0.10 (not yet released)
* `ncpile_top()` and `ncpile_bottom()` have been added, returning the top
or bottommost plane, respectively, of the pile containing their argument.
* Added `cell_load_egc32()`, allowing a cell to be released and then reloaded
with a UTF-8 EGC of up to 4 bytes, passed as a `uint32_t` (as opposed to a
`const char *`).
* 2.0.9 (2020-12-01)
* `ncmenu`s now automatically expand or shrink to match their binding plane.

View File

@ -884,6 +884,12 @@ struct ncplane* ncplane_below(struct ncplane* n);
// Return the ncplane above this one, or NULL if this is at the stack's top.
struct ncplane* ncplane_above(struct ncplane* n);
// Return the topmost plane of the pile containing 'n'.
struct ncplane* ncpile_top(struct ncplane* n);
// Return the bottommost plane of the pile containing 'n'.
struct ncplane* ncpile_bottom(struct ncplane* n);
```
Each plane holds a user pointer which can be retrieved and set (or ignored). In
@ -1747,6 +1753,7 @@ cell_double_wide_p(const cell* c){
return (c->channels & CELL_WIDEASIAN_MASK);
}
// Load a 7-bit char 'ch' into the cell 'c'.
static inline int
cell_load_char(struct ncplane* n, cell* c, char ch){
cell_release(n, c);
@ -1755,6 +1762,15 @@ cell_load_char(struct ncplane* n, cell* c, char ch){
return 1;
}
// Load a UTF-8 encoded EGC of up to 4 bytes into the cell 'c'.
static inline int
cell_load_egc32(struct ncplane* n, cell* c, uint32_t egc){
cell_release(n, c);
c->channels &= ~(CELL_WIDEASIAN_MASK | CELL_NOBACKGROUND_MASK);
c->gcluster = htole(egc);
return 1;
}
// return a pointer to the NUL-terminated EGC referenced by 'c'. this pointer
// is invalidated by any further operation on the plane 'n', so...watch out!
const char* cell_extended_gcluster(const struct ncplane* n, const cell* c);

View File

@ -76,6 +76,8 @@ typedef struct cell {
**int cell_load_char(struct ncplane* ***n***, cell* ***c***, char ***ch***);**
**int cell_load_egc32(struct ncplane* ***n***, cell* ***c***, uint32_t ***egc***);**
**char* cell_extract(const struct ncplane* ***n***, const cell* ***c***, uint16_t* ***stylemask***, uint64_t* ***channels***);**
**uint32_t cell_bchannel(const cell* ***c***);**

View File

@ -33,6 +33,10 @@ typedef struct ncplane_options {
**struct ncplane* notcurses_bottom(struct notcurses* ***n***);**
**struct ncplane* ncpile_top(struct ncplane* ***n***);**
**struct ncplane* ncpile_bottom(struct ncplane* ***n***);**
**struct ncplane* ncplane_reparent(struct ncplane* ***n***, struct ncplane* ***newparent***);**
**struct ncplane* ncplane_reparent_family(struct ncplane* ***n***, struct ncplane* ***newparent***);**
@ -238,7 +242,7 @@ of the rendering region. Only those cells where **src** intersects with **dst**
might see changes. It is an error to merge a plane onto itself.
**ncplane_erase** zeroes out every cell of the plane, dumps the egcpool, and
homes the cursor. The base cell is preserved.
homes the cursor. The base cell is preserved, as are the active attributes.
When a plane is resized (whether by **ncplane_resize**, **SIGWINCH**, or any
other mechanism), a depth-first recursion is performed on its children.
@ -304,6 +308,10 @@ plane is the bottommost plane, NULL is returned. It cannot fail.
**ncplane_set_scrolling** returns **true** if scrolling was previously enabled,
and **false** otherwise.
**ncpile_top** and **ncpile_bottom** return the topmost and bottommost planes,
respectively, of the pile containing their argument. **notcurses_top** and
**notcurses_bottom** do the same for the standard pile.
**ncplane_at_yx** and **ncplane_at_cursor** return a heap-allocated copy of the
EGC at the relevant cell, or NULL if the cell is invalid. The caller should free
this result. **ncplane_at_yx_cell** and **ncplane_at_cursor_cell** instead load

View File

@ -730,11 +730,23 @@ cellcmp(const struct ncplane* n1, const cell* RESTRICT c1,
static inline int
cell_load_char(struct ncplane* n, cell* c, char ch){
cell_release(n, c);
// FIXME don't allow non-printing garbage
c->channels &= ~(CELL_WIDEASIAN_MASK | CELL_NOBACKGROUND_MASK);
c->gcluster = htole((uint32_t)ch);
return 1;
}
// Load a UTF-8 encoded EGC of up to 4 bytes into the cell 'c'.
static inline int
cell_load_egc32(struct ncplane* n, cell* c, uint32_t egc){
cell_release(n, c);
// FIXME don't allow non-printing garbage, nor invalid forms
// FIXME this might well be a wide egc, augh
c->channels &= ~(CELL_WIDEASIAN_MASK | CELL_NOBACKGROUND_MASK);
c->gcluster = htole(egc);
return 1;
}
// These log levels consciously map cleanly to those of libav; Notcurses itself
// does not use this full granularity. The log level does not affect the opening
// and closing banners, which can be disabled via the notcurses_option struct's
@ -844,6 +856,12 @@ API struct notcurses* notcurses_init(const notcurses_options* opts, FILE* fp);
// Destroy a Notcurses context.
API int notcurses_stop(struct notcurses* nc);
// Return the topmost plane of the pile containing 'n'.
API struct ncplane* ncpile_top(struct ncplane* n);
// Return the bottommost plane of the pile containing 'n'.
API struct ncplane* ncpile_bottom(struct ncplane* n);
// Renders the pile of which 'n' is a part. Rendering this pile again will blow
// away the render. To actually write out the render, call ncpile_rasterize().
API int ncpile_render(struct ncplane* n);
@ -1068,6 +1086,7 @@ API struct ncplane* ncplane_new(struct ncplane* n, int rows, int cols, int y, in
API int ncplane_resize_realign(struct ncplane* n);
// Replace the ncplane's existing resizecb with 'resizecb' (which may be NULL).
// The standard plane's resizecb may not be changed.
API void ncplane_set_resizecb(struct ncplane* n, int(*resizecb)(struct ncplane*));
// Returns the ncplane's current resize callback.
@ -1088,7 +1107,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,
// 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
// be bound to the same parent.
// be bound to the same parent. Bound planes are *not* duplicated; the new
// plane is bound to the parent of 'n', but has no bound planes.
API struct ncplane* ncplane_dup(const struct ncplane* n, void* opaque);
// provided a coordinate relative to the origin of 'src', map it to the same
@ -1812,10 +1832,10 @@ API int ncplane_mergedown(const struct ncplane* RESTRICT src,
int begsrcy, int begsrcx, int leny, int lenx,
int dsty, int dstx);
// Erase every cell in the ncplane, resetting all attributes to normal, all
// colors to the default color, and all cells to undrawn. All cells associated
// with this ncplane is invalidated, and must not be used after the call,
// *excluding* the base cell. The cursor is homed.
// Erase every cell in the ncplane (each cell is initialized to the null glyph
// and the default channels/styles). All cells associated with this ncplane are
// invalidated, and must not be used after the call, *excluding* the base cell.
// The cursor is homed. The plane's active attributes are unaffected.
API void ncplane_erase(struct ncplane* n);
// Extract the 32-bit background channel from a cell.

View File

@ -502,8 +502,6 @@ inline int ncplane_cursor_move_yx(ncplane* n, int y, int x){
ncplane* ncplane_dup(const ncplane* n, void* opaque){
int dimy = n->leny;
int dimx = n->lenx;
uint16_t attr = ncplane_styles(n);
uint64_t chan = ncplane_channels(n);
// if we're duping the standard plane, we need adjust for marginalia
const struct notcurses* nc = ncplane_notcurses_const(n);
const int placey = n->absy - nc->margin_t;
@ -515,6 +513,8 @@ ncplane* ncplane_dup(const ncplane* n, void* opaque){
.cols = dimx,
.userptr = opaque,
.name = n->name,
.resizecb = ncplane_resizecb(n),
.flags = 0,
};
ncplane* newn = ncplane_create(n->boundto, &nopts);
if(newn){
@ -526,8 +526,9 @@ ncplane* ncplane_dup(const ncplane* n, void* opaque){
ncplane_destroy(newn);
return NULL;
}
newn->stylemask = attr;
newn->channels = chan;
newn->align = n->align;
newn->stylemask = ncplane_styles(n);
newn->channels = ncplane_channels(n);
memmove(newn->fb, n->fb, sizeof(*n->fb) * dimx * dimy);
// we dupd the egcpool, so just dup the goffset
newn->basecell = n->basecell;
@ -2036,6 +2037,14 @@ ncplane* notcurses_bottom(notcurses* n){
return ncplane_pile(n->stdplane)->bottom;
}
ncplane* ncpile_top(ncplane* n){
return ncplane_pile(n)->top;
}
ncplane* ncpile_bottom(ncplane* n){
return ncplane_pile(n)->bottom;
}
ncplane* ncplane_below(ncplane* n){
return n->below;
}
@ -2168,6 +2177,9 @@ const ncplane* ncplane_parent_const(const ncplane* n){
}
void ncplane_set_resizecb(ncplane* n, int(*resizecb)(ncplane*)){
if(n == notcurses_stdplane(ncplane_notcurses(n))){
return;
}
n->resizecb = resizecb;
}