Check and enable sixel scrolling in example.
This commit is contained in:
parent
0ebc0054c4
commit
b2c5b019cc
|
@ -29,10 +29,12 @@
|
|||
# include "config.h"
|
||||
#endif // HAVE_CONFIG_H
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <getopt.h>
|
||||
|
@ -46,17 +48,19 @@
|
|||
# define DEFAULT_TIMEOUT_MILLIS 500
|
||||
#endif // !DEFAULT_TIMEOUT_MILLIS
|
||||
|
||||
#define DECRQM_SET 1
|
||||
#define DECRQM_RST 2
|
||||
#define DECRQM_UNREC 0
|
||||
#define DECRQM_SET 1
|
||||
#define DECRQM_RST 2
|
||||
|
||||
#define DECTCEM 25
|
||||
#define DECSDM 80
|
||||
#define BTN_EVENT_TRACKING 1002
|
||||
#define SGR_MOUSE_PIXELMODE 1016
|
||||
#define ALT_SCRBUF 1049
|
||||
|
||||
#define SIXEL_SEQ_HEAD CTLSEQS_DCS "0;1q\"1;1;"
|
||||
|
||||
static char sixel_seq[2048] = SIXEL_SEQ_HEAD;
|
||||
static char sixel_seq[4096] = SIXEL_SEQ_HEAD;
|
||||
|
||||
struct sixdraw_ctx {
|
||||
struct termios termios;
|
||||
|
@ -70,7 +74,9 @@ struct sixdraw_ctx {
|
|||
bool hide_cursor;
|
||||
bool alt_scrbuf;
|
||||
bool btnev_tracking;
|
||||
bool legacy_xterm;
|
||||
bool sgr_pixelmode;
|
||||
bool sixel_scroll;
|
||||
int in_fd;
|
||||
int out_fd;
|
||||
int timeout;
|
||||
|
@ -100,11 +106,6 @@ terminate(struct sixdraw_ctx *ctx)
|
|||
ctlseqs_matcher_free(ctx->matcher);
|
||||
ctlseqs_reader_free(ctx->reader);
|
||||
|
||||
// Restore cursor status.
|
||||
if (ctx->hide_cursor) {
|
||||
fprintf(ctx->out_file, CTLSEQS_DECSET("%d"), DECTCEM);
|
||||
}
|
||||
|
||||
// Restore normal screen buffer.
|
||||
if (ctx->alt_scrbuf) {
|
||||
fprintf(ctx->out_file, CTLSEQS_DECRST("%d"), ALT_SCRBUF);
|
||||
|
@ -118,6 +119,16 @@ terminate(struct sixdraw_ctx *ctx)
|
|||
fprintf(ctx->out_file, CTLSEQS_DECRST("%d"), SGR_MOUSE_PIXELMODE);
|
||||
}
|
||||
|
||||
// Restore cursor status.
|
||||
if (ctx->hide_cursor) {
|
||||
fprintf(ctx->out_file, CTLSEQS_DECSET("%d"), DECTCEM);
|
||||
}
|
||||
|
||||
// Restore original sixel mode.
|
||||
if (ctx->sixel_scroll) {
|
||||
fprintf(ctx->out_file, ctx->legacy_xterm ? CTLSEQS_DECRST("%d") : CTLSEQS_DECSET("%d"), DECSDM);
|
||||
}
|
||||
|
||||
// Restore original terminal modes.
|
||||
if (ctx->has_termios) {
|
||||
tcsetattr(ctx->in_fd, TCSANOW, &ctx->termios);
|
||||
|
@ -157,13 +168,41 @@ decrqm(struct sixdraw_ctx *ctx, unsigned mode, char const *name)
|
|||
print_error(ctx, "failed to get %s status", name);
|
||||
return false;
|
||||
}
|
||||
if (result[0].num != mode || (result[1].num != DECRQM_SET && result[1].num != DECRQM_RST)) {
|
||||
if (result[0].num != mode || result[1].num == DECRQM_UNREC) {
|
||||
print_error(ctx, "%s status not recognizable", name);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static long
|
||||
xtversion(struct sixdraw_ctx *ctx) {
|
||||
ssize_t retval;
|
||||
union ctlseqs_value *result = ctx->result;
|
||||
fprintf(ctx->out_file, CTLSEQS_XTVERSION());
|
||||
do {
|
||||
retval = ctlseqs_read(ctx->reader, ctx->matcher, ctx->timeout);
|
||||
} while (retval == CTLSEQS_PARTIAL);
|
||||
if (retval != 3) {
|
||||
// Terminal emulator does not recognize XTVERSION;
|
||||
return -1;
|
||||
}
|
||||
char const *xtversion = result[1].str;
|
||||
if (result[0].len < sizeof("XTerm(")) {
|
||||
return -2;
|
||||
}
|
||||
if (strncmp(xtversion, "XTerm(", sizeof("XTerm(") - 1) != 0) {
|
||||
// Terminal emulator is not XTerm.
|
||||
return -2;
|
||||
}
|
||||
errno = 0;
|
||||
long version_num = strtol(xtversion + (sizeof("XTerm(") - 1), NULL, 10);
|
||||
if (errno) {
|
||||
return -3;
|
||||
}
|
||||
return version_num;
|
||||
}
|
||||
|
||||
static void
|
||||
print_sixel_dot(struct sixdraw_ctx *ctx, unsigned x, unsigned y)
|
||||
{
|
||||
|
@ -225,7 +264,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_SGR_MOUSE(CTLSEQS_PH_NUM, CTLSEQS_PH_NUM, CTLSEQS_PH_NUM, "M")
|
||||
CTLSEQS_RESP_SGR_MOUSE(CTLSEQS_PH_NUM, CTLSEQS_PH_NUM, CTLSEQS_PH_NUM, "M"),
|
||||
CTLSEQS_RESP_XTVERSION(CTLSEQS_PH_STR),
|
||||
};
|
||||
struct ctlseqs_matcher_options matcher_options = {
|
||||
.patterns = patterns,
|
||||
|
@ -330,6 +370,25 @@ prepare(struct sixdraw_ctx *ctx)
|
|||
fprintf(ctx->out_file, CTLSEQS_DECRST("%d"), DECTCEM);
|
||||
}
|
||||
|
||||
// Check terminal name and version.
|
||||
long xterm_version = xtversion(ctx);
|
||||
if (xterm_version >= 0 && xterm_version < 369) {
|
||||
ctx->legacy_xterm = true;
|
||||
} else {
|
||||
ctx->legacy_xterm = false;
|
||||
}
|
||||
|
||||
// Enable sixel scrolling.
|
||||
if (!decrqm(ctx, DECSDM, "sixel scrolling")) {
|
||||
return false;
|
||||
}
|
||||
// Before patch #369, XTerm implemented DECSDM incorrectly.
|
||||
// See https://invisible-island.net/xterm/xterm.log.html#xterm_369
|
||||
ctx->sixel_scroll = result[1].num == (ctx->legacy_xterm ? DECRQM_RST : DECRQM_SET);
|
||||
if (ctx->sixel_scroll) {
|
||||
fprintf(ctx->out_file, ctx->legacy_xterm ? CTLSEQS_DECSET("%d") : CTLSEQS_DECRST("%d"), DECSDM);
|
||||
}
|
||||
|
||||
// Enable button event tracking mode.
|
||||
if (!decrqm(ctx, BTN_EVENT_TRACKING, "button event tracking mode")) {
|
||||
return false;
|
||||
|
|
Loading…
Reference in New Issue