commit 70432622424f20d7132f5965b89127a720d90a1a
Author: Alexander Rogachev <[email protected]>
Date:   Sat Jan 6 19:46:05 2024 +0400

    [st][patch][ligatures] A couple of fixes:
    - Fixed buffer overflow on single cell redraw in case of glyph expansion 
using some fonts.
    - Set cluster level to 1 in HarfBuzz for prevent merging of composite 
emojis.

diff --git 
a/st.suckless.org/patches/ligatures/0.9/st-ligatures-20230105-0.9.diff 
b/st.suckless.org/patches/ligatures/0.9/st-ligatures-20240105-0.9.diff
similarity index 90%
rename from st.suckless.org/patches/ligatures/0.9/st-ligatures-20230105-0.9.diff
rename to st.suckless.org/patches/ligatures/0.9/st-ligatures-20240105-0.9.diff
index f47ac98a..ef299c46 100644
--- a/st.suckless.org/patches/ligatures/0.9/st-ligatures-20230105-0.9.diff
+++ b/st.suckless.org/patches/ligatures/0.9/st-ligatures-20240105-0.9.diff
@@ -42,10 +42,10 @@ index 1e306f8..3e13e53 100644
  STCPPFLAGS = -DVERSION=\"$(VERSION)\" -D_XOPEN_SOURCE=600
 diff --git a/hb.c b/hb.c
 new file mode 100644
-index 0000000..528c040
+index 0000000..99412c8
 --- /dev/null
 +++ b/hb.c
-@@ -0,0 +1,124 @@
+@@ -0,0 +1,125 @@
 +#include <stdlib.h>
 +#include <stdio.h>
 +#include <math.h>
@@ -136,6 +136,7 @@ index 0000000..528c040
 +
 +      hb_buffer_t *buffer = hb_buffer_create();
 +      hb_buffer_set_direction(buffer, HB_DIRECTION_LTR);
++      hb_buffer_set_cluster_level(buffer, 
HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS);
 +
 +      /* Resize the buffer if required length is larger. */
 +      if (hbrunebuffer.capacity < length) {
@@ -172,7 +173,7 @@ index 0000000..528c040
 +}
 diff --git a/hb.h b/hb.h
 new file mode 100644
-index 0000000..88de9bd
+index 0000000..3b0ef44
 --- /dev/null
 +++ b/hb.h
 @@ -0,0 +1,14 @@
@@ -181,10 +182,10 @@ index 0000000..88de9bd
 +#include <hb-ft.h>
 +
 +typedef struct {
-+  hb_buffer_t *buffer;
-+  hb_glyph_info_t *glyphs;
-+  hb_glyph_position_t *positions;
-+  unsigned int count;
++      hb_buffer_t *buffer;
++      hb_glyph_info_t *glyphs;
++      hb_glyph_position_t *positions;
++      unsigned int count;
 +} HbTransformData;
 +
 +void hbunloadfonts();
@@ -232,7 +233,7 @@ index 6de960d..94679e4 100644
  void xfinishdraw(void);
  void xloadcols(void);
 diff --git a/x.c b/x.c
-index 2a3bd38..9b97075 100644
+index 2a3bd38..66605ae 100644
 --- a/x.c
 +++ b/x.c
 @@ -19,6 +19,7 @@ char *argv0;
@@ -243,14 +244,17 @@ index 2a3bd38..9b97075 100644
  
  /* types used in config.h */
  typedef struct {
-@@ -141,6 +142,7 @@ typedef struct {
+@@ -141,8 +142,9 @@ typedef struct {
  } DC;
  
  static inline ushort sixd_to_16bit(int);
 +static void xresetfontsettings(ushort mode, Font **font, int *frcflags);
  static int xmakeglyphfontspecs(XftGlyphFontSpec *, const Glyph *, int, int, 
int);
- static void xdrawglyphfontspecs(const XftGlyphFontSpec *, Glyph, int, int, 
int);
+-static void xdrawglyphfontspecs(const XftGlyphFontSpec *, Glyph, int, int, 
int);
++static void xdrawglyphfontspecs(const XftGlyphFontSpec *, Glyph, int, int, 
int, int);
  static void xdrawglyph(Glyph, int, int);
+ static void xclear(int, int, int, int);
+ static int xgeommasktogravity(int);
 @@ -757,7 +759,7 @@ xresize(int col, int row)
        xclear(0, 0, win.w, win.h);
  
@@ -302,13 +306,13 @@ index 2a3bd38..9b97075 100644
  int
  xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, 
int x, int y)
  {
-@@ -1253,119 +1274,148 @@ xmakeglyphfontspecs(XftGlyphFontSpec *specs, const 
Glyph *glyphs, int len, int x
+@@ -1253,128 +1274,156 @@ xmakeglyphfontspecs(XftGlyphFontSpec *specs, const 
Glyph *glyphs, int len, int x
        FcPattern *fcpattern, *fontpattern;
        FcFontSet *fcsets[] = { NULL };
        FcCharSet *fccharset;
 -      int i, f, numspecs = 0;
 +      int i, f, length = 0, start = 0, numspecs = 0;
-+  float cluster_xp = xp, cluster_yp = yp;
++      float cluster_xp = xp, cluster_yp = yp;
 +      HbTransformData shaped = { 0 };
 +
 +      /* Initial values. */
@@ -356,7 +360,7 @@ index 2a3bd38..9b97075 100644
                        }
 -                      yp = winy + font->ascent;
 -              }
--
+ 
 -              /* Lookup character index with default font. */
 -              glyphidx = XftCharIndex(xw.dpy, font->match, rune);
 -              if (glyphidx) {
@@ -368,7 +372,7 @@ index 2a3bd38..9b97075 100644
 -                      numspecs++;
 -                      continue;
 -              }
- 
+-
 -              /* Fallback on font cache, search the font cache for match. */
 -              for (f = 0; f < frclen; f++) {
 -                      glyphidx = XftCharIndex(xw.dpy, frc[f].font, rune);
@@ -481,13 +485,16 @@ index 2a3bd38..9b97075 100644
 +                              }
                        }
 -              }
--
+ 
 -              /* Nothing was found. Use fontconfig to find matching font. */
 -              if (f >= frclen) {
 -                      if (!font->set)
 -                              font->set = FcFontSort(0, font->pattern,
 -                                                     1, 0, &fcres);
 -                      fcsets[0] = font->set;
++                      /* Cleanup and get ready for next segment. */
++                      hbcleanup(&shaped);
++                      start = i;
  
 -                      /*
 -                       * Nothing was found in the cache. Now use
@@ -503,10 +510,7 @@ index 2a3bd38..9b97075 100644
 -                      FcPatternAddCharSet(fcpattern, FC_CHARSET,
 -                                      fccharset);
 -                      FcPatternAddBool(fcpattern, FC_SCALABLE, 1);
-+                      /* Cleanup and get ready for next segment. */
-+                      hbcleanup(&shaped);
-+                      start = i;
- 
+-
 -                      FcConfigSubstitute(0, fcpattern,
 -                                      FcMatchPattern);
 -                      FcDefaultSubstitute(fcpattern);
@@ -551,7 +555,27 @@ index 2a3bd38..9b97075 100644
        }
  
        return numspecs;
-@@ -1517,14 +1567,17 @@ xdrawglyph(Glyph g, int x, int y)
+ }
+ 
+ void
+-xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int 
x, int y)
++xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int 
x, int y, int charlen)
+ {
+-      int charlen = len * ((base.mode & ATTR_WIDE) ? 2 : 1);
+       int winx = borderpx + x * win.cw, winy = borderpx + y * win.ch,
+           width = charlen * win.cw;
+       Color *fg, *bg, *temp, revfg, revbg, truefg, truebg;
+@@ -1510,21 +1559,24 @@ void
+ xdrawglyph(Glyph g, int x, int y)
+ {
+       int numspecs;
+-      XftGlyphFontSpec spec;
++      XftGlyphFontSpec *specs = xw.specbuf;
+ 
+-      numspecs = xmakeglyphfontspecs(&spec, &g, 1, x, y);
+-      xdrawglyphfontspecs(&spec, g, numspecs, x, y);
++      numspecs = xmakeglyphfontspecs(specs, &g, 1, x, y);
++      xdrawglyphfontspecs(specs, g, numspecs, x, y, (g.mode & ATTR_WIDE) ? 2 
: 1);
  }
  
  void
@@ -571,7 +595,7 @@ index 2a3bd38..9b97075 100644
  
        if (IS_SET(MODE_HIDE))
                return;
-@@ -1652,18 +1705,16 @@ xdrawline(Line line, int x1, int y1, int x2)
+@@ -1652,18 +1704,16 @@ xdrawline(Line line, int x1, int y1, int x2)
        Glyph base, new;
        XftGlyphFontSpec *specs = xw.specbuf;
  
@@ -590,11 +614,11 @@ index 2a3bd38..9b97075 100644
 -                      numspecs -= i;
 +              if ((i > 0) && ATTRCMP(base, new)) {
 +                      numspecs = xmakeglyphfontspecs(specs, &line[ox], x - 
ox, ox, y1);
-+                      xdrawglyphfontspecs(specs, base, numspecs, ox, y1);
++                      xdrawglyphfontspecs(specs, base, numspecs, ox, y1, x - 
ox);
                        i = 0;
                }
                if (i == 0) {
-@@ -1672,8 +1723,10 @@ xdrawline(Line line, int x1, int y1, int x2)
+@@ -1672,8 +1722,10 @@ xdrawline(Line line, int x1, int y1, int x2)
                }
                i++;
        }
