mirror of
https://github.com/dankamongmen/notcurses
synced 2025-03-09 17:19:03 -04:00
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:
parent
df33f381e5
commit
cab19cf790
7
NEWS.md
7
NEWS.md
@ -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*`.
|
||||
|
14
USAGE.md
14
USAGE.md
@ -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.
|
||||
|
@ -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.
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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__":
|
||||
|
@ -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
|
||||
|
@ -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()
|
||||
|
||||
|
@ -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,13 +967,11 @@ 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->rstate.mstreamfp = open_memstream(&ret->rstate.mstream, &ret->rstate.mstrsize)) == NULL){
|
||||
free_plane(ret->top);
|
||||
goto err;
|
||||
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user