mirror of
https://github.com/dankamongmen/notcurses
synced 2025-03-09 17:19:03 -04:00
ncplane_putegc_yx() copies directly as opposed to going through putc() #797
This commit is contained in:
parent
0767aaec01
commit
97571e86af
15
USAGE.md
15
USAGE.md
@ -1626,6 +1626,21 @@ void cell_release(struct ncplane* n, cell* c);
|
||||
#define NCSTYLE_PROTECT 0x00010000ul
|
||||
#define NCSTYLE_ITALIC 0x01000000ul
|
||||
|
||||
// copy the UTF8-encoded EGC out of the cell, whether simple or complex. the
|
||||
// result is not tied to the ncplane, and persists across erases / destruction.
|
||||
static inline char*
|
||||
cell_strdup(const struct ncplane* n, const cell* c){
|
||||
char* ret;
|
||||
if(cell_simple_p(c)){
|
||||
if( (ret = (char*)malloc(2)) ){ // cast is here for C++ clients
|
||||
ret[0] = c->gcluster;
|
||||
ret[1] = '\0';
|
||||
}
|
||||
}else{
|
||||
ret = strdup(cell_extended_gcluster(n, c));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Set the specified style bits for the cell 'c', whether they're actively
|
||||
// supported or not.
|
||||
|
@ -729,7 +729,8 @@ cell_simple_p(const cell* c){
|
||||
// is invalidated by any further operation on the plane 'n', so...watch out!
|
||||
API const char* cell_extended_gcluster(const struct ncplane* n, const cell* c);
|
||||
|
||||
// Extract the EGC from 'c' as a nul-terminated string.
|
||||
// copy the UTF8-encoded EGC out of the cell, whether simple or complex. the
|
||||
// result is not tied to the ncplane, and persists across erases / destruction.
|
||||
static inline char*
|
||||
cell_strdup(const struct ncplane* n, const cell* c){
|
||||
char* ret;
|
||||
|
@ -410,13 +410,6 @@ pool_egc_copy(const egcpool* e, const cell* c){
|
||||
return ret;
|
||||
}
|
||||
|
||||
// copy the UTF8-encoded EGC out of the cell, whether simple or complex. the
|
||||
// result is not tied to the ncplane, and persists across erases / destruction.
|
||||
static inline char*
|
||||
cell_egc_copy(const ncplane* n, const cell* c){
|
||||
return pool_egc_copy(&n->pool, c);
|
||||
}
|
||||
|
||||
// For our first attempt, O(1) uniform conversion from 8-bit r/g/b down to
|
||||
// ~2.4-bit 6x6x6 cube + greyscale (assumed on entry; I know no way to
|
||||
// even semi-portably recover the palette) proceeds via: map each 8-bit to
|
||||
|
@ -1284,17 +1284,66 @@ int ncplane_putc_yx(ncplane* n, int y, int x, const cell* c){
|
||||
}
|
||||
|
||||
int ncplane_putegc_yx(ncplane* n, int y, int x, const char* gclust, int* sbytes){
|
||||
cell c = CELL_TRIVIAL_INITIALIZER;
|
||||
int primed = cell_prime(n, &c, gclust, n->attrword, n->channels);
|
||||
int cols;
|
||||
int bytes = utf8_egc_len(gclust, &cols);
|
||||
if(sbytes){
|
||||
*sbytes = primed;
|
||||
*sbytes = bytes;
|
||||
}
|
||||
if(primed < 0){
|
||||
// if scrolling is enabled, check *before ncplane_cursor_move_yx()* whether
|
||||
// we're past the end of the line, and move to the next line if so.
|
||||
bool wide = cols > 1;
|
||||
if(x == -1 && y == -1 && n->x + wide >= n->lenx){
|
||||
if(!n->scrolling){
|
||||
return -1;
|
||||
}
|
||||
scroll_down(n);
|
||||
}
|
||||
if(ncplane_cursor_move_yx(n, y, x)){
|
||||
return -1;
|
||||
}
|
||||
int ret = ncplane_putc_yx(n, y, x, &c);
|
||||
cell_release(n, &c);
|
||||
return ret;
|
||||
if(*gclust == '\n'){
|
||||
if(n->scrolling){
|
||||
scroll_down(n);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
// A wide character obliterates anything to its immediate right (and marks
|
||||
// that cell as wide). Any character placed atop one half of a wide character
|
||||
// obliterates the other half. Note that a wide char can thus obliterate two
|
||||
// wide chars, totalling four columns.
|
||||
cell* targ = ncplane_cell_ref_yx(n, n->y, n->x);
|
||||
if(n->x > 0){
|
||||
if(cell_double_wide_p(targ)){ // replaced cell is half of a wide char
|
||||
if(targ->gcluster == 0){ // we're the right half
|
||||
cell_obliterate(n, &n->fb[nfbcellidx(n, n->y, n->x - 1)]);
|
||||
}else{
|
||||
cell_obliterate(n, &n->fb[nfbcellidx(n, n->y, n->x + 1)]);
|
||||
}
|
||||
}
|
||||
}
|
||||
uint64_t channels = n->channels & ~CELL_WIDEASIAN_MASK;
|
||||
if(wide){
|
||||
channels |= CELL_WIDEASIAN_MASK;
|
||||
}
|
||||
if(cell_prime(n, targ, gclust, n->attrword, channels) < 0){
|
||||
return -1;
|
||||
}
|
||||
if(wide){ // must set our right wide, and check for further damage
|
||||
if(n->x < n->lenx - 1){ // check to our right
|
||||
cell* candidate = &n->fb[nfbcellidx(n, n->y, n->x + 1)];
|
||||
if(n->x < n->lenx - 2){
|
||||
if(cell_wide_left_p(candidate)){
|
||||
cell_obliterate(n, &n->fb[nfbcellidx(n, n->y, n->x + 2)]);
|
||||
}
|
||||
}
|
||||
cell_obliterate(n, candidate);
|
||||
cell_set_wide(candidate);
|
||||
candidate->channels = channels;
|
||||
candidate->attrword = n->attrword;
|
||||
}
|
||||
}
|
||||
n->x += cols;
|
||||
return cols;
|
||||
}
|
||||
|
||||
int ncplane_putsimple_stainable(ncplane* n, char c){
|
||||
@ -1867,7 +1916,7 @@ void ncplane_erase(ncplane* n){
|
||||
// we must preserve the background, but a pure cell_duplicate() would be
|
||||
// wiped out by the egcpool_dump(). do a duplication (to get the attrword
|
||||
// and channels), and then reload.
|
||||
char* egc = cell_egc_copy(n, &n->basecell);
|
||||
char* egc = cell_strdup(n, &n->basecell);
|
||||
memset(n->fb, 0, sizeof(*n->fb) * n->lenx * n->leny);
|
||||
egcpool_dump(&n->pool);
|
||||
egcpool_init(&n->pool);
|
||||
|
@ -284,7 +284,7 @@ TEST_CASE("Wide") {
|
||||
|
||||
// should be wide char 1
|
||||
REQUIRE(3 == ncplane_at_yx_cell(n_, 0, 0, &c));
|
||||
egc = cell_egc_copy(n_, &c);
|
||||
egc = cell_strdup(n_, &c);
|
||||
REQUIRE(egc);
|
||||
CHECK(!strcmp("\xe5\x85\xa8", egc));
|
||||
CHECK(cell_double_wide_p(&c));
|
||||
@ -297,7 +297,7 @@ TEST_CASE("Wide") {
|
||||
cell_init(&c);
|
||||
// should be wide char 1 right side
|
||||
REQUIRE(0 == ncplane_at_yx_cell(n_, 0, 1, &c));
|
||||
egc = cell_egc_copy(n_, &c);
|
||||
egc = cell_strdup(n_, &c);
|
||||
REQUIRE(egc);
|
||||
CHECK(!strcmp("", egc));
|
||||
CHECK(cell_double_wide_p(&c));
|
||||
@ -311,7 +311,7 @@ TEST_CASE("Wide") {
|
||||
|
||||
// should be wide char 2
|
||||
REQUIRE(3 == ncplane_at_yx_cell(n_, 0, 2, &c));
|
||||
egc = cell_egc_copy(n_, &c);
|
||||
egc = cell_strdup(n_, &c);
|
||||
REQUIRE(egc);
|
||||
CHECK(!strcmp("\xe5\xbd\xa2", egc));
|
||||
CHECK(cell_double_wide_p(&c));
|
||||
@ -324,7 +324,7 @@ TEST_CASE("Wide") {
|
||||
cell_init(&c);
|
||||
// should be wide char 2 right side
|
||||
CHECK(0 == ncplane_at_yx_cell(n_, 0, 3, &c));
|
||||
egc = cell_egc_copy(n_, &c);
|
||||
egc = cell_strdup(n_, &c);
|
||||
REQUIRE(egc);
|
||||
CHECK(!strcmp("", egc));
|
||||
CHECK(cell_double_wide_p(&c));
|
||||
|
Loading…
x
Reference in New Issue
Block a user