diff --git a/CMakeLists.txt b/CMakeLists.txt index bb736496b..beced0586 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ # 3.14.0 introduced NAME_WLE cmake_minimum_required(VERSION 3.14.0) -project(notcurses VERSION 2.4.0 +project(notcurses VERSION 2.4.1 DESCRIPTION "Blingful UI for modern terminal emulators" HOMEPAGE_URL "https://nick-black.com/dankwiki/index.php/notcurses" LANGUAGES C CXX) diff --git a/NEWS.md b/NEWS.md index 5d680655b..02a470433 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,10 +1,9 @@ This document attempts to list user-visible changes and any major internal rearrangements of Notcurses. -* 2.4.1 (not yet released) - * `notcurses_check_pixel_support()` still returns 0 if there is no support - for bitmap graphics, but now returns an `ncpixelimple_e` to differentiate - the pixel backend otherwise. This result is strictly informative. +* 2.4.2 (not yet released) + * You can now set a resize callback on the standard plane. + * Added `notcurses_getvec()`, providing batched input. * Added `NCOPTION_DRAIN_INPUT`. Notcurses now launches a thread to process input, so that it can respond to terminal messages with minimal latency. Input read from `stdin` intended for the client is buffered until @@ -14,6 +13,14 @@ rearrangements of Notcurses. continue reading). Likewise added `NCDIRECT_OPTION_DRAIN_INPUT`. * Removed a bunch of deprecated `static inline` functions from the headers. +* 2.4.1 (2021-09-12) + * `notcurses_check_pixel_support()` still returns 0 if there is no support + for bitmap graphics, but now returns an `ncpixelimple_e` to differentiate + the pixel backend otherwise. This result is strictly informative. + * Added `ncstrwidth_valid()`, which is like `ncstrwidth()` except that it + returns partial results in the case of an invalid character. `ncstrwidth()` + will become a `static line` wrapper of `ncstrwidth_valid()` in ABI3. + * 2.4.0 (2021-09-06) * Mouse events in the Linux console are now reported from GPM when built with `-DUSE_GPM=on`. diff --git a/cffi/notcurses-pydemo.1.md b/cffi/notcurses-pydemo.1.md index 6365dd237..a626067c8 100644 --- a/cffi/notcurses-pydemo.1.md +++ b/cffi/notcurses-pydemo.1.md @@ -1,6 +1,6 @@ % notcurses-pydemo(1) % nick black -% v2.4.0 +% v2.4.1 # NAME diff --git a/cffi/setup.py b/cffi/setup.py index 0069ac429..b34f67b18 100644 --- a/cffi/setup.py +++ b/cffi/setup.py @@ -34,7 +34,7 @@ def read(fname): setup( name="notcurses", - version="2.4.0", + version="2.4.1", packages=['notcurses'], scripts=['notcurses-pydemo', 'ncdirect-pydemo'], package_dir={'': 'src'}, diff --git a/doc/Doxyfile b/doc/Doxyfile index 30e65f6f3..88d77b72e 100644 --- a/doc/Doxyfile +++ b/doc/Doxyfile @@ -38,7 +38,7 @@ PROJECT_NAME = Notcurses # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 2.4.0 +PROJECT_NUMBER = 2.4.1 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/doc/man/index.html b/doc/man/index.html index 3bb2d5913..44dbaecd4 100644 --- a/doc/man/index.html +++ b/doc/man/index.html @@ -38,7 +38,7 @@ -

notcurses manual pages (v2.4.0)

+

notcurses manual pages (v2.4.1)

notcurses(3)—a blingful TUI library

Executables (section 1)