@@ -602,7 +626,7 @@ index 2a3bd38..9b97075 100644
 -              xdrawglyphfontspecs(specs, base, i, ox, y1);
 +      if (i > 0) {
 +              numspecs = xmakeglyphfontspecs(specs, &line[ox], x2 - ox, ox, 
y1);
-+              xdrawglyphfontspecs(specs, base, numspecs, ox, y1);
++              xdrawglyphfontspecs(specs, base, numspecs, ox, y1, x2 - ox);
 +      }
  }
  
diff --git 
a/st.suckless.org/patches/ligatures/0.9/st-ligatures-alpha-20230105-0.9.diff 
b/st.suckless.org/patches/ligatures/0.9/st-ligatures-alpha-20240105-0.9.diff
similarity index 90%
rename from 
st.suckless.org/patches/ligatures/0.9/st-ligatures-alpha-20230105-0.9.diff
rename to 
st.suckless.org/patches/ligatures/0.9/st-ligatures-alpha-20240105-0.9.diff
index 9ea80b0a..ff51b6c5 100644
--- a/st.suckless.org/patches/ligatures/0.9/st-ligatures-alpha-20230105-0.9.diff
+++ b/st.suckless.org/patches/ligatures/0.9/st-ligatures-alpha-20240105-0.9.diff
@@ -43,10 +43,10 @@ index 47c615e..d7439a3 100644
  STCPPFLAGS = -DVERSION=\"$(VERSION)\" -D_XOPEN_SOURCE=600
 diff --git a/hb.c b/hb.c
 new file mode 100644
-index 0000000..528c040
+index 0000000..58d534b
 --- /dev/null
 +++ b/hb.c
-@@ -0,0 +1,124 @@
+@@ -0,0 +1,125 @@
 +#include <stdlib.h>
 +#include <stdio.h>
 +#include <math.h>
@@ -137,6 +137,7 @@ index 0000000..528c040
 +
 +      hb_buffer_t *buffer = hb_buffer_create();
 +      hb_buffer_set_direction(buffer, HB_DIRECTION_LTR);
++      hb_buffer_set_cluster_level(buffer, 
HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS);
 +
 +      /* Resize the buffer if required length is larger. */
 +      if (hbrunebuffer.capacity < length) {
@@ -173,7 +174,7 @@ index 0000000..528c040
 +}
 diff --git a/hb.h b/hb.h
 new file mode 100644
-index 0000000..88de9bd
+index 0000000..3b0ef44
 --- /dev/null
 +++ b/hb.h
 @@ -0,0 +1,14 @@
@@ -182,10 +183,10 @@ index 0000000..88de9bd
 +#include <hb-ft.h>
 +
 +typedef struct {
-+  hb_buffer_t *buffer;
-+  hb_glyph_info_t *glyphs;
-+  hb_glyph_position_t *positions;
-+  unsigned int count;
++      hb_buffer_t *buffer;
++      hb_glyph_info_t *glyphs;
++      hb_glyph_position_t *positions;
++      unsigned int count;
 +} HbTransformData;
 +
 +void hbunloadfonts();
@@ -233,7 +234,7 @@ index 6de960d..94679e4 100644
  void xfinishdraw(void);
  void xloadcols(void);
 diff --git a/x.c b/x.c
-index 27e81d1..9d84793 100644
+index 27e81d1..0632636 100644
 --- a/x.c
 +++ b/x.c
 @@ -19,6 +19,7 @@ char *argv0;
@@ -244,14 +245,17 @@ index 27e81d1..9d84793 100644
  
  /* types used in config.h */
  typedef struct {
-@@ -142,6 +143,7 @@ typedef struct {
+@@ -142,8 +143,9 @@ typedef struct {
  } DC;
  
  static inline ushort sixd_to_16bit(int);
 +static void xresetfontsettings(ushort mode, Font **font, int *frcflags);
  static int xmakeglyphfontspecs(XftGlyphFontSpec *, const Glyph *, int, int, 
int);
- static void xdrawglyphfontspecs(const XftGlyphFontSpec *, Glyph, int, int, 
int);
+-static void xdrawglyphfontspecs(const XftGlyphFontSpec *, Glyph, int, int, 
int);
++static void xdrawglyphfontspecs(const XftGlyphFontSpec *, Glyph, int, int, 
int, int);
  static void xdrawglyph(Glyph, int, int);
+ static void xclear(int, int, int, int);
+ static int xgeommasktogravity(int);
 @@ -759,7 +761,7 @@ xresize(int col, int row)
        xclear(0, 0, win.w, win.h);
  
@@ -303,13 +307,13 @@ index 27e81d1..9d84793 100644
  int
  xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, 
int x, int y)
  {
-@@ -1270,121 +1291,151 @@ xmakeglyphfontspecs(XftGlyphFontSpec *specs, const 
Glyph *glyphs, int len, int x
+@@ -1270,128 +1291,157 @@ xmakeglyphfontspecs(XftGlyphFontSpec *specs, const 
Glyph *glyphs, int len, int x
        FcPattern *fcpattern, *fontpattern;
        FcFontSet *fcsets[] = { NULL };
        FcCharSet *fccharset;
 -      int i, f, numspecs = 0;
 +      int i, f, length = 0, start = 0, numspecs = 0;
-+  float cluster_xp = xp, cluster_yp = yp;
++      float cluster_xp = xp, cluster_yp = yp;
 +      HbTransformData shaped = { 0 };
 +
 +      /* Initial values. */
@@ -357,7 +361,7 @@ index 27e81d1..9d84793 100644
                        }
 -                      yp = winy + font->ascent;
 -              }
--
+ 
 -              /* Lookup character index with default font. */
 -              glyphidx = XftCharIndex(xw.dpy, font->match, rune);
 -              if (glyphidx) {
@@ -369,7 +373,7 @@ index 27e81d1..9d84793 100644
 -                      numspecs++;
 -                      continue;
 -              }
- 
+-
 -              /* Fallback on font cache, search the font cache for match. */
 -              for (f = 0; f < frclen; f++) {
 -                      glyphidx = XftCharIndex(xw.dpy, frc[f].font, rune);
@@ -482,13 +486,16 @@ index 27e81d1..9d84793 100644
 +                              }
                        }
 -              }
--
+ 
 -              /* Nothing was found. Use fontconfig to find matching font. */
 -              if (f >= frclen) {
 -                      if (!font->set)
 -                              font->set = FcFontSort(0, font->pattern,
 -                                                     1, 0, &fcres);
 -                      fcsets[0] = font->set;
++                      /* Cleanup and get ready for next segment. */
++                      hbcleanup(&shaped);
++                      start = i;
  
 -                      /*
 -                       * Nothing was found in the cache. Now use
@@ -504,10 +511,7 @@ index 27e81d1..9d84793 100644
 -                      FcPatternAddCharSet(fcpattern, FC_CHARSET,
 -                                      fccharset);
 -                      FcPatternAddBool(fcpattern, FC_SCALABLE, 1);
-+                      /* Cleanup and get ready for next segment. */
-+                      hbcleanup(&shaped);
-+                      start = i;
- 
+-
 -                      FcConfigSubstitute(0, fcpattern,
 -                                      FcMatchPattern);
 -                      FcDefaultSubstitute(fcpattern);
@@ -555,7 +559,25 @@ index 27e81d1..9d84793 100644
        return numspecs;
  }
  
