Subregion renders #293 (#404)

Add four new fields to notcurses_options: margin_{tblr}, which requests margins to the top, right, bottom, and left. Render only within those margins, leaving the screen otherwise untouched (well, cleared if using the alternate screen). #293
pull/405/head
Nick Black 4 years ago committed by GitHub
parent 982d729c69
commit c056a0a026
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -35,7 +35,7 @@ Packages for Debian Unstable and Ubuntu Focal are available from [DSSCAW](https:
* [Features missing relative to NCURSES](#features-missing-relative-to-ncurses)
* [Adapting NCURSES programs](#adapting-ncurses-programs)
* [Environment notes](#environment-notes)
* [DirectColor detection](#DirectColor-detection)
* [TrueColor detection](#TrueColor-detection)
* [Fonts](#fonts)
* [FAQs](#faqs)
* [Supplemental material](#supplemental-material)
@ -57,9 +57,9 @@ Packages for Debian Unstable and Ubuntu Focal are available from [DSSCAW](https:
notcurses abandons the X/Open Curses API bundled as part of the Single UNIX
Specification. The latter shows its age, and seems not capable of making use of
terminal functionality such as unindexed 24-bit color ("DirectColor", not to be
confused with 8-bit indexed 24-bit color, aka "TrueColor" or (by NCURSES) as
"extended color"). For some necessary background, consult Thomas E. Dickey's
terminal functionality such as unindexed 24-bit color ("TrueColor", not to be
confused with the 8-bit indexed 24-bit "extended color" of NCURSES).
For some necessary background, consult Thomas E. Dickey's
superb and authoritative [NCURSES FAQ](https://invisible-island.net/ncurses/ncurses.faq.html#xterm_16MegaColors).
As such, notcurses is not a drop-in Curses replacement. It is almost certainly
less portable, and definitely tested on less hardware. Sorry about that.
@ -212,6 +212,11 @@ typedef struct notcurses_options {
// Progressively higher log levels result in more logging to stderr. By
// default, nothing is printed to stderr once fullscreen service begins.
ncloglevel_e loglevel;
// Desirable margins. If all are 0 (default), we will render to the entirety
// of the screen. If the screen is too small, we do what we can--this is
// strictly best-effort. Absolute coordinates are relative to the rendering
// area ((0, 0) is always the origin of the rendering area).
int margin_t, margin_r, margin_b, margin_l;
} notcurses_options;
// Initialize a notcurses context on the connected terminal at 'fp'. 'fp' must
@ -2498,12 +2503,12 @@ These are pretty obvious, implementation-wise.
* The unit tests assume dimensions of at least 80x24. They might work in a
smaller terminal. They might not. Don't file bugs on it.
### DirectColor detection
### TrueColor detection
notcurses aims to use only information found in the terminal's terminfo entry to detect capabilities, DirectColor
notcurses aims to use only information found in the terminal's terminfo entry to detect capabilities, TrueColor
being one of them. Support for this is indicated by terminfo having a flag, added in NCURSES 6.1, named `RGB` set
to `true`. However, as of today there are few and far between terminfo entries which have the capability in their
database entry and so DirectColor won't be used in most cases. Terminal emulators have had for years a kludge to
database entry and so TrueColor won't be used in most cases. Terminal emulators have had for years a kludge to
work around this limitation of terminfo in the form of the `COLORTERM` environment variable which, if set to either
`truecolor` or `24bit` does the job of indicating the capability of sending the escapes 48 and 38 together with a
tripartite RGB (0 ≤ c ≤ 255 for all three components) to specify fore- and background colors.
@ -2590,7 +2595,7 @@ up someday **FIXME**.
I study the history of NCURSES, primarily using Thomas E. Dickey's FAQ and
the mailing list archives.
* 2019-11-14: I file [Outcurses issue #56](https://github.com/dankamongmen/ncreels/issues/56)
regarding use of DirectColor in outcurses. This is partially inspired by
regarding use of TrueColor in outcurses. This is partially inspired by
Lexi Summer Hale's essay [everything you ever wanted to know about terminals](http://xn--rpa.cc/irl/term.html).
I get into contact with Thomas E. Dickey and confirm that what I'm hoping
to do doesn't really fit in with the codified Curses API.

@ -9,13 +9,14 @@ notcurses-demo - Show off some notcurses features
# SYNOPSIS
**notcurses-demo** [**-h|--help**] [**-p path**] [**-d delaymult**]
[**-l loglevel**] [**-f renderfile**] [**-J jsonfile**] [**-ikVc**] demospec
[**-l loglevel**] [**-f renderfile**] [**-J jsonfile**] [**-m margins**]
[**-ikVc**] demospec
# DESCRIPTION
**notcurses-demo** demonstrates the capabilities of the notcurses library. It
can be run in any terminal emulator or console with a correct terminfo(5)
database, but is at is best in a "DirectColor" 24bpp RGB environment. If
database, but is at is best in a 24bpp TrueColor RGB environment. If
**notcurses-demo** seems to generate garbage, something is likely configured in
a way that is going to prevent notcurses from working.
@ -53,6 +54,8 @@ At any time, press 'q' to quit. The demo is best run in at least an 80x45 termin
**-J jsonfile**: Emit JSON summary of run to **jsonfile**.
**-m margins**: Define rendering margins (see below).
**-k**: Inhibit use of the alternate screen. Necessary if you want the output left on your terminal after the program exits.
**-c**: Do not attempt to seed the PRNG. This is useful when benchmarking.
@ -65,6 +68,11 @@ At any time, press 'q' to quit. The demo is best run in at least an 80x45 termin
demospec: Select which demos to run, and what order to run them in. The default is **ixethbcgrwuvlfsjo**. See above for a list of demos.
Default margins are all 0, and thus the full screen will be rendered. Using
**-m**, margins can be supplied. Provide a single number to set all four margins
to the same value, or four comma-delimited values for the top, right, bottom,
and left margins respectively. Negative margins are illegal.
# NOTES
Proper display requires:

@ -17,7 +17,7 @@ notcurses - TUI library for modern terminal emulators
notcurses builds atop the **terminfo(5)** abstraction layer to provide
reasonably portable vivid character displays. It is an intellectual descendant
of **ncurses(3NCURSES)**, but goes beyond that library (and the X/Open Curses
API it implements). notcurses is capable of subregion fades, 24bpp DirectColor,
API it implements). notcurses is capable of subregion fades, 24bpp TrueColor,
transparency, multimedia, and safe multithreaded use.
A program wishing to use notcurses will need to link it, ideally using the

@ -19,6 +19,7 @@ typedef struct notcurses_options {
bool no_quit_sighandlers;
bool no_winch_sighandler;
FILE* renderfp;
int margin_t, margin_r, margin_b, margin_l;
} notcurses_options;
```
@ -58,6 +59,16 @@ information and some details of the configured terminal. This can be inhibited
with **suppress_banner**. This will also inhibit the performance summary normally
printed by **notcurses_stop(3)**.
Notcurses can render to a subregion of the terminal by specifying desired
margins on all four sides. By default, all margins are zero, and thus rendering
will be performed on the entirety of the viewing area. This is orthogonal to
use of the alternate screen; using the alternate screen plus margins will see
the full screen cleared, followed by rendering to a subregion. Inhibiting the
alternate screen plus margins will see rendering to a subregion, with the screen
outside this region not cleared. This is the only means by which existing
output can be undisturbed by notcurses. Margins are best-effort. Supplying any
negative margin is an error.
## Fatal signals
It is important to reset the terminal before exiting, whether terminating due

@ -107,8 +107,6 @@ mbswidth(const char* mbs){
return cols;
}
#define NCPALETTESIZE 256
// A cell corresponds to a single character cell on some plane, which can be
// occupied by a single grapheme cluster (some root spacing glyph, along with
// possible combining characters, which might span multiple columns). At any
@ -232,6 +230,11 @@ typedef struct notcurses_options {
// Progressively higher log levels result in more logging to stderr. By
// default, nothing is printed to stderr once fullscreen service begins.
ncloglevel_e loglevel;
// Desirable margins. If all are 0 (default), we will render to the entirety
// of the screen. If the screen is too small, we do what we can--this is
// strictly best-effort. Absolute coordinates are relative to the rendering
// area ((0, 0) is always the origin of the rendering area).
int margin_t, margin_r, margin_b, margin_l;
} notcurses_options;
// Initialize a notcurses context on the connected terminal at 'fp'. 'fp' must
@ -953,6 +956,7 @@ API int ncplane_stain(struct ncplane* n, int ystop, int xstop, uint64_t ul,
// excluding the base cell.
API void ncplane_erase(struct ncplane* n);
#define NCPALETTESIZE 256
#define CELL_WIDEASIAN_MASK 0x8000000080000000ull
#define CELL_BGDEFAULT_MASK 0x0000000040000000ull
#define CELL_FGDEFAULT_MASK (CELL_BGDEFAULT_MASK << 32u)

@ -72,6 +72,11 @@ typedef struct notcurses_options {
// Progressively higher log levels result in more logging to stderr. By
// default, nothing is printed to stderr once fullscreen service begins.
ncloglevel_e loglevel;
// Desirable margins. If all are 0 (default), we will render to the entirety
// of the screen. If the screen is too small, we do what we can--this is
// strictly best-effort. Absolute coordinates are relative to the rendering
// area ((0, 0) is always the origin of the rendering area).
int margin_t, margin_r, margin_b, margin_l;
} notcurses_options;
struct notcurses* notcurses_init(const notcurses_options*, FILE*);
int notcurses_stop(struct notcurses*);
@ -322,7 +327,7 @@ typedef struct multiselector_options {
uint64_t bgchannels; // background channels, used only in body
} multiselector_options;
struct ncmultiselector* ncmultiselector_create(struct ncplane* n, int y, int x, const multiselector_options* opts);
int ncmultiselector_selected(struct ncmultiselector* n, bool* selected, unsigned n);
int ncmultiselector_selected(struct ncmultiselector* n, bool* selected, unsigned count);
struct ncplane* ncmultiselector_plane(struct ncmultiselector* n);
bool ncmultiselector_offer_input(struct ncmultiselector* n, const struct ncinput* nc);
void ncmultiselector_destroy(struct ncmultiselector* n, char** item);

@ -21,7 +21,7 @@ fn main() {
// to bindgen, and lets you build up options for
// the resulting bindings.
let bindings = bindgen::Builder::default()
.clang_arg("-I../../include") // FIXME pass via envvar?
.clang_arg("-I../../include -D_XOPEN_SOURCE") // FIXME pass via envvar?
// The input header we would like to generate
// bindings for.
.header("wrapper.h")

@ -11,3 +11,4 @@ homepage = "https://nick-black.com/dankwiki/index.php/Notcurses"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
libnotcurses-sys = "^1.2.3"

@ -10,9 +10,9 @@
#include <stdatomic.h>
#include "demo.h"
// ansi terminal definition-4-life
// (non-)ansi terminal definition-4-life
static const int MIN_SUPPORTED_ROWS = 24;
static const int MIN_SUPPORTED_COLS = 80;
static const int MIN_SUPPORTED_COLS = 76; // allow a bit of margin, sigh
static int democount;
static demoresult* results;
@ -120,7 +120,7 @@ static struct {
static void
usage(const char* exe, int status){
FILE* out = status == EXIT_SUCCESS ? stdout : stderr;
fprintf(out, "usage: %s [ -hVikc ] [ -p path ] [ -l loglevel ] [ -d mult ] [ -J jsonfile ] [ -f renderfile ] demospec\n", exe);
fprintf(out, "usage: %s [ -hVikc ] [ -m margins ] [ -p path ] [ -l loglevel ] [ -d mult ] [ -J jsonfile ] [ -f renderfile ] demospec\n", exe);
fprintf(out, " -h: this message\n");
fprintf(out, " -V: print program name and version\n");
fprintf(out, " -l: logging level (%d: silent..%d: manic)\n", NCLOGLEVEL_SILENT, NCLOGLEVEL_TRACE);
@ -131,6 +131,7 @@ usage(const char* exe, int status){
fprintf(out, " -J: emit JSON summary to file\n");
fprintf(out, " -c: constant PRNG seed, useful for benchmarking\n");
fprintf(out, " -p: data file path (default: %s)\n", NOTCURSES_SHARE);
fprintf(out, " -m: margin, or 4 comma-separated margins\n");
fprintf(out, "if no specification is provided, run %s\n", DEFAULT_DEMO);
for(size_t i = 0 ; i < sizeof(demos) / sizeof(*demos) ; ++i){
if(demos[i].name){
@ -140,6 +141,53 @@ usage(const char* exe, int status){
exit(status);
}
// extract an integer, which must be non-negative, and followed by either a
// comma or a NUL terminator.
static int
lex_long(const char* op, int* i, char** endptr){
errno = 0;
long l = strtol(op, endptr, 10);
if(l < 0 || (l == LONG_MAX && errno == ERANGE) || (l > INT_MAX)){
fprintf(stderr, "Invalid margin: %s\n", op);
return -1;
}
if((**endptr != ',' && **endptr) || *endptr == op){
fprintf(stderr, "Invalid margin: %s\n", op);
return -1;
}
*i = l;
return 0;
}
static int
lex_margins(const char* op, notcurses_options* opts){
if(opts->margin_t || opts->margin_r || opts->margin_b || opts->margin_l){
fprintf(stderr, "Provided margins twice!\n");
return -1;
}
char* eptr;
if(lex_long(op, &opts->margin_t, &eptr)){
return -1;
}
if(!*eptr){ // allow a single value to be specified for all four margins
opts->margin_r = opts->margin_l = opts->margin_b = opts->margin_t;
return 0;
}
op = ++eptr; // once here, we require four values
if(lex_long(op, &opts->margin_r, &eptr) || !*eptr){
return -1;
}
op = ++eptr;
if(lex_long(op, &opts->margin_b, &eptr) || !*eptr){
return -1;
}
op = ++eptr;
if(lex_long(op, &opts->margin_l, &eptr) || *eptr){ // must end in NUL
return -1;
}
return 0;
}
static demoresult*
ext_demos(struct notcurses* nc, const char* spec, bool ignore_failures){
int ret = 0;
@ -189,7 +237,7 @@ handle_opts(int argc, char** argv, notcurses_options* opts, bool* ignore_failure
*json_output = NULL;
int c;
memset(opts, 0, sizeof(*opts));
while((c = getopt(argc, argv, "VhickJ:l:r:d:f:p:")) != EOF){
while((c = getopt(argc, argv, "VhickJ:l:r:d:f:p:m:")) != EOF){
switch(c){
case 'h':
usage(*argv, EXIT_SUCCESS);
@ -206,6 +254,11 @@ handle_opts(int argc, char** argv, notcurses_options* opts, bool* ignore_failure
usage(*argv, EXIT_FAILURE);
}
break;
}case 'm':{
if(lex_margins(optarg, opts)){
usage(*argv, EXIT_FAILURE);
}
break;
}case 'V':
printf("notcurses-demo version %s\n", notcurses_version());
exit(EXIT_SUCCESS);

@ -181,7 +181,8 @@ eagles(struct notcurses* nc){
}else if(e[i].yoff + height >= truey){
e[i].yoff = truey - height - 1;
}
e[i].xoff += (random() % (truex / 80)) + 1;
int scale = truex >= 80 ? truex / 80 : 1;
e[i].xoff += (random() % scale) + 1;
ncplane_move_yx(e[i].n, e[i].yoff, e[i].xoff);
++eaglesmoved;
}

@ -211,7 +211,7 @@ message(struct ncplane* n, int maxy, int maxx, int num, int total,
ncplane_printf_yx(n, 1, 4, " %03dx%03d (%d/%d) ", maxx, maxy, num + 1, total);
ncplane_styles_off(n, NCSTYLE_ITALIC);
ncplane_set_fg_rgb(n, 224, 128, 224);
ncplane_putstr_yx(n, 3, 1, " 🔥 unicode 13, resize awareness, 24b directcolor…🔥 ");
ncplane_putstr_yx(n, 3, 1, " 🔥 unicode 13, resize awareness, 24b truecolor…🔥 ");
ncplane_set_fg_rgb(n, 255, 255, 255);
return 0;
}

@ -227,7 +227,7 @@ typedef struct ncdirect {
char* initc; // set a palette entry's RGB value
char* oc; // restore original colors
char* clear; // clear the screen
bool RGBflag; // terminfo-reported "RGB" flag for 24bpc directcolor
bool RGBflag; // terminfo-reported "RGB" flag for 24bpc truecolor
bool CCCflag; // terminfo-reported "CCC" flag for palette set capability
FILE* ttyfp; // FILE* for controlling tty, from opts->ttyfp
palette256 palette; // 256-indexed palette can be used instead of/with RGB
@ -284,7 +284,7 @@ typedef struct notcurses {
char* getm; // get mouse events
char* initc; // set a palette entry's RGB value
char* oc; // restore original colors
bool RGBflag; // terminfo-reported "RGB" flag for 24bpc directcolor
bool RGBflag; // terminfo-reported "RGB" flag for 24bpc truecolor
bool CCCflag; // terminfo-reported "CCC" flag for palette set capability
bool AMflag; // ti-reported "AM" flag for automatic movement to next line
@ -307,6 +307,9 @@ typedef struct notcurses {
// be reset (semantics are relied upon by widgets for mouse click detection).
uint64_t input_events;
// desired margins (best-effort only), copied in from notcurses_options
int margin_t, margin_b, margin_r, margin_l;
palette256 palette; // 256-indexed palette can be used instead of/with RGB
bool palette_damage[NCPALETTESIZE];
struct esctrie* inputescapes; // trie of input escapes -> ncspecial_keys

@ -283,8 +283,8 @@ ncplane_create(notcurses* nc, int rows, int cols, int yoff, int xoff){
p->leny = rows;
p->lenx = cols;
p->x = p->y = 0;
p->absx = xoff;
p->absy = yoff;
p->absx = xoff + nc->margin_l;
p->absy = yoff + nc->margin_t;
p->attrword = 0;
p->channels = 0;
egcpool_init(&p->pool);
@ -301,7 +301,8 @@ ncplane_create(notcurses* nc, int rows, int cols, int yoff, int xoff){
// the z-buffer. clear out all cells. this is for a wholly new context.
static ncplane*
create_initial_ncplane(notcurses* nc, int dimy, int dimx){
nc->stdscr = ncplane_create(nc, dimy, dimx, 0, 0);
nc->stdscr = ncplane_create(nc, dimy - (nc->margin_t + nc->margin_b),
dimx - (nc->margin_l + nc->margin_r), 0, 0);
return nc->stdscr;
}
@ -497,6 +498,15 @@ int notcurses_resize(notcurses* n, int* rows, int* cols){
if(update_term_dimensions(n->ttyfd, rows, cols)){
return -1;
}
// FIXME can we emerge from the previous call with rows/cols <= 0?
*rows -= n->margin_t + n->margin_b;
if(*rows <= 0){
*rows = 1;
}
*cols -= n->margin_l + n->margin_r;
if(*cols <= 0){
*cols = 1;
}
if(*rows == oldrows && *cols == oldcols){
return 0; // no change
}
@ -551,7 +561,7 @@ query_rgb(void){
if(!rgb){
// RGB terminfo capability being a new thing (as of ncurses 6.1), it's not commonly found in
// terminal entries today. COLORTERM, however, is a de-facto (if imperfect/kludgy) standard way
// of indicating DirectColor support for a terminal. The variable takes one of two case-sensitive
// of indicating TrueColor support for a terminal. The variable takes one of two case-sensitive
// values:
//
// truecolor
@ -567,8 +577,7 @@ query_rgb(void){
}
static int
interrogate_terminfo(notcurses* nc, const notcurses_options* opts,
int* dimy, int* dimx){
interrogate_terminfo(notcurses* nc, const notcurses_options* opts, int* dimy, int* dimx){
update_term_dimensions(nc->ttyfd, dimy, dimx);
char* shortname_term = termname();
char* longname_term = longname();
@ -826,6 +835,10 @@ notcurses* notcurses_init(const notcurses_options* opts, FILE* outfp){
if(!opts){
opts = &defaultopts;
}
if(opts->margin_t < 0 || opts->margin_b < 0 || opts->margin_l < 0 || opts->margin_r < 0){
fprintf(stderr, "Provided an illegal negative margin, refusing to start\n");
return NULL;
}
const char* encoding = nl_langinfo(CODESET);
if(encoding == NULL || (strcmp(encoding, "ANSI_X3.4-1968") && strcmp(encoding, "UTF-8"))){
fprintf(stderr, "Encoding (\"%s\") was neither ANSI_X3.4-1968 nor UTF-8, refusing to start\n",
@ -837,6 +850,10 @@ notcurses* notcurses_init(const notcurses_options* opts, FILE* outfp){
if(ret == NULL){
return ret;
}
ret->margin_t = opts->margin_t;
ret->margin_b = opts->margin_b;
ret->margin_l = opts->margin_l;
ret->margin_r = opts->margin_r;
ret->stats.fbbytes = 0;
ret->stashstats.fbbytes = 0;
reset_stats(&ret->stats);
@ -921,9 +938,9 @@ notcurses* notcurses_init(const notcurses_options* opts, FILE* outfp){
if(!opts->suppress_banner){
char prefixbuf[BPREFIXSTRLEN + 1];
term_fg_palindex(ret, ret->ttyfp, ret->colors <= 256 ? 50 % ret->colors : 0x20e080);
fprintf(ret->ttyfp, "\n notcurses %s by nick black et al", notcurses_version());
printf("\n notcurses %s by nick black et al", notcurses_version());
term_fg_palindex(ret, ret->ttyfp, ret->colors <= 256 ? 12 % ret->colors : 0x2080e0);
fprintf(ret->ttyfp, "\n %d rows, %d columns (%sB), %d colors (%s)\n"
printf("\n %d rows, %d columns (%sB), %d colors (%s)\n"
" compiled with gcc-%s\n"
" terminfo from %s\n",
ret->stdscr->leny, ret->stdscr->lenx,
@ -931,25 +948,26 @@ notcurses* notcurses_init(const notcurses_options* opts, FILE* outfp){
ret->colors, ret->RGBflag ? "direct" : "palette",
__VERSION__, curses_version());
#ifdef USE_FFMPEG
fprintf(ret->ttyfp, " avformat %u.%u.%u\n avutil %u.%u.%u\n swscale %u.%u.%u\n",
printf(" avformat %u.%u.%u\n avutil %u.%u.%u\n swscale %u.%u.%u\n",
LIBAVFORMAT_VERSION_MAJOR, LIBAVFORMAT_VERSION_MINOR, LIBAVFORMAT_VERSION_MICRO,
LIBAVUTIL_VERSION_MAJOR, LIBAVUTIL_VERSION_MINOR, LIBAVUTIL_VERSION_MICRO,
LIBSWSCALE_VERSION_MAJOR, LIBSWSCALE_VERSION_MINOR, LIBSWSCALE_VERSION_MICRO);
fflush(stdout);
#else
term_fg_palindex(ret, ret->ttyfp, ret->colors <= 88 ? 1 % ret->colors : 0xcb);
fprintf(ret->ttyfp, "\n Warning! Notcurses was built without ffmpeg support\n");
fprintf(stderr, "\n Warning! Notcurses was built without ffmpeg support\n");
#endif
term_fg_palindex(ret, ret->ttyfp, ret->colors <= 88 ? 1 % ret->colors : 0xcb);
if(!ret->RGBflag){ // FIXME
fprintf(ret->ttyfp, "\n Warning! Colors subject to https://github.com/dankamongmen/notcurses/issues/4");
fprintf(ret->ttyfp, "\n Specify a (correct) DirectColor TERM, or COLORTERM=24bit.\n");
fprintf(stderr, "\n Warning! Colors subject to https://github.com/dankamongmen/notcurses/issues/4");
fprintf(stderr, "\n Specify a (correct) TrueColor TERM, or COLORTERM=24bit.\n");
}else{
if(!ret->CCCflag){
fprintf(ret->ttyfp, "\n Warning! Advertised DirectColor but no 'ccc' flag\n");
fprintf(stderr, "\n Warning! Advertised TrueColor but no 'ccc' flag\n");
}
}
if(strcmp(encoding, "UTF-8")){
fprintf(ret->ttyfp, "\n Warning! Encoding is not UTF-8.\n");
if(strcmp(encoding, "UTF-8")){ // it definitely exists, but could be ASCII
fprintf(stderr, "\n Warning! Encoding is not UTF-8.\n");
}
}
// flush on the switch to alternate screen, lest initial output be swept away

@ -212,8 +212,8 @@ paint(notcurses* nc, ncplane* p, struct crender* rvec, cell* fb){
// don't use ncplane_dim_yx()/ncplane_yx() here, lest we deadlock
dimy = p->leny;
dimx = p->lenx;
offy = p->absy;
offx = p->absx;
offy = p->absy - nc->stdscr->absy;
offx = p->absx - nc->stdscr->absx;
//fprintf(stderr, "PLANE %p %d %d %d %d %d %d\n", p, dimy, dimx, offy, offx, nc->stdscr->leny, nc->stdscr->lenx);
// skip content above or to the left of the physical screen
int starty, startx;
@ -764,19 +764,23 @@ notcurses_rasterize(notcurses* nc, const struct crender* rvec){
// we only need to emit a coordinate if it was damaged. the damagemap is a
// bit per coordinate, rows by rows, column by column within a row, with the
// MSB being the first coordinate.
size_t damageidx = 0;
// don't write a clearscreen. we only update things that have been changed.
// we explicitly move the cursor at the beginning of each output line, so no
// need to home it expliticly.
update_palette(nc, out);
for(y = 0 ; y < nc->stdscr->leny ; ++y){
// FIXME need to track outer{x,y} (position on screen) and inner{x,y}
// (position within lastframe/rvec, which is lfdimx-sized)
for(y = nc->stdscr->absy ; y < nc->stdscr->leny + nc->stdscr->absy ; ++y){
const int innery = y - nc->stdscr->absy;
// how many characters have we elided? it's not worthwhile to invoke a
// cursor movement with cup if we only elided one or two. set to INT_MAX
// whenever we're on a new line. leave room to avoid overflow.
int needmove = INT_MAX - nc->stdscr->lenx;
for(x = 0 ; x < nc->stdscr->lenx ; ++x){
for(x = nc->stdscr->absx ; x < nc->stdscr->lenx + nc->stdscr->absx ; ++x){
const int innerx = x - nc->stdscr->absx;
const size_t damageidx = innery * nc->lfdimx + innerx;
unsigned r, g, b, br, bg, bb, palfg, palbg;
const cell* srccell = &nc->lastframe[y * nc->lfdimx + x];
const cell* srccell = &nc->lastframe[innery * nc->lfdimx + innerx];
// cell c;
// memcpy(c, srccell, sizeof(*c)); // unsafe copy of gcluster
//fprintf(stderr, "COPYING: %d from %p\n", c->gcluster, &nc->pool);
@ -907,9 +911,8 @@ fprintf(stderr, "RAST %u [%s] to %d/%d\n", srccell->gcluster, egcpool_extended_g
}
if(cell_double_wide_p(srccell)){
++x;
++damageidx;
}
++damageidx;
//fprintf(stderr, "damageidx: %ld\n", damageidx);
}
}
ret |= fflush(out);

Loading…
Cancel
Save