eliminate recursion in ncplane_polyfill_yx #2328

pull/2333/head
nick black 3 years ago committed by nick black
parent 51e90ca7e9
commit 91420af5ce

@ -128,8 +128,8 @@ add_compile_options(-fno-signed-zeros -fno-trapping-math -fassociative-math)
add_compile_options(-fno-math-errno -freciprocal-math -funsafe-math-optimizations)
add_compile_options(-fexceptions -fstrict-aliasing)
if(${USE_ASAN})
add_compile_options(-fsanitize=undefined)
add_link_options(-fsanitize=undefined)
add_compile_options(-fsanitize=address)
add_link_options(-fsanitize=address)
endif()
endif()

@ -12,8 +12,11 @@ rearrangements of Notcurses.
deprecated functionality, ABI3 ought require small changes, if any.
* 2.4.9 (not yet released)
* Added `ncnmetric()`, which uses `snprintf()` internally. `ncmetric()`
was reimplemented as a trivial wrapper around `ncnmetric()`.
* `qprefix()`, `bprefix()`, and `iprefix()` have been renamed
`ncqprefix()`, `ncbprefix()`, and `nciprefix()`, respectively.
The former forms have been deprecated, and will be removed in abi3.
* `notcurses_mice_enable()` and `notcurses_mouse_disable()` replace
`notcurses_mouse_enable()` and `notcurses_mouse_disable()`, which
have been deprecated, and will be removed in ABI3.