-@@ -1534,14 +1585,17 @@ xdrawglyph(Glyph g, int x, int y)
+ void
+-xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int 
x, int y)
++xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int 
x, int y, int charlen)
+ {
+-      int charlen = len * ((base.mode & ATTR_WIDE) ? 2 : 1);
+       int winx = borderpx + x * win.cw, winy = borderpx + y * win.ch,
+           width = charlen * win.cw;
+       Color *fg, *bg, *temp, revfg, revbg, truefg, truebg;
+@@ -1527,21 +1577,24 @@ void
+ xdrawglyph(Glyph g, int x, int y)
+ {
+       int numspecs;
+-      XftGlyphFontSpec spec;
++      XftGlyphFontSpec *specs = xw.specbuf;
+ 
+-      numspecs = xmakeglyphfontspecs(&spec, &g, 1, x, y);
+-      xdrawglyphfontspecs(&spec, g, numspecs, x, y);
++      numspecs = xmakeglyphfontspecs(specs, &g, 1, x, y);
++      xdrawglyphfontspecs(specs, g, numspecs, x, y, (g.mode & ATTR_WIDE) ? 2 
: 1);
  }
  
  void
@@ -575,7 +597,7 @@ index 27e81d1..9d84793 100644
  
        if (IS_SET(MODE_HIDE))
                return;
-@@ -1669,18 +1723,16 @@ xdrawline(Line line, int x1, int y1, int x2)
+@@ -1669,18 +1722,16 @@ xdrawline(Line line, int x1, int y1, int x2)
        Glyph base, new;
        XftGlyphFontSpec *specs = xw.specbuf;
  
@@ -594,11 +616,11 @@ index 27e81d1..9d84793 100644
 -                      numspecs -= i;
 +              if ((i > 0) && ATTRCMP(base, new)) {
 +                      numspecs = xmakeglyphfontspecs(specs, &line[ox], x - 
ox, ox, y1);
-+                      xdrawglyphfontspecs(specs, base, numspecs, ox, y1);
++                      xdrawglyphfontspecs(specs, base, numspecs, ox, y1, x - 
ox);
                        i = 0;
                }
                if (i == 0) {
-@@ -1689,8 +1741,10 @@ xdrawline(Line line, int x1, int y1, int x2)
+@@ -1689,8 +1740,10 @@ xdrawline(Line line, int x1, int y1, int x2)
                }
                i++;
        }
@@ -606,7 +628,7 @@ index 27e81d1..9d84793 100644
 -              xdrawglyphfontspecs(specs, base, i, ox, y1);
 +      if (i > 0) {
 +              numspecs = xmakeglyphfontspecs(specs, &line[ox], x2 - ox, ox, 
y1);
-+              xdrawglyphfontspecs(specs, base, numspecs, ox, y1);
++              xdrawglyphfontspecs(specs, base, numspecs, ox, y1, x2 - ox);
 +      }
  }
  
diff --git 
a/st.suckless.org/patches/ligatures/0.9/st-ligatures-alpha-scrollback-20230105-0.9.diff
 
b/st.suckless.org/patches/ligatures/0.9/st-ligatures-alpha-scrollback-20240105-0.9.diff
similarity index 90%
rename from 
st.suckless.org/patches/ligatures/0.9/st-ligatures-alpha-scrollback-20230105-0.9.diff
rename to 
st.suckless.org/patches/ligatures/0.9/st-ligatures-alpha-scrollback-20240105-0.9.diff
index 688cc6b5..09e9819f 100644
--- 
a/st.suckless.org/patches/ligatures/0.9/st-ligatures-alpha-scrollback-20230105-0.9.diff
+++ 
b/st.suckless.org/patches/ligatures/0.9/st-ligatures-alpha-scrollback-20240105-0.9.diff
@@ -43,10 +43,10 @@ index 47c615e..d7439a3 100644
  STCPPFLAGS = -DVERSION=\"$(VERSION)\" -D_XOPEN_SOURCE=600
 diff --git a/hb.c b/hb.c
 new file mode 100644
-index 0000000..528c040
+index 0000000..99412c8
 --- /dev/null
 +++ b/hb.c
-@@ -0,0 +1,124 @@
+@@ -0,0 +1,125 @@
 +#include <stdlib.h>
 +#include <stdio.h>
 +#include <math.h>
@@ -137,6 +137,7 @@ index 0000000..528c040
 +
 +      hb_buffer_t *buffer = hb_buffer_create();
 +      hb_buffer_set_direction(buffer, HB_DIRECTION_LTR);
++      hb_buffer_set_cluster_level(buffer, 
HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS);
 +
 +      /* Resize the buffer if required length is larger. */
 +      if (hbrunebuffer.capacity < length) {
@@ -173,7 +174,7 @@ index 0000000..528c040
 +}
 diff --git a/hb.h b/hb.h
 new file mode 100644
-index 0000000..88de9bd
+index 0000000..3b0ef44
 --- /dev/null
 +++ b/hb.h
 @@ -0,0 +1,14 @@
@@ -182,10 +183,10 @@ index 0000000..88de9bd
 +#include <hb-ft.h>
 +
 +typedef struct {
-+  hb_buffer_t *buffer;
-+  hb_glyph_info_t *glyphs;
-+  hb_glyph_position_t *positions;
-+  unsigned int count;
++      hb_buffer_t *buffer;
++      hb_glyph_info_t *glyphs;
++      hb_glyph_position_t *positions;
++      unsigned int count;
 +} HbTransformData;
 +
 +void hbunloadfonts();
@@ -234,7 +235,7 @@ index 6de960d..94679e4 100644
  void xfinishdraw(void);
  void xloadcols(void);
 diff --git a/x.c b/x.c
-index 27e81d1..5d19ed7 100644
+index 27e81d1..5e11c1f 100644
 --- a/x.c
 +++ b/x.c
 @@ -19,6 +19,7 @@ char *argv0;
@@ -245,14 +246,17 @@ index 27e81d1..5d19ed7 100644
  
  /* types used in config.h */
  typedef struct {
-@@ -142,6 +143,7 @@ typedef struct {
+@@ -142,8 +143,9 @@ typedef struct {
  } DC;
  
  static inline ushort sixd_to_16bit(int);
 +static void xresetfontsettings(ushort mode, Font **font, int *frcflags);
  static int xmakeglyphfontspecs(XftGlyphFontSpec *, const Glyph *, int, int, 
int);
- static void xdrawglyphfontspecs(const XftGlyphFontSpec *, Glyph, int, int, 
int);
+-static void xdrawglyphfontspecs(const XftGlyphFontSpec *, Glyph, int, int, 
int);
++static void xdrawglyphfontspecs(const XftGlyphFontSpec *, Glyph, int, int, 
int, int);
  static void xdrawglyph(Glyph, int, int);
+ static void xclear(int, int, int, int);
+ static int xgeommasktogravity(int);
 @@ -759,7 +761,7 @@ xresize(int col, int row)
        xclear(0, 0, win.w, win.h);
  
@@ -304,13 +308,13 @@ index 27e81d1..5d19ed7 100644
  int
  xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, 
int x, int y)
  {
-@@ -1270,119 +1291,148 @@ xmakeglyphfontspecs(XftGlyphFontSpec *specs, const 
Glyph *glyphs, int len, int x
+@@ -1270,128 +1291,156 @@ xmakeglyphfontspecs(XftGlyphFontSpec *specs, const 
Glyph *glyphs, int len, int x
        FcPattern *fcpattern, *fontpattern;
        FcFontSet *fcsets[] = { NULL };
        FcCharSet *fccharset;
 -      int i, f, numspecs = 0;
 +      int i, f, length = 0, start = 0, numspecs = 0;
-+  float cluster_xp = xp, cluster_yp = yp;
++      float cluster_xp = xp, cluster_yp = yp;
 +      HbTransformData shaped = { 0 };
 +
 +      /* Initial values. */
@@ -358,7 +362,7 @@ index 27e81d1..5d19ed7 100644
                        }
 -                      yp = winy + font->ascent;
 -              }
--
+ 
 -              /* Lookup character index with default font. */
 -              glyphidx = XftCharIndex(xw.dpy, font->match, rune);
 -              if (glyphidx) {
@@ -370,7 +374,7 @@ index 27e81d1..5d19ed7 100644
 -                      numspecs++;
 -                      continue;
 -              }
- 
+-
 -              /* Fallback on font cache, search the font cache for match. */
 -              for (f = 0; f < frclen; f++) {
 -                      glyphidx = XftCharIndex(xw.dpy, frc[f].font, rune);
@@ -483,13 +487,16 @@ index 27e81d1..5d19ed7 100644
 +                              }
                        }
 -              }
--
+ 
 -              /* Nothing was found. Use fontconfig to find matching font. */
 -              if (f >= frclen) {
 -                      if (!font->set)
 -                              font->set = FcFontSort(0, font->pattern,
 -                                                     1, 0, &fcres);
 -                      fcsets[0] = font->set;
++                      /* Cleanup and get ready for next segment. */
++                      hbcleanup(&shaped);
++                      start = i;
  
 -                      /*
 -                       * Nothing was found in the cache. Now use
@@ -505,10 +512,7 @@ index 27e81d1..5d19ed7 100644
 -                      FcPatternAddCharSet(fcpattern, FC_CHARSET,
 -                                      fccharset);
 -                      FcPatternAddBool(fcpattern, FC_SCALABLE, 1);
-+                      /* Cleanup and get ready for next segment. */
-+                      hbcleanup(&shaped);
-+                      start = i;
- 
+-
 -                      FcConfigSubstitute(0, fcpattern,
 -                                      FcMatchPattern);
 -                      FcDefaultSubstitute(fcpattern);
@@ -553,7 +557,27 @@ index 27e81d1..5d19ed7 100644
        }
  
        return numspecs;
-@@ -1534,14 +1584,17 @@ xdrawglyph(Glyph g, int x, int y)
+ }
+ 
+ void
+-xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int 
x, int y)
++xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int 
x, int y, int charlen)
+ {
+-      int charlen = len * ((base.mode & ATTR_WIDE) ? 2 : 1);
+       int winx = borderpx + x * win.cw, winy = borderpx + y * win.ch,
+           width = charlen * win.cw;
+       Color *fg, *bg, *temp, revfg, revbg, truefg, truebg;
+@@ -1527,21 +1576,24 @@ void
+ xdrawglyph(Glyph g, int x, int y)
+ {
+       int numspecs;
+-      XftGlyphFontSpec spec;
++      XftGlyphFontSpec *specs = xw.specbuf;
+ 
+-      numspecs = xmakeglyphfontspecs(&spec, &g, 1, x, y);
+-      xdrawglyphfontspecs(&spec, g, numspecs, x, y);
++      numspecs = xmakeglyphfontspecs(specs, &g, 1, x, y);
++      xdrawglyphfontspecs(specs, g, numspecs, x, y, (g.mode & ATTR_WIDE) ? 2 
: 1);
  }
  
  void
@@ -573,7 +597,7 @@ index 27e81d1..5d19ed7 100644
  
        if (IS_SET(MODE_HIDE))
                return;
-@@ -1669,18 +1722,16 @@ xdrawline(Line line, int x1, int y1, int x2)
+@@ -1669,18 +1721,16 @@ xdrawline(Line line, int x1, int y1, int x2)
        Glyph base, new;
        XftGlyphFontSpec *specs = xw.specbuf;
  
@@ -592,11 +616,11 @@ index 27e81d1..5d19ed7 100644
 -                      numspecs -= i;
 +              if ((i > 0) && ATTRCMP(base, new)) {
 +                      numspecs = xmakeglyphfontspecs(specs, &line[ox], x - 
ox, ox, y1);
-+                      xdrawglyphfontspecs(specs, base, numspecs, ox, y1);
++                      xdrawglyphfontspecs(specs, base, numspecs, ox, y1, x - 
ox);
                        i = 0;
                }
                if (i == 0) {
-@@ -1689,8 +1740,10 @@ xdrawline(Line line, int x1, int y1, int x2)
+@@ -1689,8 +1739,10 @@ xdrawline(Line line, int x1, int y1, int x2)
                }
                i++;
        }
@@ -604,7 +628,7 @@ index 27e81d1..5d19ed7 100644
 -              xdrawglyphfontspecs(specs, base, i, ox, y1);
 +      if (i > 0) {
 +              numspecs = xmakeglyphfontspecs(specs, &line[ox], x2 - ox, ox, 
y1);
-+              xdrawglyphfontspecs(specs, base, numspecs, ox, y1);
++              xdrawglyphfontspecs(specs, base, numspecs, ox, y1, x2 - ox);
 +      }
  }
  
diff --git 
a/st.suckless.org/patches/ligatures/0.9/st-ligatures-alpha-scrollback-ringbuffer-20230105-0.9.diff
 
b/st.suckless.org/patches/ligatures/0.9/st-ligatures-alpha-scrollback-ringbuffer-20240105-0.9.diff
similarity index 89%
rename from 
st.suckless.org/patches/ligatures/0.9/st-ligatures-alpha-scrollback-ringbuffer-20230105-0.9.diff
rename to 
st.suckless.org/patches/ligatures/0.9/st-ligatures-alpha-scrollback-ringbuffer-20240105-0.9.diff
index 600a18d5..ae7da80a 100644
--- 
a/st.suckless.org/patches/ligatures/0.9/st-ligatures-alpha-scrollback-ringbuffer-20230105-0.9.diff
+++ 
b/st.suckless.org/patches/ligatures/0.9/st-ligatures-alpha-scrollback-ringbuffer-20240105-0.9.diff
@@ -43,10 +43,10 @@ index 47c615e..d7439a3 100644
  STCPPFLAGS = -DVERSION=\"$(VERSION)\" -D_XOPEN_SOURCE=600
 diff --git a/hb.c b/hb.c
 new file mode 100644
-index 0000000..528c040
+index 0000000..99412c8
 --- /dev/null
 +++ b/hb.c
-@@ -0,0 +1,124 @@
+@@ -0,0 +1,125 @@
 +#include <stdlib.h>
 +#include <stdio.h>
 +#include <math.h>
@@ -137,6 +137,7 @@ index 0000000..528c040
 +
 +      hb_buffer_t *buffer = hb_buffer_create();
 +      hb_buffer_set_direction(buffer, HB_DIRECTION_LTR);
++      hb_buffer_set_cluster_level(buffer, 
HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS);
 +
 +      /* Resize the buffer if required length is larger. */
 +      if (hbrunebuffer.capacity < length) {
@@ -173,7 +174,7 @@ index 0000000..528c040
 +}
 diff --git a/hb.h b/hb.h
 new file mode 100644
-index 0000000..88de9bd
+index 0000000..3b0ef44
 --- /dev/null
 +++ b/hb.h
 @@ -0,0 +1,14 @@
@@ -182,20 +183,20 @@ index 0000000..88de9bd
 +#include <hb-ft.h>
 +
 +typedef struct {
-+  hb_buffer_t *buffer;
-+  hb_glyph_info_t *glyphs;
-+  hb_glyph_position_t *positions;
-+  unsigned int count;
++      hb_buffer_t *buffer;
++      hb_glyph_info_t *glyphs;
++      hb_glyph_position_t *positions;
++      unsigned int count;
 +} HbTransformData;
 +
 +void hbunloadfonts();
 +void hbtransform(HbTransformData *, XftFont *, const Glyph *, int, int);
 +void hbcleanup(HbTransformData *);
 diff --git a/st.c b/st.c
-index 79ee9ba..454771d 100644
+index c44797b..18aa1bf 100644
 --- a/st.c
 +++ b/st.c
-@@ -2711,7 +2711,9 @@ draw(void)
+@@ -2759,7 +2759,9 @@ draw(void)
        drawregion(0, 0, term.col, term.row);
        if (TSCREEN.off == 0)
                xdrawcursor(cx, term.c.y, TLINE(term.c.y)[cx],
@@ -207,7 +208,7 @@ index 79ee9ba..454771d 100644
        term.ocy = term.c.y;
        xfinishdraw();
 diff --git a/st.h b/st.h
-index 78762a2..01eea49 100644
+index 073851a..d0b071d 100644
 --- a/st.h
 +++ b/st.h
 @@ -11,7 +11,8 @@
@@ -234,7 +235,7 @@ index 6de960d..94679e4 100644
  void xfinishdraw(void);
  void xloadcols(void);
 diff --git a/x.c b/x.c
-index 27e81d1..5d19ed7 100644
+index b81f5be..c1611bb 100644
 --- a/x.c
 +++ b/x.c
 @@ -19,6 +19,7 @@ char *argv0;
@@ -245,15 +246,18 @@ index 27e81d1..5d19ed7 100644
  
  /* types used in config.h */
  typedef struct {
-@@ -142,6 +143,7 @@ typedef struct {
+@@ -144,8 +145,9 @@ typedef struct {
  } DC;
  
  static inline ushort sixd_to_16bit(int);
 +static void xresetfontsettings(ushort mode, Font **font, int *frcflags);
  static int xmakeglyphfontspecs(XftGlyphFontSpec *, const Glyph *, int, int, 
int);
- static void xdrawglyphfontspecs(const XftGlyphFontSpec *, Glyph, int, int, 
int);
+-static void xdrawglyphfontspecs(const XftGlyphFontSpec *, Glyph, int, int, 
int);
++static void xdrawglyphfontspecs(const XftGlyphFontSpec *, Glyph, int, int, 
int, int);
  static void xdrawglyph(Glyph, int, int);
-@@ -759,7 +761,7 @@ xresize(int col, int row)
+ static void xclear(int, int, int, int);
+ static int xgeommasktogravity(int);
+@@ -761,7 +763,7 @@ xresize(int col, int row)
        xclear(0, 0, win.w, win.h);
  
        /* resize to new width */
@@ -262,7 +266,7 @@ index 27e81d1..5d19ed7 100644
  }
  
  ushort
-@@ -1071,6 +1073,9 @@ xunloadfont(Font *f)
+@@ -1073,6 +1075,9 @@ xunloadfont(Font *f)
  void
  xunloadfonts(void)
  {
@@ -272,7 +276,7 @@ index 27e81d1..5d19ed7 100644
        /* Free the loaded fonts in the font cache.  */
        while (frclen > 0)
                XftFontClose(xw.dpy, frc[--frclen].font);
-@@ -1202,7 +1207,7 @@ xinit(int cols, int rows)
+@@ -1204,7 +1209,7 @@ xinit(int cols, int rows)
        XFillRectangle(xw.dpy, xw.buf, dc.gc, 0, 0, win.w, win.h);
  
        /* font spec buffer */
@@ -281,7 +285,7 @@ index 27e81d1..5d19ed7 100644
  
        /* Xft rendering context */
        xw.draw = XftDrawCreate(xw.dpy, xw.buf, xw.vis, xw.cmap);
-@@ -1256,6 +1261,22 @@ xinit(int cols, int rows)
+@@ -1258,6 +1263,22 @@ xinit(int cols, int rows)
                xsel.xtarget = XA_STRING;
  }
  
@@ -304,13 +308,13 @@ index 27e81d1..5d19ed7 100644
  int
  xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, 
int x, int y)
  {
-@@ -1270,119 +1291,148 @@ xmakeglyphfontspecs(XftGlyphFontSpec *specs, const 
Glyph *glyphs, int len, int x
+@@ -1272,128 +1293,156 @@ xmakeglyphfontspecs(XftGlyphFontSpec *specs, const 
Glyph *glyphs, int len, int x
        FcPattern *fcpattern, *fontpattern;
        FcFontSet *fcsets[] = { NULL };
        FcCharSet *fccharset;
 -      int i, f, numspecs = 0;
 +      int i, f, length = 0, start = 0, numspecs = 0;
-+  float cluster_xp = xp, cluster_yp = yp;
++      float cluster_xp = xp, cluster_yp = yp;
 +      HbTransformData shaped = { 0 };
 +
 +      /* Initial values. */
@@ -358,7 +362,7 @@ index 27e81d1..5d19ed7 100644
                        }
 -                      yp = winy + font->ascent;
 -              }
--
+ 
 -              /* Lookup character index with default font. */
 -              glyphidx = XftCharIndex(xw.dpy, font->match, rune);
 -              if (glyphidx) {
@@ -370,7 +374,7 @@ index 27e81d1..5d19ed7 100644
 -                      numspecs++;
 -                      continue;
 -              }
- 
+-
 -              /* Fallback on font cache, search the font cache for match. */
 -              for (f = 0; f < frclen; f++) {
 -                      glyphidx = XftCharIndex(xw.dpy, frc[f].font, rune);
@@ -483,13 +487,16 @@ index 27e81d1..5d19ed7 100644
 +                              }
                        }
 -              }
