Update sixdraw.
This commit is contained in:
parent
c7730bf220
commit
b19ef960a0
|
@ -26,6 +26,7 @@
|
|||
#endif // HAVE_CONFIG_H
|
||||
|
||||
#include <signal.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
@ -41,6 +42,11 @@
|
|||
# define SIXDRAW_DEFAULT_TIMEOUT_MILLIS 500
|
||||
#endif // !SIXDRAW_DEFAULT_TIMEOUT_MILLIS
|
||||
|
||||
#define SIXDRAW_DECRQM_SET 1
|
||||
#define SIXDRAW_DECRQM_RST 2
|
||||
#define SIXDRAW_DECTCEM 25u
|
||||
#define SIXDRAW_ALT_SCRBUF 1049u
|
||||
|
||||
struct sixdraw_ctx {
|
||||
struct termios termios;
|
||||
union ctlseqs_value buffer[64];
|
||||
|
@ -49,6 +55,7 @@ struct sixdraw_ctx {
|
|||
struct ctlseqs_reader *reader;
|
||||
bool has_termios;
|
||||
bool show_cursor;
|
||||
bool normal_scrbuf;
|
||||
int in_fd;
|
||||
int out_fd;
|
||||
int timeout;
|
||||
|
@ -59,8 +66,13 @@ struct sixdraw_ctx {
|
|||
};
|
||||
|
||||
static inline void
|
||||
sixdraw_print_error(struct sixdraw_ctx const *ctx, char const *msg)
|
||||
sixdraw_print_error(struct sixdraw_ctx const *ctx, char const *format, ...)
|
||||
{
|
||||
char msg[1024];
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
vsnprintf(msg, 1024, format, args);
|
||||
va_end(args);
|
||||
dprintf(ctx->out_fd, "%s: [error] %s.\n", ctx->prog_name, msg);
|
||||
}
|
||||
|
||||
|
@ -91,7 +103,17 @@ sixdraw_terminate(struct sixdraw_ctx *ctx)
|
|||
ctlseqs_matcher_free(ctx->matcher);
|
||||
ctlseqs_reader_free(ctx->reader);
|
||||
|
||||
// Restore original terminal modes
|
||||
// Restore cursor status.
|
||||
if (ctx->show_cursor) {
|
||||
dprintf(ctx->out_fd, CTLSEQS_DECSET("%u"), SIXDRAW_DECTCEM);
|
||||
}
|
||||
|
||||
// Restore normal screen buffer.
|
||||
if (ctx->normal_scrbuf) {
|
||||
dprintf(ctx->out_fd, CTLSEQS_DECRST("%u"), SIXDRAW_ALT_SCRBUF);
|
||||
}
|
||||
|
||||
// Restore original terminal modes.
|
||||
if (ctx->has_termios) {
|
||||
tcsetattr(ctx->in_fd, TCSANOW, &ctx->termios);
|
||||
}
|
||||
|
@ -102,9 +124,11 @@ sixdraw_get_winsize(struct sixdraw_ctx *ctx)
|
|||
{
|
||||
struct winsize ws = { 0 };
|
||||
if (ioctl(ctx->in_fd, TIOCGWINSZ, &ws) != 0) {
|
||||
sixdraw_print_error(ctx, "failed to get terminal window size");
|
||||
return false;
|
||||
}
|
||||
if (ws.ws_xpixel == 0 || ws.ws_ypixel == 0) {
|
||||
sixdraw_print_error(ctx, "failed to get terminal window size (in pixels)");
|
||||
return false;
|
||||
}
|
||||
ctx->rows = ws.ws_row;
|
||||
|
@ -114,6 +138,26 @@ sixdraw_get_winsize(struct sixdraw_ctx *ctx)
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
sixdraw_decrqm(struct sixdraw_ctx *ctx, unsigned mode_id, char const *name)
|
||||
{
|
||||
ssize_t result;
|
||||
union ctlseqs_value *buffer = ctx->buffer;
|
||||
dprintf(ctx->out_fd, CTLSEQS_DECRQM("%u"), mode_id);
|
||||
do {
|
||||
result = ctlseqs_read(ctx->reader, ctx->matcher, ctx->timeout);
|
||||
} while (result == CTLSEQS_PARTIAL);
|
||||
if (result != 1) {
|
||||
sixdraw_print_error(ctx, "failed to get %s status", name);
|
||||
return false;
|
||||
}
|
||||
if (buffer[0].num != mode_id || (buffer[1].num != SIXDRAW_DECRQM_SET && buffer[1].num != SIXDRAW_DECRQM_RST)) {
|
||||
sixdraw_print_error(ctx, "%s status not recognizable", name);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
sixdraw_init(struct sixdraw_ctx *ctx, int argc, char **argv)
|
||||
{
|
||||
|
@ -219,7 +263,6 @@ sixdraw_prepare(struct sixdraw_ctx *ctx)
|
|||
|
||||
// Get initial terminal window size.
|
||||
if (!sixdraw_get_winsize(ctx)) {
|
||||
sixdraw_print_error(ctx, "failed to get terminal window size");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -253,19 +296,26 @@ sixdraw_prepare(struct sixdraw_ctx *ctx)
|
|||
}
|
||||
|
||||
// Get current cursor status.
|
||||
dprintf(ctx->out_fd, CTLSEQS_DECRQM("25"));
|
||||
do {
|
||||
result = ctlseqs_read(ctx->reader, ctx->matcher, ctx->timeout);
|
||||
} while (result == CTLSEQS_PARTIAL);
|
||||
if (result != 1) {
|
||||
sixdraw_print_error(ctx, "failed to get cursor status");
|
||||
if (!sixdraw_decrqm(ctx, SIXDRAW_DECTCEM, "cursor")) {
|
||||
return false;
|
||||
}
|
||||
if (buffer[0].num != 25 || (buffer[1].num != 1 && buffer[1].num != 2)) {
|
||||
sixdraw_print_error(ctx, "cursor status not recognizable");
|
||||
ctx->show_cursor = buffer[1].num == SIXDRAW_DECRQM_SET;
|
||||
|
||||
// Hide cursor.
|
||||
if (ctx->show_cursor) {
|
||||
dprintf(ctx->out_fd, CTLSEQS_DECRST("%u"), SIXDRAW_DECTCEM);
|
||||
}
|
||||
|
||||
// Get current screen buffer status.
|
||||
if (!sixdraw_decrqm(ctx, SIXDRAW_ALT_SCRBUF, "screen buffer")) {
|
||||
return false;
|
||||
}
|
||||
ctx->show_cursor = buffer[1].num == 1;
|
||||
ctx->normal_scrbuf = buffer[1].num == SIXDRAW_DECRQM_RST;
|
||||
|
||||
// Switch to alternate screen buffer.
|
||||
if (ctx->normal_scrbuf) {
|
||||
dprintf(ctx->out_fd, CTLSEQS_DECSET("%u"), SIXDRAW_ALT_SCRBUF);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue