From 1a9cbf9302cea34372aebbf921f4dbed914e2b28 Mon Sep 17 00:00:00 2001 From: CismonX Date: Fri, 8 Jan 2021 08:00:49 +0800 Subject: [PATCH] Update sixdraw. --- examples/sixdraw.c | 155 +++++++++++++++++++++++---------------------- 1 file changed, 80 insertions(+), 75 deletions(-) diff --git a/examples/sixdraw.c b/examples/sixdraw.c index 69d28ac..c7652e7 100644 --- a/examples/sixdraw.c +++ b/examples/sixdraw.c @@ -49,9 +49,10 @@ #define DECRQM_SET 1 #define DECRQM_RST 2 -#define DECTCEM 25u -#define SGR_MOUSE_PIXELMODE 1016u -#define ALT_SCRBUF 1049u +#define DECTCEM 25 +#define BTN_EVENT_TRACKING 1002 +#define SGR_MOUSE_PIXELMODE 1016 +#define ALT_SCRBUF 1049 #define SIXEL_SEQ_HEAD CTLSEQS_DCS "0;1q\"1;1;" @@ -62,14 +63,13 @@ struct sixdraw_ctx { struct ctlseqs_matcher *matcher; struct ctlseqs_reader *reader; bool has_termios; - bool show_cursor; - bool normal_scrbuf; + bool hide_cursor; + bool alt_scrbuf; + bool btnev_tracking; bool sgr_pixelmode; int in_fd; int out_fd; int timeout; - unsigned rows; - unsigned cols; unsigned ch_width; unsigned ch_height; unsigned line_color; @@ -86,27 +86,6 @@ print_error(struct sixdraw_ctx const *ctx, char const *format, ...) dprintf(ctx->out_fd, "%s: [error] %s.\n", ctx->prog_name, msg); } -static inline void -clear_signal(int signum) -{ - sigset_t sigset; - sigemptyset(&sigset); - sigaddset(&sigset, signum); - sigwait(&sigset, &signum); -} - -static bool -handle_signals(struct sixdraw_ctx *ctx) -{ - sigset_t sigset; - sigpending(&sigset); - if (!sigismember(&sigset, SIGWINCH)) { - return false; - } - clear_signal(SIGWINCH); - return true; -} - static void terminate(struct sixdraw_ctx *ctx) { @@ -114,23 +93,27 @@ terminate(struct sixdraw_ctx *ctx) ctlseqs_reader_free(ctx->reader); // Restore cursor status. - if (ctx->show_cursor) { - dprintf(ctx->out_fd, CTLSEQS_DECSET("%u"), DECTCEM); + if (ctx->hide_cursor) { + dprintf(ctx->out_fd, CTLSEQS_DECSET("%d"), DECTCEM); } // Restore normal screen buffer. - if (ctx->normal_scrbuf) { - dprintf(ctx->out_fd, CTLSEQS_DECRST("%u"), ALT_SCRBUF); + if (ctx->alt_scrbuf) { + dprintf(ctx->out_fd, CTLSEQS_DECRST("%d"), ALT_SCRBUF); + } + + // Restore original mouse modes. + if (ctx->btnev_tracking) { + dprintf(ctx->out_fd, CTLSEQS_DECRST("%d"), BTN_EVENT_TRACKING); + } + if (ctx->sgr_pixelmode) { + dprintf(ctx->out_fd, CTLSEQS_DECRST("%d"), SGR_MOUSE_PIXELMODE); } // Restore original terminal modes. if (ctx->has_termios) { tcsetattr(ctx->in_fd, TCSANOW, &ctx->termios); } - - if (!ctx->sgr_pixelmode) { - dprintf(ctx->out_fd, CTLSEQS_DECRST("%u"), SGR_MOUSE_PIXELMODE); - } } static bool @@ -145,19 +128,17 @@ get_winsize(struct sixdraw_ctx *ctx) print_error(ctx, "failed to get terminal window size (in pixels)"); return false; } - ctx->rows = ws.ws_row; - ctx->cols = ws.ws_col; ctx->ch_width = ws.ws_xpixel / ws.ws_col; ctx->ch_height = ws.ws_ypixel / ws.ws_row; return true; } static bool -decrqm(struct sixdraw_ctx *ctx, unsigned mode_id, char const *name) +decrqm(struct sixdraw_ctx *ctx, unsigned mode, char const *name) { ssize_t retval; union ctlseqs_value *result = ctx->result; - dprintf(ctx->out_fd, CTLSEQS_DECRQM("%u"), mode_id); + dprintf(ctx->out_fd, CTLSEQS_DECRQM("%d"), mode); do { retval = ctlseqs_read(ctx->reader, ctx->matcher, ctx->timeout); } while (retval == CTLSEQS_PARTIAL); @@ -165,7 +146,7 @@ decrqm(struct sixdraw_ctx *ctx, unsigned mode_id, char const *name) print_error(ctx, "failed to get %s status", name); return false; } - if (result[0].num != mode_id || (result[1].num != DECRQM_SET && result[1].num != DECRQM_RST)) { + if (result[0].num != mode || (result[1].num != DECRQM_SET && result[1].num != DECRQM_RST)) { print_error(ctx, "%s status not recognizable", name); return false; } @@ -175,9 +156,9 @@ decrqm(struct sixdraw_ctx *ctx, unsigned mode_id, char const *name) static inline void get_sixel_color(unsigned rgb888, unsigned *red, unsigned *green, unsigned *blue) { - *red = ((rgb888 >> 16) & 0xFF) * 100 / 255; - *green = ((rgb888 >> 8) & 0xFF) * 100 / 255; - *blue = ((rgb888 >> 0) & 0xFF) * 100 / 255; + *red = ((rgb888 >> 16) & 0xFF) * 100 / 0xFF; + *green = ((rgb888 >> 8) & 0xFF) * 100 / 0xFF; + *blue = ((rgb888 >> 0) & 0xFF) * 100 / 0xFF; } static inline char * @@ -208,7 +189,7 @@ print_sixel_dot(struct sixdraw_ctx *ctx, unsigned x, unsigned y) row = y % ctx->ch_height; col = x % ctx->ch_width; offset += sprintf(sixel_seq + offset, "%.*s", row / 6, "----------------"); - offset += sprintf(sixel_seq + offset, "!%u?%u", col, (1 << row % 6) + 0x3F); + offset += sprintf(sixel_seq + offset, "!%u?%c" CTLSEQS_ST, col, (1 << row % 6) + 0x3F); write(ctx->out_fd, sixel_seq, offset); } @@ -226,7 +207,7 @@ init(struct sixdraw_ctx *ctx, int argc, char **argv) // Process command line arguments. int opt; - while (-1 != (opt = getopt(argc, argv, "t:"))) { + while (-1 != (opt = getopt(argc, argv, "t:c:"))) { switch (opt) { case 't': ctx->timeout = atoi(optarg); @@ -248,7 +229,8 @@ init(struct sixdraw_ctx *ctx, int argc, char **argv) } char const *patterns[] = { CTLSEQS_RESP_PRIMARY_DA(CTLSEQS_PH_NUMS), - CTLSEQS_RESP_DECRQM(CTLSEQS_PH_NUM, CTLSEQS_PH_NUM) + CTLSEQS_RESP_DECRQM(CTLSEQS_PH_NUM, CTLSEQS_PH_NUM), + CTLSEQS_RESP_SGR_MOUSE(CTLSEQS_PH_NUM, CTLSEQS_PH_NUM, CTLSEQS_PH_NUM, "M") }; struct ctlseqs_matcher_options matcher_options = { .patterns = patterns, @@ -275,13 +257,6 @@ init(struct sixdraw_ctx *ctx, int argc, char **argv) return false; } - // Block SIGWINCH. - sigset_t sigset; - sigemptyset(&sigset); - sigaddset(&sigset, SIGWINCH); - sigprocmask(SIG_BLOCK, &sigset, NULL); - signal(SIGWINCH, SIG_DFL); - return true; } @@ -347,48 +322,78 @@ prepare(struct sixdraw_ctx *ctx) return false; } - // Switch into SGR mouse pixel mode. - if (!decrqm(ctx, SGR_MOUSE_PIXELMODE, "SGR mouse pixel mode")) { - return false; - } - ctx->sgr_pixelmode = result[1].num == DECRQM_SET; - if (!ctx->sgr_pixelmode) { - dprintf(ctx->out_fd, CTLSEQS_DECSET("%u"), SGR_MOUSE_PIXELMODE); - } - // Hide cursor. if (!decrqm(ctx, DECTCEM, "cursor")) { return false; } - ctx->show_cursor = result[1].num == DECRQM_SET; - if (ctx->show_cursor) { - dprintf(ctx->out_fd, CTLSEQS_DECRST("%u"), DECTCEM); + ctx->hide_cursor = result[1].num == DECRQM_SET; + if (ctx->hide_cursor) { + dprintf(ctx->out_fd, CTLSEQS_DECRST("%d"), DECTCEM); } // Switch to alternate screen buffer. if (!decrqm(ctx, ALT_SCRBUF, "screen buffer")) { return false; } - ctx->normal_scrbuf = result[1].num == DECRQM_RST; - if (ctx->normal_scrbuf) { - dprintf(ctx->out_fd, CTLSEQS_DECSET("%u"), ALT_SCRBUF); + ctx->alt_scrbuf = result[1].num == DECRQM_RST; + if (ctx->alt_scrbuf) { + dprintf(ctx->out_fd, CTLSEQS_DECSET("%d"), ALT_SCRBUF); + } + + // Enable button event tracking mode. + if (!decrqm(ctx, BTN_EVENT_TRACKING, "button event tracking mode")) { + return false; + } + ctx->btnev_tracking = result[1].num == DECRQM_RST; + if (ctx->btnev_tracking) { + dprintf(ctx->out_fd, CTLSEQS_DECSET("%d"), BTN_EVENT_TRACKING); + } + + // Enable SGR mouse pixel mode. + if (!decrqm(ctx, SGR_MOUSE_PIXELMODE, "SGR mouse pixel mode")) { + return false; + } + ctx->sgr_pixelmode = result[1].num == DECRQM_RST; + if (ctx->sgr_pixelmode) { + dprintf(ctx->out_fd, CTLSEQS_DECSET("%d"), SGR_MOUSE_PIXELMODE); } return true; } +static bool +draw(struct sixdraw_ctx *ctx) +{ + union ctlseqs_value *result = ctx->result; + while (true) { + switch (ctlseqs_read(ctx->reader, ctx->matcher, -1)) { + case 2: // CTLSEQS_RESP_SGR_MOUSE + print_sixel_dot(ctx, result[1].num, result[2].num); + break; + case CTLSEQS_NOSEQ: + // Press Ctrl+C to exit. + if (result[1].str[0] == 0x03) { + return true; + } + break; + case CTLSEQS_ERROR: + case CTLSEQS_NOMEM: + case CTLSEQS_EOF: + return false; + } + } +} + int main(int argc, char **argv) { - int status = 0; - + int status; struct sixdraw_ctx ctx; - if (!init(&ctx, argc, argv) || !prepare(&ctx)) { + if (init(&ctx, argc, argv) && prepare(&ctx)) { + status = draw(&ctx) ? 0 : -1; + } else { status = -1; - goto terminate; } - - terminate: terminate(&ctx); return status; }