--
+ 
 -              /* Nothing was found. Use fontconfig to find matching font. */
 -              if (f >= frclen) {
 -                      if (!font->set)
 -                              font->set = FcFontSort(0, font->pattern,
 -                                                     1, 0, &fcres);
 -                      fcsets[0] = font->set;
++                      /* Cleanup and get ready for next segment. */
++                      hbcleanup(&shaped);
++                      start = i;
  
 -                      /*
 -                       * Nothing was found in the cache. Now use
@@ -505,10 +512,7 @@ index 27e81d1..5d19ed7 100644
 -                      FcPatternAddCharSet(fcpattern, FC_CHARSET,
 -                                      fccharset);
 -                      FcPatternAddBool(fcpattern, FC_SCALABLE, 1);
-+                      /* Cleanup and get ready for next segment. */
-+                      hbcleanup(&shaped);
-+                      start = i;
- 
+-
 -                      FcConfigSubstitute(0, fcpattern,
 -                                      FcMatchPattern);
 -                      FcDefaultSubstitute(fcpattern);
@@ -553,7 +557,27 @@ index 27e81d1..5d19ed7 100644
        }
  
        return numspecs;
-@@ -1534,14 +1584,17 @@ xdrawglyph(Glyph g, int x, int y)
+ }
+ 
+ void
+-xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int 
x, int y)
++xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int 
x, int y, int charlen)
+ {
+-      int charlen = len * ((base.mode & ATTR_WIDE) ? 2 : 1);
+       int winx = borderpx + x * win.cw, winy = borderpx + y * win.ch,
+           width = charlen * win.cw;
+       Color *fg, *bg, *temp, revfg, revbg, truefg, truebg;
+@@ -1529,21 +1578,24 @@ void
+ xdrawglyph(Glyph g, int x, int y)
+ {
+       int numspecs;
+-      XftGlyphFontSpec spec;
++      XftGlyphFontSpec *specs = xw.specbuf;
+ 
+-      numspecs = xmakeglyphfontspecs(&spec, &g, 1, x, y);
+-      xdrawglyphfontspecs(&spec, g, numspecs, x, y);
++      numspecs = xmakeglyphfontspecs(specs, &g, 1, x, y);
++      xdrawglyphfontspecs(specs, g, numspecs, x, y, (g.mode & ATTR_WIDE) ? 2 
: 1);
  }
  
  void
@@ -573,7 +597,7 @@ index 27e81d1..5d19ed7 100644
  
        if (IS_SET(MODE_HIDE))
                return;
-@@ -1669,18 +1722,16 @@ xdrawline(Line line, int x1, int y1, int x2)
+@@ -1671,18 +1723,16 @@ xdrawline(Line line, int x1, int y1, int x2)
        Glyph base, new;
        XftGlyphFontSpec *specs = xw.specbuf;
  
@@ -592,11 +616,11 @@ index 27e81d1..5d19ed7 100644
 -                      numspecs -= i;
 +              if ((i > 0) && ATTRCMP(base, new)) {
 +                      numspecs = xmakeglyphfontspecs(specs, &line[ox], x - 
ox, ox, y1);
-+                      xdrawglyphfontspecs(specs, base, numspecs, ox, y1);
++                      xdrawglyphfontspecs(specs, base, numspecs, ox, y1, x - 
ox);
                        i = 0;
                }
                if (i == 0) {
-@@ -1689,8 +1740,10 @@ xdrawline(Line line, int x1, int y1, int x2)
+@@ -1691,8 +1741,10 @@ xdrawline(Line line, int x1, int y1, int x2)
                }
                i++;
        }
@@ -604,7 +628,7 @@ index 27e81d1..5d19ed7 100644
 -              xdrawglyphfontspecs(specs, base, i, ox, y1);
 +      if (i > 0) {
 +              numspecs = xmakeglyphfontspecs(specs, &line[ox], x2 - ox, ox, 
y1);
-+              xdrawglyphfontspecs(specs, base, numspecs, ox, y1);
++              xdrawglyphfontspecs(specs, base, numspecs, ox, y1, x2 - ox);
 +      }
  }
  
diff --git 
a/st.suckless.org/patches/ligatures/0.9/st-ligatures-boxdraw-20230105-0.9.diff 
b/st.suckless.org/patches/ligatures/0.9/st-ligatures-boxdraw-20240105-0.9.diff
similarity index 91%
rename from 
st.suckless.org/patches/ligatures/0.9/st-ligatures-boxdraw-20230105-0.9.diff
rename to 
st.suckless.org/patches/ligatures/0.9/st-ligatures-boxdraw-20240105-0.9.diff
index 31c91740..4f62f432 100644
--- 
a/st.suckless.org/patches/ligatures/0.9/st-ligatures-boxdraw-20230105-0.9.diff
+++ 
b/st.suckless.org/patches/ligatures/0.9/st-ligatures-boxdraw-20240105-0.9.diff
@@ -43,10 +43,10 @@ index 1e306f8..3e13e53 100644
  STCPPFLAGS = -DVERSION=\"$(VERSION)\" -D_XOPEN_SOURCE=600
 diff --git a/hb.c b/hb.c
 new file mode 100644
-index 0000000..528c040
+index 0000000..99412c8
 --- /dev/null
 +++ b/hb.c
-@@ -0,0 +1,124 @@
+@@ -0,0 +1,125 @@
 +#include <stdlib.h>
 +#include <stdio.h>
 +#include <math.h>
@@ -137,6 +137,7 @@ index 0000000..528c040
 +
 +      hb_buffer_t *buffer = hb_buffer_create();
 +      hb_buffer_set_direction(buffer, HB_DIRECTION_LTR);
++      hb_buffer_set_cluster_level(buffer, 
HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS);
 +
 +      /* Resize the buffer if required length is larger. */
 +      if (hbrunebuffer.capacity < length) {
@@ -173,7 +174,7 @@ index 0000000..528c040
 +}
 diff --git a/hb.h b/hb.h
 new file mode 100644
-index 0000000..88de9bd
+index 0000000..3b0ef44
 --- /dev/null
 +++ b/hb.h
 @@ -0,0 +1,14 @@
@@ -182,10 +183,10 @@ index 0000000..88de9bd
 +#include <hb-ft.h>
 +
 +typedef struct {
-+  hb_buffer_t *buffer;
-+  hb_glyph_info_t *glyphs;
-+  hb_glyph_position_t *positions;
-+  unsigned int count;
++      hb_buffer_t *buffer;
++      hb_glyph_info_t *glyphs;
++      hb_glyph_position_t *positions;
++      unsigned int count;
 +} HbTransformData;
 +
 +void hbunloadfonts();
