Cursor work (placement, drop RETAIN_CURSOR) #953

notcurses_enable_cursor() now accepts placement arguments.
both it and notcurses_disable_cursor() now return int rather
than void. add notcurses_cursor_move_yx().
This commit is contained in:
nick black 2020-08-25 02:54:46 -04:00 committed by Nick Black
parent df33f381e5
commit cab19cf790
11 changed files with 112 additions and 46 deletions

View File

@ -6,6 +6,13 @@ rearrangements of Notcurses.
functions which once returned `nc_err_e` now return a bimodal `int`. Those
functions which accepted a value-result `nc_err_e*` no longer take this
argument.
* `notcurses_cursor_move_yx()` has been added for placement of the terminal
cursor. Remember, you must call `notcurses_cursor_enable()` before it will
be made visible.
* `notcurses_cursor_enable()` now takes two `int` parameters specifying the
desired location of the cursor. Both `notcurses_cursor_enable()` and
`notcurses_cursor_disable()` now return `int` rather than `void`.
* `NCOPTION_RETAIN_CURSOR` has been removed.
* 1.6.17 (2020-08-22)
* `ncdirect_flush()` now takes a `const struct ncdirect*`.

View File

@ -99,10 +99,6 @@ typedef enum {
// registration of these signal handlers.
#define NCOPTION_NO_QUIT_SIGHANDLERS 0x0008
// By default, we hide the cursor if possible. This flag inhibits use of
// the civis capability, retaining the cursor.
#define NCOPTION_RETAIN_CURSOR 0x0010
// Notcurses typically prints version info in notcurses_init() and performance
// info in notcurses_stop(). This inhibits that output.
#define NCOPTION_SUPPRESS_BANNERS 0x0020
@ -231,6 +227,16 @@ notcurses_term_dim_yx(const struct notcurses* n, int* restrict rows,
// NCKEY_RESIZE event has been read and you're not ready to render.
int notcurses_refresh(struct notcurses* n, int* restrict y, int* restrict x);
// Enable or disable the terminal's cursor, if supported. Immediate effect.
void notcurses_cursor_enable(struct notcurses* nc);
void notcurses_cursor_disable(struct notcurses* nc);
// Move the terminal cursor to the specified location. If 'y' or 'x' is
// negative, there is no movement along that axis. Returns error if the
// coordinates are outside the viewing area. The cursor must be explicitly
// enabled with notcurses_cursor_enable() to be seen.
int notcurses_cursor_move_yx(struct notcurses* nc, int y, int x);
// Returns a 16-bit bitmask in the LSBs of supported curses-style attributes
// (NCSTYLE_UNDERLINE, NCSTYLE_BOLD, etc.) The attribute is only
// indicated as supported if the terminal can support it together with color.

View File

@ -15,7 +15,6 @@ notcurses_init - initialize a notcurses instance
#define NCOPTION_VERIFY_SIXEL 0x0002ull
#define NCOPTION_NO_WINCH_SIGHANDLER 0x0004ull
#define NCOPTION_NO_QUIT_SIGHANDLERS 0x0008ull
#define NCOPTION_RETAIN_CURSOR 0x0010ull
#define NCOPTION_SUPPRESS_BANNERS 0x0020ull
#define NCOPTION_NO_ALTERNATE_SCREEN 0x0040ull
#define NCOPTION_NO_FONT_CHANGES 0x0080ull
@ -47,6 +46,12 @@ typedef struct notcurses_options {
**struct notcurses* notcurses_init(const notcurses_options* opts, FILE* fp);**
**int notcurses_cursor_enable(struct notcurses* nc, int y, int x);**
**int notcurses_cursor_move_yx(struct notcurses* nc, int y, int x);**
**int notcurses_cursor_disable(struct notcurses* nc);**
# DESCRIPTION
**notcurses_init** prepares the terminal for cursor-addressable (multiline)
@ -74,9 +79,9 @@ by setting **NCOPTION_NO_ALTERNATE_SCREEN** in **flags**. Users tend to have
strong opinions regarding the alternate screen, so it's often useful to expose
this via a command-line option.
notcurses furthermore hides the cursor by default, but **NCOPTION_RETAIN_CURSOR**
can prevent this (the cursor can be dynamically enabled or disabled during
execution via **notcurses_cursor_enable(3)** and **notcurses_cursor_disable(3)**).
notcurses hides the cursor by default. It can be dynamically enabled or
disabled during execution via **notcurses_cursor_enable(3)** and
**notcurses_cursor_disable(3)**, and moved with **notcurses_cursor_move_yx()**.
**notcurses_init** typically emits some diagnostics at startup, including version
information and some details of the configured terminal. This can be inhibited
@ -123,9 +128,6 @@ zero. The following flags are defined:
cleaning up the terminal on such exceptions. With this flag, the handler
will not be installed.
* **NCOPTION_RETAIN_CURSOR**: Notcurses typically disables the cursor on
startup. With this flag, the cursor will be left enabled.
* **NCOPTION_SUPPRESS_BANNERS**: Disables the diagnostics and version
information printed on startup, and the performance summary on exit.

View File

@ -151,14 +151,19 @@ namespace ncpp
return notcurses_cantruecolor (nc);
}
void cursor_enable () const noexcept
int cursor_enable (int y, int x) const noexcept
{
notcurses_cursor_enable (nc);
return error_guard (notcurses_cursor_enable (nc, y, x), -1);
}
void cursor_disable () const noexcept
int cursor_disable () const noexcept
{
notcurses_cursor_disable (nc);
return error_guard (notcurses_cursor_disable (nc), -1);
}
int cursor_move_yx (int y, int x) const noexcept
{
return error_guard (notcurses_cursor_move_yx (nc, y, x), -1);
}
void get_stats (ncstats *stats) const noexcept

View File

@ -781,9 +781,7 @@ typedef enum {
// registration of these signal handlers.
#define NCOPTION_NO_QUIT_SIGHANDLERS 0x0008ull
// By default, we hide the cursor if possible. This flag inhibits use of
// the civis capability, retaining the cursor.
#define NCOPTION_RETAIN_CURSOR 0x0010ull
// NCOPTION_RETAIN_CURSOR was removed in 1.6.18. It ought be repurposed. FIXME.
// Notcurses typically prints version info in notcurses_init() and performance
// info in notcurses_stop(). This inhibits that output.
@ -2570,9 +2568,17 @@ bprefix(uintmax_t val, uintmax_t decimal, char* buf, int omitdec){
return ncmetric(val, decimal, buf, omitdec, 1024, 'i');
}
// Enable or disable the terminal's cursor, if supported. Immediate effect.
API void notcurses_cursor_enable(struct notcurses* nc);
API void notcurses_cursor_disable(struct notcurses* nc);
// Enable or disable the terminal's cursor, if supported, placing it at
// 'y', 'x'. Immediate effect (no need for a call to notcurses_render()).
// It is an error if 'y', 'x' lies outside the standard plane.
API int notcurses_cursor_enable(struct notcurses* nc, int y, int x);
API int notcurses_cursor_disable(struct notcurses* nc);
// Move the terminal cursor to the specified location. If 'y' or 'x' is
// negative, there is no movement along that axis. Returns error if the
// coordinates are outside the viewing area. The cursor must be explicitly
// enabled with notcurses_cursor_enable() to be seen.
API int notcurses_cursor_move_yx(struct notcurses* nc, int y, int x);
// Palette API. Some terminals only support 256 colors, but allow the full
// palette to be specified with arbitrary RGB colors. In all cases, it's more

View File

@ -431,6 +431,9 @@ bool ncdirect_canutf8(const struct ncdirect* n);
int ncdirect_render_image(struct ncdirect* n, const char* filename, ncalign_e align, ncblitter_e blitter, ncscale_e scale);
struct ncplane* ncplane_parent(struct ncplane* n);
const struct ncplane* ncplane_parent_const(const struct ncplane* n);
int notcurses_cursor_enable(struct notcurses* nc, int y, int x);
int notcurses_cursor_move_yx(struct notcurses* nc, int y, int x);
int notcurses_cursor_disable(struct notcurses* nc);
""")
if __name__ == "__main__":

View File

@ -14,7 +14,6 @@ NCOPTION_INHIBIT_SETLOCALE = 0x0001
NCOPTION_VERIFY_SIXEL = 0x0002
NCOPTION_NO_WINCH_SIGHANDLER = 0x0004
NCOPTION_NO_QUIT_SIGHANDLERS = 0x0008
NCOPTION_RETAIN_CURSOR = 0x0010
NCOPTION_SUPPRESS_BANNERS = 0x0020
NCOPTION_NO_ALTERNATE_SCREEN = 0x0040
NCOPTION_NO_FONT_CHANGES = 0x0080

View File

@ -101,7 +101,7 @@ typedef struct renderstate {
// the current cursor position. this is independent of whether the cursor is
// visible. it is the cell at which the next write will take place. this is
// modified by: output, cursor moves, clearing the screen (during refresh)
// modified by: output, cursor moves, clearing the screen (during refresh).
int y, x;
uint32_t curattr;// current attributes set (does not include colors)
@ -275,6 +275,9 @@ typedef struct notcurses {
int lfdimy; // lfdimx/lfdimy are 0 until first render
egcpool pool; // duplicate EGCs into this pool
int cursory; // desired cursor placement according to user. -1 is a don't-
int cursorx; // care, otherwise moved here after each render.
ncstats stats; // some statistics across the lifetime of the notcurses ctx
ncstats stashstats; // cumulative stats, unaffected by notcurses_reset_stats()

View File

@ -859,6 +859,7 @@ notcurses* notcurses_init(const notcurses_options* opts, FILE* outfp){
ret->margin_b = opts->margin_b;
ret->margin_l = opts->margin_l;
ret->margin_r = opts->margin_r;
ret->cursory = ret->cursorx = -1;
ret->stats.fbbytes = 0;
ret->stashstats.fbbytes = 0;
reset_stats(&ret->stats);
@ -966,11 +967,9 @@ notcurses* notcurses_init(const notcurses_options* opts, FILE* outfp){
free_plane(ret->top);
goto err;
}
if(!(opts->flags & NCOPTION_RETAIN_CURSOR)){
if(ret->tcache.civis && tty_emit("civis", ret->tcache.civis, ret->ttyfd)){
free_plane(ret->top);
goto err;
}
if(ret->tcache.civis && tty_emit("civis", ret->tcache.civis, ret->ttyfd)){
free_plane(ret->top);
goto err;
}
}
if((ret->rstate.mstreamfp = open_memstream(&ret->rstate.mstream, &ret->rstate.mstrsize)) == NULL){
@ -1885,22 +1884,6 @@ void ncplane_erase(ncplane* n){
n->y = n->x = 0;
}
void notcurses_cursor_enable(notcurses* nc){
if(nc->ttyfd >= 0){
if(nc->tcache.cnorm){
tty_emit("cnorm", nc->tcache.cnorm, nc->ttyfd);
}
}
}
void notcurses_cursor_disable(notcurses* nc){
if(nc->ttyfd >= 0){
if(nc->tcache.civis){
tty_emit("civis", nc->tcache.civis, nc->ttyfd);
}
}
}
ncplane* notcurses_top(notcurses* n){
return n->top;
}

View File

@ -968,7 +968,7 @@ int notcurses_refresh(notcurses* nc, int* restrict dimy, int* restrict dimx){
return 0;
}
int notcurses_render_to_file(struct notcurses* nc, FILE* fp){
int notcurses_render_to_file(notcurses* nc, FILE* fp){
if(nc->lfdimx == 0 || nc->lfdimy == 0){
return 0;
}
@ -1101,3 +1101,52 @@ int ncdirect_fg(ncdirect* nc, unsigned rgb){
nc->fgrgb = rgb;
return 0;
}
int notcurses_cursor_enable(notcurses* nc, int y, int x){
if(y < 0 || x < 0){
logerror(nc, "Illegal cursor placement: %d, %d\n", y, x);
return -1;
}
if(y >= nc->stdplane->leny || x >= nc->stdplane->lenx){
logerror(nc, "Illegal cursor placement: %d, %d\n", y, x);
return -1;
}
if(nc->ttyfd >= 0){
if(nc->tcache.cnorm){
if(stage_cursor(nc, nc->ttyfp, y, x) || fflush(nc->ttyfp)){
return -1;
}
nc->cursory = y;
nc->cursorx = x;
if(tty_emit("cnorm", nc->tcache.cnorm, nc->ttyfd) == 0){
return 0;
}
}
}
return -1;
}
int notcurses_cursor_disable(notcurses* nc){
nc->cursory = -1;
nc->cursorx = -1;
if(nc->ttyfd >= 0){
if(nc->tcache.civis){
if(tty_emit("civis", nc->tcache.civis, nc->ttyfd) == 0){
return 0;
}
}
}
return -1;
}
int notcurses_cursor_move_yx(notcurses* nc, int y, int x){
if(nc->cursory >= 0 && nc->cursorx >= 0){
return -1;
}
if(stage_cursor(nc, nc->ttyfp, y, x) || fflush(nc->ttyfp)){
return -1;
}
nc->cursory = y;
nc->cursorx = x;
return 0;
}

View File

@ -28,6 +28,9 @@ auto main() -> int {
if(nr == nullptr){
return EXIT_FAILURE;
}
if(!nc.cursor_enable(2 + opts.physrows, 2 + opts.physcols)){
return EXIT_FAILURE;
}
ncinput ni;
nc.render();
while(nc.getc(true, &ni) != (char32_t)-1){
@ -41,7 +44,7 @@ auto main() -> int {
ncreader_destroy(nr, &contents);
nc.stop();
if(contents){
printf("%s\n", contents);
printf("input: %s\n", contents);
}
return EXIT_SUCCESS;
}