diff --git a/src/document/html/parser/link.c b/src/document/html/parser/link.c index f25275b56..6afc6c4fa 100644 --- a/src/document/html/parser/link.c +++ b/src/document/html/parser/link.c @@ -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; diff --git a/src/terminal/Makefile b/src/terminal/Makefile index faf4e9aa4..317c32172 100644 --- a/src/terminal/Makefile +++ b/src/terminal/Makefile @@ -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 diff --git a/src/terminal/kbd.c b/src/terminal/kbd.c index eb10e7381..c54b3d1ce 100644 --- a/src/terminal/kbd.c +++ b/src/terminal/kbd.c @@ -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, diff --git a/src/terminal/kitty.c b/src/terminal/kitty.c index 4b2f1b333..ee625e420 100644 --- a/src/terminal/kitty.c +++ b/src/terminal/kitty.c @@ -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; diff --git a/src/terminal/kitty.h b/src/terminal/kitty.h index 965d86e07..f199c057a 100644 --- a/src/terminal/kitty.h +++ b/src/terminal/kitty.h @@ -21,6 +21,7 @@ struct k_image { int width; int height; int id; + int ID; int number; int x; int y; diff --git a/src/terminal/map.cpp b/src/terminal/map.cpp new file mode 100644 index 000000000..0ffa0cea1 --- /dev/null +++ b/src/terminal/map.cpp @@ -0,0 +1,46 @@ +#include "terminal/map.h" +#include + +#include + +static std::map map_ID; +static std::map 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); + } +} diff --git a/src/terminal/map.h b/src/terminal/map.h new file mode 100644 index 000000000..f97da1c57 --- /dev/null +++ b/src/terminal/map.h @@ -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 */ diff --git a/src/terminal/meson.build b/src/terminal/meson.build index 7458cffdb..08c5a075c 100644 --- a/src/terminal/meson.build +++ b/src/terminal/meson.build @@ -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') diff --git a/src/viewer/text/draw.c b/src/viewer/text/draw.c index fce89155e..c4cc82951 100644 --- a/src/viewer/text/draw.c +++ b/src/viewer/text/draw.c @@ -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; }