[ncstrwidth] yield to ncstrwidth_valid

pull/2388/head
nick black 3 years ago
parent 02f00b01e7
commit 0b4232d07d
No known key found for this signature in database
GPG Key ID: 5F43400C21CBFACC

@ -100,14 +100,7 @@ typedef enum {
// and the number of valid bytes and columns will be written into *|validbytes| // and the number of valid bytes and columns will be written into *|validbytes|
// and *|validwidth| (assuming them non-NULL). If the entire string is valid, // and *|validwidth| (assuming them non-NULL). If the entire string is valid,
// *|validbytes| and *|validwidth| reflect the entire string. // *|validbytes| and *|validwidth| reflect the entire string.
API int ncstrwidth_valid(const char* egcs, int* validbytes, int* validwidth); API int ncstrwidth(const char* egcs, int* validbytes, int* validwidth);
// Returns the number of columns occupied by a multibyte (UTF-8) string, or
// -1 if a non-printable/illegal character is encountered.
static inline int
ncstrwidth(const char* mbs){
return ncstrwidth_valid(mbs, NULL, NULL);
}
// Returns a heap-allocated copy of the user name under which we are running. // Returns a heap-allocated copy of the user name under which we are running.
API ALLOC char* notcurses_accountname(void); API ALLOC char* notcurses_accountname(void);
@ -2058,7 +2051,7 @@ static inline int
ncplane_putstr_aligned(struct ncplane* n, int y, ncalign_e align, const char* s){ ncplane_putstr_aligned(struct ncplane* n, int y, ncalign_e align, const char* s){
int validbytes, validwidth; int validbytes, validwidth;
// we'll want to do the partial write if there's an error somewhere within // we'll want to do the partial write if there's an error somewhere within
ncstrwidth_valid(s, &validbytes, &validwidth); ncstrwidth(s, &validbytes, &validwidth);
int xpos = ncplane_halign(n, align, validwidth); int xpos = ncplane_halign(n, align, validwidth);
if(xpos < 0){ if(xpos < 0){
return -1; return -1;
@ -3544,7 +3537,8 @@ API const char* ncnmetric(uintmax_t val, size_t s, uintmax_t decimal,
#define NCBPREFIXSTRLEN (NCBPREFIXCOLUMNS + 1) // Does not include a '\0' (xxxx.xxUi), i == prefix #define NCBPREFIXSTRLEN (NCBPREFIXCOLUMNS + 1) // Does not include a '\0' (xxxx.xxUi), i == prefix
// Used as arguments to a variable field width (i.e. "%*s" -- these are the *). // Used as arguments to a variable field width (i.e. "%*s" -- these are the *).
// We need this convoluted grotesquery to properly handle 'µ'. // We need this convoluted grotesquery to properly handle 'µ'.
#define NCMETRICFWIDTH(x, cols) ((int)(strlen(x) - ncstrwidth(x) + (cols))) #define NCMETRICFWIDTH(x, cols) \
((int)(strlen(x) - ncstrwidth(x, NULL, NULL) + (cols)))
#define NCPREFIXFMT(x) NCMETRICFWIDTH((x), NCPREFIXCOLUMNS), (x) #define NCPREFIXFMT(x) NCMETRICFWIDTH((x), NCPREFIXCOLUMNS), (x)
#define NCIPREFIXFMT(x) NCMETRIXFWIDTH((x), NCIPREFIXCOLUMNS), (x) #define NCIPREFIXFMT(x) NCMETRIXFWIDTH((x), NCIPREFIXCOLUMNS), (x)
#define NCBPREFIXFMT(x) NCMETRICFWIDTH((x), NCBPREFIXCOLUMNS), (x) #define NCBPREFIXFMT(x) NCMETRICFWIDTH((x), NCBPREFIXCOLUMNS), (x)

@ -199,7 +199,7 @@ animate(struct notcurses* nc, struct ncprogbar* left, struct ncprogbar* right){
int endx = -1; int endx = -1;
int totallength = 0; int totallength = 0;
for(const char** c = cycles ; *c ; ++c){ for(const char** c = cycles ; *c ; ++c){
totallength += ncstrwidth(*c); totallength += ncstrwidth(*c, NULL, NULL);
} }
int totalmoves = determine_totalmoves(std, ncprogbar_plane(left), ncprogbar_plane(right), int totalmoves = determine_totalmoves(std, ncprogbar_plane(left), ncprogbar_plane(right),
heady, headx, endy, endx, totallength); heady, headx, endy, endx, totallength);

@ -394,11 +394,11 @@ hud_print_finished(elem* list){
} }
char buf[NCPREFIXCOLUMNS + 2]; char buf[NCPREFIXCOLUMNS + 2];
ncnmetric(e->totalns, sizeof(buf), NANOSECS_IN_SEC, buf, 0, 1000, '\0'); ncnmetric(e->totalns, sizeof(buf), NANOSECS_IN_SEC, buf, 0, 1000, '\0');
for(int x = 6 ; x < 14 - ncstrwidth(buf) ; ++x){ for(int x = 6 ; x < 14 - ncstrwidth(buf, NULL, NULL) ; ++x){
nccell ci = CELL_TRIVIAL_INITIALIZER; nccell ci = CELL_TRIVIAL_INITIALIZER;
ncplane_putc_yx(hud, 1, x, &ci); ncplane_putc_yx(hud, 1, x, &ci);
} }
if(ncplane_printf_yx(hud, line, 14 - ncstrwidth(buf), "%ss", buf) < 0){ if(ncplane_printf_yx(hud, line, 14 - ncstrwidth(buf, NULL, NULL), "%ss", buf) < 0){
return -1; return -1;
} }
if(ncplane_putstr_yx(hud, line, 16, e->name) < 0){ if(ncplane_putstr_yx(hud, line, 16, e->name) < 0){
@ -614,12 +614,12 @@ int demo_render(struct notcurses* nc){
} }
char buf[NCPREFIXCOLUMNS + 2]; char buf[NCPREFIXCOLUMNS + 2];
ncnmetric(ns, sizeof(buf), NANOSECS_IN_SEC, buf, 0, 1000, '\0'); ncnmetric(ns, sizeof(buf), NANOSECS_IN_SEC, buf, 0, 1000, '\0');
for(int x = 6 ; x < 14 - ncstrwidth(buf) ; ++x){ for(int x = 6 ; x < 14 - ncstrwidth(buf, NULL, NULL) ; ++x){
nccell ci = CELL_TRIVIAL_INITIALIZER; nccell ci = CELL_TRIVIAL_INITIALIZER;
ncplane_putc_yx(hud, 1, x, &ci); ncplane_putc_yx(hud, 1, x, &ci);
} }
//fprintf(stderr, "[%s] %zu %d\n", buf, strlen(buf), ncstrwidth(buf)); //fprintf(stderr, "[%s] %zu %d\n", buf, strlen(buf), ncstrwidth(buf, NULL, NULL));
if(ncplane_printf_yx(hud, 1, 14 - ncstrwidth(buf), "%ss", buf) < 0){ if(ncplane_printf_yx(hud, 1, 14 - ncstrwidth(buf, NULL, NULL), "%ss", buf) < 0){
return -1; return -1;
} }
if(ncplane_putstr_yx(hud, 1, 16, elems->name) < 0){ if(ncplane_putstr_yx(hud, 1, 16, elems->name) < 0){

@ -651,7 +651,7 @@ neologo_present(struct notcurses* nc, const char* nlogo){
if(nl){ // chomp any newline if(nl){ // chomp any newline
lines[linecount - 1][linelen] = '\0'; lines[linecount - 1][linelen] = '\0';
} }
size_t collen = ncstrwidth(lines[linecount - 1]); size_t collen = ncstrwidth(lines[linecount - 1], NULL, NULL);
if(collen > maxlinelen){ if(collen > maxlinelen){
maxlinelen = collen; maxlinelen = collen;
} }

@ -797,7 +797,11 @@ int ncdirect_vprintf_aligned(ncdirect* n, int y, ncalign_e align, const char* fm
if(r == NULL){ if(r == NULL){
return -1; return -1;
} }
const size_t len = ncstrwidth(r); const int len = ncstrwidth(r, NULL, NULL);
if(len < 0){
free(r);
return -1;
}
const int x = ncdirect_align(n, align, len); const int x = ncdirect_align(n, align, len);
if(ncdirect_cursor_move_yx(n, y, x)){ if(ncdirect_cursor_move_yx(n, y, x)){
free(r); free(r);

@ -48,6 +48,11 @@ typedef HANDLE ipipe;
// local state for the input thread. don't put this large struct on the stack. // local state for the input thread. don't put this large struct on the stack.
typedef struct inputctx { typedef struct inputctx {
// these two are not ringbuffers; we always move any leftover materia to the
// front of the queue (it ought be a handful of bytes at most).
unsigned char tbuf[BUFSIZ]; // only used if we have distinct terminal fd
unsigned char ibuf[BUFSIZ]; // might be intermingled bulk/control data
int stdinfd; // bulk in fd. always >= 0 (almost always 0). we do not int stdinfd; // bulk in fd. always >= 0 (almost always 0). we do not
// own this descriptor, and must not close() it. // own this descriptor, and must not close() it.
int termfd; // terminal fd: -1 with no controlling terminal, or int termfd; // terminal fd: -1 with no controlling terminal, or
@ -60,11 +65,6 @@ typedef struct inputctx {
int rmargin, bmargin; // margins in use at right and bottom int rmargin, bmargin; // margins in use at right and bottom
automaton amata; automaton amata;
// these two are not ringbuffers; we always move any leftover materia to the
// front of the queue (it ought be a handful of bytes at most).
unsigned char ibuf[BUFSIZ]; // might be intermingled bulk/control data
unsigned char tbuf[BUFSIZ]; // only used if we have distinct terminal fd
int ibufvalid; // we mustn't read() if ibufvalid == sizeof(ibuf) int ibufvalid; // we mustn't read() if ibufvalid == sizeof(ibuf)
int tbufvalid; // only used if we have distinct terminal connection int tbufvalid; // only used if we have distinct terminal connection
@ -447,6 +447,8 @@ mark_pipe_ready(ipipe pipes[static 2]){
if(!WriteFile(pipes[1], &sig, sizeof(sig), &wrote, NULL) || wrote != sizeof(sig)){ if(!WriteFile(pipes[1], &sig, sizeof(sig), &wrote, NULL) || wrote != sizeof(sig)){
logwarn("error writing to pipe\n"); logwarn("error writing to pipe\n");
#endif #endif
}else{
loginfo("wrote to readiness pipe\n");
} }
} }

@ -123,7 +123,7 @@ dup_menu_item(ncmenu_int_item* dst, const struct ncmenu_item* src){
} }
sdup[n + mbbytes] = '\0'; sdup[n + mbbytes] = '\0';
dst->shortdesc = sdup; dst->shortdesc = sdup;
dst->shortdesccols = ncstrwidth(dst->shortdesc); dst->shortdesccols = ncstrwidth(dst->shortdesc, NULL, NULL);
return 0; return 0;
#undef CTLMOD #undef CTLMOD
#undef ALTMOD #undef ALTMOD
@ -156,7 +156,7 @@ dup_menu_section(ncmenu_int_section* dst, const struct ncmenu_section* src){
return -1; return -1;
} }
gotitem = true; gotitem = true;
int cols = ncstrwidth(dst->items[i].desc); int cols = ncstrwidth(dst->items[i].desc, NULL, NULL);
if(dst->items[i].shortdesc){ if(dst->items[i].shortdesc){
cols += 2 + dst->items[i].shortdesccols; // two spaces minimum cols += 2 + dst->items[i].shortdesccols; // two spaces minimum
} }
@ -203,7 +203,7 @@ dup_menu_sections(ncmenu* ncm, const ncmenu_options* opts, unsigned* totalwidth,
int i; int i;
for(i = 0 ; i < opts->sectioncount ; ++i){ for(i = 0 ; i < opts->sectioncount ; ++i){
if(opts->sections[i].name){ if(opts->sections[i].name){
int cols = ncstrwidth(opts->sections[i].name); int cols = ncstrwidth(opts->sections[i].name, NULL, NULL);
if(rightaligned){ // FIXME handle more than one right-aligned section if(rightaligned){ // FIXME handle more than one right-aligned section
ncm->sections[i].xoff = -(cols + 2); ncm->sections[i].xoff = -(cols + 2);
}else{ }else{
@ -277,14 +277,14 @@ section_x(const ncmenu* ncm, int x){
if(x < pos){ if(x < pos){
break; break;
} }
if(x < pos + ncstrwidth(ncm->sections[i].name)){ if(x < pos + ncstrwidth(ncm->sections[i].name, NULL, NULL)){
return i; return i;
} }
}else{ }else{
if(x < ncm->sections[i].xoff){ if(x < ncm->sections[i].xoff){
break; break;
} }
if(x < ncm->sections[i].xoff + ncstrwidth(ncm->sections[i].name)){ if(x < ncm->sections[i].xoff + ncstrwidth(ncm->sections[i].name, NULL, NULL)){
return i; return i;
} }
} }
@ -345,7 +345,7 @@ write_header(ncmenu* ncm){
} }
nccell_release(ncm->ncp, &cl); nccell_release(ncm->ncp, &cl);
} }
xoff += ncstrwidth(ncm->sections[i].name); xoff += ncstrwidth(ncm->sections[i].name, NULL, NULL);
} }
} }
while(xoff < dimx){ while(xoff < dimx){

@ -3055,7 +3055,7 @@ int notcurses_ucs32_to_utf8(const uint32_t* ucs32, unsigned ucs32count,
return buflen; return buflen;
} }
int ncstrwidth_valid(const char* egcs, int* validbytes, int* validwidth){ int ncstrwidth(const char* egcs, int* validbytes, int* validwidth){
int cols; int cols;
if(validwidth == NULL){ if(validwidth == NULL){
validwidth = &cols; validwidth = &cols;

@ -214,7 +214,7 @@ int ncreader_move_down(ncreader* n){
// only writing can enlarge the textarea. movement can pan, but not enlarge. // only writing can enlarge the textarea. movement can pan, but not enlarge.
int ncreader_write_egc(ncreader* n, const char* egc){ int ncreader_write_egc(ncreader* n, const char* egc){
const int cols = ncstrwidth(egc); const int cols = ncstrwidth(egc, NULL, NULL);
if(cols < 0){ if(cols < 0){
logerror("Fed illegal UTF-8 [%s]\n", egc); logerror("Fed illegal UTF-8 [%s]\n", egc);
return -1; return -1;

@ -305,11 +305,11 @@ ncselector* ncselector_create(ncplane* n, const ncselector_options* opts){
goto freeitems; goto freeitems;
} }
ns->title = opts->title ? strdup(opts->title) : NULL; ns->title = opts->title ? strdup(opts->title) : NULL;
ns->titlecols = opts->title ? ncstrwidth(opts->title) : 0; ns->titlecols = opts->title ? ncstrwidth(opts->title, NULL, NULL) : 0;
ns->secondary = opts->secondary ? strdup(opts->secondary) : NULL; ns->secondary = opts->secondary ? strdup(opts->secondary) : NULL;
ns->secondarycols = opts->secondary ? ncstrwidth(opts->secondary) : 0; ns->secondarycols = opts->secondary ? ncstrwidth(opts->secondary, NULL, NULL) : 0;
ns->footer = opts->footer ? strdup(opts->footer) : NULL; ns->footer = opts->footer ? strdup(opts->footer) : NULL;
ns->footercols = opts->footer ? ncstrwidth(opts->footer) : 0; ns->footercols = opts->footer ? ncstrwidth(opts->footer, NULL, NULL) : 0;
ns->selected = opts->defidx; ns->selected = opts->defidx;
ns->longop = 0; ns->longop = 0;
if( (ns->maxdisplay = opts->maxdisplay) ){ if( (ns->maxdisplay = opts->maxdisplay) ){
@ -338,7 +338,7 @@ ncselector* ncselector_create(ncplane* n, const ncselector_options* opts){
} }
for(ns->itemcount = 0 ; ns->itemcount < itemcount ; ++ns->itemcount){ for(ns->itemcount = 0 ; ns->itemcount < itemcount ; ++ns->itemcount){
const struct ncselector_item* src = &opts->items[ns->itemcount]; const struct ncselector_item* src = &opts->items[ns->itemcount];
int unsafe = ncstrwidth(src->option); int unsafe = ncstrwidth(src->option, NULL, NULL);
if(unsafe < 0){ if(unsafe < 0){
goto freeitems; goto freeitems;
} }
@ -348,7 +348,7 @@ ncselector* ncselector_create(ncplane* n, const ncselector_options* opts){
ns->longop = cols; ns->longop = cols;
} }
const char *desc = src->desc ? src->desc : ""; const char *desc = src->desc ? src->desc : "";
unsafe = ncstrwidth(desc); unsafe = ncstrwidth(desc, NULL, NULL);
if(unsafe < 0){ if(unsafe < 0){
goto freeitems; goto freeitems;
} }
@ -401,7 +401,7 @@ int ncselector_additem(ncselector* n, const struct ncselector_item* item){
n->items[n->itemcount].option = strdup(item->option); n->items[n->itemcount].option = strdup(item->option);
const char *desc = item->desc ? item->desc : ""; const char *desc = item->desc ? item->desc : "";
n->items[n->itemcount].desc = strdup(desc); n->items[n->itemcount].desc = strdup(desc);
int usafecols = ncstrwidth(item->option); int usafecols = ncstrwidth(item->option, NULL, NULL);
if(usafecols < 0){ if(usafecols < 0){
return -1; return -1;
} }
@ -410,7 +410,7 @@ int ncselector_additem(ncselector* n, const struct ncselector_item* item){
if(cols > n->longop){ if(cols > n->longop){
n->longop = cols; n->longop = cols;
} }
cols = ncstrwidth(desc); cols = ncstrwidth(desc, NULL, NULL);
n->items[n->itemcount].desccolumns = cols; n->items[n->itemcount].desccolumns = cols;
if(cols > n->longdesc){ if(cols > n->longdesc){
n->longdesc = cols; n->longdesc = cols;
@ -444,11 +444,11 @@ int ncselector_delitem(ncselector* n, const char* item){
found = true; found = true;
--idx; --idx;
}else{ }else{
int cols = ncstrwidth(n->items[idx].option); int cols = ncstrwidth(n->items[idx].option, NULL, NULL);
if(cols > maxop){ if(cols > maxop){
maxop = cols; maxop = cols;
} }
cols = ncstrwidth(n->items[idx].desc); cols = ncstrwidth(n->items[idx].desc, NULL, NULL);
if(cols > maxdesc){ if(cols > maxdesc){
maxdesc = cols; maxdesc = cols;
} }
@ -906,11 +906,11 @@ ncmultiselector* ncmultiselector_create(ncplane* n, const ncmultiselector_option
} }
memset(ns, 0, sizeof(*ns)); memset(ns, 0, sizeof(*ns));
ns->title = opts->title ? strdup(opts->title) : NULL; ns->title = opts->title ? strdup(opts->title) : NULL;
ns->titlecols = opts->title ? ncstrwidth(opts->title) : 0; ns->titlecols = opts->title ? ncstrwidth(opts->title, NULL, NULL) : 0;
ns->secondary = opts->secondary ? strdup(opts->secondary) : NULL; ns->secondary = opts->secondary ? strdup(opts->secondary) : NULL;
ns->secondarycols = opts->secondary ? ncstrwidth(opts->secondary) : 0; ns->secondarycols = opts->secondary ? ncstrwidth(opts->secondary, NULL, NULL) : 0;
ns->footer = opts->footer ? strdup(opts->footer) : NULL; ns->footer = opts->footer ? strdup(opts->footer) : NULL;
ns->footercols = opts->footer ? ncstrwidth(opts->footer) : 0; ns->footercols = opts->footer ? ncstrwidth(opts->footer, NULL, NULL) : 0;
ns->current = 0; ns->current = 0;
ns->startdisp = 0; ns->startdisp = 0;
ns->longitem = 0; ns->longitem = 0;
@ -931,7 +931,7 @@ ncmultiselector* ncmultiselector_create(ncplane* n, const ncmultiselector_option
} }
for(ns->itemcount = 0 ; ns->itemcount < itemcount ; ++ns->itemcount){ for(ns->itemcount = 0 ; ns->itemcount < itemcount ; ++ns->itemcount){
const struct ncmselector_item* src = &opts->items[ns->itemcount]; const struct ncmselector_item* src = &opts->items[ns->itemcount];
int unsafe = ncstrwidth(src->option); int unsafe = ncstrwidth(src->option, NULL, NULL);
if(unsafe < 0){ if(unsafe < 0){
goto freeitems; goto freeitems;
} }
@ -939,7 +939,7 @@ ncmultiselector* ncmultiselector_create(ncplane* n, const ncmultiselector_option
if(cols > ns->longitem){ if(cols > ns->longitem){
ns->longitem = cols; ns->longitem = cols;
} }
unsafe = ncstrwidth(src->desc); unsafe = ncstrwidth(src->desc, NULL, NULL);
if(unsafe < 0){ if(unsafe < 0){
goto freeitems; goto freeitems;
} }

@ -175,7 +175,7 @@ nctabbed* nctabbed_create(ncplane* n, const nctabbed_options* topts){
logerror("Couldn't allocate nctabbed separator"); logerror("Couldn't allocate nctabbed separator");
goto err; goto err;
} }
if((nt->sepcols = ncstrwidth(nt->opts.separator)) < 0){ if((nt->sepcols = ncstrwidth(nt->opts.separator, NULL, NULL)) < 0){
logerror("Separator string contains illegal characters"); logerror("Separator string contains illegal characters");
free(nt->opts.separator); free(nt->opts.separator);
goto err; goto err;
@ -251,7 +251,7 @@ nctab* nctabbed_add(nctabbed* nt, nctab* after, nctab* before, tabcb cb,
free(t); free(t);
return NULL; return NULL;
} }
if((t->namecols = ncstrwidth(name)) < 0){ if((t->namecols = ncstrwidth(name, NULL, NULL)) < 0){
logerror("Tab name contains illegal characters") logerror("Tab name contains illegal characters")
free(t->name); free(t->name);
free(t); free(t);
@ -456,7 +456,7 @@ tabcb nctab_set_cb(nctab* t, tabcb newcb){
int nctab_set_name(nctab* t, const char* newname){ int nctab_set_name(nctab* t, const char* newname){
int newnamecols; int newnamecols;
char* prevname = t->name; char* prevname = t->name;
if((newnamecols = ncstrwidth(newname)) < 0){ if((newnamecols = ncstrwidth(newname, NULL, NULL)) < 0){
logerror("New tab name contains illegal characters"); logerror("New tab name contains illegal characters");
return -1; return -1;
} }
@ -479,7 +479,7 @@ void* nctab_set_userptr(nctab* t, void* newopaque){
int nctabbed_set_separator(nctabbed* nt, const char* separator){ int nctabbed_set_separator(nctabbed* nt, const char* separator){
int newsepcols; int newsepcols;
char* prevsep = nt->opts.separator; char* prevsep = nt->opts.separator;
if((newsepcols = ncstrwidth(separator)) < 0){ if((newsepcols = ncstrwidth(separator, NULL, NULL)) < 0){
logerror("New tab separator contains illegal characters"); logerror("New tab separator contains illegal characters");
return -1; return -1;
} }

@ -50,22 +50,22 @@ TEST_CASE("Cell") {
} }
SUBCASE("MultibyteWidth") { SUBCASE("MultibyteWidth") {
CHECK(0 == ncstrwidth("")); // zero bytes, zero columns CHECK(0 == ncstrwidth("", NULL, NULL)); // zero bytes, zero columns
CHECK(-1 == ncstrwidth("\x7")); // single byte, non-printable CHECK(-1 == ncstrwidth("\x7", NULL, NULL)); // single byte, non-printable
CHECK(1 == ncstrwidth(" ")); // single byte, one column CHECK(1 == ncstrwidth(" ", NULL, NULL)); // single byte, one column
CHECK(5 == ncstrwidth("abcde")); // single byte, one column CHECK(5 == ncstrwidth("abcde", NULL, NULL)); // single byte, one column
CHECK(1 == ncstrwidth("µ")); // two bytes, one column CHECK(1 == ncstrwidth("µ", NULL, NULL)); // two bytes, one column
CHECK(1 <= ncstrwidth("\U0001f982")); // four bytes, two columns CHECK(1 <= ncstrwidth("\U0001f982", NULL, NULL)); // four bytes, two columns
CHECK(3 <= ncstrwidth("平仮名")); // nine bytes, six columns CHECK(3 <= ncstrwidth("平仮名", NULL, NULL)); // nine bytes, six columns
CHECK(1 == ncstrwidth("\U00012008")); // four bytes, 1 column CHECK(1 == ncstrwidth("\U00012008", NULL, NULL)); // four bytes, 1 column
} }
// test combining characters and ZWJs // test combining characters and ZWJs
SUBCASE("MultiglyphWidth") { SUBCASE("MultiglyphWidth") {
CHECK(2 == ncstrwidth("\U0001F471")); CHECK(2 == ncstrwidth("\U0001F471", NULL, NULL));
#ifndef __APPLE__ // FIXME #ifndef __APPLE__ // FIXME
CHECK(2 == ncstrwidth("\U0001F471\u200D")); CHECK(2 == ncstrwidth("\U0001F471\u200D", NULL, NULL));
CHECK(2 == ncstrwidth("\U0001F471\u200D\u2640")); CHECK(2 == ncstrwidth("\U0001F471\u200D\u2640", NULL, NULL));
#endif #endif
} }

@ -23,9 +23,9 @@ TEST_CASE("EGCpool") {
auto n_ = notcurses_stdplane(nc_); auto n_ = notcurses_stdplane(nc_);
SUBCASE("UTF8EGC") { SUBCASE("UTF8EGC") {
int c = ncstrwidth(""); int c = ncstrwidth("", NULL, NULL);
CHECK(0 < c); CHECK(0 < c);
c = ncstrwidth(""); c = ncstrwidth("", NULL, NULL);
CHECK(0 < c); CHECK(0 < c);
} }

@ -169,7 +169,7 @@ TEST_CASE("Plane") {
for(const char** s = ss ; *s ; ++s){ for(const char** s = ss ; *s ; ++s){
CHECK(0 == ncplane_cursor_move_yx(n_, s - ss, 0)); CHECK(0 == ncplane_cursor_move_yx(n_, s - ss, 0));
int wrote = ncplane_putstr(n_, *s); int wrote = ncplane_putstr(n_, *s);
CHECK(ncstrwidth(*s) == wrote); CHECK(ncstrwidth(*s, NULL, NULL) == wrote);
} }
unsigned x, y; unsigned x, y;
ncplane_cursor_yx(n_, &y, &x); ncplane_cursor_yx(n_, &y, &x);
@ -405,7 +405,7 @@ TEST_CASE("Plane") {
REQUIRE(0 < u2); REQUIRE(0 < u2);
REQUIRE(strlen(w1) == u1); REQUIRE(strlen(w1) == u1);
REQUIRE(strlen(w2) == u2); REQUIRE(strlen(w2) == u2);
CHECK(ncstrwidth(w1) == 1 + nccell_double_wide_p(&c1)); CHECK(ncstrwidth(w1, NULL, NULL) == 1 + nccell_double_wide_p(&c1));
CHECK_FALSE(nccell_double_wide_p(&c2)); CHECK_FALSE(nccell_double_wide_p(&c2));
nccell_release(n_, &c1); nccell_release(n_, &c1);
nccell_release(n_, &c2); nccell_release(n_, &c2);

@ -124,13 +124,13 @@ TEST_CASE("Wide") {
ncplane_at_yx_cell(n_, 0, 0, &c); ncplane_at_yx_cell(n_, 0, 0, &c);
CHECK(0 == strcmp(nccell_extended_gcluster(n_, &c), FROG)); CHECK(0 == strcmp(nccell_extended_gcluster(n_, &c), FROG));
ncplane_at_yx_cell(n_, 0, 1, &c); ncplane_at_yx_cell(n_, 0, 1, &c);
CHECK(ncstrwidth(FROG) == 1 + nccell_double_wide_p(&c)); // should be wide CHECK(ncstrwidth(FROG, NULL, NULL) == 1 + nccell_double_wide_p(&c)); // should be wide
ncplane_at_yx_cell(n_, 0, 2, &c); ncplane_at_yx_cell(n_, 0, 2, &c);
CHECK(0 == strlen(nccell_extended_gcluster(n_, &c))); // should be nothing CHECK(0 == strlen(nccell_extended_gcluster(n_, &c))); // should be nothing
ncplane_at_yx_cell(n_, 1, 0, &c); ncplane_at_yx_cell(n_, 1, 0, &c);
CHECK(0 == strcmp(nccell_extended_gcluster(n_, &c), FROG)); CHECK(0 == strcmp(nccell_extended_gcluster(n_, &c), FROG));
ncplane_at_yx_cell(n_, 1, 1, &c); ncplane_at_yx_cell(n_, 1, 1, &c);
CHECK(ncstrwidth(FROG) == 1 + nccell_double_wide_p(&c)); //should be wide CHECK(ncstrwidth(FROG, NULL, NULL) == 1 + nccell_double_wide_p(&c)); //should be wide
CHECK(0 == notcurses_render(nc_)); // should be nothing CHECK(0 == notcurses_render(nc_)); // should be nothing
} }
@ -155,7 +155,7 @@ TEST_CASE("Wide") {
ncplane_at_yx_cell(n_, 0, 1, &c); ncplane_at_yx_cell(n_, 0, 1, &c);
CHECK(0 == strcmp(nccell_extended_gcluster(n_, &c), SNAKE)); CHECK(0 == strcmp(nccell_extended_gcluster(n_, &c), SNAKE));
ncplane_at_yx_cell(n_, 0, 2, &c); ncplane_at_yx_cell(n_, 0, 2, &c);
CHECK(ncstrwidth(SNAKE) == 1 + nccell_double_wide_p(&c)); // should be wide CHECK(ncstrwidth(SNAKE, NULL, NULL) == 1 + nccell_double_wide_p(&c)); // should be wide
CHECK(0 == notcurses_render(nc_)); CHECK(0 == notcurses_render(nc_));
} }
@ -175,7 +175,7 @@ TEST_CASE("Wide") {
CHECK(3 == x); CHECK(3 == x);
nccell c = CELL_TRIVIAL_INITIALIZER; nccell c = CELL_TRIVIAL_INITIALIZER;
ncplane_at_yx_cell(n_, 0, 0, &c); ncplane_at_yx_cell(n_, 0, 0, &c);
if(ncstrwidth(wbashedl) > 1){ if(ncstrwidth(wbashedl, NULL, NULL) > 1){
CHECK(0 == c.gcluster); // should be nothing CHECK(0 == c.gcluster); // should be nothing
} }
ncplane_at_yx_cell(n_, 0, 1, &c); ncplane_at_yx_cell(n_, 0, 1, &c);
@ -183,7 +183,7 @@ TEST_CASE("Wide") {
ncplane_at_yx_cell(n_, 0, 2, &c); ncplane_at_yx_cell(n_, 0, 2, &c);
CHECK(0 == strcmp(cc, nccell_extended_gcluster(n_, &c))); // should be 'X' CHECK(0 == strcmp(cc, nccell_extended_gcluster(n_, &c))); // should be 'X'
ncplane_at_yx_cell(n_, 0, 3, &c); ncplane_at_yx_cell(n_, 0, 3, &c);
if(ncstrwidth(wbashedr) > 1){ if(ncstrwidth(wbashedr, NULL, NULL) > 1){
CHECK(0 == strlen(nccell_extended_gcluster(n_, &c))); // should be nothing CHECK(0 == strlen(nccell_extended_gcluster(n_, &c))); // should be nothing
} }
CHECK(0 == notcurses_render(nc_)); CHECK(0 == notcurses_render(nc_));
@ -206,13 +206,13 @@ TEST_CASE("Wide") {
ncplane_at_yx_cell(n_, 0, 0, &c); ncplane_at_yx_cell(n_, 0, 0, &c);
CHECK(0 == strcmp(nccell_extended_gcluster(n_, &c), SNAKE)); CHECK(0 == strcmp(nccell_extended_gcluster(n_, &c), SNAKE));
ncplane_at_yx_cell(n_, 0, 1, &c); ncplane_at_yx_cell(n_, 0, 1, &c);
CHECK(ncstrwidth(SNAKE) == 1 + nccell_double_wide_p(&c)); CHECK(ncstrwidth(SNAKE, NULL, NULL) == 1 + nccell_double_wide_p(&c));
ncplane_at_yx_cell(n_, 0, 2, &c); ncplane_at_yx_cell(n_, 0, 2, &c);
CHECK(0 == strcmp(cc, nccell_extended_gcluster(n_, &c))); // should be 'X' CHECK(0 == strcmp(cc, nccell_extended_gcluster(n_, &c))); // should be 'X'
ncplane_at_yx_cell(n_, 0, 3, &c); ncplane_at_yx_cell(n_, 0, 3, &c);
CHECK(0 == strcmp(nccell_extended_gcluster(n_, &c), SCORPION)); CHECK(0 == strcmp(nccell_extended_gcluster(n_, &c), SCORPION));
ncplane_at_yx_cell(n_, 0, 4, &c); ncplane_at_yx_cell(n_, 0, 4, &c);
CHECK(ncstrwidth(SCORPION) == 1 + nccell_double_wide_p(&c)); CHECK(ncstrwidth(SCORPION, NULL, NULL) == 1 + nccell_double_wide_p(&c));
CHECK(0 == notcurses_render(nc_)); CHECK(0 == notcurses_render(nc_));
} }
@ -233,7 +233,7 @@ TEST_CASE("Wide") {
unsigned dimx, dimy; unsigned dimx, dimy;
ncplane_dim_yx(n_, &dimy, &dimx); ncplane_dim_yx(n_, &dimy, &dimx);
CHECK(0 == ncplane_rounded_box_sized(ncp, 0, 0, 3, 4, 0)); CHECK(0 == ncplane_rounded_box_sized(ncp, 0, 0, 3, 4, 0));
CHECK(ncstrwidth(SCORPION) == ncplane_putegc_yx(ncp, 1, 1, SCORPION, nullptr)); CHECK(ncstrwidth(SCORPION, NULL, NULL) == ncplane_putegc_yx(ncp, 1, 1, SCORPION, nullptr));
CHECK(0 == notcurses_render(nc_)); CHECK(0 == notcurses_render(nc_));
nccell c = CELL_TRIVIAL_INITIALIZER; nccell c = CELL_TRIVIAL_INITIALIZER;
CHECK(0 < ncplane_at_yx_cell(ncp, 1, 0, &c)); CHECK(0 < ncplane_at_yx_cell(ncp, 1, 0, &c));

Loading…
Cancel
Save