mirror of
https://github.com/dankamongmen/notcurses
synced 2025-03-09 09:09:03 -04:00
* ncdirect_cursor_{push, pop, yx} declarations #401 * direct PoC: invoke ncdirect_cursor_yx() #401 * direct PoC: move to top of screen #401 * OTHERS.md: mention blessings * ncdirect_cursor_yx working #401 * CHANGELOG: mention ncdirect_cursor_*() #401
This commit is contained in:
parent
1a670ba443
commit
1c7796a2b0
@ -1,6 +1,13 @@
|
||||
This document attempts to list user-visible changes and any major internal
|
||||
rearrangements of Notcurses.
|
||||
|
||||
* 1.3.2 (not yet released)
|
||||
* `ncdirect_cursor_push()`, `notcurses_cursor_pop()`, and
|
||||
`ncdirect_cursor_yx()` have been added. These are not supported on all
|
||||
terminals. `ncdirect_cursor_yx()` ought be considered experimental; it
|
||||
must read a response from the terminal, and this can interact poorly with
|
||||
other uses of standard input.
|
||||
|
||||
* 1.3.1 (2020-04-18)
|
||||
* `ncplane_at_yx()` and `ncplane_at_cursor()` have been changed to return a
|
||||
heap-allocated EGC, and write the attributes and channels to value-result
|
||||
|
23
OTHERS.md
Normal file
23
OTHERS.md
Normal file
@ -0,0 +1,23 @@
|
||||
# Other TUI libraries of note
|
||||
|
||||
* [NCURSES](https://invisible-island.net/ncurses/) (C)
|
||||
* [tui-rs](https://github.com/fdehau/tui-rs) (Rust)
|
||||
* [blessed-contrib](https://github.com/yaronn/blessed-contrib) (Javascript)
|
||||
* [FINAL CUT](https://github.com/gansm/finalcut) (C++)
|
||||
* [crossterm](https://github.com/crossterm-rs/crossterm) (Rust)
|
||||
* [tty-cursor](https://github.com/piotrmurach/tty-cursor) (Ruby)
|
||||
* [caca](http://caca.zoy.org/wiki/libcaca) (C)
|
||||
* [Newt](https://pagure.io/newt) (C)
|
||||
* [vty](http://hackage.haskell.org/package/vty) (Haskell)
|
||||
* [hscharm](https://hackage.haskell.org/package/hscharm) (Haskell)
|
||||
* [S-Lang](http://www.jedsoft.org/slang/) (S-Lang)
|
||||
* [termbox-go](https://github.com/nsf/termbox-go) (Go)
|
||||
* [tcell](https://github.com/gdamore/tcell) (Go)
|
||||
* [termui](https://github.com/gizak/termui) (Go)
|
||||
* [gocui](https://github.com/jroimartin/gocui) (Go)
|
||||
* [tview](https://github.com/rivo/tview) (Go)
|
||||
* [blessings](https://github.com/erikrose/blessings) [Python]
|
||||
|
||||
## Declarative
|
||||
|
||||
* [brick](https://github.com/jtdaugherty/brick) (Haskell, atop vty)
|
@ -2647,12 +2647,6 @@ up someday **FIXME**.
|
||||
* Portable: [terminfo(5)](http://man7.org/linux/man-pages/man5/terminfo.5.html)
|
||||
* Portable: [user_caps(5)](http://man7.org/linux/man-pages/man5/user_caps.5.html)
|
||||
|
||||
### Other TUI libraries of note
|
||||
|
||||
* [tui-rs](https://github.com/fdehau/tui-rs) (Rust)
|
||||
* [blessed-contrib](https://github.com/yaronn/blessed-contrib) (Javascript)
|
||||
* [FINAL CUT](https://github.com/gansm/finalcut) (C++)
|
||||
|
||||
### History
|
||||
|
||||
* 2020-04-12: notcurses [1.3.0 "hypnotize"](https://github.com/dankamongmen/notcurses/releases/tag/v1.3.0).
|
||||
|
@ -83,6 +83,16 @@ API int ncdirect_cursor_left(struct ncdirect* nc, int num);
|
||||
API int ncdirect_cursor_right(struct ncdirect* nc, int num);
|
||||
API int ncdirect_cursor_down(struct ncdirect* nc, int num);
|
||||
|
||||
// Get the cursor position, when supported. This requires writing to the
|
||||
// terminal, and then reading from it. If the terminal doesn't reply, or
|
||||
// doesn't reply in a way we understand, the results might be deleterious.
|
||||
API int ncdirect_cursor_yx(struct ncdirect* n, int* y, int* x);
|
||||
|
||||
// Push or pop the cursor location to the terminal's stack. The depth of this
|
||||
// stack, and indeed its existence, is terminal-dependent.
|
||||
API int ncdirect_cursor_push(struct ncdirect* n);
|
||||
API int ncdirect_cursor_pop(struct ncdirect* n);
|
||||
|
||||
// Clear the screen.
|
||||
API int ncdirect_clear(struct ncdirect* nc);
|
||||
|
||||
|
111
src/lib/direct.c
111
src/lib/direct.c
@ -1,3 +1,7 @@
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <termios.h>
|
||||
#include "internal.h"
|
||||
|
||||
int ncdirect_cursor_up(ncdirect* nc, int num){
|
||||
@ -100,6 +104,112 @@ int ncdirect_cursor_move_yx(ncdirect* n, int y, int x){
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
cursor_yx_get(FILE* outfp, FILE* infp, int* y, int* x){
|
||||
if(fprintf(outfp, "\033[6n") != 4){
|
||||
return -1;
|
||||
}
|
||||
int in;
|
||||
bool done = false;
|
||||
enum { // what we expect now
|
||||
CURSOR_ESC, // 27 (0x1b)
|
||||
CURSOR_LSQUARE,
|
||||
CURSOR_ROW, // delimited by a semicolon
|
||||
CURSOR_COLUMN,
|
||||
CURSOR_R,
|
||||
} state = CURSOR_ESC;
|
||||
int row = 0, column = 0;
|
||||
while((in = getc(infp)) != EOF){
|
||||
bool valid = false;
|
||||
switch(state){
|
||||
case CURSOR_ESC: valid = (in == '\x1b'); ++state; break;
|
||||
case CURSOR_LSQUARE: valid = (in == '['); ++state; break;
|
||||
case CURSOR_ROW:
|
||||
if(isdigit(in)){
|
||||
row *= 10;
|
||||
row += in - '0';
|
||||
valid = true;
|
||||
}else if(in == ';'){
|
||||
++state;
|
||||
valid = true;
|
||||
}
|
||||
break;
|
||||
case CURSOR_COLUMN:
|
||||
if(isdigit(in)){
|
||||
column *= 10;
|
||||
column += in - '0';
|
||||
valid = true;
|
||||
}else if(in == 'R'){
|
||||
++state;
|
||||
valid = true;
|
||||
}
|
||||
break;
|
||||
case CURSOR_R: default: // logical error, whoops
|
||||
break;
|
||||
}
|
||||
if(!valid){
|
||||
fprintf(stderr, "Unexpected result from terminal: %d\n", in);
|
||||
break;
|
||||
}
|
||||
if(state == CURSOR_R){
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!done){
|
||||
return -1;
|
||||
}
|
||||
if(y){
|
||||
*y = row;
|
||||
}
|
||||
if(x){
|
||||
*x = column;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// no terminfo capability for this. dangerous!
|
||||
int ncdirect_cursor_yx(ncdirect* n, int* y, int* x){
|
||||
int infd = fileno(stdin); // FIXME n->ttyfp?
|
||||
if(infd < 0){
|
||||
fprintf(stderr, "Couldn't get file descriptor from stdin\n");
|
||||
return -1;
|
||||
}
|
||||
// do *not* close infd!
|
||||
struct termios termio, oldtermios;
|
||||
if(tcgetattr(infd, &termio)){
|
||||
fprintf(stderr, "Couldn't get terminal info from %d (%s)\n", infd, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
memcpy(&oldtermios, &termio, sizeof(termio));
|
||||
termio.c_lflag &= ~(ICANON | ECHO);
|
||||
if(tcsetattr(infd, TCSAFLUSH, &termio)){
|
||||
fprintf(stderr, "Couldn't put terminal into cbreak mode via %d (%s)\n",
|
||||
infd, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
int ret = cursor_yx_get(n->ttyfp, stdin, y, x);
|
||||
if(tcsetattr(infd, TCSANOW, &oldtermios)){
|
||||
fprintf(stderr, "Couldn't restore terminal mode on %d (%s)\n",
|
||||
infd, strerror(errno)); // don't return error for this
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ncdirect_cursor_push(ncdirect* n){
|
||||
if(n->sc == NULL){
|
||||
return -1;
|
||||
}
|
||||
return term_emit("sc", n->sc, n->ttyfp, false);
|
||||
}
|
||||
|
||||
int ncdirect_cursor_pop(ncdirect* n){
|
||||
if(n->rc == NULL){
|
||||
return -1;
|
||||
}
|
||||
return term_emit("rc", n->rc, n->ttyfp, false);
|
||||
}
|
||||
|
||||
int ncdirect_stop(ncdirect* nc){
|
||||
int ret = 0;
|
||||
if(nc){
|
||||
@ -116,4 +226,3 @@ int ncdirect_stop(ncdirect* nc){
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -273,9 +273,11 @@ typedef struct ncdirect {
|
||||
char* initc; // set a palette entry's RGB value
|
||||
char* oc; // restore original colors
|
||||
char* clear; // clear the screen
|
||||
FILE* ttyfp; // FILE* for controlling tty, from opts->ttyfp
|
||||
char* sc; // push the cursor location onto the stack
|
||||
char* rc; // pop the cursor location off the stack
|
||||
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
|
||||
uint16_t fgrgb, bgrgb; // last RGB values of foreground/background
|
||||
bool fgdefault, bgdefault; // are FG/BG currently using default colors?
|
||||
|
@ -24,30 +24,6 @@ int main(void){
|
||||
}
|
||||
}
|
||||
fflush(stdout);
|
||||
notcurses_options opts;
|
||||
memset(&opts, 0, sizeof(opts));
|
||||
opts.inhibit_alternate_screen = true;
|
||||
struct notcurses* nc = notcurses_init(&opts, stdout);
|
||||
if(!nc){
|
||||
fprintf(stderr, "Couldn't initialize notcurses\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
ncplane_set_fg(notcurses_stdplane(nc), 0x00ff00);
|
||||
if(ncplane_putstr_aligned(notcurses_stdplane(nc), geom.ws_row - 2, NCALIGN_CENTER, " erperperp ") <= 0){
|
||||
notcurses_stop(nc);
|
||||
fprintf(stderr, "Error printing\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
if(notcurses_render(nc)){
|
||||
notcurses_stop(nc);
|
||||
fprintf(stderr, "Error rendering\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
sleep(2);
|
||||
if(notcurses_stop(nc)){
|
||||
fprintf(stderr, "Error stopping notcurses\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
struct ncdirect* n; // see bug #391
|
||||
if((n = ncdirect_init(NULL, stdout)) == NULL){
|
||||
return EXIT_FAILURE;
|
||||
@ -65,5 +41,30 @@ int main(void){
|
||||
ret |= ncdirect_cursor_right(n, geom.ws_col / 2);
|
||||
ret |= ncdirect_cursor_up(n, geom.ws_row / 2);
|
||||
printf(" erperperp! \n");
|
||||
int y = -420, x = -420;
|
||||
// FIXME try a push/pop
|
||||
if(ncdirect_cursor_yx(n, &y, &x) == 0){
|
||||
printf("\n\tRead cursor position: y: %d x: %d\n", y, x);
|
||||
y += 2; // we just went down two lines
|
||||
while(y > 3){
|
||||
const int up = y >= 3 ? 3 : y;
|
||||
ret |= ncdirect_cursor_up(n, up);
|
||||
fflush(stdout);
|
||||
y -= up;
|
||||
int newy;
|
||||
if(ncdirect_cursor_yx(n, &newy, NULL)){
|
||||
ret = -1;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
if(newy != y){
|
||||
fprintf(stderr, "Expected %d, got %d\n", y, newy);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
printf("\n\tRead cursor position: y: %d x: %d\n", newy, x);
|
||||
y += 2;
|
||||
}
|
||||
}else{
|
||||
ret = -1;
|
||||
}
|
||||
return ret ? EXIT_FAILURE : EXIT_SUCCESS;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user