0
0
mirror of https://github.com/rkd77/elinks.git synced 2025-06-30 22:19:29 -04:00

[kitty] Try to decode kitty escape sequences

This commit is contained in:
Witold Filipczyk 2025-06-09 17:54:23 +02:00
parent f2872b3711
commit 8f02de86e8
9 changed files with 152 additions and 11 deletions

View File

@ -320,8 +320,8 @@ html_img_kitty(struct html_context *html_context, char *a,
}
int xw = (im->width + document->options.cell_width - 1) / document->options.cell_width;
int y;
im->id = html_top->name - document->text.source;
im->number = im_number;
im->number = html_top->name - document->text.source;
im->ID = im_number;
for (y = 0; y < how_many; y++) {
int x;

View File

@ -1,7 +1,7 @@
top_builddir=../..
include $(top_builddir)/Makefile.config
OBJS-$(CONFIG_KITTY) += kitty.o
OBJS-$(CONFIG_KITTY) += kitty.o map.obj
OBJS-$(CONFIG_MOUSE) += mouse.o
OBJS-$(CONFIG_LIBSIXEL) += sixel.o
OBJS-$(CONFIG_TERMINFO) += terminfo.o

View File

@ -38,6 +38,9 @@
#include "terminal/hardio.h"
#include "terminal/itrm.h"
#include "terminal/kbd.h"
#ifdef CONFIG_KITTY
#include "terminal/map.h"
#endif
#include "terminal/mouse.h"
#include "terminal/terminal.h"
#include "util/error.h"
@ -785,6 +788,74 @@ get_ui_double_esc(void)
return ui_double_esc;
}
#ifdef CONFIG_KITTY
static int
decode_kitty_escape_sequence(struct itrm *itrm)
{
ELOG
int i = 3;
int was_esc = 0;
if (itrm->in.queue.len < 3) {
return -1;
}
if (itrm->in.queue.data[2] != 'G') {
return -1;
}
for (i = 3; i < itrm->in.queue.len; i++) {
if (itrm->in.queue.data[i] == ASCII_ESC) {
was_esc = i + 1;
break;
}
}
if (!was_esc) {
return -1;
}
if (was_esc >= itrm->in.queue.len || itrm->in.queue.data[was_esc] != '\\') {
return -1;
}
itrm->in.queue.data[was_esc] = '\0';
const char *data = (const char *)(itrm->in.queue.data + 3);
char *ok = strstr(data, "OK");
int id = -1;
int ID = -1;
if (ok) {
char *ieq = strstr(data, "i=");
if (ieq) {
id = atoi(ieq + 2);
}
char *Ieq = strstr(data, "I=");
if (Ieq) {
ID = atoi(Ieq + 2);
}
if (id >= 0 && ID >= 0) {
set_id_ID(id, ID);
}
} else {
char *enoent = strstr(data, "ENOENT");
if (enoent) {
char *ieq = strstr(data, "i=");
if (ieq) {
id = atoi(ieq + 2);
}
if (id >= 0) {
remove_id(id);
}
}
}
itrm->in.queue.data[was_esc] = '\\';
return was_esc + 1;
}
#endif
/** Decode a control sequence that begins with CSI (CONTROL SEQUENCE
* INTRODUCER) encoded as ESC [, and set @a *ev accordingly.
* (ECMA-48 also allows 0x9B as a single-byte CSI, but we don't
@ -1163,6 +1234,10 @@ process_queue(struct itrm *itrm)
el = decode_terminal_escape_sequence(itrm, &ev);
} else if (itrm->in.queue.data[1] == 0x4F /* SS3 */) {
el = decode_terminal_application_key(itrm, &ev);
#ifdef CONFIG_KITTY
} else if (itrm->in.queue.data[1] == '_') {
el = decode_kitty_escape_sequence(itrm);
#endif
} else if (itrm->in.queue.data[1] == ASCII_ESC) {
/* ESC ESC can be either Alt-Esc or the
* beginning of e.g. ESC ESC 0x5B 0x41,

View File

@ -16,6 +16,7 @@
#include "osdep/osdep.h"
#include "terminal/hardio.h"
#include "terminal/kitty.h"
#include "terminal/map.h"
#include "terminal/screen.h"
#include "terminal/terminal.h"
#include "util/base64.h"
@ -91,7 +92,7 @@ try_to_draw_k_images(struct terminal *term)
{
ELOG
if (!term->kitty || !term->number_of_images) {
if (!term->kitty) {
return;
}
struct string text;
@ -118,13 +119,15 @@ try_to_draw_k_images(struct terminal *term)
}
add_cursor_move_to_string(&text, im->cy + 1, im->cx + 1);
if (!im->sent) {
int id = get_id_from_ID(im->ID);
if (id < 0) {
int m;
int left = im->pixels.length;
int sent = 0;
while (1) {
m = left >= 4000;
add_format_to_string(&text, "\033_Gf=32,i=%d,s=%d,v=%d,m=%d,t=d,q=1;", im->number, im->width, im->height, m);
add_format_to_string(&text, "\033_Gf=32,I=%d,s=%d,v=%d,m=%d,t=d,a=T;", im->ID, im->width, im->height, m);
add_bytes_to_string(&text, im->pixels.source + sent, m ? 4000 : left);
add_to_string(&text, "\033\\");
if (!m) {
@ -133,9 +136,9 @@ try_to_draw_k_images(struct terminal *term)
sent += 4000;
left -= 4000;
};
im->sent = 1;
} else {
add_format_to_string(&text, "\033_Gi=%d,x=%d,y=%d,w=%d,h=%d,a=p,q=1\033\\", id, im->x, im->y, im->w, im->h);
}
add_format_to_string(&text, "\033_Gi=%d,x=%d,y=%d,w=%d,h=%d,a=p,q=1\033\\", im->number, im->x, im->y, im->w, im->h);
if (text.length) {
if (term->master) want_draw();
@ -194,7 +197,7 @@ copy_k_frame(struct k_image *src, struct el_box *box, int cell_width, int cell_h
dest->width = src->width;
dest->height = src->height;
dest->id = src->id;
dest->ID = src->ID;
dest->number = src->number;
dest->sent = src->sent;

View File

@ -21,6 +21,7 @@ struct k_image {
int width;
int height;
int id;
int ID;
int number;
int x;
int y;

46
src/terminal/map.cpp Normal file
View File

@ -0,0 +1,46 @@
#include "terminal/map.h"
#include <map>
#include <stdio.h>
static std::map<unsigned int, unsigned int> map_ID;
static std::map<unsigned int, unsigned int> reverse_map_ID;
// -1 not found
int
get_id_from_ID(unsigned int ID)
{
auto search = map_ID.find(ID);
if (search == map_ID.end()) {
return -1;
}
return search->second;
}
void
set_id_ID(unsigned int id, unsigned int ID)
{
map_ID[ID] = id;
reverse_map_ID[id] = ID;
}
void
remove_id(unsigned int id)
{
auto search = reverse_map_ID.find(id);
if (search == reverse_map_ID.end()) {
return;
}
unsigned int ID = search->second;
reverse_map_ID.erase(search);
auto search2 = map_ID.find(ID);
if (search2 != map_ID.end()) {
map_ID.erase(search2);
}
}

16
src/terminal/map.h Normal file
View File

@ -0,0 +1,16 @@
#ifndef EL__TERMINAL_MAP_H
#define EL__TERMINAL_MAP_H
#ifdef __cplusplus
extern "C" {
#endif
int get_id_from_ID(unsigned int ID);
void set_id_ID(unsigned int id, unsigned int ID);
void remove_id(unsigned int id);
#ifdef __cplusplus
}
#endif
#endif /* EL__TERMINAL_MAP_H */

View File

@ -1,5 +1,5 @@
if conf_data.get('CONFIG_KITTY')
srcs += files('kitty.c')
srcs += files('kitty.c', 'map.cpp')
endif
if conf_data.get('CONFIG_MOUSE')
srcs += files('mouse.c')

View File

@ -480,7 +480,7 @@ draw_doc(struct session *ses, struct document_view *doc_view, int active)
if (!found) {
for (;cx < data[im.cy].length; cx++) {
if (im.id == data[im.cy].ch.chars[cx].number) {
if (im.number == data[im.cy].ch.chars[cx].number) {
found = 1;
break;
}