@@ -233,7 +234,7 @@ index 6de960d..94679e4 100644
  void xfinishdraw(void);
  void xloadcols(void);
 diff --git a/x.c b/x.c
-index bf6bbf9..929a59a 100644
+index bf6bbf9..96b117f 100644
 --- a/x.c
 +++ b/x.c
 @@ -19,6 +19,7 @@ char *argv0;
@@ -244,14 +245,17 @@ index bf6bbf9..929a59a 100644
  
  /* types used in config.h */
  typedef struct {
-@@ -141,6 +142,7 @@ typedef struct {
+@@ -141,8 +142,9 @@ typedef struct {
  } DC;
  
  static inline ushort sixd_to_16bit(int);
 +static void xresetfontsettings(ushort mode, Font **font, int *frcflags);
  static int xmakeglyphfontspecs(XftGlyphFontSpec *, const Glyph *, int, int, 
int);
- static void xdrawglyphfontspecs(const XftGlyphFontSpec *, Glyph, int, int, 
int);
+-static void xdrawglyphfontspecs(const XftGlyphFontSpec *, Glyph, int, int, 
int);
++static void xdrawglyphfontspecs(const XftGlyphFontSpec *, Glyph, int, int, 
int, int);
  static void xdrawglyph(Glyph, int, int);
+ static void xclear(int, int, int, int);
+ static int xgeommasktogravity(int);
 @@ -757,7 +759,7 @@ xresize(int col, int row)
        xclear(0, 0, win.w, win.h);
  
@@ -303,7 +307,7 @@ index bf6bbf9..929a59a 100644
  int
  xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, 
int x, int y)
  {
-@@ -1255,126 +1276,158 @@ xmakeglyphfontspecs(XftGlyphFontSpec *specs, const 
Glyph *glyphs, int len, int x
+@@ -1255,133 +1276,164 @@ xmakeglyphfontspecs(XftGlyphFontSpec *specs, const 
Glyph *glyphs, int len, int x
        FcPattern *fcpattern, *fontpattern;
        FcFontSet *fcsets[] = { NULL };
        FcCharSet *fccharset;
@@ -567,7 +571,25 @@ index bf6bbf9..929a59a 100644
        return numspecs;
  }
  
-@@ -1528,14 +1581,17 @@ xdrawglyph(Glyph g, int x, int y)
+ void
+-xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int 
x, int y)
++xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int 
x, int y, int charlen)
+ {
+-      int charlen = len * ((base.mode & ATTR_WIDE) ? 2 : 1);
+       int winx = borderpx + x * win.cw, winy = borderpx + y * win.ch,
+           width = charlen * win.cw;
+       Color *fg, *bg, *temp, revfg, revbg, truefg, truebg;
+@@ -1521,21 +1573,24 @@ void
+ xdrawglyph(Glyph g, int x, int y)
+ {
+       int numspecs;
+-      XftGlyphFontSpec spec;
++      XftGlyphFontSpec *specs = xw.specbuf;
+ 
+-      numspecs = xmakeglyphfontspecs(&spec, &g, 1, x, y);
+-      xdrawglyphfontspecs(&spec, g, numspecs, x, y);
++      numspecs = xmakeglyphfontspecs(specs, &g, 1, x, y);
++      xdrawglyphfontspecs(specs, g, numspecs, x, y, (g.mode & ATTR_WIDE) ? 2 
: 1);
  }
  
  void
@@ -587,7 +609,7 @@ index bf6bbf9..929a59a 100644
  
        if (IS_SET(MODE_HIDE))
                return;
-@@ -1663,18 +1719,16 @@ xdrawline(Line line, int x1, int y1, int x2)
+@@ -1663,18 +1718,16 @@ xdrawline(Line line, int x1, int y1, int x2)
        Glyph base, new;
        XftGlyphFontSpec *specs = xw.specbuf;
  
@@ -606,11 +628,11 @@ index bf6bbf9..929a59a 100644
 -                      numspecs -= i;
 +              if ((i > 0) && ATTRCMP(base, new)) {
 +                      numspecs = xmakeglyphfontspecs(specs, &line[ox], x - 
ox, ox, y1);
-+                      xdrawglyphfontspecs(specs, base, numspecs, ox, y1);
++                      xdrawglyphfontspecs(specs, base, numspecs, ox, y1, x - 
ox);
                        i = 0;
                }
                if (i == 0) {
-@@ -1683,8 +1737,10 @@ xdrawline(Line line, int x1, int y1, int x2)
+@@ -1683,8 +1736,10 @@ xdrawline(Line line, int x1, int y1, int x2)
                }
                i++;
        }
@@ -618,7 +640,7 @@ index bf6bbf9..929a59a 100644
 -              xdrawglyphfontspecs(specs, base, i, ox, y1);
 +      if (i > 0) {
 +              numspecs = xmakeglyphfontspecs(specs, &line[ox], x2 - ox, ox, 
y1);
-+              xdrawglyphfontspecs(specs, base, numspecs, ox, y1);
++              xdrawglyphfontspecs(specs, base, numspecs, ox, y1, x2 - ox);
 +      }
  }
  
diff --git 
a/st.suckless.org/patches/ligatures/0.9/st-ligatures-scrollback-20230105-0.9.diff
 
b/st.suckless.org/patches/ligatures/0.9/st-ligatures-scrollback-20240105-0.9.diff
similarity index 91%
rename from 
st.suckless.org/patches/ligatures/0.9/st-ligatures-scrollback-20230105-0.9.diff
rename to 
st.suckless.org/patches/ligatures/0.9/st-ligatures-scrollback-20240105-0.9.diff
index 8f72dd95..3c21dfc3 100644
--- 
a/st.suckless.org/patches/ligatures/0.9/st-ligatures-scrollback-20230105-0.9.diff
+++ 
b/st.suckless.org/patches/ligatures/0.9/st-ligatures-scrollback-20240105-0.9.diff
@@ -42,10 +42,10 @@ index 1e306f8..3e13e53 100644
  STCPPFLAGS = -DVERSION=\"$(VERSION)\" -D_XOPEN_SOURCE=600
 diff --git a/hb.c b/hb.c
 new file mode 100644
-index 0000000..528c040
+index 0000000..99412c8
 --- /dev/null
 +++ b/hb.c
-@@ -0,0 +1,124 @@
+@@ -0,0 +1,125 @@
 +#include <stdlib.h>
 +#include <stdio.h>
 +#include <math.h>
@@ -136,6 +136,7 @@ index 0000000..528c040
 +
 +      hb_buffer_t *buffer = hb_buffer_create();
 +      hb_buffer_set_direction(buffer, HB_DIRECTION_LTR);
++      hb_buffer_set_cluster_level(buffer, 
HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS);
 +
 +      /* Resize the buffer if required length is larger. */
 +      if (hbrunebuffer.capacity < length) {
@@ -172,7 +173,7 @@ index 0000000..528c040
 +}
 diff --git a/hb.h b/hb.h
 new file mode 100644
-index 0000000..88de9bd
+index 0000000..3b0ef44
 --- /dev/null
 +++ b/hb.h
 @@ -0,0 +1,14 @@
@@ -181,10 +182,10 @@ index 0000000..88de9bd
 +#include <hb-ft.h>
 +
 +typedef struct {
-+  hb_buffer_t *buffer;
-+  hb_glyph_info_t *glyphs;
-+  hb_glyph_position_t *positions;
-+  unsigned int count;
++      hb_buffer_t *buffer;
++      hb_glyph_info_t *glyphs;
++      hb_glyph_position_t *positions;
++      unsigned int count;
 +} HbTransformData;
 +
 +void hbunloadfonts();
@@ -232,7 +233,7 @@ index 6de960d..94679e4 100644
  void xfinishdraw(void);
  void xloadcols(void);
 diff --git a/x.c b/x.c
-index 2a3bd38..e66cf0c 100644
+index 2a3bd38..0bb51ff 100644
 --- a/x.c
 +++ b/x.c
 @@ -19,6 +19,7 @@ char *argv0;
