Closed arztareef closed 4 months ago
i am still waiting for the patch :))
I just wanted to start by saying that
i am still waiting for the patch
is rather arrogant and disrespectful of other people's time. It reads like you are somehow entitled to have someone else providing you with a custom solution to your specific issue.
I am not sure if it will ever be feasible to provide a standalone patch for sixel support given its complexity and how it integrates with other patches.
One could always try though using flexipatch-finalizer.
st-flexipatch is not exactly 1 to 1 with suckless st, so that is something to take into account as well.
I am creating a directory ~/sixel
and then cloning both suckless st, st-flexipatch, and the finalizer into it.
$ git clone https://git.suckless.org/st
Cloning into 'st'...
remote: Enumerating objects: 4177, done.
remote: Counting objects: 100% (4177/4177), done.
remote: Compressing objects: 100% (3382/3382), done.
remote: Total 4177 (delta 2526), reused 1279 (delta 792), pack-reused 0
Receiving objects: 100% (4177/4177), 1.85 MiB | 2.21 MiB/s, done.
Resolving deltas: 100% (2526/2526), done.
$ git clone git@github.com:bakkeby/st-flexipatch.git
Cloning into 'st-flexipatch'...
remote: Enumerating objects: 1411, done.
remote: Counting objects: 100% (977/977), done.
remote: Compressing objects: 100% (284/284), done.
remote: Total 1411 (delta 782), reused 755 (delta 692), pack-reused 434
Receiving objects: 100% (1411/1411), 400.04 KiB | 1.02 MiB/s, done.
Resolving deltas: 100% (993/993), done.
$ git clone git@github.com:bakkeby/flexipatch-finalizer.git
Cloning into 'flexipatch-finalizer'...
remote: Enumerating objects: 52, done.
remote: Counting objects: 100% (6/6), done.
remote: Compressing objects: 100% (5/5), done.
remote: Total 52 (delta 2), reused 3 (delta 1), pack-reused 46
Receiving objects: 100% (52/52), 12.47 KiB | 134.00 KiB/s, done.
Resolving deltas: 100% (29/29), done.
The flexipatch-finalizer script depends on the patches.h
file, so we compile it once to generate it.
$ make -C st-flexipatch
make: Entering directory '/home/sbakkeby/sixel/st-flexipatch'
c99 -I/usr/X11R6/include `pkg-config --cflags fontconfig` `pkg-config --cflags freetype2` -DVERSION=\"0.9.1\" -DICON=\"/usr/local/share/pixmaps/st.png\" -D_XOPEN_SOURCE=600 -O1 -c st.c
c99 -I/usr/X11R6/include `pkg-config --cflags fontconfig` `pkg-config --cflags freetype2` -DVERSION=\"0.9.1\" -DICON=\"/usr/local/share/pixmaps/st.png\" -D_XOPEN_SOURCE=600 -O1 -c x.c
c99 -o st st.o x.o -L/usr/X11R6/lib -lm -lrt -lX11 -lutil -lXft `pkg-config --libs fontconfig` `pkg-config --libs freetype2`
make: Leaving directory '/home/sbakkeby/sixel/st-flexipatch'
I run the flexipatch-finalizer script on st-flexipatch outputting to a new directory stf_base
.
$ ./flexipatch-finalizer/flexipatch-finalizer.sh -d st-flexipatch/ -o stf_base -r
Now we do the same again, but first we enable the sixel patch in the patches.h
file. You can use your preferred editor to do this, but to make these instructions easier I am just going to do an inplace replace using sed.
$ sed -i 's/SIXEL_PATCH 0/SIXEL_PATCH 1/' st-flexipatch/patches.h
Then I run the flexipatch-finalizer script outputting to a new directory stf_sixel
.
$ ./flexipatch-finalizer/flexipatch-finalizer.sh -d st-flexipatch/ -o stf_sixel -r
The finalizer script doesn't include the .git repository in the output directory, so we do not need to worry about that.
Next we are going to copy the .git
directory of the suckless st into stf_base. You can also move all the files from stf_base into the suckless st, but I think it is easier to just copy the directory instead.
$ cp -r st/.git stf_base
Now we do a git status
on that to see what files are present.
$ git -C stf_base status
On branch master
Your branch is up to date with 'origin/master'.
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: FAQ
modified: Makefile
modified: config.def.h
modified: config.mk
modified: st.c
modified: st.h
modified: st.info
modified: win.h
modified: x.c
Untracked files:
(use "git add <file>..." to include in what will be committed)
config.h
hb.c
patch/
sixel.c
sixel_hls.c
sixel_hls.h
st
st.desktop
st.o
x.o
no changes added to commit (use "git add" and/or "git commit -a")
I think that it should be safe to delete the untracked files, so let's try that.
$ rm -rf stf_base/config.h stf_base/hb.c stf_base/patch/ stf_base/sixel* stf_base/st stf_base/st.desktop stf_base/*.o
Will it still compile?
$ make -C stf_base
make: Entering directory '/home/sbakkeby/sixel/stf_base'
cp config.def.h config.h
c99 -I/usr/X11R6/include `pkg-config --cflags fontconfig` `pkg-config --cflags freetype2` -DVERSION=\"0.9.1\" -DICON=\"/usr/local/share/pixmaps/st.png\" -D_XOPEN_SOURCE=600 -O1 -c st.c
c99 -I/usr/X11R6/include `pkg-config --cflags fontconfig` `pkg-config --cflags freetype2` -DVERSION=\"0.9.1\" -DICON=\"/usr/local/share/pixmaps/st.png\" -D_XOPEN_SOURCE=600 -O1 -c x.c
c99 -o st st.o x.o -L/usr/X11R6/lib -lm -lrt -lX11 -lutil -lXft `pkg-config --libs fontconfig` `pkg-config --libs freetype2`
make: Leaving directory '/home/sbakkeby/sixel/stf_base'
Looks like it. Great. Committing those then.
$ git -C stf_base commit -m "Base changes" --all
[master 0117e1a] Base changes
9 files changed, 571 insertions(+), 419 deletions(-)
Now we have the difference between suckless st and st-flexipatch in a base commit. We are now going to apply the sixel changes on top of that.
Again we could copy files, but I am going to try just borrowing the .git
directory from the base directory instead.
$ cp -r stf_base/.git stf_sixel/
Checking the status.
$ git -C stf_sixel status
On branch master
Your branch is ahead of 'origin/master' by 1 commit.
(use "git push" to publish your local commits)
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: config.def.h
modified: st.c
modified: st.h
modified: x.c
Untracked files:
(use "git add <file>..." to include in what will be committed)
config.h
hb.c
patch/
sixel.c
sixel.h
sixel_hls.c
sixel_hls.h
st
st.desktop
st.o
x.o
no changes added to commit (use "git add" and/or "git commit -a")
The hb.c
file I know comes from the ligatures patch so that should not be relevant. If I look in the patch directory there doesn't seem to be anything relevant to sixel there either.
$ ls stf_sixel/patch
keyboardselect_reflow.txt utils.h
So I think for the untracked files we are only interested in the ones named sixel. Let's add those.
$ git -C stf_sixel add sixel\*
Again deleting the untracked files is not strictly necessary for this exercise, but doing it anyway just to have a clean status before going forward.
$ rm -r stf_sixel/config.h stf_sixel/hb.c stf_sixel/patch/ stf_sixel/st stf_sixel/st.desktop stf_sixel/*.o
Now the status looks like this:
$ git -C stf_sixel status
On branch master
Your branch is ahead of 'origin/master' by 1 commit.
(use "git push" to publish your local commits)
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file: sixel.c
new file: sixel.h
new file: sixel_hls.c
new file: sixel_hls.h
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: config.def.h
modified: st.c
modified: st.h
modified: x.c
Committing that.
$ git -C stf_sixel commit -m "Adding sixel patch" --all
[master 3421a00] Adding sixel patch
8 files changed, 1271 insertions(+), 5 deletions(-)
create mode 100644 sixel.c
create mode 100644 sixel.h
create mode 100644 sixel_hls.c
create mode 100644 sixel_hls.h
So now we have two commits on top of stuckless st, the base changes and our sixel patch.
$ git -C stf_sixel log -3 | cat
commit 3421a00a07b68e5931128e86122dac8467039fdf
Author: Bakkeby <bakkeby@gmail.com>
Date: Sat Apr 20 22:33:05 2024 +0200
Adding sixel patch
commit 0117e1a9c9983691eaa3ea0dcd491876f63f3a6c
Author: Bakkeby <bakkeby@gmail.com>
Date: Sat Apr 20 22:16:01 2024 +0200
Base changes
commit d63b9eb90245926b531bd54b1d591adb96613e70
Author: Hiltjo Posthuma <hiltjo@codemadness.org>
Date: Fri Apr 5 12:18:41 2024 +0200
bump version to 0.9.2
Now we are going to try to, uhm, remove the base changes from the equation.
This is most likely going to cause some conflicts so crossing fingers. Using git revert to remove the base commit.
$ git -C stf_sixel revert 0117e1a9c9983691eaa3ea0dcd491876f63f3a6c
Auto-merging config.def.h
Auto-merging st.c
CONFLICT (content): Merge conflict in st.c
Auto-merging st.h
CONFLICT (content): Merge conflict in st.h
Auto-merging x.c
CONFLICT (content): Merge conflict in x.c
error: could not revert 0117e1a... Base changes
hint: After resolving the conflicts, mark them with
hint: "git add/rm <pathspec>", then run
hint: "git revert --continue".
hint: You can instead skip this commit with "git revert --skip".
hint: To abort and get back to the state before "git revert",
hint: run "git revert --abort".
OK, so we have some 13 conflicts.
$ grep -c "<< HEAD" stf_sixel/st.c stf_sixel/st.h stf_sixel/x.c
stf_sixel/st.c:8
stf_sixel/st.h:2
stf_sixel/x.c:3
At a first glance they don't look that bad.
Starting with st.c.
<<<<<<< HEAD
MODE_WRAP = 1 << 0,
MODE_INSERT = 1 << 1,
MODE_ALTSCREEN = 1 << 2,
MODE_CRLF = 1 << 3,
MODE_ECHO = 1 << 4,
MODE_PRINT = 1 << 5,
MODE_UTF8 = 1 << 6,
MODE_SIXEL = 1 << 7,
MODE_SIXEL_CUR_RT = 1 << 8,
MODE_SIXEL_SDM = 1 << 9
=======
MODE_WRAP = 1 << 0,
MODE_INSERT = 1 << 1,
MODE_ALTSCREEN = 1 << 2,
MODE_CRLF = 1 << 3,
MODE_ECHO = 1 << 4,
MODE_PRINT = 1 << 5,
MODE_UTF8 = 1 << 6,
>>>>>>> parent of 0117e1a (Base changes)
I think this is just spacing issues. Going to keep the latter and adding the MODE_SIXEL ones.
Next is:
<<<<<<< HEAD
char buffer[40];
int n = 0, len;
ImageList *im, *next;
int pi, pa;
int maxcol = term.col;
=======
char buf[40];
int len;
>>>>>>> parent of 0117e1a (Base changes)
Fine to keep HEAD.
<<<<<<< HEAD
case 2: /* screen */
tclearregion(0, 0, maxcol-1, term.row-1);
tdeleteimages();
break;
case 3: /* scrollback */
for (im = term.images; im; im = next) {
next = im->next;
if (im->y < 0)
delete_image(im);
}
break;
case 6: /* sixels */
tdeleteimages();
tfulldirt();
=======
case 2: /* all */
tclearregion(0, 0, term.col-1, term.row-1);
>>>>>>> parent of 0117e1a (Base changes)
Going to keep HEAD.
<<<<<<< HEAD
case 'S': /* SU -- Scroll <n> line up ; XTSMGRAPHICS */
if (csiescseq.priv) {
if (csiescseq.narg > 1) {
/* XTSMGRAPHICS */
pi = csiescseq.arg[0];
pa = csiescseq.arg[1];
if (pi == 1 && (pa == 1 || pa == 2 || pa == 4)) {
/* number of sixel color registers */
/* (read, reset and read the maximum value give the same response) */
n = snprintf(buffer, sizeof buffer, "\033[?1;0;%dS", DECSIXEL_PALETTE_MAX);
ttywrite(buffer, n, 1);
break;
} else if (pi == 2 && (pa == 1 || pa == 2 || pa == 4)) {
/* sixel graphics geometry (in pixels) */
/* (read, reset and read the maximum value give the same response) */
n = snprintf(buffer, sizeof buffer, "\033[?2;0;%d;%dS",
MIN(term.col * win.cw, DECSIXEL_WIDTH_MAX),
MIN(term.row * win.ch, DECSIXEL_HEIGHT_MAX));
ttywrite(buffer, n, 1);
break;
}
/* the number of color registers and sixel geometry can't be changed */
n = snprintf(buffer, sizeof buffer, "\033[?%d;3;0S", pi); /* failure */
ttywrite(buffer, n, 1);
}
goto unknown;
}
=======
case 'S': /* SU -- Scroll <n> line up */
if (csiescseq.priv) break;
>>>>>>> parent of 0117e1a (Base changes)
Going to keep HEAD.
<<<<<<< HEAD
strreset();
=======
>>>>>>> parent of 0117e1a (Base changes)
Going to keep HEAD.
if (IS_SET(MODE_SIXEL) && sixel_st.state != PS_ESC) {
charsize = sixel_parser_parse(&sixel_st, (const unsigned char*)buf + n, buflen - n);
continue;
} else if (IS_SET(MODE_UTF8))
{
Going to keep HEAD.
<<<<<<< HEAD
int x, x2;
Line line;
ImageList *im, *next;
=======
TCursor c;
>>>>>>> parent of 0117e1a (Base changes)
I think we'll need to keep both, the variable c
is used in the code in the resize function.
<<<<<<< HEAD
/* expand images into new text cells to prevent them from being deleted in
* xfinishdraw() that draws the images */
for (i = 0; i < 2; i++) {
for (im = term.images; im; im = next) {
next = im->next;
if (im->y < 0 || im->y >= term.row) {
delete_image(im);
continue;
}
line = term.line[im->y];
x2 = MIN(im->x + im->cols, term.col);
for (x = im->x; x < x2; x++)
line[x].mode |= ATTR_SIXEL;
}
tswapscreen();
}
=======
term.c = c;
>>>>>>> parent of 0117e1a (Base changes)
Unsure about this one, maybe keep both, again unsure in which order.
That was the last one for st.c, checking st.h next.
<<<<<<< HEAD
ATTR_NULL = 0,
ATTR_SET = 1 << 0,
ATTR_BOLD = 1 << 1,
ATTR_FAINT = 1 << 2,
ATTR_ITALIC = 1 << 3,
ATTR_UNDERLINE = 1 << 4,
ATTR_BLINK = 1 << 5,
ATTR_REVERSE = 1 << 6,
ATTR_INVISIBLE = 1 << 7,
ATTR_STRUCK = 1 << 8,
ATTR_WRAP = 1 << 9,
ATTR_WIDE = 1 << 10,
ATTR_WDUMMY = 1 << 11,
ATTR_SIXEL = 1 << 16,
ATTR_BOLD_FAINT = ATTR_BOLD | ATTR_FAINT,
};
typedef struct _ImageList {
struct _ImageList *next, *prev;
unsigned char *pixels;
void *pixmap;
void *clipmask;
int width;
int height;
int x;
int y;
int cols;
int cw;
int ch;
int transparent;
} ImageList;
/* Used to control which screen(s) keybindings and mouse shortcuts apply to. */
enum screen {
S_PRI = -1, /* primary screen */
S_ALL = 0, /* both primary and alt screen */
S_ALT = 1 /* alternate screen */
};
=======
ATTR_NULL = 0,
ATTR_BOLD = 1 << 0,
ATTR_FAINT = 1 << 1,
ATTR_ITALIC = 1 << 2,
ATTR_UNDERLINE = 1 << 3,
ATTR_BLINK = 1 << 4,
ATTR_REVERSE = 1 << 5,
ATTR_INVISIBLE = 1 << 6,
ATTR_STRUCK = 1 << 7,
ATTR_WRAP = 1 << 8,
ATTR_WIDE = 1 << 9,
ATTR_WDUMMY = 1 << 10,
ATTR_BOLD_FAINT = ATTR_BOLD | ATTR_FAINT,
};
>>>>>>> parent of 0117e1a (Base changes)
Again most of the conflicts here are spacing for the glyph_attribute enum. Also the ATTR_SET has been added.
Kept the spacing of the original and added ATTR_SET as 1 << 11.
<<<<<<< HEAD
typedef struct {
Glyph attr; /* current char attributes */
int x;
int y;
char state;
} TCursor;
/* Internal representation of the screen */
typedef struct {
int row; /* nb row */
int col; /* nb col */
Line *line; /* screen */
Line *alt; /* alternate screen */
int *dirty; /* dirtyness of lines */
TCursor c; /* cursor */
int ocx; /* old cursor col */
int ocy; /* old cursor row */
int top; /* top scroll limit */
int bot; /* bottom scroll limit */
int mode; /* terminal mode flags */
int esc; /* escape state flags */
char trantbl[4]; /* charset table translation */
int charset; /* current charset */
int icharset; /* selected charset for sequence */
int *tabs;
ImageList *images; /* sixel images */
ImageList *images_alt; /* sixel images for alternate screen */
Rune lastc; /* last printed char outside of sequence, 0 if control */
} Term;
=======
>>>>>>> parent of 0117e1a (Base changes)
I suppose just keep HEAD.
Moving on to x.c.
<<<<<<< HEAD
#include <Imlib2.h>
#include "sixel.h"
=======
/* types used in config.h */
typedef struct {
uint mod;
KeySym keysym;
void (*func)(const Arg *);
const Arg arg;
} Shortcut;
typedef struct {
uint mod;
uint button;
void (*func)(const Arg *);
const Arg arg;
uint release;
} MouseShortcut;
typedef struct {
KeySym k;
uint mask;
char *s;
/* three-valued logic variables: 0 indifferent, 1 on, -1 off */
signed char appkey; /* application keypad */
signed char appcursor; /* application cursor */
} Key;
>>>>>>> parent of 0117e1a (Base changes)
I suppose keep both.
<<<<<<< HEAD
ImageList *im;
xunloadfonts();
xloadfonts(usedfont, arg->f);
/* deleting old pixmaps forces the new scaled pixmaps to be created */
for (im = term.images; im; im = im->next) {
if (im->pixmap)
XFreePixmap(xw.dpy, (Drawable)im->pixmap);
if (im->clipmask)
XFreePixmap(xw.dpy, (Drawable)im->clipmask);
im->pixmap = NULL;
im->clipmask = NULL;
}
=======
xunloadfonts();
xloadfonts(usedfont, arg->f);
>>>>>>> parent of 0117e1a (Base changes)
The unloading of fonts is present in HEAD so keep that.
void
xfinishdraw(void)
{
<<<<<<< HEAD
ImageList *im, *next;
Imlib_Image origin, scaled;
XGCValues gcvalues;
... 100 lines ...
}
XCopyArea(xw.dpy, xw.buf, xw.win, dc.gc, 0, 0, win.w, win.h, 0, 0);
XSetForeground(xw.dpy, dc.gc, dc.col[IS_SET(MODE_REVERSE) ? defaultfg : defaultbg].pixel);
=======
XCopyArea(xw.dpy, xw.buf, xw.win, dc.gc, 0, 0, win.w,
win.h, 0, 0);
XSetForeground(xw.dpy, dc.gc,
dc.col[IS_SET(MODE_REVERSE)?
defaultfg : defaultbg].pixel);
>>>>>>> parent of 0117e1a (Base changes)
The only conflict here are that line breaks have been removed from the two last functions. For the patch perhaps we just remove the XCopyArea and XSetForeground rows from HEAD and keep the rest.
OK, now that that is done we check the git status again.
$ git -C stf_sixel status
On branch master
Your branch is ahead of 'origin/master' by 2 commits.
(use "git push" to publish your local commits)
You are currently reverting commit 0117e1a.
(fix conflicts and run "git revert --continue")
(use "git revert --skip" to skip this patch)
(use "git revert --abort" to cancel the revert operation)
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: FAQ
modified: Makefile
modified: config.def.h
modified: config.mk
modified: st.info
modified: win.h
Unmerged paths:
(use "git restore --staged <file>..." to unstage)
(use "git add <file>..." to mark resolution)
both modified: st.c
both modified: st.h
both modified: x.c
We add the st.c, st.h and x.c to mark conflict resolution.
$ git -C stf_sixel add st.c st.h x.c
We continue the revert.
$ git -C stf_sixel revert --continue
[master 41502b9] Revert "Base changes"
9 files changed, 416 insertions(+), 520 deletions(-)
If we try to complile, however, we get a bunch of errors.
$ make -C stf_sixel
make: Entering directory '/home/sbakkeby/sixel/stf_sixel'
cp config.def.h config.h
c99 -I/usr/X11R6/include `pkg-config --cflags fontconfig` `pkg-config --cflags freetype2` -DVERSION=\"0.9.2\" -D_XOPEN_SOURCE=600 -O1 -c st.c
In file included from st.c:23:
sixel.h:61:1: error: unknown type name ‘Pixmap’
61 | Pixmap sixel_create_clipmask(char *pixels, int width, int height);
| ^~~~~~
st.c:98:3: error: conflicting types for ‘TCursor’; have ‘struct <anonymous>’
98 | } TCursor;
| ^~~~~~~
In file included from st.c:20:
st.h:101:3: note: previous declaration of ‘TCursor’ with type ‘TCursor’
101 | } TCursor;
| ^~~~~~~
...
Why though? Ah, because the base included changes to config.mk that we no longer have.
Let's add those back in.
$ git -C stf_sixel diff
diff --git a/Makefile b/Makefile
index 15db421..899b163 100644
--- a/Makefile
+++ b/Makefile
@@ -4,7 +4,7 @@
include config.mk
-SRC = st.c x.c
+SRC = st.c x.c $(SIXEL_C)
OBJ = $(SRC:.c=.o)
all: st
diff --git a/config.mk b/config.mk
index fdc29a7..bc61b40 100644
--- a/config.mk
+++ b/config.mk
@@ -12,11 +12,14 @@ X11LIB = /usr/X11R6/lib
PKG_CONFIG = pkg-config
+SIXEL_C = sixel.c sixel_hls.c
+SIXEL_LIBS = `$(PKG_CONFIG) --libs imlib2`
+
# includes and libs
INCS = -I$(X11INC) \
`$(PKG_CONFIG) --cflags fontconfig` \
`$(PKG_CONFIG) --cflags freetype2`
-LIBS = -L$(X11LIB) -lm -lrt -lX11 -lutil -lXft \
+LIBS = -L$(X11LIB) -lm -lrt -lX11 -lutil -lXft $(SIXEL_LIBS) \
`$(PKG_CONFIG) --libs fontconfig` \
`$(PKG_CONFIG) --libs freetype2`
Still get compilation errors though.
I believe that this has to do with that sixel.c includes st.h and there were a series of changes that had to be made to move various definitions from st.c to st.h.
To continue this one would have to work through what goes where and in what form to sort out the compilation errors.
The alternative would be to try manually apply the patch based on the two commits - but this is a diff of ~3500 lines so that is also going to take some serious effort.
Now let's say that someone spends that effort to port sixel as a patch for st (and it actually works mind you), then the next obstacle would be to get that integrated into your own build.
I'd assume that there would be conflicts there as well due to the nature of the sixel changes.
I would like to apologise if my words have somehow led to make you believe that i am trying to waste someone's time by ordering them to help me w/ to fix something which is custom. I apologise for the inconvenience method of selecting my words. Now that i read back to my request, I realise that I have made a great mistake of choosing my words lightly. It was merely a desperate attempt to fix a problem of mine and with no where else to go, I decided to seek help to the only person who has mastered the arts of suckless software (Im not trying to flatter you, nor trying to brainwash you). Either way, I apologise if I have wasted your time in anyway possible and I promise you I won't do with it with anyone else. Thanks a lot bakkeby, I am a great admirer of your work.
I just had to make another comment, I am deeply ashamed of my behaviour and I would whole heartedly like to apologise for this arrogant behaviour of mine. I would like you to understand that I never had any intention to be arrogant or any sort of bad intention, I just needed some help and I rephrased my pleading in an incorrect way. (I would like to apologise if my english is quite garbage :/ im throwing a lot of error jargons here and there). I am sorry to waste your time bakkeby.
Hello there, bakkeby 😀 (thanks if you're reading this). I would like to add sixel support for my fork of st (https://codeberg.org/arztareef/st). I have tried to patch it with some files from saitoha and other but i failed :/ . I would really appreciate it if you could drop a diff file for the patch. Thanks in advance :)