Check and enable sixel scrolling in example.
This commit is contained in:
parent
0ebc0054c4
commit
b2c5b019cc
|
@ -29,10 +29,12 @@
|
||||||
# include "config.h"
|
# include "config.h"
|
||||||
#endif // HAVE_CONFIG_H
|
#endif // HAVE_CONFIG_H
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
|
@ -46,17 +48,19 @@
|
||||||
# define DEFAULT_TIMEOUT_MILLIS 500
|
# define DEFAULT_TIMEOUT_MILLIS 500
|
||||||
#endif // !DEFAULT_TIMEOUT_MILLIS
|
#endif // !DEFAULT_TIMEOUT_MILLIS
|
||||||
|
|
||||||
#define DECRQM_SET 1
|
#define DECRQM_UNREC 0
|
||||||
#define DECRQM_RST 2
|
#define DECRQM_SET 1
|
||||||
|
#define DECRQM_RST 2
|
||||||
|
|
||||||
#define DECTCEM 25
|
#define DECTCEM 25
|
||||||
|
#define DECSDM 80
|
||||||
#define BTN_EVENT_TRACKING 1002
|
#define BTN_EVENT_TRACKING 1002
|
||||||
#define SGR_MOUSE_PIXELMODE 1016
|
#define SGR_MOUSE_PIXELMODE 1016
|
||||||
#define ALT_SCRBUF 1049
|
#define ALT_SCRBUF 1049
|
||||||
|
|
||||||
#define SIXEL_SEQ_HEAD CTLSEQS_DCS "0;1q\"1;1;"
|
#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 sixdraw_ctx {
|
||||||
struct termios termios;
|
struct termios termios;
|
||||||
|
@ -70,7 +74,9 @@ struct sixdraw_ctx {
|
||||||
bool hide_cursor;
|
bool hide_cursor;
|
||||||
bool alt_scrbuf;
|
bool alt_scrbuf;
|
||||||
bool btnev_tracking;
|
bool btnev_tracking;
|
||||||
|
bool legacy_xterm;
|
||||||
bool sgr_pixelmode;
|
bool sgr_pixelmode;
|
||||||
|
bool sixel_scroll;
|
||||||
int in_fd;
|
int in_fd;
|
||||||
int out_fd;
|
int out_fd;
|
||||||
int timeout;
|
int timeout;
|
||||||
|
@ -100,11 +106,6 @@ terminate(struct sixdraw_ctx *ctx)
|
||||||
ctlseqs_matcher_free(ctx->matcher);
|
ctlseqs_matcher_free(ctx->matcher);
|
||||||
ctlseqs_reader_free(ctx->reader);
|
ctlseqs_reader_free(ctx->reader);
|
||||||
|
|
||||||
// Restore cursor status.
|
|
||||||
if (ctx->hide_cursor) {
|
|
||||||
fprintf(ctx->out_file, CTLSEQS_DECSET("%d"), DECTCEM);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Restore normal screen buffer.
|
// Restore normal screen buffer.
|
||||||
if (ctx->alt_scrbuf) {
|
if (ctx->alt_scrbuf) {
|
||||||
fprintf(ctx->out_file, CTLSEQS_DECRST("%d"), 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);
|
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.
|
// Restore original terminal modes.
|
||||||
if (ctx->has_termios) {
|
if (ctx->has_termios) {
|
||||||
tcsetattr(ctx->in_fd, TCSANOW, &ctx->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);
|
print_error(ctx, "failed to get %s status", name);
|
||||||
return false;
|
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);
|
print_error(ctx, "%s status not recognizable", name);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
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
|
static void
|
||||||
print_sixel_dot(struct sixdraw_ctx *ctx, unsigned x, unsigned y)
|
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[] = {
|
char const *patterns[] = {
|
||||||
CTLSEQS_RESP_PRIMARY_DA(CTLSEQS_PH_NUMS),
|
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")
|
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 = {
|
struct ctlseqs_matcher_options matcher_options = {
|
||||||
.patterns = patterns,
|
.patterns = patterns,
|
||||||
|
@ -330,6 +370,25 @@ prepare(struct sixdraw_ctx *ctx)
|
||||||
fprintf(ctx->out_file, CTLSEQS_DECRST("%d"), DECTCEM);
|
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.
|
// Enable button event tracking mode.
|
||||||
if (!decrqm(ctx, BTN_EVENT_TRACKING, "button event tracking mode")) {
|
if (!decrqm(ctx, BTN_EVENT_TRACKING, "button event tracking mode")) {
|
||||||
return false;
|
return false;
|
||||||
|
|
Loading…
Reference in New Issue