ncls—list files, displaying multimedia along with them
diff --git a/doc/man/man1/ncls.1.md b/doc/man/man1/ncls.1.md index 978eee5fb..d875cb40b 100644 --- a/doc/man/man1/ncls.1.md +++ b/doc/man/man1/ncls.1.md @@ -1,6 +1,6 @@ % ncls(1) % nick black -% v2.4.0 +% v2.4.1 # NAME diff --git a/doc/man/man1/ncneofetch.1.md b/doc/man/man1/ncneofetch.1.md index 32a17cbbf..8a099c1e6 100644 --- a/doc/man/man1/ncneofetch.1.md +++ b/doc/man/man1/ncneofetch.1.md @@ -1,6 +1,6 @@ % ncneofetch(1) % nick black -% v2.4.0 +% v2.4.1 # NAME diff --git a/doc/man/man1/ncplayer.1.md b/doc/man/man1/ncplayer.1.md index 2f247f530..24562ea50 100644 --- a/doc/man/man1/ncplayer.1.md +++ b/doc/man/man1/ncplayer.1.md @@ -1,6 +1,6 @@ % ncplayer(1) % nick black -% v2.4.0 +% v2.4.1 # NAME diff --git a/doc/man/man1/nctetris.1.md b/doc/man/man1/nctetris.1.md index e90d7339f..e37b46ca1 100644 --- a/doc/man/man1/nctetris.1.md +++ b/doc/man/man1/nctetris.1.md @@ -1,6 +1,6 @@ % nctetris(1) % nick black -% v2.4.0 +% v2.4.1 # NAME diff --git a/doc/man/man1/notcurses-demo.1.md b/doc/man/man1/notcurses-demo.1.md index 73d88e3de..8f593ea59 100644 --- a/doc/man/man1/notcurses-demo.1.md +++ b/doc/man/man1/notcurses-demo.1.md @@ -1,6 +1,6 @@ % notcurses-demo(1) % nick black -% v2.4.0 +% v2.4.1 # NAME diff --git a/doc/man/man1/notcurses-info.1.md b/doc/man/man1/notcurses-info.1.md index 6c3b50ac1..d9a6b6302 100644 --- a/doc/man/man1/notcurses-info.1.md +++ b/doc/man/man1/notcurses-info.1.md @@ -1,6 +1,6 @@ % notcurses-info(1) % nick black -% v2.4.0 +% v2.4.1 # NAME diff --git a/doc/man/man1/notcurses-input.1.md b/doc/man/man1/notcurses-input.1.md index c98f94d09..03a196d54 100644 --- a/doc/man/man1/notcurses-input.1.md +++ b/doc/man/man1/notcurses-input.1.md @@ -1,6 +1,6 @@ % notcurses-input(1) % nick black -% v2.4.0 +% v2.4.1 # NAME diff --git a/doc/man/man1/notcurses-tester.1.md b/doc/man/man1/notcurses-tester.1.md index 1e2d36ff6..4376b6e09 100644 --- a/doc/man/man1/notcurses-tester.1.md +++ b/doc/man/man1/notcurses-tester.1.md @@ -1,6 +1,6 @@ % notcurses-tester(1) % nick black -% v2.4.0 +% v2.4.1 # NAME diff --git a/doc/man/man3/notcurses.3.md b/doc/man/man3/notcurses.3.md index 305b4893a..6e7e8576c 100644 --- a/doc/man/man3/notcurses.3.md +++ b/doc/man/man3/notcurses.3.md @@ -1,6 +1,6 @@ % notcurses(3) % nick black -% v2.4.0 +% v2.4.1 # NAME diff --git a/doc/man/man3/notcurses_capabilities.3.md b/doc/man/man3/notcurses_capabilities.3.md index 04388cb64..55a08a4ac 100644 --- a/doc/man/man3/notcurses_capabilities.3.md +++ b/doc/man/man3/notcurses_capabilities.3.md @@ -1,6 +1,6 @@ % notcurses_capabilities(3) % nick black -% v2.4.0 +% v2.4.1 # NAME diff --git a/doc/man/man3/notcurses_cell.3.md b/doc/man/man3/notcurses_cell.3.md index 50fb701ab..d0c007074 100644 --- a/doc/man/man3/notcurses_cell.3.md +++ b/doc/man/man3/notcurses_cell.3.md @@ -1,6 +1,6 @@ % notcurses_cell(3) % nick black -% v2.4.0 +% v2.4.1 # NAME diff --git a/doc/man/man3/notcurses_channels.3.md b/doc/man/man3/notcurses_channels.3.md index d7b21b72b..a34b2879d 100644 --- a/doc/man/man3/notcurses_channels.3.md +++ b/doc/man/man3/notcurses_channels.3.md @@ -1,6 +1,6 @@ % notcurses_channels(3) % nick black -% v2.4.0 +% v2.4.1 # NAME diff --git a/doc/man/man3/notcurses_core.3.md b/doc/man/man3/notcurses_core.3.md index adc59cc73..6ffd92cd3 100644 --- a/doc/man/man3/notcurses_core.3.md +++ b/doc/man/man3/notcurses_core.3.md @@ -1,6 +1,6 @@ % notcurses_core(3) % nick black -% v2.4.0 +% v2.4.1 # NAME diff --git a/doc/man/man3/notcurses_direct.3.md b/doc/man/man3/notcurses_direct.3.md index 1fe633ec9..05d06f928 100644 --- a/doc/man/man3/notcurses_direct.3.md +++ b/doc/man/man3/notcurses_direct.3.md @@ -1,6 +1,6 @@ % notcurses_direct(3) % nick black -% v2.4.0 +% v2.4.1 # NAME diff --git a/doc/man/man3/notcurses_fade.3.md b/doc/man/man3/notcurses_fade.3.md index 3630d094f..2bc0f0b7b 100644 --- a/doc/man/man3/notcurses_fade.3.md +++ b/doc/man/man3/notcurses_fade.3.md @@ -1,6 +1,6 @@ % notcurses_fade(3) % nick black -% v2.4.0 +% v2.4.1 # NAME diff --git a/doc/man/man3/notcurses_fds.3.md b/doc/man/man3/notcurses_fds.3.md index 9ecff4d57..8370c886f 100644 --- a/doc/man/man3/notcurses_fds.3.md +++ b/doc/man/man3/notcurses_fds.3.md @@ -1,6 +1,6 @@ % notcurses_fds(3) % nick black -% v2.4.0 +% v2.4.1 # NAME diff --git a/doc/man/man3/notcurses_init.3.md b/doc/man/man3/notcurses_init.3.md index b27d570ae..bfa1be98f 100644 --- a/doc/man/man3/notcurses_init.3.md +++ b/doc/man/man3/notcurses_init.3.md @@ -1,6 +1,6 @@ % notcurses_init(3) % nick black -% v2.4.0 +% v2.4.1 # NAME diff --git a/doc/man/man3/notcurses_input.3.md b/doc/man/man3/notcurses_input.3.md index 6f50564cf..e2feb00dc 100644 --- a/doc/man/man3/notcurses_input.3.md +++ b/doc/man/man3/notcurses_input.3.md @@ -1,6 +1,6 @@ % notcurses_input(3) % nick black -% v2.4.0 +% v2.4.1 # NAME diff --git a/doc/man/man3/notcurses_lines.3.md b/doc/man/man3/notcurses_lines.3.md index e8a3b34da..c22b60154 100644 --- a/doc/man/man3/notcurses_lines.3.md +++ b/doc/man/man3/notcurses_lines.3.md @@ -1,6 +1,6 @@ % notcurses_lines(3) % nick black -% v2.4.0 +% v2.4.1 # NAME diff --git a/doc/man/man3/notcurses_menu.3.md b/doc/man/man3/notcurses_menu.3.md index ef1a181c2..e353b29f8 100644 --- a/doc/man/man3/notcurses_menu.3.md +++ b/doc/man/man3/notcurses_menu.3.md @@ -1,6 +1,6 @@ % notcurses_menu(3) % nick black -% v2.4.0 +% v2.4.1 # NAME diff --git a/doc/man/man3/notcurses_metric.3.md b/doc/man/man3/notcurses_metric.3.md index 0ca3739ce..c50ecbc07 100644 --- a/doc/man/man3/notcurses_metric.3.md +++ b/doc/man/man3/notcurses_metric.3.md @@ -1,6 +1,6 @@ % notcurses_metric(3) % nick black -% v2.4.0 +% v2.4.1 # NAME diff --git a/doc/man/man3/notcurses_multiselector.3.md b/doc/man/man3/notcurses_multiselector.3.md index 94b8e4ded..a01936f2f 100644 --- a/doc/man/man3/notcurses_multiselector.3.md +++ b/doc/man/man3/notcurses_multiselector.3.md @@ -1,6 +1,6 @@ % notcurses_multiselector(3) % nick black -% v2.4.0 +% v2.4.1 # NAME diff --git a/doc/man/man3/notcurses_output.3.md b/doc/man/man3/notcurses_output.3.md index 9bc5a7743..a0fada18b 100644 --- a/doc/man/man3/notcurses_output.3.md +++ b/doc/man/man3/notcurses_output.3.md @@ -1,6 +1,6 @@ % notcurses_output(3) % nick black -% v2.4.0 +% v2.4.1 # NAME diff --git a/doc/man/man3/notcurses_palette.3.md b/doc/man/man3/notcurses_palette.3.md index a8f675d40..96375868f 100644 --- a/doc/man/man3/notcurses_palette.3.md +++ b/doc/man/man3/notcurses_palette.3.md @@ -1,6 +1,6 @@ % notcurses_palette(3) % nick black -% v2.4.0 +% v2.4.1 # NAME diff --git a/doc/man/man3/notcurses_plane.3.md b/doc/man/man3/notcurses_plane.3.md index c571b4494..38dfdfa12 100644 --- a/doc/man/man3/notcurses_plane.3.md +++ b/doc/man/man3/notcurses_plane.3.md @@ -1,6 +1,6 @@ % notcurses_plane(3) % nick black -% v2.4.0 +% v2.4.1 # NAME diff --git a/doc/man/man3/notcurses_plot.3.md b/doc/man/man3/notcurses_plot.3.md index 76c48ee4c..142b72dc0 100644 --- a/doc/man/man3/notcurses_plot.3.md +++ b/doc/man/man3/notcurses_plot.3.md @@ -1,6 +1,6 @@ % notcurses_plot(3) % nick black -% v2.4.0 +% v2.4.1 # NAME diff --git a/doc/man/man3/notcurses_reader.3.md b/doc/man/man3/notcurses_reader.3.md index 45997df70..06b7f3494 100644 --- a/doc/man/man3/notcurses_reader.3.md +++ b/doc/man/man3/notcurses_reader.3.md @@ -1,6 +1,6 @@ % notcurses_reader(3) % nick black -% v2.4.0 +% v2.4.1 # NAME diff --git a/doc/man/man3/notcurses_reel.3.md b/doc/man/man3/notcurses_reel.3.md index 93f860ccb..a0d73b390 100644 --- a/doc/man/man3/notcurses_reel.3.md +++ b/doc/man/man3/notcurses_reel.3.md @@ -1,6 +1,6 @@ % notcurses_reel(3) % nick black -% v2.4.0 +% v2.4.1 # NAME diff --git a/doc/man/man3/notcurses_refresh.3.md b/doc/man/man3/notcurses_refresh.3.md index 807de33ef..0c525feec 100644 --- a/doc/man/man3/notcurses_refresh.3.md +++ b/doc/man/man3/notcurses_refresh.3.md @@ -1,6 +1,6 @@ % notcurses_refresh(3) % nick black -% v2.4.0 +% v2.4.1 # NAME diff --git a/doc/man/man3/notcurses_render.3.md b/doc/man/man3/notcurses_render.3.md index ca57aa1d9..6e0a5ebfb 100644 --- a/doc/man/man3/notcurses_render.3.md +++ b/doc/man/man3/notcurses_render.3.md @@ -1,6 +1,6 @@ % notcurses_render(3) % nick black -% v2.4.0 +% v2.4.1 # NAME diff --git a/doc/man/man3/notcurses_selector.3.md b/doc/man/man3/notcurses_selector.3.md index 9dfd1f68e..e59ac2ffd 100644 --- a/doc/man/man3/notcurses_selector.3.md +++ b/doc/man/man3/notcurses_selector.3.md @@ -1,6 +1,6 @@ % notcurses_selector(3) % nick black -% v2.4.0 +% v2.4.1 # NAME diff --git a/doc/man/man3/notcurses_stats.3.md b/doc/man/man3/notcurses_stats.3.md index f721a5321..d52143b24 100644 --- a/doc/man/man3/notcurses_stats.3.md +++ b/doc/man/man3/notcurses_stats.3.md @@ -1,6 +1,6 @@ % notcurses_stats(3) % nick black -% v2.4.0 +% v2.4.1 # NAME diff --git a/doc/man/man3/notcurses_stdplane.3.md b/doc/man/man3/notcurses_stdplane.3.md index ca1e6446c..798b3daac 100644 --- a/doc/man/man3/notcurses_stdplane.3.md +++ b/doc/man/man3/notcurses_stdplane.3.md @@ -1,6 +1,6 @@ % notcurses_stdplane(3) % nick black -% v2.4.0 +% v2.4.1 # NAME diff --git a/doc/man/man3/notcurses_stop.3.md b/doc/man/man3/notcurses_stop.3.md index 35eac7ee5..4679dd173 100644 --- a/doc/man/man3/notcurses_stop.3.md +++ b/doc/man/man3/notcurses_stop.3.md @@ -1,6 +1,6 @@ % notcurses_stop(3) % nick black -% v2.4.0 +% v2.4.1 # NAME diff --git a/doc/man/man3/notcurses_tabbed.3.md b/doc/man/man3/notcurses_tabbed.3.md index bc352f685..3c4684a07 100644 --- a/doc/man/man3/notcurses_tabbed.3.md +++ b/doc/man/man3/notcurses_tabbed.3.md @@ -1,5 +1,5 @@ % notcurses_tabbed(3) -% v2.4.0 +% v2.4.1 # NAME diff --git a/doc/man/man3/notcurses_tree.3.md b/doc/man/man3/notcurses_tree.3.md index 015f50261..bd7bcb612 100644 --- a/doc/man/man3/notcurses_tree.3.md +++ b/doc/man/man3/notcurses_tree.3.md @@ -1,6 +1,6 @@ % notcurses_tree(3) % nick black -% v2.4.0 +% v2.4.1 # NAME diff --git a/doc/man/man3/notcurses_util.3.md b/doc/man/man3/notcurses_util.3.md index 777e1b570..9c064b527 100644 --- a/doc/man/man3/notcurses_util.3.md +++ b/doc/man/man3/notcurses_util.3.md @@ -1,6 +1,6 @@ % notcurses_util(3) % nick black -% v2.4.0 +% v2.4.1 # NAME diff --git a/doc/man/man3/notcurses_visual.3.md b/doc/man/man3/notcurses_visual.3.md index fad66d3a6..5880de8d9 100644 --- a/doc/man/man3/notcurses_visual.3.md +++ b/doc/man/man3/notcurses_visual.3.md @@ -1,6 +1,6 @@ % notcurses_visual(3) % nick black -% v2.4.0 +% v2.4.1 # NAME notcurses_visual - notcurses multimedia diff --git a/include/notcurses/notcurses.h b/include/notcurses/notcurses.h index b3e4127fc..0baf42f6f 100644 --- a/include/notcurses/notcurses.h +++ b/include/notcurses/notcurses.h @@ -905,6 +905,9 @@ typedef enum { // eventually preventing Notcurses from processing terminal messages. #define NCOPTION_DRAIN_INPUT 0x0100ull +// "CLI mode" is just NCOPTION_NO_CLEAR_BITMAPS | NCOPTION_NO_ALTERNATE_SCREEN | +// NCOPTION_PRESERVE_CURSOR, plus enabling scrolling on the standard plane. + // Configuration for notcurses_init(). typedef struct notcurses_options { // The name of the terminfo database entry describing this terminal. If NULL, @@ -1441,9 +1444,19 @@ typedef enum { NCPIXEL_SIXEL, // sixel NCPIXEL_LINUXFB, // linux framebuffer NCPIXEL_ITERM2, // iTerm2 - NCPIXEL_KITTY_STATIC, // kitty prior to C=1 and animation - NCPIXEL_KITTY_ANIMATED, // kitty with animation but not selfref - NCPIXEL_KITTY_SELFREF, // kitty with reflexive composition + // C=1 (disabling scrolling) was only introduced in 0.20.0, at the same + // time as animation. prior to this, graphics had to be entirely redrawn + // on any change, and it wasn't possible to use the bottom line. + NCPIXEL_KITTY_STATIC, + // until 0.22.0's introduction of 'a=c' for self-referential composition, we + // had to keep a complete copy of the RGBA data, in case a wiped cell needed + // to be rebuilt. we'd otherwise have to unpack the glyph and store it into + // the auxvec on the fly. + NCPIXEL_KITTY_ANIMATED, + // with 0.22.0, we only ever write transparent cells after writing the + // original image (which we now deflate, since we needn't unpack it later). + // the only data we need keep is the auxvecs. + NCPIXEL_KITTY_SELFREF, } ncpixelimpl_e; // Can we blit pixel-accurate bitmaps? @@ -3964,238 +3977,15 @@ API void notcurses_debug(const struct notcurses* nc, FILE* debugfp) // DEPRECATED MATERIAL, GOING AWAY IN ABI3 -__attribute__ ((deprecated)) static inline int -ncplane_align(const struct ncplane* n, ncalign_e align, int c){ - return ncplane_halign(n, align, c); -} - -__attribute__ ((deprecated)) static inline void -cell_init(nccell* c){ - nccell_init(c); -} - -__attribute__ ((deprecated)) API int cell_load(struct ncplane* n, nccell* c, const char* gcluster); -// nccell_load(), plus blast the styling with 'attr' and 'channels'. - -__attribute__ ((deprecated)) static inline int -cell_prime(struct ncplane* n, nccell* c, const char* gcluster, - uint32_t stylemask, uint64_t channels){ - return nccell_prime(n, c, gcluster, stylemask, channels); -} - __attribute__ ((deprecated)) API int cell_duplicate(struct ncplane* n, nccell* targ, const nccell* c); __attribute__ ((deprecated)) API void cell_release(struct ncplane* n, nccell* c); -// replaced by ncvisual_media_defblitter(). this original version never returns -// NCBLIT_3x2. deprecated, going away in ABI3. -__attribute__ ((deprecated)) static inline ncblitter_e -ncvisual_default_blitter(bool utf8, ncscale_e scale){ - if(utf8){ - // NCBLIT_3x2/NCBLIT_2x2 are better image quality, especially for large - // images, but not the general default because they doesn't preserve - // aspect ratio (as does NCBLIT_2x1). NCSCALE_STRETCH throws away aspect - // ratio, and can safely use NCBLIT_3x2/2x2. - if(scale == NCSCALE_STRETCH){ - return NCBLIT_3x2; - } - return NCBLIT_2x1; - } - return NCBLIT_1x1; -} - -__attribute__ ((deprecated)) static inline void -cell_set_styles(nccell* c, unsigned stylebits){ - nccell_set_styles(c, stylebits); -} - -// Extract the style bits from the nccell. -__attribute__ ((deprecated)) static inline unsigned -cell_styles(const nccell* c){ - return nccell_styles(c); -} - -__attribute__ ((deprecated)) static inline void -cell_on_styles(nccell* c, unsigned stylebits){ - nccell_on_styles(c, stylebits); -} - -__attribute__ ((deprecated)) static inline void -cell_off_styles(nccell* c, unsigned stylebits){ - nccell_off_styles(c, stylebits); -} - -__attribute__ ((deprecated)) static inline void -cell_set_fg_default(nccell* c){ - nccell_set_fg_default(c); -} - -__attribute__ ((deprecated)) static inline void -cell_set_bg_default(nccell* c){ - nccell_set_bg_default(c); -} - -__attribute__ ((deprecated)) static inline int -cell_set_fg_alpha(nccell* c, int alpha){ - return nccell_set_fg_alpha(c, alpha); -} - -__attribute__ ((deprecated)) static inline int -cell_set_bg_alpha(nccell* c, int alpha){ - return nccell_set_bg_alpha(c, alpha); -} - -__attribute__ ((deprecated)) static inline bool -cell_double_wide_p(const nccell* c){ - return nccell_double_wide_p(c); -} - -__attribute__ ((deprecated)) static inline bool -cell_wide_right_p(const nccell* c){ - return nccell_wide_right_p(c); -} - -__attribute__ ((deprecated)) static inline bool -cell_wide_left_p(const nccell* c){ - return nccell_wide_left_p(c); -} - -__attribute__ ((deprecated)) API const char* -cell_extended_gcluster(const struct ncplane* n, const nccell* c); - -__attribute__ ((deprecated)) ALLOC static inline char* -cell_strdup(const struct ncplane* n, const nccell* c){ - return nccell_strdup(n, c); -} - -__attribute__ ((deprecated)) static inline char* -cell_extract(const struct ncplane* n, const nccell* c, - uint16_t* stylemask, uint64_t* channels){ - return nccell_extract(n, c, stylemask, channels); -} - -__attribute__ ((deprecated)) static inline bool -cellcmp(const struct ncplane* n1, const nccell* RESTRICT c1, - const struct ncplane* n2, const nccell* RESTRICT c2){ - return nccellcmp(n1, c1, n2, c2); -} - -__attribute__ ((deprecated)) static inline int -cell_load_char(struct ncplane* n, nccell* c, char ch){ - return nccell_load_char(n, c, ch); -} - -__attribute__ ((deprecated)) static inline int -cell_load_egc32(struct ncplane* n, nccell* c, uint32_t egc){ - return nccell_load_egc32(n, c, egc); -} - // This function will be removed in ABI3 in favor of ncplane_create(). // It persists in ABI2 only for backwards compatibility. API ALLOC struct ncplane* ncplane_new(struct ncplane* n, int rows, int cols, int y, int x, void* opaque, const char* name) __attribute__ ((deprecated)); -__attribute__ ((deprecated)) static inline uint32_t -cell_fg_rgb(const nccell* cl){ - return nccell_fg_rgb(cl); -} - -__attribute__ ((deprecated)) static inline uint32_t -cell_bg_rgb(const nccell* cl){ - return nccell_bg_rgb(cl); -} - -__attribute__ ((deprecated)) static inline uint32_t -cell_fg_alpha(const nccell* cl){ - return nccell_fg_alpha(cl); -} - -__attribute__ ((deprecated)) static inline uint32_t -cell_bg_alpha(const nccell* cl){ - return nccell_bg_alpha(cl); -} - -__attribute__ ((deprecated)) static inline uint32_t -cell_fg_rgb8(const nccell* cl, unsigned* r, unsigned* g, unsigned* b){ - return nccell_fg_rgb8(cl, r, g, b); -} - -// Extract 24 bits of background RGB from 'cl', split into components. -__attribute__ ((deprecated)) static inline uint32_t -cell_bg_rgb8(const nccell* cl, unsigned* r, unsigned* g, unsigned* b){ - return nccell_bg_rgb8(cl, r, g, b); -} - -__attribute__ ((deprecated)) static inline int -cell_set_fg_rgb8(nccell* cl, int r, int g, int b){ - return nccell_set_fg_rgb8(cl, r, g, b); -} - -__attribute__ ((deprecated)) static inline void -cell_set_fg_rgb8_clipped(nccell* cl, int r, int g, int b){ - nccell_set_fg_rgb8_clipped(cl, r, g, b); -} - -__attribute__ ((deprecated)) static inline int -cell_set_fg_rgb(nccell* c, uint32_t channel){ - return nccell_set_fg_rgb(c, channel); -} - -__attribute__ ((deprecated)) static inline int -cell_set_fg_palindex(nccell* cl, int idx){ - return nccell_set_fg_palindex(cl, idx); -} - -__attribute__ ((deprecated)) static inline uint32_t -cell_fg_palindex(const nccell* cl){ - return nccell_fg_palindex(cl); -} - -__attribute__ ((deprecated)) static inline int -cell_set_bg_rgb8(nccell* cl, int r, int g, int b){ - return nccell_set_bg_rgb8(cl, r, g, b); -} - -__attribute__ ((deprecated)) static inline void -cell_set_bg_rgb8_clipped(nccell* cl, int r, int g, int b){ - nccell_set_bg_rgb8_clipped(cl, r, g, b); -} - -__attribute__ ((deprecated)) static inline int -cell_set_bg_rgb(nccell* c, uint32_t channel){ - return nccell_set_bg_rgb(c, channel); -} - -__attribute__ ((deprecated)) static inline int -cell_set_bg_palindex(nccell* cl, int idx){ - return nccell_set_bg_palindex(cl, idx); -} - -__attribute__ ((deprecated)) static inline uint32_t -cell_bg_palindex(const nccell* cl){ - return nccell_bg_palindex(cl); -} - -__attribute__ ((deprecated)) static inline bool -cell_fg_default_p(const nccell* cl){ - return nccell_fg_default_p(cl); -} - -__attribute__ ((deprecated)) static inline bool -cell_fg_palindex_p(const nccell* cl){ - return nccell_fg_palindex_p(cl); -} - -__attribute__ ((deprecated)) static inline bool -cell_bg_default_p(const nccell* cl){ - return nccell_bg_default_p(cl); -} - -__attribute__ ((deprecated)) static inline bool -cell_bg_palindex_p(const nccell* cl){ - return nccell_bg_palindex_p(cl); -} - API void ncplane_styles_set(struct ncplane* n, unsigned stylebits) __attribute__ ((deprecated)); API void ncplane_styles_on(struct ncplane* n, unsigned stylebits) @@ -4213,21 +4003,6 @@ cells_double_box(struct ncplane* n, uint32_t styles, uint64_t channels, nccell* ul, nccell* ur, nccell* ll, nccell* lr, nccell* hl, nccell* vl); -// Deprecated in favor of ncplane_as_rgba. This will be removed in ABI3. -ALLOC __attribute__ ((deprecated)) __attribute__ ((nonnull (1))) -static inline uint32_t* -ncplane_rgba(const struct ncplane* n, ncblitter_e blit, - int begy, int begx, int leny, int lenx){ - return ncplane_as_rgba(n, blit, begy, begx, leny, lenx, NULL, NULL); -} - -__attribute__ ((deprecated)) static inline int -ncvisual_geom(const struct notcurses* nc, const struct ncvisual* n, - const struct ncvisual_options* vopts, - int* y, int* x, int* scaley, int* scalex){ - return ncvisual_blitter_geom(nc, n, vopts, y, x, scaley, scalex, NULL); -} - // Deprecated form of nctablet_plane(). API struct ncplane* nctablet_ncplane(struct nctablet* t) __attribute__ ((deprecated)); @@ -4238,21 +4013,6 @@ API ALLOC ncpalette* palette256_new(struct notcurses* nc) API int palette256_use(struct notcurses* nc, const ncpalette* p) __attribute__ ((deprecated)); -__attribute__ ((deprecated)) static inline int -palette256_set_rgb8(ncpalette* p, int idx, int r, int g, int b){ - return ncpalette_set_rgb8(p, idx, r, g, b); -} - -__attribute__ ((deprecated)) static inline int -palette256_set(ncpalette* p, int idx, unsigned rgb){ - return ncpalette_set(p, idx, rgb); -} - -__attribute__ ((deprecated)) static inline int -palette256_get_rgb8(const ncpalette* p, int idx, unsigned* RESTRICT r, unsigned* RESTRICT g, unsigned* RESTRICT b){ - return ncpalette_get_rgb8(p, idx, r, g, b); -} - API void palette256_free(ncpalette* p) __attribute__ ((deprecated)); // Inflate each pixel in the image to 'scale'x'scale' pixels. It is an error @@ -4267,8 +4027,6 @@ API int notcurses_render_to_buffer(struct notcurses* nc, char** buf, size_t* buf API int notcurses_render_to_file(struct notcurses* nc, FILE* fp) __attribute__ ((deprecated)); -typedef nccell cell; // FIXME backwards-compat, remove in ABI3 - API void notcurses_debug_caps(const struct notcurses* nc, FILE* debugfp) __attribute__ ((deprecated)) __attribute__ ((nonnull (1, 2))); @@ -4277,17 +4035,6 @@ __attribute__ ((deprecated)) API int nccell_width(const struct ncplane* n, const API ALLOC char* ncvisual_subtitle(const struct ncvisual* ncv) __attribute__ ((nonnull (1))) __attribute__ ((deprecated)); -#define CELL_ALPHA_HIGHCONTRAST NCALPHA_HIGHCONTRAST -#define CELL_ALPHA_TRANSPARENT NCALPHA_TRANSPARENT -#define CELL_ALPHA_BLEND NCALPHA_BLEND -#define CELL_ALPHA_OPAQUE NCALPHA_OPAQUE -#define NCSTYLE_PROTECT 0 -#define NCSTYLE_STANDOUT 0 -#define NCSTYLE_REVERSE 0 -#define NCSTYLE_INVIS 0 -#define NCSTYLE_DIM 0 -#define NCSTYLE_BLINK 0 - #undef ALLOC #undef API diff --git a/python/setup.py b/python/setup.py index 412b1d88f..973661a5b 100644 --- a/python/setup.py +++ b/python/setup.py @@ -38,7 +38,7 @@ if environ.get('LDFLAGS') is None: setup( name="notcurses", - version="2.4.0", + version="2.4.1", packages=['notcurses'], ext_modules=[ Extension( diff --git a/rust/Cargo.toml b/rust/Cargo.toml index 74d896e0b..9281fe25d 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libnotcurses-sys" -version = "2.4.0" +version = "2.4.1" authors = [ "nick black ", "José Luis Cruz " diff --git a/rust/build/build.rs b/rust/build/build.rs index 37e3fac34..a53b501c7 100644 --- a/rust/build/build.rs +++ b/rust/build/build.rs @@ -7,7 +7,7 @@ use std::path::PathBuf; // largely taken from https://rust-lang.github.io/rust-bindgen/tutorial-3.html fn main() { let plib = pkg_config::Config::new() - .atleast_version("2.4.0") + .atleast_version("2.4.1") .probe("notcurses") .unwrap(); diff --git a/rust/examples/pixel-cell.rs b/rust/examples/pixel-cell.rs index cac719ed4..2bcb1c4b4 100644 --- a/rust/examples/pixel-cell.rs +++ b/rust/examples/pixel-cell.rs @@ -14,7 +14,7 @@ use libnotcurses_sys::*; fn main() -> NcResult<()> { let mut nc = Nc::new()?; - if !nc.check_pixel_support()? { + if nc.check_pixel_support() == NCPIXEL_NONE { nc.stop()?; return Err(NcError::new_msg("Current terminal doesn't support pixels.")); } diff --git a/rust/src/bindings.rs b/rust/src/bindings.rs index 0f9c39fd1..de8697cdb 100644 --- a/rust/src/bindings.rs +++ b/rust/src/bindings.rs @@ -666,7 +666,6 @@ pub use ffi::{ // NCSTYLE_UNDERCURL, // NCSTYLE_BOLD, // NCSTYLE_STRUCK, -// NCSTYLE_BLINK, // NCSTYLE_NONE, // nctablet -------------------------------------------------------------------- diff --git a/rust/src/cells/mod.rs b/rust/src/cells/mod.rs index 6263b8e98..ff4f889fa 100644 --- a/rust/src/cells/mod.rs +++ b/rust/src/cells/mod.rs @@ -205,7 +205,7 @@ use crate::{NcChannel, NcPlane}; /// multicolumn glyph. whether a cell is the left or right side of the glyph /// can be determined by checking whether ->gcluster is zero. /// -pub type NcCell = crate::bindings::ffi::cell; +pub type NcCell = crate::bindings::ffi::nccell; // RETHINK: // @@ -290,7 +290,6 @@ pub type NcEgcBackstop = u8; /// - [`NCSTYLE_UNDERCURL`] /// - [`NCSTYLE_STRUCK`] /// - [`NCSTYLE_BOLD`] -/// - [`NCSTYLE_BLINK`] /// - [`NCSTYLE_NONE`] /// /// ## Diagram @@ -321,9 +320,6 @@ pub const NCSTYLE_STRUCK: u16 = crate::bindings::ffi::NCSTYLE_STRUCK as u16; /// pub const NCSTYLE_BOLD: u16 = crate::bindings::ffi::NCSTYLE_BOLD as u16; -/// -pub const NCSTYLE_BLINK: u16 = crate::bindings::ffi::NCSTYLE_BLINK as u16; - /// pub const NCSTYLE_NONE: u16 = crate::bindings::ffi::NCSTYLE_NONE as u16; @@ -344,7 +340,6 @@ impl NcStyleMethods for NcStyle { NCSTYLE_UNDERCURL, NCSTYLE_STRUCK, NCSTYLE_BOLD, - NCSTYLE_BLINK, NCSTYLE_NONE, ]; for s in &styles { diff --git a/rust/src/macros.rs b/rust/src/macros.rs index 7766ffc15..847ee2e23 100644 --- a/rust/src/macros.rs +++ b/rust/src/macros.rs @@ -125,7 +125,7 @@ macro_rules! rsleep { #[doc(hidden)] macro_rules! cstring { ($s:expr) => { - std::ffi::CString::new($s).unwrap().as_ptr(); + std::ffi::CString::new($s).unwrap().as_ptr() }; } @@ -134,7 +134,7 @@ macro_rules! cstring { #[doc(hidden)] macro_rules! cstring_mut { ($s:expr) => { - std::ffi::CString::new($s).unwrap().into_raw(); + std::ffi::CString::new($s).unwrap().into_raw() }; } @@ -184,10 +184,10 @@ macro_rules! error { } }}; ($res:expr, $msg:expr) => { - error![$res, $msg, ()]; + error![$res, $msg, ()] }; ($res:expr) => { - error![$res, "", ()]; + error![$res, "", ()] }; } diff --git a/rust/src/notcurses/methods.rs b/rust/src/notcurses/methods.rs index 9cf9f2629..8d2d0473b 100644 --- a/rust/src/notcurses/methods.rs +++ b/rust/src/notcurses/methods.rs @@ -4,10 +4,10 @@ use core::ptr::{null, null_mut}; use crate::{ cstring, error, error_ref_mut, notcurses_init, rstring, Nc, NcAlign, NcBlitter, NcChannels, - NcDim, NcError, NcFile, NcInput, NcLogLevel, NcOptions, NcPlane, NcResult, NcScale, NcStats, - NcStyle, NcStyleMethods, NcTime, NCOPTION_NO_ALTERNATE_SCREEN, NCOPTION_SUPPRESS_BANNERS, - NCRESULT_ERR, NCSTYLE_BLINK, NCSTYLE_BOLD, NCSTYLE_ITALIC, NCSTYLE_NONE, NCSTYLE_STRUCK, - NCSTYLE_UNDERCURL, NCSTYLE_UNDERLINE, + NcDim, NcError, NcFile, NcInput, NcLogLevel, NcOptions, NcPixelImpl, NcPlane, NcResult, + NcScale, NcStats, NcStyle, NcStyleMethods, NcTime, NCOPTION_NO_ALTERNATE_SCREEN, + NCOPTION_SUPPRESS_BANNERS, NCRESULT_ERR, NCSTYLE_BOLD, NCSTYLE_ITALIC, NCSTYLE_NONE, + NCSTYLE_STRUCK, NCSTYLE_UNDERCURL, NCSTYLE_UNDERLINE, }; /// # `NcOptions` Constructors @@ -251,22 +251,14 @@ impl Nc { /// Checks for pixel support. /// - /// Returns `false` for no support, or `true` if pixel output is supported. - /// - /// This function must successfully return before - /// [NCBLIT_PIXEL][crate::NCBLIT_PIXEL] is available. - /// - /// Must not be called concurrently with either input or rasterization. + /// Returns [`NcPixelImpl`] with a non-zero constant corresponding to some + /// pixel-blitting mechanism if bitmap support (via any mechanism) has been + /// detected, or else 0 (NCPIXEL_NONE). /// /// *C style function: [notcurses_check_pixel_support()][crate::notcurses_check-pixel_support].* #[allow(clippy::wildcard_in_or_patterns)] - pub fn check_pixel_support(&self) -> NcResult { - let res = unsafe { crate::notcurses_check_pixel_support(self) }; - match res { - 0 => Ok(false), - 1 => Ok(true), - NCRESULT_ERR | _ => Err(NcError::with_msg(res, "Notcuses.check_pixel_support()")), - } + pub fn check_pixel_support(&self) -> NcPixelImpl { + unsafe { crate::notcurses_check_pixel_support(self) } } /// Disables the terminal's cursor, if supported. @@ -432,7 +424,7 @@ impl Nc { /// spaces. /// /// The supported styles are: `italic`, `underline`, `undercurl`, - /// `struck`, `bold`, `blink` and `none`. + /// `struck`, `bold`, and `none`. /// /// If a style is are not recognized returns an error. /// @@ -448,7 +440,6 @@ impl Nc { "undercurl" => style.add(NCSTYLE_UNDERCURL), "struck" => style.add(NCSTYLE_STRUCK), "bold" => style.add(NCSTYLE_BOLD), - "blink" => style.add(NCSTYLE_BLINK), "none" => (), _ => { errstr.push_str(s); @@ -693,7 +684,6 @@ impl Nc { NCSTYLE_UNDERCURL => "undercurl", NCSTYLE_STRUCK => "struck", NCSTYLE_BOLD => "bold", - NCSTYLE_BLINK => "blink", #[allow(unreachable_patterns)] // FIXME NCSTYLE_NONE => "none", _ => "none", diff --git a/rust/src/notcurses/mod.rs b/rust/src/notcurses/mod.rs index 047d6013b..003151c5e 100644 --- a/rust/src/notcurses/mod.rs +++ b/rust/src/notcurses/mod.rs @@ -196,7 +196,7 @@ pub const NCLOGLEVEL_VERBOSE: NcLogLevel = crate::bindings::ffi::ncloglevel_e_NC /// you probably don't want what's happening to happen pub const NCLOGLEVEL_WARNING: NcLogLevel = crate::bindings::ffi::ncloglevel_e_NCLOGLEVEL_WARNING; -// NcAlign -- ------------------------------------------------------------------ +// NcAlign --------------------------------------------------------------------- /// Alignment within a plane or terminal. /// Left/right-justified, or centered. diff --git a/rust/src/visual/mod.rs b/rust/src/visual/mod.rs index 77b0e20ec..b374133c0 100644 --- a/rust/src/visual/mod.rs +++ b/rust/src/visual/mod.rs @@ -10,7 +10,6 @@ //W ncvisual_at_yx //W ncvisual_decode //W ncvisual_decode_loop -// ncvisual_default_blitter //W ncvisual_destroy //W ncvisual_from_bgra //W ncvisual_from_file @@ -236,6 +235,29 @@ pub const NCBLIT_DEFAULT: NcBlitter = crate::bindings::ffi::ncblitter_e_NCBLIT_D /// See [Sixel in Wikipedia](https://en.wikipedia.org/wiki/Sixel). pub const NCBLIT_PIXEL: NcBlitter = crate::bindings::ffi::ncblitter_e_NCBLIT_PIXEL; +/// Pixel blitting implementations. (Informative only). +/// +/// Returned by [`check_pixel_support`][Notcurses#method.check_pixel_support]. +pub type NcPixelImpl = crate::bindings::ffi::ncpixelimpl_e; + +/// No pixel support. +pub const NCPIXEL_NONE: NcPixelImpl = crate::bindings::ffi::ncpixelimpl_e_NCPIXEL_NONE; +/// Sixel +pub const NCPIXEL_SIXEL: NcPixelImpl = crate::bindings::ffi::ncpixelimpl_e_NCPIXEL_SIXEL; +/// Linux framebuffer. +pub const NCPIXEL_LINUXFB: NcPixelImpl = crate::bindings::ffi::ncpixelimpl_e_NCPIXEL_LINUXFB; +/// iTerm2 +pub const NCPIXEL_ITERM2: NcPixelImpl = crate::bindings::ffi::ncpixelimpl_e_NCPIXEL_ITERM2; +/// Kitty prior to C=1 and animation. +pub const NCPIXEL_KITTY_STATIC: NcPixelImpl = + crate::bindings::ffi::ncpixelimpl_e_NCPIXEL_KITTY_STATIC; +/// Kitty with animation but not reflexive composition. +pub const NCPIXEL_KITTY_ANIMATED: NcPixelImpl = + crate::bindings::ffi::ncpixelimpl_e_NCPIXEL_KITTY_ANIMATED; +/// Kitty with reflexive composition. +pub const NCPIXEL_KITTY_SELFREF: NcPixelImpl = + crate::bindings::ffi::ncpixelimpl_e_NCPIXEL_KITTY_SELFREF; + /// Contains the pixel geometry information as returned by the /// NcPlane.[pixelgeom()][crate::NcPlane#method.pixelgeom] method. /// diff --git a/src/demo/fission.c b/src/demo/fission.c index 836f136f3..db72ed0b9 100644 --- a/src/demo/fission.c +++ b/src/demo/fission.c @@ -155,7 +155,7 @@ int fission_demo(struct notcurses* nc){ ncplane_resize_simple(n, newy, newx); continue; } - cell c = CELL_TRIVIAL_INITIALIZER; + nccell c = CELL_TRIVIAL_INITIALIZER; uint16_t smask; uint64_t channels; char* egc = ncplane_at_yx(stdn, usey, usex, &smask, &channels); diff --git a/src/demo/intro.c b/src/demo/intro.c index 6ea136497..460571b9e 100644 --- a/src/demo/intro.c +++ b/src/demo/intro.c @@ -225,11 +225,11 @@ int intro(struct notcurses* nc){ if(rows < 45){ ncplane_set_fg_rgb8(ncp, 0xc0, 0x80, 0x80); ncplane_set_bg_rgb8(ncp, 0x20, 0x20, 0x20); - ncplane_on_styles(ncp, NCSTYLE_BLINK); // heh FIXME replace with pulse + ncplane_on_styles(ncp, NCSTYLE_BOLD); // FIXME maybe use pulse? if(ncplane_putstr_aligned(ncp, 2, NCALIGN_CENTER, "demo runs best with at least 45 lines") < 0){ return -1; } - ncplane_off_styles(ncp, NCSTYLE_BLINK); // heh FIXME replace with pulse + ncplane_off_styles(ncp, NCSTYLE_BOLD); } struct timespec now; clock_gettime(CLOCK_MONOTONIC, &now); diff --git a/src/lib/blit.c b/src/lib/blit.c index 1e32b0060..208189f55 100644 --- a/src/lib/blit.c +++ b/src/lib/blit.c @@ -613,7 +613,7 @@ sex_solver(const uint32_t rgbas[6], uint64_t* channels, unsigned blendcolors, } static const char* -sex_trans_check(cell* c, const uint32_t rgbas[6], unsigned blendcolors, +sex_trans_check(nccell* c, const uint32_t rgbas[6], unsigned blendcolors, uint32_t transcolor, unsigned nointerpolate){ // bit is *set* where sextant *is not* // 32: bottom right 16: bottom left diff --git a/src/lib/kitty.c b/src/lib/kitty.c index 9b7a3027f..36bc21508 100644 --- a/src/lib/kitty.c +++ b/src/lib/kitty.c @@ -301,17 +301,31 @@ int kitty_rebuild(sprixel* s, int ycell, int xcell, uint8_t* auxvec){ return -1; } +// does this auxvec correspond to a sprixcell which was nulled out during the +// blitting of the frame (can only happen with a multiframe that's seen some +// wiping)? +static inline unsigned +kitty_anim_auxvec_blitsource_p(const sprixel* s, const uint8_t* auxvec){ + const size_t offset = s->cellpxy * s->cellpxx * 4; + if(auxvec[offset]){ + return 1; + } + return 0; +} + // an animation auxvec requires storing all the pixel data for the cell, // instead of just the alpha channel. pass the start of the RGBA to be // copied, and the rowstride. dimy and dimx are the source image's total // size in pixels. posy and posx are the origin of the cell to be copied, // again in pixels. data is the image source. around the edges, we might -// get truncated regions. +// get truncated regions. we also need to store a final byte indicating +// whether the null write originated in blitting or wiping, as that affects +// our rebuild animation. static inline void* kitty_anim_auxvec(int dimy, int dimx, int posy, int posx, int cellpxy, int cellpxx, const uint32_t* data, int rowstride, uint8_t* existing, uint32_t transcolor){ - const size_t slen = 4 * cellpxy * cellpxx; + const size_t slen = 4 * cellpxy * cellpxx + 1; uint32_t* a = existing ? existing : malloc(slen); if(a){ for(int y = posy ; y < posy + cellpxy && y < dimy ; ++y){ @@ -334,6 +348,7 @@ kitty_anim_auxvec(int dimy, int dimx, int posy, int posx, } } } + ((uint8_t*)a)[slen - 1] = 0; // reset blitsource ownership return a; } @@ -397,6 +412,9 @@ int kitty_wipe_animation(sprixel* s, int ycell, int xcell){ if(kitty_blit_wipe_selfref(s, f, ycell, xcell) < 0){ return -1; } + int tamidx = ycell * s->dimx + xcell; + uint8_t* auxvec = s->n->tam[tamidx].auxvector; + auxvec[s->cellpxx * s->cellpxy * 4] = 0; s->invalidated = SPRIXEL_INVALIDATED; return 1; } @@ -644,10 +662,10 @@ add_to_deflator(z_stream* zctx, const uint32_t* src, int encodeable, bool wipe[s // writes to |*animated| based on normalized |level| static int -prep_deflator(kitty_graphics_e level, z_stream* zctx, int pixy, int pixx, +prep_deflator(ncpixelimpl_e level, z_stream* zctx, int pixy, int pixx, unsigned* animated){ memset(zctx, 0, sizeof(*zctx)); - if(level >= KITTY_ANIMATION){ + if(level >= NCPIXEL_KITTY_ANIMATED){ int zret; // 2 seems to work well for things that are going to compress up // meaningfully at all, while not taking too much time. @@ -679,12 +697,12 @@ destroy_deflator(unsigned animated, z_stream* zctx, int pixy, int pixx){ } } -// if we're KITTY_SELFREF, and we're blitting a secondary frame, we need +// if we're NCPIXEL_KITTY_SELFREF, and we're blitting a secondary frame, we need // carry through the TAM's annihilation entires...but we also need load the // frame *without* annihilations, lest we be unable to build it. we thus go // back through the TAM following a selfref blit, and any sprixcells which // are annihilated will have their annhilation appended to the main blit. -// ought only be called for KITTY_SELFREF. +// ought only be called for NCPIXEL_KITTY_SELFREF. static int finalize_multiframe_selfref(sprixel* s, fbuf* f){ int prewiped = 0; @@ -711,7 +729,7 @@ finalize_multiframe_selfref(sprixel* s, fbuf* f){ static int write_kitty_data(fbuf* f, int linesize, int leny, int lenx, int cols, const uint32_t* data, const blitterargs* bargs, - tament* tam, int* parse_start, kitty_graphics_e level){ + tament* tam, int* parse_start, ncpixelimpl_e level){ //fprintf(stderr, "drawing kitty %p\n", tam); if(linesize % sizeof(*data)){ logerror("Stride (%d) badly aligned\n", linesize); @@ -740,7 +758,7 @@ write_kitty_data(fbuf* f, int linesize, int leny, int lenx, int cols, //fprintf(stderr, "total: %d chunks = %d, s=%d,v=%d\n", total, chunks, lenx, leny); char out[17]; // three pixels base64 to no more than 17 bytes // set high if we are (1) reloading a frame with (2) annihilated cells copied over - // from the TAM and (3) we are KITTY_SELFREF. calls finalize_multiframe_selfref(). + // from the TAM and (3) we are NCPIXEL_KITTY_SELFREF. calls finalize_multiframe_selfref(). bool selfref_annihilated = false; while(chunks--){ // q=2 has been able to go on chunks other than the last chunk since @@ -796,7 +814,7 @@ write_kitty_data(fbuf* f, int linesize, int leny, int lenx, int cols, // data in them. on the first pixel of the cell, ditch the previous // auxvec in its entirety, and copy over the entire cell. if(x % cdimx == 0 && y % cdimy == 0){ - if(level == KITTY_ANIMATION){ + if(level == NCPIXEL_KITTY_ANIMATED){ uint8_t* tmp; tmp = kitty_anim_auxvec(leny, lenx, y, x, cdimy, cdimx, data, linesize, tam[tyx].auxvector, @@ -805,7 +823,7 @@ write_kitty_data(fbuf* f, int linesize, int leny, int lenx, int cols, goto err; } tam[tyx].auxvector = tmp; - }else if(level == KITTY_SELFREF){ + }else if(level == NCPIXEL_KITTY_SELFREF){ if(tam[tyx].auxvector == NULL){ tam[tyx].auxvector = malloc(sizeof(tam[tyx].state)); if(tam[tyx].auxvector == NULL){ @@ -823,25 +841,26 @@ write_kitty_data(fbuf* f, int linesize, int leny, int lenx, int cols, const int vyx = (y % cdimy) * cdimx + (x % cdimx); tam[tyx].auxvector[vyx] = ncpixel_a(source[e]); wipe[e] = 1; - }else if(level == KITTY_SELFREF){ + }else if(level == NCPIXEL_KITTY_SELFREF){ selfref_annihilated = true; }else{ + tam[tyx].auxvector[s->cellpxx * s->cellpxy * 4] = 1; wipe[e] = 1; } if(rgba_trans_p(source[e], transcolor)){ ncpixel_set_a(&source[e], 0); // in case it was transcolor if(x % cdimx == 0 && y % cdimy == 0){ tam[tyx].state = SPRIXCELL_ANNIHILATED_TRANS; - if(level == KITTY_SELFREF){ + if(level == NCPIXEL_KITTY_SELFREF){ *tam[tyx].auxvector = SPRIXCELL_TRANSPARENT; } - }else if(level == KITTY_SELFREF && tam[tyx].state == SPRIXCELL_ANNIHILATED_TRANS){ + }else if(level == NCPIXEL_KITTY_SELFREF && tam[tyx].state == SPRIXCELL_ANNIHILATED_TRANS){ *tam[tyx].auxvector = SPRIXCELL_MIXED_KITTY; } }else{ - if(x % cdimx == 0 && y % cdimy == 0 && level == KITTY_SELFREF){ + if(x % cdimx == 0 && y % cdimy == 0 && level == NCPIXEL_KITTY_SELFREF){ *tam[tyx].auxvector = SPRIXCELL_OPAQUE_KITTY; - }else if(level == KITTY_SELFREF && *tam[tyx].auxvector == SPRIXCELL_TRANSPARENT){ + }else if(level == NCPIXEL_KITTY_SELFREF && *tam[tyx].auxvector == SPRIXCELL_TRANSPARENT){ *tam[tyx].auxvector = SPRIXCELL_MIXED_KITTY; } tam[tyx].state = SPRIXCELL_ANNIHILATED; @@ -950,9 +969,11 @@ int kitty_rebuild_animation(sprixel* s, int ycell, int xcell, uint8_t* auxvec){ logdebug("placing %d/%d at %d/%d\n", ylen, xlen, ycell * s->cellpxy, xcell * s->cellpxx); while(chunks--){ if(totalout == 0){ - if(fbuf_printf(f, "\e_Ga=f,x=%d,y=%d,s=%d,v=%d,i=%d,X=1,r=1,%s;", + const int c = kitty_anim_auxvec_blitsource_p(s, auxvec) ? 2 : 1; + const int r = kitty_anim_auxvec_blitsource_p(s, auxvec) ? 1 : 2; + if(fbuf_printf(f, "\e_Ga=f,x=%d,y=%d,s=%d,v=%d,i=%d,X=1,c=%d,r=%d,%s;", xcell * s->cellpxx, ycell * s->cellpxy, xlen, ylen, - s->id, chunks ? "m=1" : "q=2") < 0){ + s->id, c, r, chunks ? "m=1" : "q=2") < 0){ return -1; } }else{ @@ -1030,7 +1051,7 @@ int kitty_rebuild_animation(sprixel* s, int ycell, int xcell, uint8_t* auxvec){ // deflate-compressed) 24bit RGB. Returns -1 on error, 1 on success. static inline int kitty_blit_core(ncplane* n, int linesize, const void* data, int leny, int lenx, - const blitterargs* bargs, kitty_graphics_e level){ + const blitterargs* bargs, ncpixelimpl_e level){ //fprintf(stderr, "IMAGE: start %p end %p\n", data, (const char*)data + leny * linesize); int cols = bargs->u.pixel.spx->dimx; int rows = bargs->u.pixel.spx->dimy; @@ -1061,7 +1082,7 @@ kitty_blit_core(ncplane* n, int linesize, const void* data, int leny, int lenx, bargs, tam, &parse_start, level)){ goto error; } - if(level == KITTY_ALWAYS_SCROLLS){ + if(level == NCPIXEL_KITTY_STATIC){ s->animating = false; } // take ownership of |buf| and |tam| on success. @@ -1081,19 +1102,19 @@ error: int kitty_blit(ncplane* n, int linesize, const void* data, int leny, int lenx, const blitterargs* bargs){ return kitty_blit_core(n, linesize, data, leny, lenx, bargs, - KITTY_ALWAYS_SCROLLS); + NCPIXEL_KITTY_STATIC); } int kitty_blit_animated(ncplane* n, int linesize, const void* data, int leny, int lenx, const blitterargs* bargs){ return kitty_blit_core(n, linesize, data, leny, lenx, bargs, - KITTY_ANIMATION); + NCPIXEL_KITTY_ANIMATED); } int kitty_blit_selfref(ncplane* n, int linesize, const void* data, int leny, int lenx, const blitterargs* bargs){ return kitty_blit_core(n, linesize, data, leny, lenx, bargs, - KITTY_SELFREF); + NCPIXEL_KITTY_SELFREF); } int kitty_remove(int id, fbuf* f){ diff --git a/src/lib/notcurses.c b/src/lib/notcurses.c index 0ccf2f957..35c75df06 100644 --- a/src/lib/notcurses.c +++ b/src/lib/notcurses.c @@ -193,7 +193,7 @@ char* ncplane_at_cursor(ncplane* n, uint16_t* stylemask, uint64_t* channels){ char* ncplane_at_yx(const ncplane* n, int y, int x, uint16_t* stylemask, uint64_t* channels){ if(y < n->leny && x < n->lenx){ if(y >= 0 && x >= 0){ - const cell* yx = &n->fb[nfbcellidx(n, y, x)]; + const nccell* yx = &n->fb[nfbcellidx(n, y, x)]; // if we're the right side of a wide glyph, we return the main glyph if(nccell_wide_right_p(yx)){ return ncplane_at_yx(n, y, x - 1, stylemask, channels); @@ -568,7 +568,6 @@ ncplane* ncplane_new_internal(notcurses* nc, ncplane* n, // create an ncplane of the specified dimensions, but do not yet place it in // the z-buffer. clear out all cells. this is for a wholly new context. -// FIXME set up using resizecb rather than special-purpose from SIGWINCH static ncplane* create_initial_ncplane(notcurses* nc, int dimy, int dimx){ ncplane_options nopts = { @@ -577,7 +576,7 @@ create_initial_ncplane(notcurses* nc, int dimy, int dimx){ .cols = dimx - (nc->margin_l + nc->margin_r), .userptr = NULL, .name = "std", - .resizecb = ncplane_resize_maximize, + .resizecb = NULL, .flags = 0, }; return nc->stdplane = ncplane_new_internal(nc, NULL, &nopts); @@ -2339,9 +2338,6 @@ ncplane* ncplane_boundlist(ncplane* n){ } void ncplane_set_resizecb(ncplane* n, int(*resizecb)(ncplane*)){ - if(n == notcurses_stdplane(ncplane_notcurses(n))){ - return; - } n->resizecb = resizecb; } diff --git a/src/lib/render.c b/src/lib/render.c index 4bf9c3ef5..34d275776 100644 --- a/src/lib/render.c +++ b/src/lib/render.c @@ -4,6 +4,49 @@ #include #include "internal.h" +static nccell* +restripe_lastframe(notcurses* nc, int rows, int cols){ + assert(rows); + assert(cols); + const size_t size = sizeof(*nc->lastframe) * (rows * cols); + nccell* tmp = malloc(size); + if(tmp == NULL){ + return NULL; + } + size_t maxlinecopy = sizeof(nccell) * (nc->lfdimx > cols ? cols : nc->lfdimx); + size_t minlineset = sizeof(nccell) * cols - maxlinecopy; + unsigned zorch = nc->lfdimx > cols ? nc->lfdimx - cols : 0; + for(int y = 0 ; y < rows ; ++y){ + if(y < nc->lfdimy){ + if(maxlinecopy){ + memcpy(&tmp[cols * y], &nc->lastframe[nc->lfdimx * y], maxlinecopy); + } + if(minlineset){ + memset(&tmp[cols * y + maxlinecopy / sizeof(nccell)], 0, minlineset); + } + // excise any egcpool entries from the right of the new plane area + if(zorch){ + for(unsigned x = maxlinecopy ; x < maxlinecopy + zorch ; ++x){ + pool_release(&nc->pool, &nc->lastframe[fbcellidx(y, nc->lfdimx, x)]); + } + } + }else{ + memset(&tmp[cols * y], 0, sizeof(nccell) * cols); + } + } + // excise any egcpool entries from below the new plane area + for(int y = rows ; y < nc->lfdimy ; ++y){ + for(int x = 0 ; x < nc->lfdimx ; ++x){ + pool_release(&nc->pool, &nc->lastframe[fbcellidx(y, nc->lfdimx, x)]); + } + } + free(nc->lastframe); + nc->lastframe = tmp; + nc->lfdimy = rows; + nc->lfdimx = cols; + return 0; +} + // Check whether the terminal geometry has changed, and if so, copy what can // be copied from the old lastframe. Assumes that the screen is always anchored // at the same origin. Initiates a resize cascade for the pile containing |pp|. @@ -35,18 +78,9 @@ notcurses_resize_internal(ncplane* pp, int* restrict rows, int* restrict cols){ *cols = 1; } if(*rows != n->lfdimy || *cols != n->lfdimx){ - n->lfdimy = *rows; - n->lfdimx = *cols; - const size_t size = sizeof(*n->lastframe) * (n->lfdimy * n->lfdimx); - nccell* fb = realloc(n->lastframe, size); - if(fb == NULL){ + if(restripe_lastframe(n, *rows, *cols)){ return -1; } - n->lastframe = fb; - // FIXME more memset()tery than we need, both wasting work and wrecking - // damage detection for the upcoming render - memset(n->lastframe, 0, size); - egcpool_dump(&n->pool); } //fprintf(stderr, "r: %d or: %d c: %d oc: %d\n", *rows, oldrows, *cols, oldcols); if(*rows == oldrows && *cols == oldcols){ @@ -56,6 +90,12 @@ notcurses_resize_internal(ncplane* pp, int* restrict rows, int* restrict cols){ pile->dimx = *cols; int ret = 0; //notcurses_debug(n, stderr); + // if this pile contains the standard plane, it ought be resized to match + // the viewing area before invoking any other resize callbacks. + if(ncplane_pile(notcurses_stdplane(n)) == pile){ + ncplane_resize_maximize(notcurses_stdplane(n)); + } + // now, begin a resize callback cascade on the root planes of the pile. for(ncplane* rootn = pile->roots ; rootn ; rootn = rootn->bnext){ if(rootn->resizecb){ ret |= rootn->resizecb(rootn); diff --git a/src/lib/sprite.h b/src/lib/sprite.h index 93c7abce5..883ccfefe 100644 --- a/src/lib/sprite.h +++ b/src/lib/sprite.h @@ -208,22 +208,6 @@ void sixel_refresh(const struct ncpile* p, sprixel* s); int sprixel_load(sprixel* spx, fbuf* f, int pixy, int pixx, int parse_start, sprixel_e state); -typedef enum { - // C=1 (disabling scrolling) was only introduced in 0.20.0, at the same - // time as animation. prior to this, graphics had to be entirely redrawn - // on any change, and it wasn't possible to use the bottom line. - KITTY_ALWAYS_SCROLLS, - // until 0.22.0's introduction of 'a=c' for self-referential composition, we - // had to keep a complete copy of the RGBA data, in case a wiped cell needed - // to be rebuilt. we'd otherwise have to unpack the glyph and store it into - // the auxvec on the fly. - KITTY_ANIMATION, - // with 0.22.0, we only ever write transparent cells after writing the - // original image (which we now deflate, since we needn't unpack it later). - // the only data we need keep is the auxvecs. - KITTY_SELFREF, -} kitty_graphics_e; - #ifdef __cplusplus } #endif diff --git a/src/lib/termdesc.c b/src/lib/termdesc.c index aed57e99d..676355161 100644 --- a/src/lib/termdesc.c +++ b/src/lib/termdesc.c @@ -74,7 +74,7 @@ setup_sixel_bitmaps(tinfo* ti, int fd, bool invert80){ // lacked animation, and must thus redraw the complete image every time it // changes. requires the older interface. static inline void -setup_kitty_bitmaps(tinfo* ti, int fd, kitty_graphics_e level){ +setup_kitty_bitmaps(tinfo* ti, int fd, ncpixelimpl_e level){ ti->pixel_scrub = kitty_scrub; ti->pixel_remove = kitty_remove; ti->pixel_draw = kitty_draw; @@ -85,7 +85,7 @@ setup_kitty_bitmaps(tinfo* ti, int fd, kitty_graphics_e level){ ti->pixel_scroll = NULL; ti->pixel_shutdown = kitty_shutdown; ti->pixel_clear_all = kitty_clear_all; - if(level == KITTY_ALWAYS_SCROLLS){ + if(level == NCPIXEL_KITTY_STATIC){ ti->pixel_wipe = kitty_wipe; ti->pixel_trans_auxvec = kitty_trans_auxvec; ti->pixel_rebuild = kitty_rebuild; @@ -93,7 +93,7 @@ setup_kitty_bitmaps(tinfo* ti, int fd, kitty_graphics_e level){ set_pixel_blitter(kitty_blit); ti->pixel_implementation = NCPIXEL_KITTY_STATIC; }else{ - if(level == KITTY_ANIMATION){ + if(level == NCPIXEL_KITTY_ANIMATED){ ti->pixel_wipe = kitty_wipe_animation; ti->pixel_rebuild = kitty_rebuild_animation; ti->sixel_maxy_pristine = 0; @@ -526,11 +526,11 @@ apply_term_heuristics(tinfo* ti, const char* termname, queried_terminals_e qterm return -1; } /*if(compare_versions(ti->termversion, "0.22.1") >= 0){ - setup_kitty_bitmaps(ti, ti->ttyfd, KITTY_SELFREF); + setup_kitty_bitmaps(ti, ti->ttyfd, NCPIXEL_KITTY_SELFREF); }else*/ if(compare_versions(ti->termversion, "0.20.0") >= 0){ - setup_kitty_bitmaps(ti, ti->ttyfd, KITTY_ANIMATION); + setup_kitty_bitmaps(ti, ti->ttyfd, NCPIXEL_KITTY_ANIMATED); }else{ - setup_kitty_bitmaps(ti, ti->ttyfd, KITTY_ALWAYS_SCROLLS); + setup_kitty_bitmaps(ti, ti->ttyfd, NCPIXEL_KITTY_STATIC); } if(add_pushcolors_escapes(ti, tablelen, tableused)){ return -1; @@ -981,7 +981,7 @@ int interrogate_terminfo(tinfo* ti, const char* termtype, FILE* out, unsigned ut build_supported_styles(ti); if(ti->pixel_draw == NULL && ti->pixel_draw_late == NULL){ if(kitty_graphics){ - setup_kitty_bitmaps(ti, ti->ttyfd, KITTY_ANIMATION); + setup_kitty_bitmaps(ti, ti->ttyfd, NCPIXEL_KITTY_ANIMATED); } // our current sixel quantization algorithm requires at least 64 color // registers. we make use of no more than 256. this needs to happen