43mbstr_find_codepoint(
const char* s, uint32_t cp,
int* col){
45 memset(&ps, 0,
sizeof(ps));
50 while((
r = mbrtowc(&w, s + bytes, MB_CUR_MAX, &ps)) != (
size_t)-1 &&
r != (
size_t)-2){
54 if(towlower(cp) == towlower(w)){
65 for(
unsigned i = 0 ; i < ms->
itemcount ; ++i){
74free_menu_sections(
ncmenu* ncm){
76 free_menu_section(&ncm->
sections[i]);
102 memset(&ps, 0,
sizeof(ps));
104 if(shortsize == (
size_t)-1){
108 bytes += shortsize + 1;
109 char* sdup = malloc(bytes);
110 int n = snprintf(sdup, bytes,
"%s%s", ncinput_alt_p(&src->
shortcut) ?
ALTMOD :
"",
111 ncinput_ctrl_p(&src->shortcut) ?
CTLMOD :
"");
112 if(
n < 0 || (
size_t)
n >= bytes){
117 memset(&ps, 0,
sizeof(ps));
118 size_t mbbytes = wcrtomb(sdup +
n, src->
shortcut.
id, &ps);
119 if(mbbytes == (
size_t)-1){
124 sdup[
n + mbbytes] =
'\0';
142 bool gotitem =
false;
149 for(
int i = 0 ; i < src->
itemcount ; ++i){
151 if(dup_menu_item(&dst->
items[i], &src->
items[i])){
167 if(mbstr_find_codepoint(dst->
items[i].
desc,
192 if(
opts->sectioncount == 0){
199 bool rightaligned =
false;
200 unsigned maxheight = 0;
201 unsigned maxwidth = *totalwidth;
204 for(i = 0 ; i <
opts->sectioncount ; ++i){
215 if(dup_menu_section(&ncm->
sections[i], &
opts->sections[i])){
222 if(*totalwidth + cols + 2 > maxwidth){
223 maxwidth = *totalwidth + cols + 2;
228 *totalwidth += cols + 2;
254 *totalwidth = maxwidth;
255 *totalheight += maxheight + 2;
260 free_menu_section(&ncm->
sections[i]);
269section_x(
const ncmenu* ncm,
int x){
270 int dimx = ncplane_dim_x(ncm->
ncp);
284 if(x < ncm->sections[i].xoff){
301 int ypos = ncm->
bottom ? dimy - 1 : 0;
307 if(ncplane_putc(ncm->
ncp, &
c) < 0){
310 if(ncplane_putc(ncm->
ncp, &
c) < 0){
325 if(ncplane_putc(ncm->
ncp, &
c) < 0){
334 if(ncplane_putstr_yx(ncm->
ncp, ypos, xoff, ncm->
sections[i].
name) < 0){
363 int dimx = ncplane_dim_x(parent);
364 int dimy = ncplane_dim_y(
n);
365 if(ncplane_resize_simple(
n, dimy, dimx)){
371 return write_header(menu);
382 if(
opts->sectioncount <= 0 || !
opts->sections){
383 logerror(
"invalid %d-ary section information",
opts->sectioncount);
389 unsigned totalheight = 1;
390 unsigned totalwidth = 2;
391 ncmenu* ret = malloc(
sizeof(*ret));
398 if(dup_menu_sections(ret,
opts, &totalwidth, &totalheight) == 0){
400 if(totalwidth < dimx){
404 .
y = ret->
bottom ? dimy - totalheight : 0,
410 .resizecb = resize_menu,
428 if(write_header(ret) == 0){
434 free_menu_sections(ret);
443section_height(
const ncmenu*
n,
int sectionidx){
444 return n->sections[sectionidx].itemcount + 2;
448section_width(
const ncmenu*
n,
int sectionidx){
449 return n->sections[sectionidx].bodycols + 2;
456 if(sectionidx < 0 || sectionidx >=
n->sectioncount){
457 logerror(
"unrolled invalid sectionidx %d", sectionidx);
460 if(
n->sections[sectionidx].enabled_item_count <= 0){
463 if(
n->sections[sectionidx].name ==
NULL){
466 n->unrolledsection = sectionidx;
469 const int height = section_height(
n, sectionidx);
470 const int width = section_width(
n, sectionidx);
471 int xpos =
n->sections[sectionidx].xoff < 0 ?
472 (int)dimx + (
n->sections[sectionidx].xoff - 2) :
n->sections[sectionidx].xoff;
473 if(xpos + width >= (
int)dimx){
474 xpos = dimx - (width + 2);
476 int ypos =
n->bottom ? dimy - height - 1 : 1;
480 if(ncplane_rounded_box_sized(
n->ncp, 0,
n->headerchannels, height, width, 0)){
484 for(
unsigned i = 0 ; i < sec->
itemcount ; ++i){
502 int cols = ncplane_putstr_yx(
n->ncp, ypos, xpos + 1, sec->
items[i].
desc);
509 int thiswidth = width;
514 for(
int j =
cols + 1 ; j < thiswidth - 1 ; ++j){
515 if(ncplane_putchar(
n->ncp,
' ') < 0){
536 n->ncp->channels =
n->headerchannels;
541 for(
int j = 1 ; j < width - 1 ; ++j){
542 if(ncplane_putegc(
n->ncp,
"─",
NULL) < 0){
546 if(ncplane_putegc(
n->ncp,
"┤",
NULL) < 0){
555 if(
n->unrolledsection < 0){
558 n->unrolledsection = -1;
560 return write_header(
n);
564 int nextsection =
n->unrolledsection;
565 int origselected =
n->unrolledsection;
567 if(++nextsection ==
n->sectioncount){
570 if(nextsection == origselected){
573 }
while(
n->sections[nextsection].name ==
NULL ||
574 n->sections[nextsection].enabled_item_count == 0);
579 int prevsection =
n->unrolledsection;
580 int origselected =
n->unrolledsection;
582 if(--prevsection < 0){
583 prevsection =
n->sectioncount - 1;
585 if(prevsection == origselected){
588 }
while(
n->sections[prevsection].name ==
NULL ||
589 n->sections[prevsection].enabled_item_count == 0);
594 if(
n->unrolledsection == -1){
601 if(origselected >= 0){
615 if(
n->unrolledsection == -1){
622 if(origselected >= 0){
636 if(
n->unrolledsection < 0){
655 unsigned dimy,
unsigned dimx,
int y,
int x){
658 if(
x > (
int)dimx - 4 ||
x <= (
int)dimx - 4 - sec->
bodycols){
666 const int itemidx =
n->bottom ?
y - ((int)dimy - (
int)sec->
itemcount) + 2 :
y - 2;
667 if(itemidx < 0 || itemidx >= (
int)sec->
itemcount){
689 if(
n->unrolledsection < 0){
693 int itemidx = ncsection_click_index(
n, sec, dimy, dimx,
y,
x);
718 if(
n->unrolledsection >= 0){
720 int itemidx = ncsection_click_index(
n, sec, dimy, dimx,
y,
x);
729 if(
y != (
n->bottom ? (
int)dimy - 1 : 0)){
732 int i = section_x(
n,
x);
733 if(i < 0 || i == n->unrolledsection){
742 for(
int si = 0 ; si <
n->sectioncount ; ++si){
747 if(!ncinput_equal_p(&sec->
shortcut, nc)){
753 if(
n->unrolledsection < 0){
786 for(
int si = 0 ; si <
n->sectioncount ; ++si){
788 if(strcmp(sec->
name, section) == 0){
789 for(
unsigned ii = 0 ; ii < sec->
itemcount ; ++ii){
791 if(strcmp(i->
desc, item) == 0){
792 const bool changed = (i->
disabled != enabled);
804 if(
n->unrolledsection == si){
827 free_menu_sections(
n);
828 if(ncplane_set_widget(
n->ncp,
NULL,
NULL) == 0){
#define logerror(fmt,...)
#define NCKEY_SCROLL_DOWN
int ncplane_cursor_move_yx(ncplane *n, int y, int x)
void * ncplane_userptr(ncplane *n)
void ncplane_set_channels(ncplane *n, uint64_t channels)
void ncplane_set_styles(ncplane *n, unsigned stylebits)
int ncplane_destroy(ncplane *ncp)
int ncplane_putegc_yx(ncplane *n, int y, int x, const char *gclust, size_t *sbytes)
const ncplane * ncplane_parent_const(const ncplane *n)
int ncplane_at_yx_cell(ncplane *n, int y, int x, nccell *c)
int ncstrwidth(const char *egcs, int *validbytes, int *validwidth)
bool ncplane_translate_abs(const ncplane *n, int *restrict y, int *restrict x)
uint64_t ncplane_channels(const ncplane *n)
ncplane * ncplane_create(ncplane *n, const ncplane_options *nopts)
void ncplane_erase(ncplane *n)
int ncplane_putc_yx(ncplane *n, int y, int x, const nccell *c)
int ncplane_set_base_cell(ncplane *ncp, const nccell *c)
void ncplane_dim_yx(const ncplane *n, unsigned *rows, unsigned *cols)
#define NCMENU_OPTION_HIDING
#define NCSTYLE_UNDERLINE
const struct ncplane_options * opts
#define NCALPHA_TRANSPARENT
#define NCMENU_OPTION_BOTTOM
#define NCCELL_TRIVIAL_INITIALIZER
#define NCCELL_INITIALIZER(c, s, chan)
#define NCPLANE_OPTION_FIXED
void nccell_release(ncplane *n, nccell *c)