[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 *|validwidth| (assuming them non-NULL). If the entire string is valid,
// *|validbytes| and *|validwidth| reflect the entire string.
API int ncstrwidth_valid(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);
}
API int ncstrwidth(const char* egcs, int* validbytes, int* validwidth);
// Returns a heap-allocated copy of the user name under which we are running.
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){
int validbytes, validwidth;
// 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);
if(xpos < 0){
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
// Used as arguments to a variable field width (i.e. "%*s" -- these are the *).
// 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 NCIPREFIXFMT(x) NCMETRIXFWIDTH((x), NCIPREFIXCOLUMNS), (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 totallength = 0;
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),
heady, headx, endy, endx, totallength);

@ -394,11 +394,11 @@ hud_print_finished(elem* list){
}
char buf[NCPREFIXCOLUMNS + 2];
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;
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;
}
if(ncplane_putstr_yx(hud, line, 16, e->name) < 0){
@ -614,12 +614,12 @@ int demo_render(struct notcurses* nc){
}
char buf[NCPREFIXCOLUMNS + 2];
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;
ncplane_putc_yx(hud, 1, x, &ci);
}
//fprintf(stderr, "[%s] %zu %d\n", buf, strlen(buf), ncstrwidth(buf));
if(ncplane_printf_yx(hud, 1, 14 - ncstrwidth(buf), "%ss", buf) < 0){
//fprintf(stderr, "[%s] %zu %d\n", buf, strlen(buf), ncstrwidth(buf, NULL, NULL));
if(ncplane_printf_yx(hud, 1, 14 - ncstrwidth(buf, NULL, NULL), "%ss", buf) < 0){
return -1;
}
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
lines[linecount - 1][linelen] = '\0';
}
size_t collen = ncstrwidth(lines[linecount - 1]);
size_t collen = ncstrwidth(lines[linecount - 1], NULL, NULL);
if(collen > maxlinelen){
maxlinelen = collen;
}

@ -797,7 +797,11 @@ int ncdirect_vprintf_aligned(ncdirect* n, int y, ncalign_e align, const char* fm
if(r == NULL){
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);
if(ncdirect_cursor_move_yx(n, y, x)){
free(r);

@ -48,6 +48,11 @@ typedef HANDLE ipipe;
// local state for the input thread. don't put this large struct on the stack.
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
// own this descriptor, and must not close() it.
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
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 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)){
logwarn("error writing to pipe\n");
#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';
dst->shortdesc = sdup;
dst->shortdesccols = ncstrwidth(dst->shortdesc);
dst->shortdesccols = ncstrwidth(dst->shortdesc, NULL, NULL);
return 0;
#undef CTLMOD
#undef ALTMOD
@ -156,7 +156,7 @@ dup_menu_section(ncmenu_int_section* dst, const struct ncmenu_section* src){
return -1;
}
gotitem = true;
int cols = ncstrwidth(dst->items[i].desc);
int cols = ncstrwidth(dst->items[i].desc, NULL, NULL);
if(dst->items[i].shortdesc){
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;
for(i = 0 ; i < opts->sectioncount ; ++i){
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
ncm->sections[i].xoff = -(cols + 2);
}else{
@ -277,14 +277,14 @@ section_x(const ncmenu* ncm, int x){
if(x < pos){
break;
}
if(x < pos + ncstrwidth(ncm->sections[i].name)){
if(x < pos + ncstrwidth(ncm->sections[i].name, NULL, NULL)){
return i;
}
}else{
if(x < ncm->sections[i].xoff){
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;
}
}
@ -345,7 +345,7 @@ write_header(ncmenu* ncm){
}
nccell_release(ncm->ncp, &cl);
}
xoff += ncstrwidth(ncm->sections[i].name);
xoff += ncstrwidth(ncm->sections[i].name, NULL, NULL);
}
}
while(xoff < dimx){

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

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

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

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

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

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

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

@ -124,13 +124,13 @@ TEST_CASE("Wide") {
ncplane_at_yx_cell(n_, 0, 0, &c);
CHECK(0 == strcmp(nccell_extended_gcluster(n_, &c), FROG));
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);
CHECK(0 == strlen(nccell_extended_gcluster(n_, &c))); // should be nothing
ncplane_at_yx_cell(n_, 1, 0, &c);
CHECK(0 == strcmp(nccell_extended_gcluster(n_, &c), FROG));
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
}
@ -155,7 +155,7 @@ TEST_CASE("Wide") {
ncplane_at_yx_cell(n_, 0, 1, &c);
CHECK(0 == strcmp(nccell_extended_gcluster(n_, &c), SNAKE));
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_));
}
@ -175,7 +175,7 @@ TEST_CASE("Wide") {
CHECK(3 == x);
nccell c = CELL_TRIVIAL_INITIALIZER;
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
}
ncplane_at_yx_cell(n_, 0, 1, &c);
@ -183,7 +183,7 @@ TEST_CASE("Wide") {
ncplane_at_yx_cell(n_, 0, 2, &c);
CHECK(0 == strcmp(cc, nccell_extended_gcluster(n_, &c))); // should be 'X'
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 == notcurses_render(nc_));
@ -206,13 +206,13 @@ TEST_CASE("Wide") {
ncplane_at_yx_cell(n_, 0, 0, &c);
CHECK(0 == strcmp(nccell_extended_gcluster(n_, &c), SNAKE));
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);
CHECK(0 == strcmp(cc, nccell_extended_gcluster(n_, &c))); // should be 'X'
ncplane_at_yx_cell(n_, 0, 3, &c);
CHECK(0 == strcmp(nccell_extended_gcluster(n_, &c), SCORPION));
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_));
}
@ -233,7 +233,7 @@ TEST_CASE("Wide") {
unsigned dimx, dimy;
ncplane_dim_yx(n_, &dimy, &dimx);
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_));
nccell c = CELL_TRIVIAL_INITIALIZER;
CHECK(0 < ncplane_at_yx_cell(ncp, 1, 0, &c));

Loading…
Cancel
Save