@@ -243,14 +244,17 @@ index 2a3bd38..e66cf0c 100644
  
  /* types used in config.h */
  typedef struct {
-@@ -141,6 +142,7 @@ typedef struct {
+@@ -141,8 +142,9 @@ typedef struct {
  } DC;
  
  static inline ushort sixd_to_16bit(int);
 +static void xresetfontsettings(ushort mode, Font **font, int *frcflags);
  static int xmakeglyphfontspecs(XftGlyphFontSpec *, const Glyph *, int, int, 
int);
- static void xdrawglyphfontspecs(const XftGlyphFontSpec *, Glyph, int, int, 
int);
+-static void xdrawglyphfontspecs(const XftGlyphFontSpec *, Glyph, int, int, 
int);
++static void xdrawglyphfontspecs(const XftGlyphFontSpec *, Glyph, int, int, 
int, int);
  static void xdrawglyph(Glyph, int, int);
+ static void xclear(int, int, int, int);
+ static int xgeommasktogravity(int);
 @@ -757,7 +759,7 @@ xresize(int col, int row)
        xclear(0, 0, win.w, win.h);
  
@@ -302,7 +306,7 @@ index 2a3bd38..e66cf0c 100644
  int
  xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, 
int x, int y)
  {
-@@ -1253,121 +1274,151 @@ xmakeglyphfontspecs(XftGlyphFontSpec *specs, const 
Glyph *glyphs, int len, int x
+@@ -1253,128 +1274,157 @@ xmakeglyphfontspecs(XftGlyphFontSpec *specs, const 
Glyph *glyphs, int len, int x
        FcPattern *fcpattern, *fontpattern;
        FcFontSet *fcsets[] = { NULL };
        FcCharSet *fccharset;
@@ -356,7 +360,7 @@ index 2a3bd38..e66cf0c 100644
                        }
 -                      yp = winy + font->ascent;
 -              }
--
+ 
 -              /* Lookup character index with default font. */
 -              glyphidx = XftCharIndex(xw.dpy, font->match, rune);
 -              if (glyphidx) {
@@ -368,7 +372,7 @@ index 2a3bd38..e66cf0c 100644
 -                      numspecs++;
 -                      continue;
 -              }
- 
+-
 -              /* Fallback on font cache, search the font cache for match. */
 -              for (f = 0; f < frclen; f++) {
 -                      glyphidx = XftCharIndex(xw.dpy, frc[f].font, rune);
@@ -481,13 +485,16 @@ index 2a3bd38..e66cf0c 100644
 +                              }
                        }
 -              }
--
+ 
 -              /* Nothing was found. Use fontconfig to find matching font. */
 -              if (f >= frclen) {
 -                      if (!font->set)
 -                              font->set = FcFontSort(0, font->pattern,
 -                                                     1, 0, &fcres);
 -                      fcsets[0] = font->set;
++                      /* Cleanup and get ready for next segment. */
++                      hbcleanup(&shaped);
++                      start = i;
  
 -                      /*
 -                       * Nothing was found in the cache. Now use
@@ -503,10 +510,7 @@ index 2a3bd38..e66cf0c 100644
 -                      FcPatternAddCharSet(fcpattern, FC_CHARSET,
 -                                      fccharset);
 -                      FcPatternAddBool(fcpattern, FC_SCALABLE, 1);
-+                      /* Cleanup and get ready for next segment. */
-+                      hbcleanup(&shaped);
-+                      start = i;
- 
+-
 -                      FcConfigSubstitute(0, fcpattern,
 -                                      FcMatchPattern);
 -                      FcDefaultSubstitute(fcpattern);
@@ -554,7 +558,25 @@ index 2a3bd38..e66cf0c 100644
        return numspecs;
  }
  
-@@ -1517,14 +1568,17 @@ xdrawglyph(Glyph g, int x, int y)
+ void
+-xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int 
x, int y)
++xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int 
x, int y, int charlen)
+ {
+-      int charlen = len * ((base.mode & ATTR_WIDE) ? 2 : 1);
+       int winx = borderpx + x * win.cw, winy = borderpx + y * win.ch,
+           width = charlen * win.cw;
+       Color *fg, *bg, *temp, revfg, revbg, truefg, truebg;
+@@ -1510,21 +1560,24 @@ void
+ xdrawglyph(Glyph g, int x, int y)
+ {
+       int numspecs;
+-      XftGlyphFontSpec spec;
++      XftGlyphFontSpec *specs = xw.specbuf;
+ 
+-      numspecs = xmakeglyphfontspecs(&spec, &g, 1, x, y);
+-      xdrawglyphfontspecs(&spec, g, numspecs, x, y);
++      numspecs = xmakeglyphfontspecs(specs, &g, 1, x, y);
++      xdrawglyphfontspecs(specs, g, numspecs, x, y, (g.mode & ATTR_WIDE) ? 2 
: 1);
  }
  
  void
@@ -574,7 +596,7 @@ index 2a3bd38..e66cf0c 100644
  
        if (IS_SET(MODE_HIDE))
                return;
-@@ -1652,18 +1706,16 @@ xdrawline(Line line, int x1, int y1, int x2)
+@@ -1652,18 +1705,16 @@ xdrawline(Line line, int x1, int y1, int x2)
        Glyph base, new;
        XftGlyphFontSpec *specs = xw.specbuf;
  
@@ -593,11 +615,11 @@ index 2a3bd38..e66cf0c 100644
 -                      numspecs -= i;
 +              if ((i > 0) && ATTRCMP(base, new)) {
 +                      numspecs = xmakeglyphfontspecs(specs, &line[ox], x - 
ox, ox, y1);
-+                      xdrawglyphfontspecs(specs, base, numspecs, ox, y1);
++                      xdrawglyphfontspecs(specs, base, numspecs, ox, y1, x - 
ox);
                        i = 0;
                }
                if (i == 0) {
-@@ -1672,8 +1724,10 @@ xdrawline(Line line, int x1, int y1, int x2)
+@@ -1672,8 +1723,10 @@ xdrawline(Line line, int x1, int y1, int x2)
                }
                i++;
        }
@@ -605,7 +627,7 @@ index 2a3bd38..e66cf0c 100644
 -              xdrawglyphfontspecs(specs, base, i, ox, y1);
 +      if (i > 0) {
 +              numspecs = xmakeglyphfontspecs(specs, &line[ox], x2 - ox, ox, 
y1);
-+              xdrawglyphfontspecs(specs, base, numspecs, ox, y1);
++              xdrawglyphfontspecs(specs, base, numspecs, ox, y1, x2 - ox);
 +      }
  }
  
diff --git 
a/st.suckless.org/patches/ligatures/0.9/st-ligatures-scrollback-ringbuffer-20230105-0.9.diff
 
b/st.suckless.org/patches/ligatures/0.9/st-ligatures-scrollback-ringbuffer-20240105-0.9.diff
similarity index 90%
rename from 
st.suckless.org/patches/ligatures/0.9/st-ligatures-scrollback-ringbuffer-20230105-0.9.diff
rename to 
st.suckless.org/patches/ligatures/0.9/st-ligatures-scrollback-ringbuffer-20240105-0.9.diff
index e9e89453..01ec9371 100644
--- 
a/st.suckless.org/patches/ligatures/0.9/st-ligatures-scrollback-ringbuffer-20230105-0.9.diff
+++ 
b/st.suckless.org/patches/ligatures/0.9/st-ligatures-scrollback-ringbuffer-20240105-0.9.diff
@@ -42,10 +42,10 @@ index 1e306f8..3e13e53 100644
  STCPPFLAGS = -DVERSION=\"$(VERSION)\" -D_XOPEN_SOURCE=600
 diff --git a/hb.c b/hb.c
 new file mode 100644
-index 0000000..528c040
+index 0000000..99412c8
 --- /dev/null
 +++ b/hb.c
-@@ -0,0 +1,124 @@
+@@ -0,0 +1,125 @@
 +#include <stdlib.h>
 +#include <stdio.h>
 +#include <math.h>
@@ -136,6 +136,7 @@ index 0000000..528c040
 +
 +      hb_buffer_t *buffer = hb_buffer_create();
 +      hb_buffer_set_direction(buffer, HB_DIRECTION_LTR);
++      hb_buffer_set_cluster_level(buffer, 
HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS);
 +
 +      /* Resize the buffer if required length is larger. */
 +      if (hbrunebuffer.capacity < length) {
@@ -172,7 +173,7 @@ index 0000000..528c040
 +}
 diff --git a/hb.h b/hb.h
 new file mode 100644
-index 0000000..88de9bd
+index 0000000..3b0ef44
 --- /dev/null
 +++ b/hb.h
 @@ -0,0 +1,14 @@
@@ -181,10 +182,10 @@ index 0000000..88de9bd
 +#include <hb-ft.h>
 +
 +typedef struct {
-+  hb_buffer_t *buffer;
-+  hb_glyph_info_t *glyphs;
-+  hb_glyph_position_t *positions;
-+  unsigned int count;
++      hb_buffer_t *buffer;
++      hb_glyph_info_t *glyphs;
++      hb_glyph_position_t *positions;
++      unsigned int count;
 +} HbTransformData;
 +
 +void hbunloadfonts();
@@ -232,7 +233,7 @@ index 6de960d..94679e4 100644
  void xfinishdraw(void);
  void xloadcols(void);
 diff --git a/x.c b/x.c
-index 9891e91..ec3567a 100644
+index 9891e91..7d42790 100644
 --- a/x.c
 +++ b/x.c
 @@ -19,6 +19,7 @@ char *argv0;