@ -451,7 +451,7 @@ are available for direct mode:
// Read a (heap-allocated) newline-delimited chunk of text. Returns NULL on
// failure. The NCDIRECT_OPTION_INHIBIT_CBREAK flag ought not be used together
// with this function, or the line-editing keybindings cannot be honored.
API char* ncdirect_readline(struct ncdirect* nc, const char* prompt);
char* ncdirect_readline(struct ncdirect* nc, const char* prompt);
int ncdirect_fg_rgb(struct ncdirect* nc, unsigned rgb);
int ncdirect_bg_rgb(struct ncdirect* nc, unsigned rgb);
@ -1674,8 +1674,8 @@ int ncplane_gradient2x1(struct ncplane* n, int y, int x, unsigned ylen,
// remaining to the right and below, respectively. It is an error for any
// coordinate to be outside the plane. Returns the number of cells set,
// or -1 on failure.
API int ncplane_format(struct ncplane* n, int y, int x, unsigned ylen,
unsigned xlen, uint16_t stylemask);
int ncplane_format(struct ncplane* n, int y, int x, unsigned ylen,
unsigned xlen, uint16_t stylemask);
// Set the given channels throughout the specified region, keeping content and
// channels unchanged. The upper left corner is at 'x', 'y', and -1 may be
@ -1684,9 +1684,9 @@ API int ncplane_format(struct ncplane* n, int y, int x, unsigned ylen,
// remaining to the right and below, respectively. It is an error for any
// coordinate to be outside the plane. Returns the number of cells set,
// or -1 on failure.
API int ncplane_stain(struct ncplane* n, int y, int x, unsigned ylen,
unsigned xlen, uint64_t ul, uint64_t ur,
uint64_t ll, uint64_t lr);
int ncplane_stain(struct ncplane* n, int y, int x, unsigned ylen,
unsigned xlen, uint64_t ul, uint64_t ur,
uint64_t ll, uint64_t lr);
```
My 14 year-old self would never forgive me if we didn't have sweet palette

@ -1807,7 +1807,7 @@ API void ncplane_center_abs(const struct ncplane* n, int* RESTRICT y,
// Only glyphs from the specified ncblitset may be present. If 'pxdimy' and/or
// 'pxdimx' are non-NULL, they will be filled in with the total pixel geometry.
API ALLOC uint32_t* ncplane_as_rgba(const struct ncplane* n, ncblitter_e blit,
unsigned begy, unsigned begx,
int begy, int begx,
unsigned leny, unsigned lenx,
unsigned* pxdimy, unsigned* pxdimx)
__attribute__ ((nonnull (1)));
@ -2869,7 +2869,7 @@ API ALLOC struct ncvisual* ncvisual_from_palidx(const void* data, int rows,
// Lengths of 0 are interpreted to mean "all available remaining area".
API ALLOC struct ncvisual* ncvisual_from_plane(const struct ncplane* n,
ncblitter_e blit,
unsigned begy, unsigned begx,
int begy, int begx,
unsigned leny, unsigned lenx)
__attribute__ ((nonnull (1)));
@ -3366,6 +3366,12 @@ API const char* ncmetric(uintmax_t val, uintmax_t decimal, char* buf,
int omitdec, uintmax_t mult, int uprefix)
__attribute__ ((nonnull (3)));
// uses snprintf() internally with the argument 's' as its bound
API const char* ncnmetric(uintmax_t val, size_t s, uintmax_t decimal,
char* buf, int omitdec, uintmax_t mult,
int uprefix)
__attribute__ ((nonnull (4)));
// The number of columns is one fewer, as the STRLEN expressions must leave
// an extra byte open in case 'µ' (U+00B5, 0xC2 0xB5) shows up. PREFIXCOLUMNS
// is the maximum number of columns used by a mult == 1000 (standard)
@ -3672,17 +3678,17 @@ API ALLOC struct ncmenu* ncmenu_create(struct ncplane* n, const ncmenu_options*
API int ncmenu_unroll(struct ncmenu* n, int sectionidx);
// Roll up any unrolled menu section, and hide the menu if using hiding.
API int ncmenu_rollup(struct ncmenu* n);
API int ncmenu_rollup(struct ncmenu* n) __attribute__ ((nonnull (1)));
// Unroll the previous/next section (relative to current unrolled). If no
// section is unrolled, the first section will be unrolled.
API int ncmenu_nextsection(struct ncmenu* n);
API int ncmenu_prevsection(struct ncmenu* n);
API int ncmenu_nextsection(struct ncmenu* n) __attribute__ ((nonnull (1)));
API int ncmenu_prevsection(struct ncmenu* n) __attribute__ ((nonnull (1)));
// Move to the previous/next item within the currently unrolled section. If no
// section is unrolled, the first section will be unrolled.
API int ncmenu_nextitem(struct ncmenu* n);
API int ncmenu_previtem(struct ncmenu* n);
API int ncmenu_nextitem(struct ncmenu* n) __attribute__ ((nonnull (1)));
API int ncmenu_previtem(struct ncmenu* n) __attribute__ ((nonnull (1)));
// Disable or enable a menu item. Returns 0 if the item was found.
API int ncmenu_item_set_status(struct ncmenu* n, const char* section,
@ -4286,6 +4292,23 @@ API int ncplane_highgradient_sized(struct ncplane* n, uint32_t ul, uint32_t ur,
uint32_t ll, uint32_t lr, int ylen, int xlen)
__attribute__ ((deprecated));
__attribute__ ((deprecated)) static inline const char*
qprefix(uintmax_t val, uintmax_t decimal, char* buf, int omitdec){
return ncmetric(val, decimal, buf, omitdec, 1000, '\0');
}
// Mibi, kebi, gibibytes sans 'i' suffix. Use IPREFIXSTRLEN + 1.
__attribute__ ((deprecated)) static inline const char*
iprefix(uintmax_t val, uintmax_t decimal, char* buf, int omitdec){
return ncmetric(val, decimal, buf, omitdec, 1024, '\0');
}
// Mibi, kebi, gibibytes. Use BPREFIXSTRLEN + 1 and BPREFIXCOLUMNS.
__attribute__ ((deprecated)) static inline const char*
bprefix(uintmax_t val, uintmax_t decimal, char* buf, int omitdec){
return ncmetric(val, decimal, buf, omitdec, 1024, 'i');
}
#undef API
#undef ALLOC

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

@ -124,7 +124,7 @@ int intro(struct notcurses* nc){
if(!notcurses_canutf8(nc)){
return 0;
}
int rows, cols;
unsigned rows, cols;
struct ncplane* ncp = notcurses_stddim_yx(nc, &rows, &cols);
uint32_t ccul, ccur, ccll, cclr;
ccul = ccur = ccll = cclr = 0;

@ -146,7 +146,7 @@ int luigi_demo(struct notcurses* nc){
if(!notcurses_canopen_images(nc)){
return 0;
}
int rows, cols;
unsigned rows, cols;
char* map = find_data("megaman2.bmp");
struct ncvisual* nv = ncvisual_from_file(map);
free(map);
@ -166,7 +166,7 @@ int luigi_demo(struct notcurses* nc){
const int height = 32;
int yoff = rows * 4 / 5 - height + 1; // tuned
struct ncplane* lns[3];
int i;
unsigned i;
struct ncplane* lastseen = NULL;
for(i = 0 ; i < 3 ; ++i){
struct ncplane_options nopts = {

@ -509,14 +509,14 @@ int witherworm_demo(struct notcurses* nc){
}
int ulen = 0;
int r;
//if(wcwidth(wcs) <= maxx - x){
if(wcwidth(wcs) <= (int)maxx - x){
if((r = ncplane_putegc(n, &(*s)[idx], &ulen)) <= 0){
if(ulen < 0){
return -1;
}else if(ulen == 0){
break; // FIXME work around missing unicode
}
//}
}
}else{
if((r = ncplane_putchar(n, '#')) < 1){
return -1;

@ -20,50 +20,58 @@ void ncplane_greyscale(ncplane *n){
// success. so a return of 0 means there's no work to be done here, and N means
// we did some work here, filling everything we could reach. out-of-plane is 0.
static int
ncplane_polyfill_recurse(ncplane* n, unsigned y, unsigned x, const nccell* c, const char* filltarg){
if(y >= (unsigned)n->leny || x >= (unsigned)n->lenx){
return 0; // not fillable
}
nccell* cur = &n->fb[nfbcellidx(n, y, x)];
const char* glust = nccell_extended_gcluster(n, cur);
//fprintf(stderr, "checking %d/%d (%s) for [%s]\n", y, x, glust, filltarg);
if(strcmp(glust, filltarg)){
return 0;
}
if(nccell_duplicate(n, cur, c) < 0){
ncplane_polyfill_inner(ncplane* n, unsigned y, unsigned x, const nccell* c, const char* filltarg){
struct topolyfill* stack = NULL;
if(create_polyfill_op(y, x, &stack) == NULL){
return -1;
}
int r, ret = 1;
int ret = 0;
do{
struct topolyfill* s = stack;
stack = stack->next;
y = s->y;
x = s->x;
nccell* cur = &n->fb[nfbcellidx(n, y, x)];
const char* glust = nccell_extended_gcluster(n, cur);
//fprintf(stderr, "checking %d/%d (%s) for [%s]\n", y, x, glust, filltarg);
if(strcmp(glust, filltarg) == 0){
++ret;
if(nccell_duplicate(n, cur, c) < 0){
// FIXME need free stack!
return -1;
}
//fprintf(stderr, "blooming from %d/%d ret: %d\n", y, x, ret);
if(y){
if((r = ncplane_polyfill_recurse(n, y - 1, x, c, filltarg)) < 0){
return -1;
}
ret += r;
}
if((r = ncplane_polyfill_recurse(n, y + 1, x, c, filltarg)) < 0){
return -1;
}
ret += r;
if(x){
if((r = ncplane_polyfill_recurse(n, y, x - 1, c, filltarg)) < 0){
return -1;
if(y){
if(create_polyfill_op(y - 1, x, &stack) == NULL){
return -1;
}
}
if(y + 1 < n->leny){
if(create_polyfill_op(y + 1, x, &stack) == NULL){
return -1;
}
}
if(x){
if(create_polyfill_op(y, x - 1, &stack) == NULL){
return -1;
}
}
if(x + 1 < n->lenx){
if(create_polyfill_op(y, x + 1, &stack) == NULL){
return -1;
}
}
}
ret += r;
}
if((r = ncplane_polyfill_recurse(n, y, x + 1, c, filltarg)) < 0){
return -1;
}
ret += r;
free(s);
}while(stack);
return ret;
}
// at the initial step only, invalid ystart, xstart is an error, so explicitly check.
int ncplane_polyfill_yx(ncplane* n, int ystart, int xstart, const nccell* c){
int ret = -1;
if(ystart < 0){
if(ystart != -1){
logerror("invalid ystart: %d\n", ystart);
logerror("invalid y: %d\n", ystart);
return -1;
}
ystart = n->y;
@ -71,7 +79,7 @@ int ncplane_polyfill_yx(ncplane* n, int ystart, int xstart, const nccell* c){
unsigned y = ystart;
if(xstart < 0){
if(xstart != -1){
logerror("invalid xstart: %d\n", xstart);
logerror("invalid x: %d\n", xstart);
return -1;
}
xstart = n->x;
@ -88,11 +96,12 @@ int ncplane_polyfill_yx(ncplane* n, int ystart, int xstart, const nccell* c){
if(strcmp(fillegc, targ) == 0){
return 0;
}
int ret = -1;
// we need an external copy of this, since we'll be writing to it on
// the first call into ncplane_polyfill_recurse()
// the first call into ncplane_polyfill_inner()
char* targcopy = strdup(targ);
if(targcopy){
ret = ncplane_polyfill_recurse(n, y, x, c, targcopy);
ret = ncplane_polyfill_inner(n, y, x, c, targcopy);
free(targcopy);
}
return ret;
@ -141,69 +150,6 @@ bool check_gradient_args(uint64_t ul, uint64_t ur, uint64_t bl, uint64_t br){
return false;
}
// takes a signed starting coordinate (where -1 indicates the cursor's
// position), and an unsigned vector (where 0 indicates "everything
// remaining", i.e. to the right and below). returns 0 iff everything
// is valid and on the plane, filling in 'ystart'/'xstart' with the
// (non-negative) starting coordinates and 'ylen'/'xlen with the
// (positive) dimensions of the affected area.
static int
check_geometry_args(const ncplane* n, int y, int x,
unsigned* ylen, unsigned* xlen,
unsigned* ystart, unsigned* xstart){
// handle the special -1 case for y/x, and reject other negatives
if(y < 0){
if(y != -1){
logerror("invalid y: %d\n", y);
return -1;
}
y = n->y;
}
if(x < 0){
if(x != -1){
logerror("invalid x: %d\n", x);
return -1;
}
x = n->x;
}
// y and x are both now definitely positive, but might be off-plane.
// lock in y and x as ystart and xstart for unsigned comparisons.
*ystart = y;
*xstart = x;
unsigned ymax, xmax;
ncplane_dim_yx(n, &ymax, &xmax);
if(*ystart >= ymax || *xstart >= xmax){
logerror("invalid starting coordinates: %u/%u\n", *ystart, *xstart);
return -1;
}
// handle the special 0 case for ylen/xlen
if(*ylen == 0){
*ylen = ymax - *ystart;
}
if(*xlen == 0){
*xlen = xmax - *xstart;
}
// ensure ylen/xlen are on-plane
if(*ylen > ymax){
logerror("ylen > dimy %u > %u\n", *ylen, ymax);
return -1;
}
if(*xlen > xmax){
logerror("xlen > dimx %u > %u\n", *xlen, xmax);
return -1;
}
// ensure x + xlen and y + ylen are on-plane, without overflow
if(ymax - *ylen < *ystart){
logerror("y + ylen > ymax %u + %u > %u\n", *ystart, *ylen, ymax);
return -1;
}
if(xmax - *xlen < *xstart){
logerror("x + xlen > xmax %u + %u > %u\n", *xstart, *xlen, xmax);
return -1;
}
return 0;
}
// calculate both channels of a gradient at a particular point, knowing that
// we're using double halfblocks, into `c`->channels.
static inline void
@ -248,7 +194,7 @@ int ncplane_gradient2x1(ncplane* n, int y, int x, unsigned ylen, unsigned xlen,
if(pool_blit_direct(&n->pool, targc, "", strlen(""), 1) <= 0){
return -1;
}
calc_highgradient(targc, ul, ur, ll, lr, yy - ystart, xx - xstart, ylen, xlen);
calc_highgradient(targc, ul, ur, ll, lr, yy - ystart, xx - xstart, ylen * 2, xlen);
++total;
}
}

@ -1448,6 +1448,69 @@ int drop_signals(void* nc);
int block_signals(sigset_t* old_blocked_signals);
int unblock_signals(const sigset_t* old_blocked_signals);
// takes a signed starting coordinate (where -1 indicates the cursor's
// position), and an unsigned vector (where 0 indicates "everything
// remaining", i.e. to the right and below). returns 0 iff everything
// is valid and on the plane, filling in 'ystart'/'xstart' with the
// (non-negative) starting coordinates and 'ylen'/'xlen with the
// (positive) dimensions of the affected area.
static inline int
check_geometry_args(const ncplane* n, int y, int x,
unsigned* ylen, unsigned* xlen,
unsigned* ystart, unsigned* xstart){
// handle the special -1 case for y/x, and reject other negatives
if(y < 0){
if(y != -1){
logerror("invalid y: %d\n", y);
return -1;
}
y = n->y;
}
if(x < 0){
if(x != -1){
logerror("invalid x: %d\n", x);
return -1;
}
x = n->x;
}
// y and x are both now definitely positive, but might be off-plane.
// lock in y and x as ystart and xstart for unsigned comparisons.
*ystart = y;
*xstart = x;
unsigned ymax, xmax;
ncplane_dim_yx(n, &ymax, &xmax);
if(*ystart >= ymax || *xstart >= xmax){
logerror("invalid starting coordinates: %u/%u\n", *ystart, *xstart);
return -1;
}
// handle the special 0 case for ylen/xlen
if(*ylen == 0){
*ylen = ymax - *ystart;
}
if(*xlen == 0){
*xlen = xmax - *xstart;
}
// ensure ylen/xlen are on-plane
if(*ylen > ymax){
logerror("ylen > dimy %u > %u\n", *ylen, ymax);
return -1;
}
if(*xlen > xmax){
logerror("xlen > dimx %u > %u\n", *xlen, xmax);
return -1;
}
// ensure x + xlen and y + ylen are on-plane, without overflow
if(ymax - *ylen < *ystart){
logerror("y + ylen > ymax %u + %u > %u\n", *ystart, *ylen, ymax);
return -1;
}
if(xmax - *xlen < *xstart){
logerror("x + xlen > xmax %u + %u > %u\n", *xstart, *xlen, xmax);
return -1;
}
return 0;
}
void ncvisual_printbanner(fbuf* f);
// alpha comes to us 0--255, but we have only 3 alpha values to map them to
@ -1615,6 +1678,27 @@ resize_bitmap(const uint32_t* bmap, int srows, int scols, size_t sstride,
return ret;
}
// a neighbor on which to polyfill. by the time we get to it, it might or
// might not have been filled in. if so, discard immediately. otherwise,
// check self, and if valid, push all neighbors.
struct topolyfill {
int y, x;
struct topolyfill* next;
};
static inline struct topolyfill*
create_polyfill_op(int y, int x, struct topolyfill** stck){
// cast for the benefit of c++ callers
struct topolyfill* n = (struct topolyfill*)malloc(sizeof(*n));
if(n){
n->y = y;
n->x = x;
n->next = *stck;
*stck = n;
}
return n;
}
// implemented by a multimedia backend (ffmpeg or oiio), and installed
// prior to calling notcurses_core_init() (by notcurses_init()).
typedef struct ncvisual_implementation {

@ -22,8 +22,9 @@ detect_utf8(void){
}
}
const char *ncmetric(uintmax_t val, uintmax_t decimal, char *buf, int omitdec,
uintmax_t mult, int uprefix){
const char* ncnmetric(uintmax_t val, size_t s, uintmax_t decimal,
char* buf, int omitdec, uintmax_t mult,
int uprefix){
// FIXME this is global to the process...ick :/
fesetround(FE_TONEAREST);
pthread_once(&utf8_detector, detect_utf8);
@ -70,15 +71,17 @@ const char *ncmetric(uintmax_t val, uintmax_t decimal, char *buf, int omitdec,
// 1,024). That can overflow with large 64-bit values, but we can first
// divide both sides by mult, and then scale by 100.
if(omitdec && (val % dv) == 0){
sprintfed = sprintf(buf, "%" PRIu64 "%lc", (uint64_t)(val / dv),
sprintfed = snprintf(buf, s, "%" PRIu64 "%lc", (uint64_t)(val / dv),
(wint_t)prefixes[consumed - 1]);
}else{
sprintfed = sprintf(buf, "%.2f%lc", (double)val / dv,
sprintfed = snprintf(buf, s, "%.2f%lc", (double)val / dv,
(wint_t)prefixes[consumed - 1]);
}
if(uprefix){
buf[sprintfed] = uprefix;
buf[sprintfed + 1] = '\0';
if((size_t)sprintfed < s){
buf[sprintfed] = uprefix;
buf[++sprintfed] = '\0';
}
}
return buf;
}
@ -86,22 +89,29 @@ const char *ncmetric(uintmax_t val, uintmax_t decimal, char *buf, int omitdec,
// val / decimal < dv (or we ran out of prefixes)
if(omitdec && val % decimal == 0){
if(consumed){
sprintfed = sprintf(buf, "%" PRIu64 "%lc", (uint64_t)(val / decimal),
sprintfed = snprintf(buf, s, "%" PRIu64 "%lc", (uint64_t)(val / decimal),
(wint_t)subprefixes[consumed - 1]);
}else{
sprintfed = sprintf(buf, "%" PRIu64, (uint64_t)(val / decimal));
sprintfed = snprintf(buf, s, "%" PRIu64, (uint64_t)(val / decimal));
}
}else{
if(consumed){
sprintfed = sprintf(buf, "%.2f%lc", (double)val / decimal,
sprintfed = snprintf(buf, s, "%.2f%lc", (double)val / decimal,
(wint_t)subprefixes[consumed - 1]);
}else{
sprintfed = sprintf(buf, "%.2f", (double)val / decimal);
sprintfed = snprintf(buf, s, "%.2f", (double)val / decimal);
}
}
if(consumed && uprefix){
buf[sprintfed] = uprefix;
buf[sprintfed + 1] = '\0';
if((size_t)sprintfed < s){
buf[sprintfed] = uprefix;
buf[++sprintfed] = '\0';
}
}
return buf;
}
const char *ncmetric(uintmax_t val, uintmax_t decimal, char *buf, int omitdec,
uintmax_t mult, int uprefix){
return ncnmetric(val, SIZE_MAX, decimal, buf, omitdec, mult, uprefix);
}

@ -1994,6 +1994,7 @@ int ncplane_vline_interp(ncplane* n, const nccell* c, unsigned len,
return ret;
}
// we must have at least 2x2, or it's an error
int ncplane_box(ncplane* n, const nccell* ul, const nccell* ur,
const nccell* ll, const nccell* lr, const nccell* hl,
const nccell* vl, unsigned ystop, unsigned xstop,
@ -2845,23 +2846,11 @@ is_bg_p(int idx, int py, int px, int width){
static inline uint32_t*
ncplane_as_rgba_internal(const ncplane* nc, ncblitter_e blit,
unsigned begy, unsigned begx, unsigned leny,
unsigned lenx, unsigned* pxdimy, unsigned* pxdimx){
int begy, int begx, unsigned leny, unsigned lenx,
unsigned* pxdimy, unsigned* pxdimx){
const notcurses* ncur = ncplane_notcurses_const(nc);
if(begx >= (unsigned)nc->lenx || begy >= (unsigned)nc->leny){
logerror("invalid origin (%u,%u)\n", begy, begx);
return NULL;
}
if(lenx == 0){ // -1 means "to the end"; use all space available
lenx = nc->lenx - begx;
}
if(leny == 0){
leny = nc->leny - begy;
}
//fprintf(stderr, "sum: %d/%d avail: %d/%d\n", begy + leny, begx + lenx, nc->leny, nc->lenx);
if(nc->lenx - begx < lenx || nc->leny - begy < leny){
logerror("invalid specs %u + %u > %d or %u + %u > %d\n",
begx, lenx, nc->lenx, begy, leny, nc->leny);
unsigned ystart, xstart;
if(check_geometry_args(nc, begy, begx, &leny, &lenx, &ystart, &xstart)){
return NULL;
}
if(blit == NCBLIT_PIXEL){ // FIXME extend this to support sprixels
@ -2887,8 +2876,8 @@ ncplane_as_rgba_internal(const ncplane* nc, ncblitter_e blit,
uint32_t* ret = malloc(sizeof(*ret) * lenx * bset->width * leny * bset->height);
//fprintf(stderr, "GEOM: %d/%d %d/%d ret: %p\n", bset->height, bset->width, *pxdimy, *pxdimx, ret);
if(ret){
for(unsigned y = begy, targy = 0 ; y < begy + leny ; ++y, targy += bset->height){
for(unsigned x = begx, targx = 0 ; x < begx + lenx ; ++x, targx += bset->width){
for(unsigned y = ystart, targy = 0 ; y < ystart + leny ; ++y, targy += bset->height){
for(unsigned x = xstart, targx = 0 ; x < xstart + lenx ; ++x, targx += bset->width){
uint16_t stylemask;
uint64_t channels;
char* c = ncplane_at_yx(nc, y, x, &stylemask, &channels);
@ -2941,7 +2930,7 @@ ncplane_as_rgba_internal(const ncplane* nc, ncblitter_e blit,
}
uint32_t* ncplane_as_rgba(const ncplane* nc, ncblitter_e blit,
unsigned begy, unsigned begx, unsigned leny,
int begy, int begx, unsigned leny,
unsigned lenx, unsigned* pxdimy, unsigned* pxdimx){
unsigned px, py;
if(!pxdimy){
@ -2955,39 +2944,15 @@ uint32_t* ncplane_as_rgba(const ncplane* nc, ncblitter_e blit,
// return a heap-allocated copy of the contents
char* ncplane_contents(ncplane* nc, int begy, int begx, unsigned leny, unsigned lenx){
if(begy < 0){
if(begy != -1){
logerror("invalid y coordinate: %d\n", begy);
}
begy = nc->y;
}
if(begx < 0){
if(begx != -1){
logerror("invalid x coordinate: %d\n", begx);
}
begx = nc->x;
}
if((unsigned)begx >= nc->lenx || (unsigned)begy >= nc->leny){
logerror("beginning coordinates (%d/%d) exceeded area (%u/%u)\n",
begy, begx, nc->leny, nc->lenx);
return NULL;
}
if(lenx == 0){ // 0 means "to the end"; use all space available
lenx = nc->lenx - begx;
}
if(leny == 0){
leny = nc->leny - begy;
}
if(nc->lenx - begx < lenx || nc->leny - begy < leny){
logerror("ending coordinates (%u/%u) exceeded lengths (%u/%u)\n",
begy + leny, begx + lenx, nc->leny, nc->lenx);
unsigned ystart, xstart;
if(check_geometry_args(nc, begy, begx, &leny, &lenx, &ystart, &xstart)){
return NULL;
}
size_t retlen = 1;
char* ret = malloc(retlen);
if(ret){
for(unsigned y = begy, targy = 0 ; y < begy + leny ; ++y, targy += 2){
for(unsigned x = begx, targx = 0 ; x < begx + lenx ; ++x, ++targx){
for(unsigned y = ystart, targy = 0 ; y < ystart + leny ; ++y, targy += 2){
for(unsigned x = xstart, targx = 0 ; x < xstart + lenx ; ++x, ++targx){
nccell ncl = CELL_TRIVIAL_INITIALIZER;
// we need ncplane_at_yx_cell() here instead of ncplane_at_yx(),
// because we should only have one copy of each wide EGC.

@ -61,10 +61,10 @@ ncreader_redraw(ncreader* n){
assert(n->xproject >= 0);
assert(n->textarea->lenx >= n->ncp->lenx);
assert(n->textarea->leny >= n->ncp->leny);
for(int y = 0 ; y < n->ncp->leny ; ++y){
const int texty = y;
for(int x = 0 ; x < n->ncp->lenx ; ++x){
const int textx = x + n->xproject;
for(unsigned y = 0 ; y < n->ncp->leny ; ++y){
const unsigned texty = y;
for(unsigned x = 0 ; x < n->ncp->lenx ; ++x){
const unsigned textx = x + n->xproject;
const nccell* src = &n->textarea->fb[nfbcellidx(n->textarea, texty, textx)];
nccell* dst = &n->ncp->fb[nfbcellidx(n->ncp, y, x)];
//fprintf(stderr, "projecting %d/%d [%s] to %d/%d [%s]\n", texty, textx, cell_extended_gcluster(n->textarea, src), y, x, cell_extended_gcluster(n->ncp, dst));
@ -121,9 +121,9 @@ int ncreader_move_left(ncreader* n){
// row. if on the right side of the viewarea, but not the right side of the
// textarea, pans right. returns 0 if a move was made.
int ncreader_move_right(ncreader* n){
int viewx = n->ncp->x;
int textx = n->textarea->x;
int y = n->ncp->y;
unsigned textx = n->textarea->x;
unsigned y = n->ncp->y;
unsigned viewx = n->ncp->x;
//fprintf(stderr, "moving right: tcurs: %dx%d vcurs: %dx%d xproj: %d\n", y, textx, y, viewx, n->xproject);
if(textx >= n->textarea->lenx - 1){
// are we on the last column of the textarea? if so, we must also be on
@ -171,7 +171,7 @@ int ncreader_move_up(ncreader* n){
// try to move down. does not move past the bottom of the textarea.
// returns 0 if a move was made.
int ncreader_move_down(ncreader* n){
int y = n->ncp->y;
unsigned y = n->ncp->y;
if(y >= n->textarea->leny - 1){
// are we on the last row of the textarea? if so, we can't move.
return -1;
@ -190,14 +190,14 @@ int ncreader_write_egc(ncreader* n, const char* egc){
logerror("Fed illegal UTF-8 [%s]\n", egc);
return -1;
}
if(n->textarea->x >= n->textarea->lenx - cols){
if(n->textarea->x >= (int)n->textarea->lenx - cols){
if(n->horscroll){
if(ncplane_resize_simple(n->textarea, n->textarea->leny, n->textarea->lenx + cols)){
return -1;
}
++n->xproject;
}
}else if(n->ncp->x >= n->ncp->lenx){
}else if((unsigned)n->ncp->x >= n->ncp->lenx){
++n->xproject;
}
// use ncplane_putegc on both planes because it'll get cursor movement right
@ -207,12 +207,12 @@ int ncreader_write_egc(ncreader* n, const char* egc){
if(ncplane_putegc(n->ncp, egc, NULL) < 0){
return -1;
}
if(n->textarea->x >= n->textarea->lenx - cols){
if(n->textarea->x >= (int)n->textarea->lenx - cols){
if(!n->horscroll){
n->textarea->x = n->textarea->lenx - cols;
}
}
if(n->ncp->x >= n->ncp->lenx - cols){
if(n->ncp->x >= (int)n->ncp->lenx - cols){
n->ncp->x = n->ncp->lenx - cols;
}
ncreader_redraw(n);
@ -275,7 +275,7 @@ ncreader_ctrl_input(ncreader* n, const ncinput* ni){
}
break;
case 'E': // cursor to end of line
while(n->textarea->x < ncplane_dim_x(n->textarea) - 1){
while(n->textarea->x < (int)ncplane_dim_x(n->textarea) - 1){
if(ncreader_move_right(n)){
break;
}
@ -320,7 +320,7 @@ ncreader_alt_input(ncreader* n, const ncinput* ni){
}
break;
case 'f': // forward one word (past end cell)
while(n->textarea->x < ncplane_dim_x(n->textarea) - 1){
while(n->textarea->x < (int)ncplane_dim_x(n->textarea) - 1){
if(ncreader_move_right(n)){
break;
}

@ -186,7 +186,10 @@ tablet_geom(const ncreel* nr, nctablet* t, int* begx, int* begy,
//fprintf(stderr, "jigsawing %p with %d/%d dir %d\n", t, frontiertop, frontierbottom, direction);
*begy = 0;
*begx = 0;
ncplane_dim_yx(nr->p, leny, lenx);
unsigned uleny, ulenx;
ncplane_dim_yx(nr->p, &uleny, &ulenx);
*leny = uleny;
*lenx = ulenx;
if(frontiertop < 0){
if(direction == DIRECTION_UP){
return -1;
@ -501,14 +504,15 @@ tighten_reel_down(ncreel* r, int ybot){
if(cur->p == NULL){
break;
}
int cury, curx, ylen;
int cury, curx;
unsigned ylen;
ncplane_yx(cur->p, &cury, &curx);
ncplane_dim_yx(cur->p, &ylen, NULL);
if(cury <= ybot - ylen - 1){
if(cury <= ybot - (int)ylen - 1){
break;
}
//fprintf(stderr, "tightening %p down to %d from %d\n", cur, ybot - ylen, cury);
cury = ybot - ylen;
cury = ybot - (int)ylen;
ncplane_move_yx(cur->p, cury, curx);
ybot = cury - 1;
if((cur = cur->prev) == r->tablets){
@ -580,7 +584,7 @@ tighten_reel(ncreel* r){
const int ybot = rylen - 1 + !!(r->ropts.bordermask & NCBOXMASK_BOTTOM);
// FIXME want to tighten down whenever we're at the bottom, and the reel
// is full, not just in this case (this can leave a gap of more than 1 row)
if(yoff + ylen + 1 >= ybot){
if(yoff + (int)ylen + 1 >= ybot){
if(tighten_reel_down(r, ybot)){
return -1;
}

@ -19,16 +19,16 @@ typedef struct ncselector {
unsigned selected; // index of selection
unsigned startdisp; // index of first option displayed
unsigned maxdisplay; // max number of items to display, 0 -> no limit
int longop; // columns occupied by longest option
int longdesc; // columns occupied by longest description
unsigned longop; // columns occupied by longest option
unsigned longdesc; // columns occupied by longest description
struct ncselector_int* items; // list of items and descriptions, heap-copied
unsigned itemcount; // number of pairs in 'items'
char* title; // can be NULL, in which case there's no riser
int titlecols; // columns occupied by title
unsigned titlecols; // columns occupied by title
char* secondary; // can be NULL
int secondarycols; // columns occupied by secondary
unsigned secondarycols; // columns occupied by secondary
char* footer; // can be NULL
int footercols; // columns occupied by footer
unsigned footercols; // columns occupied by footer
uint64_t opchannels; // option channels
uint64_t descchannels; // description channels
uint64_t titlechannels; // title channels
@ -42,15 +42,15 @@ typedef struct ncmultiselector {
unsigned current; // index of highlighted item
unsigned startdisp; // index of first option displayed
unsigned maxdisplay; // max number of items to display, 0 -> no limit
int longitem; // columns occupied by longest item
unsigned longitem; // columns occupied by longest item
struct ncmselector_int* items; // items, descriptions, and statuses, heap-copied
unsigned itemcount; // number of pairs in 'items'
char* title; // can be NULL, in which case there's no riser
unsigned titlecols; // columns occupied by title
char* secondary; // can be NULL
int secondarycols; // columns occupied by secondary
unsigned secondarycols; // columns occupied by secondary
char* footer; // can be NULL
int footercols; // columns occupied by footer
unsigned footercols; // columns occupied by footer
uint64_t opchannels; // option channels
uint64_t descchannels; // description channels
uint64_t titlechannels; // title channels
@ -62,7 +62,7 @@ typedef struct ncmultiselector {
// ideal body width given the ncselector's items and secondary/footer
static int
ncselector_body_width(const ncselector* n){
int cols = 0;
unsigned cols = 0;
// the body is the maximum of
// * longop + longdesc + 5
// * secondary + 2
@ -162,7 +162,7 @@ ncselector_draw(ncselector* n){
// Top line of body (background and possibly up arrow)
++yoff;
ncplane_cursor_move_yx(n->ncp, yoff, xoff + 1);
for(int i = xoff + 1 ; i < dimx - 1 ; ++i){
for(unsigned i = xoff + 1 ; i < dimx - 1 ; ++i){
nccell transc = CELL_TRIVIAL_INITIALIZER; // fall back to base cell
ncplane_putc(n->ncp, &transc);
}
@ -181,12 +181,12 @@ ncselector_draw(ncselector* n){
n->uarrowy = yoff;
unsigned printidx = n->startdisp;
unsigned printed = 0;
for(yoff += 1 ; yoff < dimy - 2 ; ++yoff){
for(yoff += 1 ; yoff < (int)dimy - 2 ; ++yoff){
if(n->maxdisplay && printed == n->maxdisplay){
break;
}
ncplane_cursor_move_yx(n->ncp, yoff, xoff + 1);
for(int i = xoff + 1 ; i < dimx - 1 ; ++i){
for(int i = xoff + 1 ; i < (int)dimx - 1 ; ++i){
nccell transc = CELL_TRIVIAL_INITIALIZER; // fall back to base cell
ncplane_putc(n->ncp, &transc);
}
@ -207,7 +207,7 @@ ncselector_draw(ncselector* n){
}
// Bottom line of body (background and possibly down arrow)
ncplane_cursor_move_yx(n->ncp, yoff, xoff + 1);
for(int i = xoff + 1 ; i < dimx - 1 ; ++i){
for(int i = xoff + 1 ; i < (int)dimx - 1 ; ++i){
nccell transc = CELL_TRIVIAL_INITIALIZER; // fall back to base cell
ncplane_putc(n->ncp, &transc);
}
@ -225,8 +225,8 @@ ncselector_draw(ncselector* n){
// calculate the necessary dimensions based off properties of the selector
static void
ncselector_dim_yx(const ncselector* n, int* ncdimy, int* ncdimx){
int rows = 0, cols = 0; // desired dimensions
ncselector_dim_yx(const ncselector* n, unsigned* ncdimy, unsigned* ncdimx){
unsigned rows = 0, cols = 0; // desired dimensions
const ncplane* parent = ncplane_parent(n->ncp);
unsigned dimy, dimx; // dimensions of containing plane
ncplane_dim_yx(parent, &dimy, &dimx);
@ -305,13 +305,21 @@ 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 cols = ncstrwidth(src->option);
int unsafe = ncstrwidth(src->option);
if(unsafe < 0){
goto freeitems;
}
unsigned cols = unsafe;
ns->items[ns->itemcount].opcolumns = cols;
if(cols > ns->longop){
ns->longop = cols;
}
const char *desc = src->desc ? src->desc : "";
cols = ncstrwidth(desc);
unsafe = ncstrwidth(desc);
if(unsafe < 0){
goto freeitems;
}
cols = unsafe;
ns->items[ns->itemcount].desccolumns = cols;
if(cols > ns->longdesc){
ns->longdesc = cols;
@ -324,7 +332,7 @@ ncselector* ncselector_create(ncplane* n, const ncselector_options* opts){
goto freeitems;
}
}
int dimy, dimx;
unsigned dimy, dimx;
ns->ncp = n;
ncselector_dim_yx(ns, &dimy, &dimx);
if(ncplane_resize_simple(n, dimy, dimx)){
@ -347,7 +355,7 @@ freeitems:
}
int ncselector_additem(ncselector* n, const struct ncselector_item* item){
int origdimy, origdimx;
unsigned origdimy, origdimx;
ncselector_dim_yx(n, &origdimy, &origdimx);
size_t newsize = sizeof(*n->items) * (n->itemcount + 1);
struct ncselector_int* items = realloc(n->items, newsize);
@ -358,7 +366,11 @@ 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 cols = ncstrwidth(item->option);
int usafecols = ncstrwidth(item->option);
if(usafecols < 0){
return -1;
}
unsigned cols = usafecols;
n->items[n->itemcount].opcolumns = cols;
if(cols > n->longop){
n->longop = cols;
@ -369,7 +381,7 @@ int ncselector_additem(ncselector* n, const struct ncselector_item* item){
n->longdesc = cols;
}
++n->itemcount;
int dimy, dimx;
unsigned dimy, dimx;
ncselector_dim_yx(n, &dimy, &dimx);
if(origdimx < dimx || origdimy < dimy){ // resize if too small
ncplane_resize_simple(n->ncp, dimy, dimx);
@ -378,7 +390,7 @@ int ncselector_additem(ncselector* n, const struct ncselector_item* item){
}
int ncselector_delitem(ncselector* n, const char* item){
int origdimy, origdimx;
unsigned origdimy, origdimx;
ncselector_dim_yx(n, &origdimy, &origdimx);
bool found = false;
int maxop = 0, maxdesc = 0;
@ -410,7 +422,7 @@ int ncselector_delitem(ncselector* n, const char* item){
if(found){
n->longop = maxop;
n->longdesc = maxdesc;
int dimy, dimx;
unsigned dimy, dimx;
ncselector_dim_yx(n, &dimy, &dimx);
if(origdimx > dimx || origdimy > dimy){ // resize if too big
ncplane_resize_simple(n->ncp, dimy, dimx);
@ -560,9 +572,9 @@ ncplane* ncmultiselector_plane(ncmultiselector* n){
}
// ideal body width given the ncselector's items and secondary/footer
static int
static unsigned
ncmultiselector_body_width(const ncmultiselector* n){
int cols = 0;
unsigned cols = 0;
// the body is the maximum of
// * longop + longdesc + 5
// * secondary + 2
@ -589,7 +601,7 @@ ncmultiselector_draw(ncmultiselector* n){
// if we have a title, we'll draw a riser. the riser is two rows tall, and
// exactly four columns longer than the title, and aligned to the right. we
// draw a rounded box. the body will blow part or all of the bottom away.
int yoff = 0;
unsigned yoff = 0;
if(n->title){
size_t riserwidth = n->titlecols + 4;
int offx = ncplane_halign(n->ncp, NCALIGN_RIGHT, riserwidth);
@ -649,7 +661,7 @@ ncmultiselector_draw(ncmultiselector* n){
// Top line of body (background and possibly up arrow)
++yoff;
ncplane_cursor_move_yx(n->ncp, yoff, xoff + 1);
for(int i = xoff + 1 ; i < dimx - 1 ; ++i){
for(unsigned i = xoff + 1 ; i < dimx - 1 ; ++i){
nccell transc = CELL_TRIVIAL_INITIALIZER; // fall back to base cell
ncplane_putc(n->ncp, &transc);
}
@ -670,7 +682,7 @@ ncmultiselector_draw(ncmultiselector* n){
break;
}
ncplane_cursor_move_yx(n->ncp, yoff, xoff + 1);
for(int i = xoff + 1 ; i < dimx - 1 ; ++i){
for(unsigned i = xoff + 1 ; i < dimx - 1 ; ++i){
nccell transc = CELL_TRIVIAL_INITIALIZER; // fall back to base cell
ncplane_putc(n->ncp, &transc);
}
@ -700,7 +712,7 @@ ncmultiselector_draw(ncmultiselector* n){
}
// Bottom line of body (background and possibly down arrow)
ncplane_cursor_move_yx(n->ncp, yoff, xoff + 1);
for(int i = xoff + 1 ; i < dimx - 1 ; ++i){
for(unsigned i = xoff + 1 ; i < dimx - 1 ; ++i){
nccell transc = CELL_TRIVIAL_INITIALIZER; // fall back to base cell
ncplane_putc(n->ncp, &transc);
}
@ -899,11 +911,19 @@ 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 cols = ncstrwidth(src->option);
int unsafe = ncstrwidth(src->option);
if(unsafe < 0){
goto freeitems;
}
unsigned cols = unsafe;
if(cols > ns->longitem){
ns->longitem = cols;
}
int cols2 = ncstrwidth(src->desc);
unsafe = ncstrwidth(src->desc);
if(unsafe < 0){
goto freeitems;
}
unsigned cols2 = unsafe;
if(cols + cols2 > ns->longitem){
ns->longitem = cols + cols2;
}

@ -1193,7 +1193,7 @@ ncplane* ncvisual_render(notcurses* nc, ncvisual* ncv, const struct ncvisual_opt
}
ncvisual* ncvisual_from_plane(const ncplane* n, ncblitter_e blit,
unsigned begy, unsigned begx,
int begy, int begx,
unsigned leny, unsigned lenx){
unsigned py, px;
uint32_t* rgba = ncplane_as_rgba(n, blit, begy, begx, leny, lenx, &py, &px);
@ -1269,26 +1269,6 @@ int ncvisual_at_yx(const ncvisual* n, unsigned y, unsigned x, uint32_t* pixel){
return 0;
}
// a neighbor on which to polyfill. by the time we get to it, it might or
// might not have been filled in. if so, discard immediately. otherwise,
// check self, and if valid, push all neighbors.
struct topolyfill {
int y, x;
struct topolyfill* next;
};
static inline struct topolyfill*
create_polyfill_op(int y, int x, struct topolyfill** stack){
struct topolyfill* n = malloc(sizeof(*n));
if(n){
n->y = y;
n->x = x;
n->next = *stack;
*stack = n;
}
return n;
}
// originally i wrote this recursively, at which point it promptly began
// exploding once i multithreaded the [yield] demo. hence the clumsy stack
// and hand-rolled iteration. alas, poor yorick!
@ -1314,6 +1294,7 @@ ncvisual_polyfill_core(ncvisual* n, unsigned y, unsigned x, uint32_t rgba, uint3
*pixel = rgba;
if(y){
if(create_polyfill_op(y - 1, x, &stack) == NULL){
// FIXME need free stack!
return -1;
}
}

@ -74,13 +74,14 @@ int main(int argc, char **argv){
totalb += conv;
add_wchar(&wbuf, &bufsize, &used, w);
}
int y, x, newy, newx;
putchar('\n');
unsigned y, x;
ncdirect_cursor_yx(n, &y, &x);
printf("%s", *argv);
fflush(stdout);
unsigned newy, newx;
ncdirect_cursor_yx(n, &newy, &newx);
int realcols = (newx - x) + ncdirect_dim_x(n) * (newy - y);
unsigned realcols = (newx - x) + ncdirect_dim_x(n) * (newy - y);
printf("\n iterated wcwidth: %d total bytes: %llu wcswidth: %d true width: %d\n\n",
totalcols, (unsigned long long)totalb, wcswidth(wbuf, used), realcols);
ncdirect_cursor_yx(n, &y, &x);
@ -123,7 +124,7 @@ int main(int argc, char **argv){
}
ncdirect_set_fg_default(n);
ncdirect_set_bg_default(n);
for(int z = 0 ; z < realcols && z < ncdirect_dim_x(n) ; ++z){
for(unsigned z = 0 ; z < realcols && z < ncdirect_dim_x(n) ; ++z){
putchar('0' + z % 10);
}
if(realcols < ncdirect_dim_x(n)){

@ -10,7 +10,7 @@ int main(void){
if(!nc){
return EXIT_FAILURE;
}
int dimy, dimx;
unsigned dimy, dimx;
struct ncplane* n = notcurses_stddim_yx(nc, &dimy, &dimx);
ncplane_printf_yx(n, dimy / 2 - 2, 0, "ࡢ‎ࡣ‎ࡤ‎ࡥ‎ࡦ‎ࡧ‎ࡨ‎ࡩ‎ࡪ‎ࢠ‎ࢡ‎ࢢ‎ࢣ‎ࢤ‎ࢥ‎ࢦ‎ࢧ‎ࢨ‎ࢩ‎ࢪ‎ࢫ‎ࢬ‎ࢭ‎ࢮ‎ࢯ‎ࢰ‎ࢱ‎ࢲ‎ࢳ‎ࢴ‎ࢶ‎ࢷ‎ࢸ‎ࢹ‎ࢺ‎ࢻ‎ࢼ‎ࢽ‎࣢ः");
ncplane_printf_yx(n, dimy / 2 - 1, 0, "࠲‎࠳‎࠴‎࠵‎࠶‎࠷‎࠸‎࠹‎࠺‎࠻‎࠼‎࠽‎࠾‎ࡀ‎ࡁ‎ࡂ‎ࡃ‎ࡄ‎ࡅ‎ࡆ‎ࡇ‎ࡈ‎ࡉ‎ࡊ‎ࡋ‎ࡌ‎ࡍ‎ࡎ‎ࡏ‎ࡐ‎ࡑ‎ࡒ‎ࡓ‎ࡔ‎ࡕ‎ࡖ‎ࡗ‎ࡘ‎࡞‎ࡡ");

@ -7,7 +7,7 @@
static int
across_row(struct notcurses* nc, int y, struct ncplane* n, struct ncplane* t,
const struct timespec* ds){
for(int x = 0 ; x < ncplane_dim_x(n) ; ++x){
for(unsigned x = 0 ; x < ncplane_dim_x(n) ; ++x){
if(ncplane_move_yx(t, y, x)){
return -1;
}
@ -21,7 +21,7 @@ across_row(struct notcurses* nc, int y, struct ncplane* n, struct ncplane* t,
static int
across_bmap(struct notcurses* nc, struct ncplane* n, struct ncplane* t, const struct timespec* ds){
for(int y = 0 ; y < ncplane_dim_y(n) - 1 ; ++y){
for(unsigned y = 0 ; y < ncplane_dim_y(n) - 1 ; ++y){
if(across_row(nc, y, n, t, ds)){
return -1;
}

@ -577,7 +577,9 @@ TEST_CASE("Fills") {
const char* qr = "a very simple qr code";
unsigned dimy, dimx;
ncplane_dim_yx(n_, &dimy, &dimx);
CHECK(0 < ncplane_qrcode(n_, &dimy, &dimx, qr, strlen(qr)));
int sdimy = dimy;
int sdimx = dimx;
CHECK(0 < ncplane_qrcode(n_, &sdimy, &sdimx, qr, strlen(qr)));
CHECK(0 == notcurses_render(nc_));
}
#endif

Loading…
Cancel
Save