diff --git a/README.md b/README.md index 58a9faf65..99de15ecb 100644 --- a/README.md +++ b/README.md @@ -1126,6 +1126,10 @@ ncplane_bg_rgb(const struct ncplane* n, unsigned* r, unsigned* g, unsigned* int ncplane_set_fg_rgb(struct ncplane* n, int r, int g, int b); int ncplane_set_bg_rgb(struct ncplane* n, int r, int g, int b); +// Same, but clipped to [0..255]. +void ncplane_set_bg_rgb_clipped(struct ncplane* n, int r, int g, int b); +void ncplane_set_fg_rgb_clipped(struct ncplane* n, int r, int g, int b); + // Same, but with rgb assembled into a channel (i.e. lower 24 bits). int ncplane_set_fg(struct ncplane* n, unsigned channel); int ncplane_set_bg(struct ncplane* n, unsigned channel); diff --git a/include/notcurses.h b/include/notcurses.h index 4df03e027..5d711ae76 100644 --- a/include/notcurses.h +++ b/include/notcurses.h @@ -862,6 +862,35 @@ channel_set_rgb(unsigned* channel, int r, int g, int b){ return 0; } +// Set the three 8-bit components of a 32-bit channel, and mark it as not using +// the default color. Retain the other bits unchanged. r, g, and b will be +// clipped to the range [0..255]. +static inline void +channel_set_rgb_clipped(unsigned* channel, int r, int g, int b){ + if(r >= 256){ + r = 255; + } + if(g >= 256){ + g = 255; + } + if(b >= 256){ + b = 255; + } + if(r <= -1){ + r = 0; + } + if(g <= -1){ + g = 0; + } + if(b <= -1){ + b = 0; + } + unsigned c = (r << 16u) | (g << 8u) | b; + c |= CELL_BGDEFAULT_MASK; + const uint64_t mask = CELL_BGDEFAULT_MASK | CELL_BG_MASK; + *channel = (*channel & ~mask) | c; +} + // Same, but provide an assembled, packed 24 bits of rgb. static inline int channel_set(unsigned* channel, unsigned rgb){ @@ -972,6 +1001,14 @@ channels_set_fg_rgb(uint64_t* channels, int r, int g, int b){ return 0; } +// Same, but clips to [0..255]. +static inline void +channels_set_fg_rgb_clipped(uint64_t* channels, int r, int g, int b){ + unsigned channel = channels_fchannel(*channels); + channel_set_rgb_clipped(&channel, r, g, b); + *channels = ((uint64_t)channel << 32llu) | (*channels & 0xffffffffllu); +} + // Set the r, g, and b channels for the background component of this 64-bit // 'channels' variable, and mark it as not using the default color. static inline int @@ -984,6 +1021,14 @@ channels_set_bg_rgb(uint64_t* channels, int r, int g, int b){ return 0; } +// Same, but clips to [0..255]. +static inline void +channels_set_bg_rgb_clipped(uint64_t* channels, int r, int g, int b){ + unsigned channel = channels_bchannel(*channels); + channel_set_rgb_clipped(&channel, r, g, b); + *channels = (*channels & 0xffffffff00000000llu) | channel; +} + // Same, but set an assembled 32 bit channel at once. static inline int channels_set_fg(uint64_t* channels, unsigned rgb){ @@ -1251,6 +1296,10 @@ ncplane_bg_rgb(const struct ncplane* n, unsigned* r, unsigned* g, unsigned* b){ API int ncplane_set_fg_rgb(struct ncplane* n, int r, int g, int b); API int ncplane_set_bg_rgb(struct ncplane* n, int r, int g, int b); +// Same, but clipped to [0..255]. +API void ncplane_set_bg_rgb_clipped(struct ncplane* n, int r, int g, int b); +API void ncplane_set_fg_rgb_clipped(struct ncplane* n, int r, int g, int b); + // Same, but with rgb assembled into a channel (i.e. lower 24 bits). API int ncplane_set_fg(struct ncplane* n, unsigned channel); API int ncplane_set_bg(struct ncplane* n, unsigned channel); diff --git a/src/lib/notcurses.c b/src/lib/notcurses.c index 6285eb3ab..c6806848f 100644 --- a/src/lib/notcurses.c +++ b/src/lib/notcurses.c @@ -902,17 +902,33 @@ uint32_t ncplane_attr(const ncplane* n){ } void ncplane_set_fg_default(struct ncplane* n){ + ncplane_lock(n); channels_set_fg_default(&n->channels); + ncplane_unlock(n); } void ncplane_set_bg_default(struct ncplane* n){ + ncplane_lock(n); channels_set_bg_default(&n->channels); + ncplane_unlock(n); +} + +void ncplane_set_bg_rgb_clipped(ncplane* n, int r, int g, int b){ + ncplane_lock(n); + channels_set_bg_rgb_clipped(&n->channels, r, g, b); + ncplane_unlock(n); } int ncplane_set_bg_rgb(ncplane* n, int r, int g, int b){ return channels_set_bg_rgb(&n->channels, r, g, b); } +void ncplane_set_fg_rgb_clipped(ncplane* n, int r, int g, int b){ + ncplane_lock(n); + channels_set_fg_rgb_clipped(&n->channels, r, g, b); + ncplane_unlock(n); +} + int ncplane_set_fg_rgb(ncplane* n, int r, int g, int b){ return channels_set_fg_rgb(&n->channels, r, g, b); } @@ -1058,7 +1074,7 @@ void ncplane_cursor_yx(ncplane* n, int* y, int* x){ static inline bool ncplane_cursor_stuck(const ncplane* n){ - return (n->x == n->lenx && n->y == n->leny); + return (n->x >= n->lenx && n->y >= n->leny); } static inline void