mirror of
https://github.com/dankamongmen/notcurses
synced 2025-03-09 17:19:03 -04:00
ncdirect: add relative move functions #419
This commit is contained in:
parent
3649cd1a92
commit
2c2da61c72
@ -391,6 +391,12 @@ int ncdirect_clear(struct ncdirect* nc); // clear the screen
|
||||
int ncdirect_cursor_move_yx(struct ncdirect* n, int y, int x);
|
||||
int ncdirect_cursor_enable(struct ncdirect* nc);
|
||||
int ncdirect_cursor_disable(struct ncdirect* nc);
|
||||
|
||||
// Relative moves. num < 0 is an error.
|
||||
int ncdirect_cursor_up(struct ncdirect* nc, int num);
|
||||
int ncdirect_cursor_left(struct ncdirect* nc, int num);
|
||||
int ncdirect_cursor_right(struct ncdirect* nc, int num);
|
||||
int ncdirect_cursor_down(struct ncdirect* nc, int num);
|
||||
```
|
||||
|
||||
### Alignment
|
||||
|
@ -44,6 +44,14 @@ ncdirect_init - minimal notcurses instances for styling text
|
||||
|
||||
**int ncdirect_cursor_disable(struct ncdirect* nc);**
|
||||
|
||||
**int ncdirect_cursor_up(struct ncdirect* nc, int num);**
|
||||
|
||||
**int ncdirect_cursor_left(struct ncdirect* nc, int num);**
|
||||
|
||||
**int ncdirect_cursor_right(struct ncdirect* nc, int num);**
|
||||
|
||||
**int ncdirect_cursor_down(struct ncdirect* nc, int num);**
|
||||
|
||||
# DESCRIPTION
|
||||
|
||||
**ncdirect_init** prepares the **FILE** provided as **fp** (which must
|
||||
@ -72,6 +80,10 @@ be specified for either **y** or **x** to leave that axis unchanged.
|
||||
**ncdirect_enable_cursor** and **ncdirect_disable_cursor** always flush the
|
||||
output stream, taking effect immediately.
|
||||
|
||||
**ncdirect_cursor_up** and friends all move relative to the current position.
|
||||
Attempting to e.g. move up while on the top row will return 0, but have no
|
||||
effect.
|
||||
|
||||
# RETURN VALUES
|
||||
|
||||
**ncdirect_init** returns **NULL** on failure. Otherwise, the return value
|
||||
|
@ -78,6 +78,10 @@ API int ncdirect_styles_off(struct ncdirect* n, unsigned stylebits);
|
||||
API int ncdirect_cursor_move_yx(struct ncdirect* n, int y, int x);
|
||||
API int ncdirect_cursor_enable(struct ncdirect* nc);
|
||||
API int ncdirect_cursor_disable(struct ncdirect* nc);
|
||||
API int ncdirect_cursor_up(struct ncdirect* nc, int num);
|
||||
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);
|
||||
|
||||
// Clear the screen.
|
||||
API int ncdirect_clear(struct ncdirect* nc);
|
||||
|
@ -257,6 +257,10 @@ int ncdirect_dim_y(const struct ncdirect* nc);
|
||||
int ncdirect_cursor_move_yx(struct ncdirect* n, int y, int x);
|
||||
int ncdirect_cursor_enable(struct ncdirect* nc);
|
||||
int ncdirect_cursor_disable(struct ncdirect* nc);
|
||||
int ncdirect_cursor_up(struct ncdirect* nc, int num);
|
||||
int ncdirect_cursor_left(struct ncdirect* nc, int num);
|
||||
int ncdirect_cursor_right(struct ncdirect* nc, int num);
|
||||
int ncdirect_cursor_down(struct ncdirect* nc, int num);
|
||||
struct ncvisual* ncplane_visual_open(struct ncplane* nc, const char* file, int* averr);
|
||||
typedef enum {
|
||||
NCSCALE_NONE,
|
||||
|
119
src/lib/direct.c
Normal file
119
src/lib/direct.c
Normal file
@ -0,0 +1,119 @@
|
||||
#include "internal.h"
|
||||
|
||||
int ncdirect_cursor_up(ncdirect* nc, int num){
|
||||
if(num < 0){
|
||||
return -1;
|
||||
}
|
||||
if(!nc->cuu){
|
||||
return -1;
|
||||
}
|
||||
return term_emit("cuu", tiparm(nc->cuu, num), nc->ttyfp, false);
|
||||
}
|
||||
|
||||
int ncdirect_cursor_left(ncdirect* nc, int num){
|
||||
if(num < 0){
|
||||
return -1;
|
||||
}
|
||||
if(!nc->cub){
|
||||
return -1;
|
||||
}
|
||||
return term_emit("cub", tiparm(nc->cub, num), nc->ttyfp, false);
|
||||
}
|
||||
|
||||
int ncdirect_cursor_right(ncdirect* nc, int num){
|
||||
if(num < 0){
|
||||
return -1;
|
||||
}
|
||||
if(!nc->cuf){ // FIXME fall back to cuf1
|
||||
return -1;
|
||||
}
|
||||
return term_emit("cuf", tiparm(nc->cuf, num), nc->ttyfp, false);
|
||||
}
|
||||
|
||||
int ncdirect_cursor_down(ncdirect* nc, int num){
|
||||
if(num < 0){
|
||||
return -1;
|
||||
}
|
||||
if(!nc->cud){
|
||||
return -1;
|
||||
}
|
||||
return term_emit("cud", tiparm(nc->cud, num), nc->ttyfp, false);
|
||||
}
|
||||
|
||||
int ncdirect_clear(ncdirect* nc){
|
||||
if(!nc->clear){
|
||||
return -1; // FIXME scroll output off the screen
|
||||
}
|
||||
return term_emit("clear", nc->clear, nc->ttyfp, true);
|
||||
}
|
||||
|
||||
int ncdirect_dim_x(const ncdirect* nc){
|
||||
int x;
|
||||
if(update_term_dimensions(fileno(nc->ttyfp), NULL, &x) == 0){
|
||||
return x;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ncdirect_dim_y(const ncdirect* nc){
|
||||
int y;
|
||||
if(update_term_dimensions(fileno(nc->ttyfp), &y, NULL) == 0){
|
||||
return y;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ncdirect_cursor_enable(ncdirect* nc){
|
||||
if(!nc->cnorm){
|
||||
return -1;
|
||||
}
|
||||
return term_emit("cnorm", nc->cnorm, nc->ttyfp, true);
|
||||
}
|
||||
|
||||
int ncdirect_cursor_disable(ncdirect* nc){
|
||||
if(!nc->civis){
|
||||
return -1;
|
||||
}
|
||||
return term_emit("civis", nc->civis, nc->ttyfp, true);
|
||||
}
|
||||
|
||||
int ncdirect_cursor_move_yx(ncdirect* n, int y, int x){
|
||||
if(y == -1){ // keep row the same, horizontal move only
|
||||
if(!n->hpa){
|
||||
return -1;
|
||||
}
|
||||
return term_emit("hpa", tiparm(n->hpa, x), n->ttyfp, false);
|
||||
}else if(x == -1){ // keep column the same, vertical move only
|
||||
if(!n->vpa){
|
||||
return -1;
|
||||
}
|
||||
return term_emit("vpa", tiparm(n->vpa, y), n->ttyfp, false);
|
||||
}
|
||||
if(n->cup){
|
||||
return term_emit("cup", tiparm(n->cup, y, x), n->ttyfp, false);
|
||||
}else if(n->vpa && n->hpa){
|
||||
if(term_emit("hpa", tiparm(n->hpa, x), n->ttyfp, false) == 0 &&
|
||||
term_emit("vpa", tiparm(n->vpa, y), n->ttyfp, false) == 0){
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ncdirect_stop(ncdirect* nc){
|
||||
int ret = 0;
|
||||
if(nc){
|
||||
if(nc->op && term_emit("op", nc->op, nc->ttyfp, true)){
|
||||
ret = -1;
|
||||
}
|
||||
if(nc->sgr0 && term_emit("sgr0", nc->sgr0, nc->ttyfp, true)){
|
||||
ret = -1;
|
||||
}
|
||||
if(nc->oc && term_emit("oc", nc->oc, nc->ttyfp, true)){
|
||||
ret = -1;
|
||||
}
|
||||
free(nc);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
@ -240,6 +240,10 @@ typedef struct ncdirect {
|
||||
char* setab; // set background color (ANSI)
|
||||
char* op; // set foreground and background color to default
|
||||
char* cup; // move cursor
|
||||
char* cuu; // move N up
|
||||
char* cub; // move N left
|
||||
char* cuf; // move N right
|
||||
char* cud; // move N down
|
||||
char* civis; // hide cursor
|
||||
char* cnorm; // restore cursor to default state
|
||||
char* hpa; // horizontal position adjusment (move cursor on row)
|
||||
|
@ -775,6 +775,10 @@ ncdirect* ncdirect_init(const char* termtype, FILE* outfp){
|
||||
term_verify_seq(&ret->setab, "setab");
|
||||
term_verify_seq(&ret->clear, "clear");
|
||||
term_verify_seq(&ret->cup, "cup");
|
||||
term_verify_seq(&ret->cuu, "cuu"); // move N up
|
||||
term_verify_seq(&ret->cuf, "cuf"); // move N right
|
||||
term_verify_seq(&ret->cud, "cud"); // move N down
|
||||
term_verify_seq(&ret->cub, "cub"); // move N left
|
||||
term_verify_seq(&ret->hpa, "hpa");
|
||||
term_verify_seq(&ret->vpa, "vpa");
|
||||
term_verify_seq(&ret->civis, "civis");
|
||||
@ -954,83 +958,6 @@ err:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int ncdirect_clear(ncdirect* nc){
|
||||
if(!nc->clear){
|
||||
return -1; // FIXME scroll output off the screen
|
||||
}
|
||||
return term_emit("clear", nc->clear, nc->ttyfp, true);
|
||||
}
|
||||
|
||||
int ncdirect_dim_x(const ncdirect* nc){
|
||||
int x;
|
||||
if(update_term_dimensions(fileno(nc->ttyfp), NULL, &x) == 0){
|
||||
return x;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ncdirect_dim_y(const ncdirect* nc){
|
||||
int y;
|
||||
if(update_term_dimensions(fileno(nc->ttyfp), &y, NULL) == 0){
|
||||
return y;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ncdirect_cursor_enable(ncdirect* nc){
|
||||
if(!nc->cnorm){
|
||||
return -1;
|
||||
}
|
||||
return term_emit("cnorm", nc->cnorm, nc->ttyfp, true);
|
||||
}
|
||||
|
||||
int ncdirect_cursor_disable(ncdirect* nc){
|
||||
if(!nc->civis){
|
||||
return -1;
|
||||
}
|
||||
return term_emit("civis", nc->civis, nc->ttyfp, true);
|
||||
}
|
||||
|
||||
int ncdirect_cursor_move_yx(ncdirect* n, int y, int x){
|
||||
if(y == -1){ // keep row the same, horizontal move only
|
||||
if(!n->hpa){
|
||||
return -1;
|
||||
}
|
||||
return term_emit("hpa", tiparm(n->hpa, x), n->ttyfp, false);
|
||||
}else if(x == -1){ // keep column the same, vertical move only
|
||||
if(!n->vpa){
|
||||
return -1;
|
||||
}
|
||||
return term_emit("vpa", tiparm(n->vpa, y), n->ttyfp, false);
|
||||
}
|
||||
if(n->cup){
|
||||
return term_emit("cup", tiparm(n->cup, y, x), n->ttyfp, false);
|
||||
}else if(n->vpa && n->hpa){
|
||||
if(term_emit("hpa", tiparm(n->hpa, x), n->ttyfp, false) == 0 &&
|
||||
term_emit("vpa", tiparm(n->vpa, y), n->ttyfp, false) == 0){
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ncdirect_stop(ncdirect* nc){
|
||||
int ret = 0;
|
||||
if(nc){
|
||||
if(nc->op && term_emit("op", nc->op, nc->ttyfp, true)){
|
||||
ret = -1;
|
||||
}
|
||||
if(nc->sgr0 && term_emit("sgr0", nc->sgr0, nc->ttyfp, true)){
|
||||
ret = -1;
|
||||
}
|
||||
if(nc->oc && term_emit("oc", nc->oc, nc->ttyfp, true)){
|
||||
ret = -1;
|
||||
}
|
||||
free(nc);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void notcurses_drop_planes(notcurses* nc){
|
||||
ncplane* p = nc->top;
|
||||
while(p){
|
||||
|
@ -854,7 +854,7 @@ notcurses_rasterize(notcurses* nc, const struct crender* rvec){
|
||||
++nc->stats.cellemissions;
|
||||
if(needmove == 1 && nc->cuf1){
|
||||
ret |= term_emit("cuf1", tiparm(nc->cuf1), out, false);
|
||||
}else if(needmove){
|
||||
}else if(needmove){ // FIXME might want to use cufN for horizontal move
|
||||
ret |= term_emit("cup", tiparm(nc->cup, y, x), out, false);
|
||||
}
|
||||
needmove = 0;
|
||||
|
@ -52,14 +52,18 @@ int main(void){
|
||||
if((n = ncdirect_init(NULL, stdout)) == NULL){
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
ncdirect_fg(n, 0xff8080);
|
||||
ncdirect_styles_on(n, NCSTYLE_STANDOUT);
|
||||
int ret = 0;
|
||||
ret |= ncdirect_fg(n, 0xff8080);
|
||||
ret |= ncdirect_styles_on(n, NCSTYLE_STANDOUT);
|
||||
printf(" erp erp \n");
|
||||
ncdirect_fg(n, 0x80ff80);
|
||||
ret |= ncdirect_fg(n, 0x80ff80);
|
||||
printf(" erp erp \n");
|
||||
ncdirect_styles_off(n, NCSTYLE_STANDOUT);
|
||||
ret |= ncdirect_styles_off(n, NCSTYLE_STANDOUT);
|
||||
printf(" erp erp \n");
|
||||
ncdirect_fg(n, 0xff8080);
|
||||
ret |= ncdirect_fg(n, 0xff8080);
|
||||
printf(" erp erp \n");
|
||||
return EXIT_SUCCESS;
|
||||
ret |= ncdirect_cursor_right(n, geom.ws_col / 2);
|
||||
ret |= ncdirect_cursor_up(n, geom.ws_row / 2);
|
||||
printf(" erperperp! \n");
|
||||
return ret ? EXIT_FAILURE : EXIT_SUCCESS;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user