mirror of
https://github.com/dankamongmen/notcurses.git
synced 2024-11-16 00:13:00 +00:00
egcpool: copy in nonspacing characters of an EGC #32
This commit is contained in:
parent
6f92ae92ab
commit
9744ca0d4c
@ -1,6 +1,7 @@
|
|||||||
#ifndef NOTCURSES_EGCPOOL
|
#ifndef NOTCURSES_EGCPOOL
|
||||||
#define NOTCURSES_EGCPOOL
|
#define NOTCURSES_EGCPOOL
|
||||||
|
|
||||||
|
#include <wchar.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@ -29,15 +30,36 @@ egcpool_init(egcpool* p){
|
|||||||
|
|
||||||
int egcpool_grow(egcpool* pool, size_t len);
|
int egcpool_grow(egcpool* pool, size_t len);
|
||||||
|
|
||||||
// FIXME needs to loop on wcwidth() == 0
|
// Eat an EGC from the UTF-8 string input. This consists of extracting a
|
||||||
|
// multibyte via mbtowc, then continuing to extract any which have zero
|
||||||
|
// width until hitting another spacing character or a NUL terminator. Writes
|
||||||
|
// the number of columns occupied to '*colcount'. Returns the number of bytes
|
||||||
|
// consumed, not including any NUL terminator. Note that neither the number
|
||||||
|
// of bytes nor columns is necessarily equivalent to the number of decoded code
|
||||||
|
// points. Such are the ways of Unicode.
|
||||||
static inline size_t
|
static inline size_t
|
||||||
utf8_gce_len(const char* gcluster){
|
utf8_gce_len(const char* gcluster, int* colcount){
|
||||||
|
size_t ret = 0;
|
||||||
|
*colcount = 0;
|
||||||
wchar_t wc;
|
wchar_t wc;
|
||||||
int r = mbtowc(&wc, gcluster, MB_CUR_MAX);
|
int r;
|
||||||
if(r <= 0){
|
do{
|
||||||
return 0; // will cascade into error in egcpool_stash()
|
r = mbtowc(&wc, gcluster, MB_CUR_MAX);
|
||||||
}
|
if(r < 0){
|
||||||
return r;
|
return -1;
|
||||||
|
}else if(r){
|
||||||
|
int cols = wcwidth(wc);
|
||||||
|
if(cols){
|
||||||
|
if(*colcount){ // this must be starting a new EGC, exit and do not claim
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
*colcount += cols;
|
||||||
|
}
|
||||||
|
ret += r;
|
||||||
|
gcluster += r;
|
||||||
|
}
|
||||||
|
}while(r);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if we're inserting a EGC of |len| bytes, ought we proactively realloc?
|
// if we're inserting a EGC of |len| bytes, ought we proactively realloc?
|
||||||
@ -57,10 +79,11 @@ egcpool_alloc_justified(const egcpool* pool, size_t len){
|
|||||||
// stash away the provided UTF8, NUL-terminated grapheme cluster. the cluster
|
// stash away the provided UTF8, NUL-terminated grapheme cluster. the cluster
|
||||||
// should not be less than 2 bytes (such a cluster should be directly stored in
|
// should not be less than 2 bytes (such a cluster should be directly stored in
|
||||||
// the cell). returns -1 on error, and otherwise a non-negative 24-bit offset.
|
// the cell). returns -1 on error, and otherwise a non-negative 24-bit offset.
|
||||||
// The number of bytes copied is stored to |*ulen|.
|
// The number of bytes copied is stored to '*ulen'. The number of presentation
|
||||||
|
// columns is stored to '*cols'.
|
||||||
static inline int
|
static inline int
|
||||||
egcpool_stash(egcpool* pool, const char* egc, size_t* ulen){
|
egcpool_stash(egcpool* pool, const char* egc, size_t* ulen, int* cols){
|
||||||
size_t len = utf8_gce_len(egc) + 1; // count the NUL terminator
|
size_t len = utf8_gce_len(egc, cols) + 1; // count the NUL terminator
|
||||||
if(len <= 2){ // should never be empty, nor a single byte + NUL
|
if(len <= 2){ // should never be empty, nor a single byte + NUL
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -602,15 +602,19 @@ term_putc(const notcurses* nc, const ncplane* n, const cell* c){
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
advance_cursor(ncplane* n){
|
advance_cursor(ncplane* n, int cols){
|
||||||
if(n->y == n->leny){
|
if(n->y == n->leny){
|
||||||
if(n->x == n->lenx){
|
if(n->x == n->lenx){
|
||||||
return; // stuck!
|
return; // stuck!
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(++n->x == n->lenx){
|
if((n->x += cols) >= n->lenx){
|
||||||
n->x = 0;
|
if(n->y == n->leny){
|
||||||
++n->y;
|
n->x = n->lenx;
|
||||||
|
}else{
|
||||||
|
n->x -= n->lenx;
|
||||||
|
++n->y;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -683,7 +687,9 @@ cell_duplicate(ncplane* n, cell* targ, const cell* c){
|
|||||||
return !!c->gcluster;
|
return !!c->gcluster;
|
||||||
}
|
}
|
||||||
size_t ulen;
|
size_t ulen;
|
||||||
int eoffset = egcpool_stash(&n->pool, extended_gcluster(n, c), &ulen);
|
int cols;
|
||||||
|
// FIXME insert colcount into cell...
|
||||||
|
int eoffset = egcpool_stash(&n->pool, extended_gcluster(n, c), &ulen, &cols);
|
||||||
if(eoffset < 0){
|
if(eoffset < 0){
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -697,7 +703,7 @@ int ncplane_putc(ncplane* n, const cell* c){
|
|||||||
}
|
}
|
||||||
cell* targ = &n->fb[fbcellidx(n, n->y, n->x)];
|
cell* targ = &n->fb[fbcellidx(n, n->y, n->x)];
|
||||||
int ret = cell_duplicate(n, targ, c);
|
int ret = cell_duplicate(n, targ, c);
|
||||||
advance_cursor(n);
|
advance_cursor(n, 1); // FIXME
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -732,7 +738,8 @@ int cell_load(ncplane* n, cell* c, const char* gcluster){
|
|||||||
return !!c->gcluster;
|
return !!c->gcluster;
|
||||||
}
|
}
|
||||||
size_t ulen;
|
size_t ulen;
|
||||||
int eoffset = egcpool_stash(&n->pool, gcluster, &ulen);
|
int cols;
|
||||||
|
int eoffset = egcpool_stash(&n->pool, gcluster, &ulen, &cols);
|
||||||
if(eoffset < 0){
|
if(eoffset < 0){
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user