@@ -243,14 +244,17 @@ index 9891e91..ec3567a 100644
  
  /* types used in config.h */
  typedef struct {
-@@ -143,6 +144,7 @@ typedef struct {
+@@ -143,8 +144,9 @@ typedef struct {
  } DC;
  
  static inline ushort sixd_to_16bit(int);
 +static void xresetfontsettings(ushort mode, Font **font, int *frcflags);
  static int xmakeglyphfontspecs(XftGlyphFontSpec *, const Glyph *, int, int, 
int);
- static void xdrawglyphfontspecs(const XftGlyphFontSpec *, Glyph, int, int, 
int);
+-static void xdrawglyphfontspecs(const XftGlyphFontSpec *, Glyph, int, int, 
int);
++static void xdrawglyphfontspecs(const XftGlyphFontSpec *, Glyph, int, int, 
int, int);
  static void xdrawglyph(Glyph, int, int);
+ static void xclear(int, int, int, int);
+ static int xgeommasktogravity(int);
 @@ -759,7 +761,7 @@ xresize(int col, int row)
        xclear(0, 0, win.w, win.h);
  
@@ -302,13 +306,13 @@ index 9891e91..ec3567a 100644
  int
  xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, 
int x, int y)
  {
-@@ -1255,119 +1276,148 @@ xmakeglyphfontspecs(XftGlyphFontSpec *specs, const 
Glyph *glyphs, int len, int x
+@@ -1255,128 +1276,156 @@ xmakeglyphfontspecs(XftGlyphFontSpec *specs, const 
Glyph *glyphs, int len, int x
        FcPattern *fcpattern, *fontpattern;
        FcFontSet *fcsets[] = { NULL };
        FcCharSet *fccharset;
 -      int i, f, numspecs = 0;
 +      int i, f, length = 0, start = 0, numspecs = 0;
-+  float cluster_xp = xp, cluster_yp = yp;
++      float cluster_xp = xp, cluster_yp = yp;
 +      HbTransformData shaped = { 0 };
 +
 +      /* Initial values. */
@@ -356,7 +360,7 @@ index 9891e91..ec3567a 100644
                        }
 -                      yp = winy + font->ascent;
 -              }
--
+ 
 -              /* Lookup character index with default font. */
 -              glyphidx = XftCharIndex(xw.dpy, font->match, rune);
 -              if (glyphidx) {
@@ -368,7 +372,7 @@ index 9891e91..ec3567a 100644
 -                      numspecs++;
 -                      continue;
 -              }
- 
+-
 -              /* Fallback on font cache, search the font cache for match. */
 -              for (f = 0; f < frclen; f++) {
 -                      glyphidx = XftCharIndex(xw.dpy, frc[f].font, rune);
@@ -481,13 +485,16 @@ index 9891e91..ec3567a 100644
 +                              }
                        }
 -              }
--
+ 
 -              /* Nothing was found. Use fontconfig to find matching font. */
 -              if (f >= frclen) {
 -                      if (!font->set)
 -                              font->set = FcFontSort(0, font->pattern,
 -                                                     1, 0, &fcres);
 -                      fcsets[0] = font->set;
++                      /* Cleanup and get ready for next segment. */
++                      hbcleanup(&shaped);
++                      start = i;
  
 -                      /*
 -                       * Nothing was found in the cache. Now use
@@ -503,10 +510,7 @@ index 9891e91..ec3567a 100644
 -                      FcPatternAddCharSet(fcpattern, FC_CHARSET,
 -                                      fccharset);
 -                      FcPatternAddBool(fcpattern, FC_SCALABLE, 1);
-+                      /* Cleanup and get ready for next segment. */
-+                      hbcleanup(&shaped);
-+                      start = i;
- 
+-
 -                      FcConfigSubstitute(0, fcpattern,
 -                                      FcMatchPattern);
 -                      FcDefaultSubstitute(fcpattern);
@@ -551,7 +555,27 @@ index 9891e91..ec3567a 100644
        }
  
        return numspecs;
-@@ -1519,14 +1569,17 @@ xdrawglyph(Glyph g, int x, int y)
+ }
+ 
+ void
+-xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int 
x, int y)
++xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int 
x, int y, int charlen)
+ {
+-      int charlen = len * ((base.mode & ATTR_WIDE) ? 2 : 1);
+       int winx = borderpx + x * win.cw, winy = borderpx + y * win.ch,
+           width = charlen * win.cw;
+       Color *fg, *bg, *temp, revfg, revbg, truefg, truebg;
+@@ -1512,21 +1561,24 @@ void
+ xdrawglyph(Glyph g, int x, int y)
+ {
+       int numspecs;
+-      XftGlyphFontSpec spec;
++      XftGlyphFontSpec *specs = xw.specbuf;
+ 
+-      numspecs = xmakeglyphfontspecs(&spec, &g, 1, x, y);
+-      xdrawglyphfontspecs(&spec, g, numspecs, x, y);
++      numspecs = xmakeglyphfontspecs(specs, &g, 1, x, y);
++      xdrawglyphfontspecs(specs, g, numspecs, x, y, (g.mode & ATTR_WIDE) ? 2 
: 1);
  }
  
  void
@@ -571,7 +595,7 @@ index 9891e91..ec3567a 100644
  
        if (IS_SET(MODE_HIDE))
                return;
-@@ -1654,18 +1707,16 @@ xdrawline(Line line, int x1, int y1, int x2)
+@@ -1654,18 +1706,16 @@ xdrawline(Line line, int x1, int y1, int x2)
        Glyph base, new;
        XftGlyphFontSpec *specs = xw.specbuf;
  
@@ -590,11 +614,11 @@ index 9891e91..ec3567a 100644
 -                      numspecs -= i;
 +              if ((i > 0) && ATTRCMP(base, new)) {
 +                      numspecs = xmakeglyphfontspecs(specs, &line[ox], x - 
ox, ox, y1);
-+                      xdrawglyphfontspecs(specs, base, numspecs, ox, y1);
++                      xdrawglyphfontspecs(specs, base, numspecs, ox, y1, x - 
ox);
                        i = 0;
                }
                if (i == 0) {
-@@ -1674,8 +1725,10 @@ xdrawline(Line line, int x1, int y1, int x2)
+@@ -1674,8 +1724,10 @@ xdrawline(Line line, int x1, int y1, int x2)
                }
                i++;
        }
@@ -602,7 +626,7 @@ index 9891e91..ec3567a 100644
 -              xdrawglyphfontspecs(specs, base, i, ox, y1);
 +      if (i > 0) {
 +              numspecs = xmakeglyphfontspecs(specs, &line[ox], x2 - ox, ox, 
y1);
-+              xdrawglyphfontspecs(specs, base, numspecs, ox, y1);
++              xdrawglyphfontspecs(specs, base, numspecs, ox, y1, x2 - ox);
 +      }
  }
  
diff --git a/st.suckless.org/patches/ligatures/index.md 
b/st.suckless.org/patches/ligatures/index.md
index 35d5e0b9..1c3a64d9 100644
--- a/st.suckless.org/patches/ligatures/index.md
+++ b/st.suckless.org/patches/ligatures/index.md
@@ -28,13 +28,13 @@ Boxdraw
 Download
 --------
 **0.9**:
-* [st-ligatures-0.9](0.9/st-ligatures-20230105-0.9.diff)
-* [st-ligatures-scrollback-0.9](0.9/st-ligatures-scrollback-20230105-0.9.diff)
-* 
[st-ligatures-scrollback-ringbuffer-0.9](0.9/st-ligatures-scrollback-ringbuffer-20230105-0.9.diff)
-* [st-ligatures-alpha-0.9](0.9/st-ligatures-alpha-20230105-0.9.diff)
-* 
[st-ligatures-alpha-scrollback-0.9](0.9/st-ligatures-alpha-scrollback-20230105-0.9.diff)
-* 
[st-ligatures-alpha-scrollback-ringbuffer-0.9](0.9/st-ligatures-alpha-scrollback-ringbuffer-20230105-0.9.diff)
-* [st-ligatures-boxdraw-0.9](0.9/st-ligatures-boxdraw-20230105-0.9.diff)
+* [st-ligatures-0.9](0.9/st-ligatures-20240105-0.9.diff)
+* [st-ligatures-scrollback-0.9](0.9/st-ligatures-scrollback-20240105-0.9.diff)
+* 
[st-ligatures-scrollback-ringbuffer-0.9](0.9/st-ligatures-scrollback-ringbuffer-20240105-0.9.diff)
+* [st-ligatures-alpha-0.9](0.9/st-ligatures-alpha-20240105-0.9.diff)
+* 
[st-ligatures-alpha-scrollback-0.9](0.9/st-ligatures-alpha-scrollback-20240105-0.9.diff)
+* 
[st-ligatures-alpha-scrollback-ringbuffer-0.9](0.9/st-ligatures-alpha-scrollback-ringbuffer-20240105-0.9.diff)
+* [st-ligatures-boxdraw-0.9](0.9/st-ligatures-boxdraw-20240105-0.9.diff)
 
 **0.8.4**:
 * [st-ligatures-0.8.4](0.8.4/st-ligatures-20210824-0.8.4.diff)


Reply via email to