patched undercurl
parent
52fea633a1
commit
79381aad47
@ -0,0 +1,153 @@
|
||||
From a3cdd0753bf578cd4e6db7c6507481f3b5c38aea Mon Sep 17 00:00:00 2001
|
||||
From: Steve Ward <planet36@gmail.com>
|
||||
Date: Tue, 16 Nov 2021 14:15:06 -0500
|
||||
Subject: [PATCH] Allow blinking cursor
|
||||
|
||||
---
|
||||
config.def.h | 19 +++++++++++++------
|
||||
x.c | 47 +++++++++++++++++++++++++++++++++++------------
|
||||
2 files changed, 48 insertions(+), 18 deletions(-)
|
||||
|
||||
diff --git a/config.def.h b/config.def.h
|
||||
index 6f05dce..1a5fed0 100644
|
||||
--- a/config.def.h
|
||||
+++ b/config.def.h
|
||||
@@ -133,13 +133,20 @@ static unsigned int defaultcs = 256;
|
||||
static unsigned int defaultrcs = 257;
|
||||
|
||||
/*
|
||||
- * Default shape of cursor
|
||||
- * 2: Block ("█")
|
||||
- * 4: Underline ("_")
|
||||
- * 6: Bar ("|")
|
||||
- * 7: Snowman ("☃")
|
||||
+ * https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h4-Functions-using-CSI-_-ordered-by-the-final-character-lparen-s-rparen:CSI-Ps-SP-q.1D81
|
||||
+ * Default style of cursor
|
||||
+ * 0: blinking block
|
||||
+ * 1: blinking block (default)
|
||||
+ * 2: steady block ("█")
|
||||
+ * 3: blinking underline
|
||||
+ * 4: steady underline ("_")
|
||||
+ * 5: blinking bar
|
||||
+ * 6: steady bar ("|")
|
||||
+ * 7: blinking st cursor
|
||||
+ * 8: steady st cursor
|
||||
*/
|
||||
-static unsigned int cursorshape = 2;
|
||||
+static unsigned int cursorstyle = 1;
|
||||
+static Rune stcursor = 0x2603; /* snowman ("☃") */
|
||||
|
||||
/*
|
||||
* Default columns and rows numbers
|
||||
diff --git a/x.c b/x.c
|
||||
index 89786b8..7d2447d 100644
|
||||
--- a/x.c
|
||||
+++ b/x.c
|
||||
@@ -253,6 +253,7 @@ static char *opt_name = NULL;
|
||||
static char *opt_title = NULL;
|
||||
|
||||
static int oldbutton = 3; /* button event on startup: 3 = release */
|
||||
+static int cursorblinks = 0;
|
||||
|
||||
void
|
||||
clipcopy(const Arg *dummy)
|
||||
@@ -1529,29 +1530,44 @@ xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og)
|
||||
/* draw the new one */
|
||||
if (IS_SET(MODE_FOCUSED)) {
|
||||
switch (win.cursor) {
|
||||
- case 7: /* st extension */
|
||||
- g.u = 0x2603; /* snowman (U+2603) */
|
||||
+ default:
|
||||
+ case 0: /* blinking block */
|
||||
+ case 1: /* blinking block (default) */
|
||||
+ if (IS_SET(MODE_BLINK))
|
||||
+ break;
|
||||
/* FALLTHROUGH */
|
||||
- case 0: /* Blinking Block */
|
||||
- case 1: /* Blinking Block (Default) */
|
||||
- case 2: /* Steady Block */
|
||||
+ case 2: /* steady block */
|
||||
xdrawglyph(g, cx, cy);
|
||||
break;
|
||||
- case 3: /* Blinking Underline */
|
||||
- case 4: /* Steady Underline */
|
||||
+ case 3: /* blinking underline */
|
||||
+ if (IS_SET(MODE_BLINK))
|
||||
+ break;
|
||||
+ /* FALLTHROUGH */
|
||||
+ case 4: /* steady underline */
|
||||
XftDrawRect(xw.draw, &drawcol,
|
||||
borderpx + cx * win.cw,
|
||||
borderpx + (cy + 1) * win.ch - \
|
||||
cursorthickness,
|
||||
win.cw, cursorthickness);
|
||||
break;
|
||||
- case 5: /* Blinking bar */
|
||||
- case 6: /* Steady bar */
|
||||
+ case 5: /* blinking bar */
|
||||
+ if (IS_SET(MODE_BLINK))
|
||||
+ break;
|
||||
+ /* FALLTHROUGH */
|
||||
+ case 6: /* steady bar */
|
||||
XftDrawRect(xw.draw, &drawcol,
|
||||
borderpx + cx * win.cw,
|
||||
borderpx + cy * win.ch,
|
||||
cursorthickness, win.ch);
|
||||
break;
|
||||
+ case 7: /* blinking st cursor */
|
||||
+ if (IS_SET(MODE_BLINK))
|
||||
+ break;
|
||||
+ /* FALLTHROUGH */
|
||||
+ case 8: /* steady st cursor */
|
||||
+ g.u = stcursor;
|
||||
+ xdrawglyph(g, cx, cy);
|
||||
+ break;
|
||||
}
|
||||
} else {
|
||||
XftDrawRect(xw.draw, &drawcol,
|
||||
@@ -1708,9 +1724,12 @@ xsetmode(int set, unsigned int flags)
|
||||
int
|
||||
xsetcursor(int cursor)
|
||||
{
|
||||
- if (!BETWEEN(cursor, 0, 7)) /* 7: st extension */
|
||||
+ if (!BETWEEN(cursor, 0, 8)) /* 7-8: st extensions */
|
||||
return 1;
|
||||
win.cursor = cursor;
|
||||
+ cursorblinks = win.cursor == 0 || win.cursor == 1 ||
|
||||
+ win.cursor == 3 || win.cursor == 5 ||
|
||||
+ win.cursor == 7;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1954,6 +1973,10 @@ run(void)
|
||||
if (FD_ISSET(ttyfd, &rfd) || xev) {
|
||||
if (!drawing) {
|
||||
trigger = now;
|
||||
+ if (IS_SET(MODE_BLINK)) {
|
||||
+ win.mode ^= MODE_BLINK;
|
||||
+ }
|
||||
+ lastblink = now;
|
||||
drawing = 1;
|
||||
}
|
||||
timeout = (maxlatency - TIMEDIFF(now, trigger)) \
|
||||
@@ -1964,7 +1987,7 @@ run(void)
|
||||
|
||||
/* idle detected or maxlatency exhausted -> draw */
|
||||
timeout = -1;
|
||||
- if (blinktimeout && tattrset(ATTR_BLINK)) {
|
||||
+ if (blinktimeout && (cursorblinks || tattrset(ATTR_BLINK))) {
|
||||
timeout = blinktimeout - TIMEDIFF(now, lastblink);
|
||||
if (timeout <= 0) {
|
||||
if (-timeout > blinktimeout) /* start visible */
|
||||
@@ -2000,7 +2023,7 @@ main(int argc, char *argv[])
|
||||
{
|
||||
xw.l = xw.t = 0;
|
||||
xw.isfixed = False;
|
||||
- xsetcursor(cursorshape);
|
||||
+ xsetcursor(cursorstyle);
|
||||
|
||||
ARGBEGIN {
|
||||
case 'a':
|
||||
--
|
||||
2.34.0
|
||||
|
@ -0,0 +1,12 @@
|
||||
diff --git a/x.c b/x.c
|
||||
index e5f1737..5cabd60 100644
|
||||
--- a/x.c
|
||||
+++ b/x.c
|
||||
@@ -673,6 +673,7 @@ setsel(char *str, Time t)
|
||||
XSetSelectionOwner(xw.dpy, XA_PRIMARY, xw.win, t);
|
||||
if (XGetSelectionOwner(xw.dpy, XA_PRIMARY) != xw.win)
|
||||
selclear();
|
||||
+ clipcopy(NULL);
|
||||
}
|
||||
|
||||
void
|
@ -0,0 +1,271 @@
|
||||
From 10fa2b6aebceb3a12219ef25376297b063638bd9 Mon Sep 17 00:00:00 2001
|
||||
From: Julius Huelsmann <juliusHuelsmann@gmail.com>
|
||||
Date: Fri, 31 Jul 2020 10:13:35 +0200
|
||||
Subject: [PATCH] patch: focus
|
||||
|
||||
---
|
||||
config.def.h | 5 ++++
|
||||
config.mk | 2 +-
|
||||
st.c | 1 -
|
||||
st.h | 2 ++
|
||||
x.c | 72 +++++++++++++++++++++++++++++++++++++++-------------
|
||||
5 files changed, 62 insertions(+), 20 deletions(-)
|
||||
|
||||
diff --git a/config.def.h b/config.def.h
|
||||
index 0895a1f..577d1f1 100644
|
||||
--- a/config.def.h
|
||||
+++ b/config.def.h
|
||||
@@ -84,6 +84,9 @@ char *termname = "st-256color";
|
||||
*/
|
||||
unsigned int tabspaces = 8;
|
||||
|
||||
+/* bg opacity */
|
||||
+float alpha = 0.8, alphaUnfocused = 0.6;
|
||||
+
|
||||
/* Terminal colors (16 first used in escape sequence) */
|
||||
static const char *colorname[] = {
|
||||
/* 8 normal colors */
|
||||
@@ -111,6 +114,7 @@ static const char *colorname[] = {
|
||||
/* more colors can be added after 255 to use with DefaultXX */
|
||||
"#cccccc",
|
||||
"#555555",
|
||||
+ "black",
|
||||
};
|
||||
|
||||
|
||||
@@ -122,6 +126,7 @@ unsigned int defaultfg = 7;
|
||||
unsigned int defaultbg = 0;
|
||||
static unsigned int defaultcs = 256;
|
||||
static unsigned int defaultrcs = 257;
|
||||
+unsigned int bg = 17, bgUnfocused = 16;
|
||||
|
||||
/*
|
||||
* Default shape of cursor
|
||||
diff --git a/config.mk b/config.mk
|
||||
index beafc35..ddc65ae 100644
|
||||
--- a/config.mk
|
||||
+++ b/config.mk
|
||||
@@ -16,7 +16,7 @@ PKG_CONFIG = pkg-config
|
||||
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 -lXrender\
|
||||
`$(PKG_CONFIG) --libs fontconfig` \
|
||||
`$(PKG_CONFIG) --libs freetype2`
|
||||
|
||||
diff --git a/st.c b/st.c
|
||||
index 0ce6ac2..c7f40c8 100644
|
||||
--- a/st.c
|
||||
+++ b/st.c
|
||||
@@ -194,7 +194,6 @@ static void tsetscroll(int, int);
|
||||
static void tswapscreen(void);
|
||||
static void tsetmode(int, int, int *, int);
|
||||
static int twrite(const char *, int, int);
|
||||
-static void tfulldirt(void);
|
||||
static void tcontrolcode(uchar );
|
||||
static void tdectest(char );
|
||||
static void tdefutf8(char);
|
||||
diff --git a/st.h b/st.h
|
||||
index d978458..44cb3fd 100644
|
||||
--- a/st.h
|
||||
+++ b/st.h
|
||||
@@ -79,6 +79,7 @@ typedef union {
|
||||
|
||||
void die(const char *, ...);
|
||||
void redraw(void);
|
||||
+void tfulldirt(void);
|
||||
void draw(void);
|
||||
|
||||
void printscreen(const Arg *);
|
||||
@@ -122,3 +123,4 @@ extern char *termname;
|
||||
extern unsigned int tabspaces;
|
||||
extern unsigned int defaultfg;
|
||||
extern unsigned int defaultbg;
|
||||
+extern float alpha, alphaUnfocused;
|
||||
diff --git a/x.c b/x.c
|
||||
index e5f1737..a2e820f 100644
|
||||
--- a/x.c
|
||||
+++ b/x.c
|
||||
@@ -105,6 +105,7 @@ typedef struct {
|
||||
XSetWindowAttributes attrs;
|
||||
int scr;
|
||||
int isfixed; /* is fixed geometry? */
|
||||
+ int depth; /* bit depth */
|
||||
int l, t; /* left and top offset */
|
||||
int gm; /* geometry mask */
|
||||
} XWindow;
|
||||
@@ -243,6 +244,7 @@ static char *usedfont = NULL;
|
||||
static double usedfontsize = 0;
|
||||
static double defaultfontsize = 0;
|
||||
|
||||
+static char *opt_alpha = NULL;
|
||||
static char *opt_class = NULL;
|
||||
static char **opt_cmd = NULL;
|
||||
static char *opt_embed = NULL;
|
||||
@@ -252,6 +254,8 @@ static char *opt_line = NULL;
|
||||
static char *opt_name = NULL;
|
||||
static char *opt_title = NULL;
|
||||
|
||||
+static int focused = 0;
|
||||
+
|
||||
static int oldbutton = 3; /* button event on startup: 3 = release */
|
||||
|
||||
void
|
||||
@@ -734,7 +738,7 @@ xresize(int col, int row)
|
||||
|
||||
XFreePixmap(xw.dpy, xw.buf);
|
||||
xw.buf = XCreatePixmap(xw.dpy, xw.win, win.w, win.h,
|
||||
- DefaultDepth(xw.dpy, xw.scr));
|
||||
+ xw.depth);
|
||||
XftDrawChange(xw.draw, xw.buf);
|
||||
xclear(0, 0, win.w, win.h);
|
||||
|
||||
@@ -772,28 +776,38 @@ xloadcolor(int i, const char *name, Color *ncolor)
|
||||
return XftColorAllocName(xw.dpy, xw.vis, xw.cmap, name, ncolor);
|
||||
}
|
||||
|
||||
+void
|
||||
+xloadalpha(void)
|
||||
+{
|
||||
+ float const usedAlpha = focused ? alpha : alphaUnfocused;
|
||||
+ if (opt_alpha) alpha = strtof(opt_alpha, NULL);
|
||||
+ dc.col[defaultbg].color.alpha = (unsigned short)(0xffff * usedAlpha);
|
||||
+ dc.col[defaultbg].pixel &= 0x00FFFFFF;
|
||||
+ dc.col[defaultbg].pixel |= (unsigned char)(0xff * usedAlpha) << 24;
|
||||
+}
|
||||
+
|
||||
void
|
||||
xloadcols(void)
|
||||
{
|
||||
- int i;
|
||||
static int loaded;
|
||||
Color *cp;
|
||||
|
||||
- if (loaded) {
|
||||
- for (cp = dc.col; cp < &dc.col[dc.collen]; ++cp)
|
||||
- XftColorFree(xw.dpy, xw.vis, xw.cmap, cp);
|
||||
- } else {
|
||||
- dc.collen = MAX(LEN(colorname), 256);
|
||||
- dc.col = xmalloc(dc.collen * sizeof(Color));
|
||||
+ if (!loaded) {
|
||||
+ dc.collen = 1 + (defaultbg = MAX(LEN(colorname), 256));
|
||||
+ dc.col = xmalloc((dc.collen) * sizeof(Color));
|
||||
}
|
||||
|
||||
- for (i = 0; i < dc.collen; i++)
|
||||
+ for (int i = 0; i+1 < dc.collen; ++i)
|
||||
if (!xloadcolor(i, NULL, &dc.col[i])) {
|
||||
if (colorname[i])
|
||||
die("could not allocate color '%s'\n", colorname[i]);
|
||||
else
|
||||
die("could not allocate color %d\n", i);
|
||||
}
|
||||
+ if (dc.collen) // cannot die, as the color is already loaded.
|
||||
+ xloadcolor(focused ?bg :bgUnfocused, NULL, &dc.col[defaultbg]);
|
||||
+
|
||||
+ xloadalpha();
|
||||
loaded = 1;
|
||||
}
|
||||
|
||||
@@ -1103,11 +1117,23 @@ xinit(int cols, int rows)
|
||||
Window parent;
|
||||
pid_t thispid = getpid();
|
||||
XColor xmousefg, xmousebg;
|
||||
+ XWindowAttributes attr;
|
||||
+ XVisualInfo vis;
|
||||
|
||||
if (!(xw.dpy = XOpenDisplay(NULL)))
|
||||
die("can't open display\n");
|
||||
xw.scr = XDefaultScreen(xw.dpy);
|
||||
- xw.vis = XDefaultVisual(xw.dpy, xw.scr);
|
||||
+
|
||||
+ if (!(opt_embed && (parent = strtol(opt_embed, NULL, 0)))) {
|
||||
+ parent = XRootWindow(xw.dpy, xw.scr);
|
||||
+ xw.depth = 32;
|
||||
+ } else {
|
||||
+ XGetWindowAttributes(xw.dpy, parent, &attr);
|
||||
+ xw.depth = attr.depth;
|
||||
+ }
|
||||
+
|
||||
+ XMatchVisualInfo(xw.dpy, xw.scr, xw.depth, TrueColor, &vis);
|
||||
+ xw.vis = vis.visual;
|
||||
|
||||
/* font */
|
||||
if (!FcInit())
|
||||
@@ -1117,7 +1143,7 @@ xinit(int cols, int rows)
|
||||
xloadfonts(usedfont, 0);
|
||||
|
||||
/* colors */
|
||||
- xw.cmap = XDefaultColormap(xw.dpy, xw.scr);
|
||||
+ xw.cmap = XCreateColormap(xw.dpy, parent, xw.vis, None);
|
||||
xloadcols();
|
||||
|
||||
/* adjust fixed window geometry */
|
||||
@@ -1137,19 +1163,15 @@ xinit(int cols, int rows)
|
||||
| ButtonMotionMask | ButtonPressMask | ButtonReleaseMask;
|
||||
xw.attrs.colormap = xw.cmap;
|
||||
|
||||
- if (!(opt_embed && (parent = strtol(opt_embed, NULL, 0))))
|
||||
- parent = XRootWindow(xw.dpy, xw.scr);
|
||||
xw.win = XCreateWindow(xw.dpy, parent, xw.l, xw.t,
|
||||
- win.w, win.h, 0, XDefaultDepth(xw.dpy, xw.scr), InputOutput,
|
||||
+ win.w, win.h, 0, xw.depth, InputOutput,
|
||||
xw.vis, CWBackPixel | CWBorderPixel | CWBitGravity
|
||||
| CWEventMask | CWColormap, &xw.attrs);
|
||||
|
||||
memset(&gcvalues, 0, sizeof(gcvalues));
|
||||
gcvalues.graphics_exposures = False;
|
||||
- dc.gc = XCreateGC(xw.dpy, parent, GCGraphicsExposures,
|
||||
- &gcvalues);
|
||||
- xw.buf = XCreatePixmap(xw.dpy, xw.win, win.w, win.h,
|
||||
- DefaultDepth(xw.dpy, xw.scr));
|
||||
+ xw.buf = XCreatePixmap(xw.dpy, xw.win, win.w, win.h, xw.depth);
|
||||
+ dc.gc = XCreateGC(xw.dpy, xw.buf, GCGraphicsExposures, &gcvalues);
|
||||
XSetForeground(xw.dpy, dc.gc, dc.col[defaultbg].pixel);
|
||||
XFillRectangle(xw.dpy, xw.buf, dc.gc, 0, 0, win.w, win.h);
|
||||
|
||||
@@ -1730,12 +1752,22 @@ focus(XEvent *ev)
|
||||
xseturgency(0);
|
||||
if (IS_SET(MODE_FOCUS))
|
||||
ttywrite("\033[I", 3, 0);
|
||||
+ if (!focused) {
|
||||
+ focused = 1;
|
||||
+ xloadcols();
|
||||
+ tfulldirt();
|
||||
+ }
|
||||
} else {
|
||||
if (xw.ime.xic)
|
||||
XUnsetICFocus(xw.ime.xic);
|
||||
win.mode &= ~MODE_FOCUSED;
|
||||
if (IS_SET(MODE_FOCUS))
|
||||
ttywrite("\033[O", 3, 0);
|
||||
+ if (focused) {
|
||||
+ focused = 0;
|
||||
+ xloadcols();
|
||||
+ tfulldirt();
|
||||
+ }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1994,6 +2026,9 @@ main(int argc, char *argv[])
|
||||
case 'a':
|
||||
allowaltscreen = 0;
|
||||
break;
|
||||
+ case 'A':
|
||||
+ opt_alpha = EARGF(usage());
|
||||
+ break;
|
||||
case 'c':
|
||||
opt_class = EARGF(usage());
|
||||
break;
|
||||
@@ -2045,6 +2080,7 @@ run:
|
||||
XSetLocaleModifiers("");
|
||||
cols = MAX(cols, 1);
|
||||
rows = MAX(rows, 1);
|
||||
+ defaultbg = MAX(LEN(colorname), 256);
|
||||
tnew(cols, rows);
|
||||
xinit(cols, rows);
|
||||
xsetenv();
|
||||
--
|
||||
2.28.0
|
||||
|
@ -1,9 +0,0 @@
|
||||
diff a/st.c b/st.c (rejected hunks)
|
||||
@@ -159,6 +161,7 @@ static void ttywriteraw(const char *, size_t);
|
||||
|
||||
static void csidump(void);
|
||||
static void csihandle(void);
|
||||
+static void readcolonargs(char **, int, int[][CAR_PER_ARG]);
|
||||
static void csiparse(void);
|
||||
static void csireset(void);
|
||||
static int eschandle(uchar);
|
@ -1,361 +0,0 @@
|
||||
diff a/x.c b/x.c (rejected hunks)
|
||||
@@ -1461,8 +1514,357 @@ xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, i
|
||||
|
||||
/* Render underline and strikethrough. */
|
||||
if (base.mode & ATTR_UNDERLINE) {
|
||||
- XftDrawRect(xw.draw, fg, winx, winy + dc.font.ascent + 1,
|
||||
- width, 1);
|
||||
// Underline Color
|
||||
const int widthThreshold = 28; // +1 width every widthThreshold px of font
|
||||
int wlw = (win.ch / widthThreshold) + 1; // Wave Line Width
|
||||
int linecolor;
|
||||
if ((base.ucolor[0] >= 0) &&
|
||||
!(base.mode & ATTR_BLINK && win.mode & MODE_BLINK) &&
|
||||
!(base.mode & ATTR_INVISIBLE)
|
||||
) {
|
||||
// Special color for underline
|
||||
// Index
|
||||
if (base.ucolor[1] < 0) {
|
||||
linecolor = dc.col[base.ucolor[0]].pixel;
|
||||
}
|
||||
// RGB
|
||||
else {
|
||||
XColor lcolor;
|
||||
lcolor.red = base.ucolor[0] * 257;
|
||||
lcolor.green = base.ucolor[1] * 257;
|
||||
lcolor.blue = base.ucolor[2] * 257;
|
||||
lcolor.flags = DoRed | DoGreen | DoBlue;
|
||||
XAllocColor(xw.dpy, xw.cmap, &lcolor);
|
||||
linecolor = lcolor.pixel;
|
||||
}
|
||||
} else {
|
||||
// Foreground color for underline
|
||||
linecolor = fg->pixel;
|
||||
}
|
||||
|
||||
XGCValues ugcv = {
|
||||
.foreground = linecolor,
|
||||
.line_width = wlw,
|
||||
.line_style = LineSolid,
|
||||
.cap_style = CapNotLast
|
||||
};
|
||||
|
||||
GC ugc = XCreateGC(xw.dpy, XftDrawDrawable(xw.draw),
|
||||
GCForeground | GCLineWidth | GCLineStyle | GCCapStyle,
|
||||
&ugcv);
|
||||
|
||||
// Underline Style
|
||||
if (base.ustyle != 3) {
|
||||
//XftDrawRect(xw.draw, fg, winx, winy + dc.font.ascent + 1, width, 1);
|
||||
XFillRectangle(xw.dpy, XftDrawDrawable(xw.draw), ugc, winx,
|
||||
winy + dc.font.ascent + 1, width, wlw);
|
||||
} else if (base.ustyle == 3) {
|
||||
int ww = win.cw;//width;
|
||||
int wh = dc.font.descent - wlw/2 - 1;//r.height/7;
|
||||
int wx = winx;
|
||||
int wy = winy + win.ch - dc.font.descent;
|
||||
|
||||
#if UNDERCURL_STYLE == UNDERCURL_CURLY
|
||||
// Draw waves
|
||||
int narcs = charlen * 2 + 1;
|
||||
XArc *arcs = xmalloc(sizeof(XArc) * narcs);
|
||||
|
||||
int i = 0;
|
||||
for (i = 0; i < charlen-1; i++) {
|
||||
arcs[i*2] = (XArc) {
|
||||
.x = wx + win.cw * i + ww / 4,
|
||||
.y = wy,
|
||||
.width = win.cw / 2,
|
||||
.height = wh,
|
||||
.angle1 = 0,
|
||||
.angle2 = 180 * 64
|
||||
};
|
||||
arcs[i*2+1] = (XArc) {
|
||||
.x = wx + win.cw * i + ww * 0.75,
|
||||
.y = wy,
|
||||
.width = win.cw/2,
|
||||
.height = wh,
|
||||
.angle1 = 180 * 64,
|
||||
.angle2 = 180 * 64
|
||||
};
|
||||
}
|
||||
// Last wave
|
||||
arcs[i*2] = (XArc) {wx + ww * i + ww / 4, wy, ww / 2, wh,
|
||||
0, 180 * 64 };
|
||||
// Last wave tail
|
||||
arcs[i*2+1] = (XArc) {wx + ww * i + ww * 0.75, wy, ceil(ww / 2.),
|
||||
wh, 180 * 64, 90 * 64};
|
||||
// First wave tail
|
||||
i++;
|
||||
arcs[i*2] = (XArc) {wx - ww/4 - 1, wy, ceil(ww / 2.), wh, 270 * 64,
|
||||
90 * 64 };
|
||||
|
||||
XDrawArcs(xw.dpy, XftDrawDrawable(xw.draw), ugc, arcs, narcs);
|
||||
|
||||
free(arcs);
|
||||
#elif UNDERCURL_STYLE == UNDERCURL_SPIKY
|
||||
// Make the underline corridor larger
|
||||
/*
|
||||
wy -= wh;
|
||||
*/
|
||||
wh *= 2;
|
||||
|
||||
// Set the angle of the slope to 45°
|
||||
ww = wh;
|
||||
|
||||
// Position of wave is independent of word, it's absolute
|
||||
wx = (wx / (ww/2)) * (ww/2);
|
||||
|
||||
int marginStart = winx - wx;
|
||||
|
||||
// Calculate number of points with floating precision
|
||||
float n = width; // Width of word in pixels
|
||||
n = (n / ww) * 2; // Number of slopes (/ or \)
|
||||
n += 2; // Add two last points
|
||||
int npoints = n; // Convert to int
|
||||
|
||||
// Total length of underline
|
||||
float waveLength = 0;
|
||||
|
||||
if (npoints >= 3) {
|
||||
// We add an aditional slot in case we use a bonus point
|
||||
XPoint *points = xmalloc(sizeof(XPoint) * (npoints + 1));
|
||||
|
||||
// First point (Starts with the word bounds)
|
||||
points[0] = (XPoint) {
|
||||
.x = wx + marginStart,
|
||||
.y = (isSlopeRising(wx, 0, ww))
|
||||
? (wy - marginStart + ww/2.f)
|
||||
: (wy + marginStart)
|
||||
};
|
||||
|
||||
// Second point (Goes back to the absolute point coordinates)
|
||||
points[1] = (XPoint) {
|
||||
.x = (ww/2.f) - marginStart,
|
||||
.y = (isSlopeRising(wx, 1, ww))
|
||||
? (ww/2.f - marginStart)
|
||||
: (-ww/2.f + marginStart)
|
||||
};
|
||||
waveLength += (ww/2.f) - marginStart;
|
||||
|
||||
// The rest of the points
|
||||
for (int i = 2; i < npoints-1; i++) {
|
||||
points[i] = (XPoint) {
|
||||
.x = ww/2,
|
||||
.y = (isSlopeRising(wx, i, ww))
|
||||
? wh/2
|
||||
: -wh/2
|
||||
};
|
||||
waveLength += ww/2;
|
||||
}
|
||||
|
||||
// Last point
|
||||
points[npoints-1] = (XPoint) {
|
||||
.x = ww/2,
|
||||
.y = (isSlopeRising(wx, npoints-1, ww))
|
||||
? wh/2
|
||||
: -wh/2
|
||||
};
|
||||
waveLength += ww/2;
|
||||
|
||||
// End
|
||||
if (waveLength < width) { // Add a bonus point?
|
||||
int marginEnd = width - waveLength;
|
||||
points[npoints] = (XPoint) {
|
||||
.x = marginEnd,
|
||||
.y = (isSlopeRising(wx, npoints, ww))
|
||||
? (marginEnd)
|
||||
: (-marginEnd)
|
||||
};
|
||||
|
||||
npoints++;
|
||||
} else if (waveLength > width) { // Is last point too far?
|
||||
int marginEnd = waveLength - width;
|
||||
points[npoints-1].x -= marginEnd;
|
||||
if (isSlopeRising(wx, npoints-1, ww))
|
||||
points[npoints-1].y -= (marginEnd);
|
||||
else
|
||||
points[npoints-1].y += (marginEnd);
|
||||
}
|
||||
|
||||
// Draw the lines
|
||||
XDrawLines(xw.dpy, XftDrawDrawable(xw.draw), ugc, points, npoints,
|
||||
CoordModePrevious);
|
||||
|
||||
// Draw a second underline with an offset of 1 pixel
|
||||
if ( ((win.ch / (widthThreshold/2)) % 2)) {
|
||||
points[0].x++;
|
||||
|
||||
XDrawLines(xw.dpy, XftDrawDrawable(xw.draw), ugc, points,
|
||||
npoints, CoordModePrevious);
|
||||
}
|
||||
|
||||
// Free resources
|
||||
free(points);
|
||||
}
|
||||
#else // UNDERCURL_CAPPED
|
||||
// Cap is half of wave width
|
||||
float capRatio = 0.5f;
|
||||
|
||||
// Make the underline corridor larger
|
||||
wh *= 2;
|
||||
|
||||
// Set the angle of the slope to 45°
|
||||
ww = wh;
|
||||
ww *= 1 + capRatio; // Add a bit of width for the cap
|
||||
|
||||
// Position of wave is independent of word, it's absolute
|
||||
wx = (wx / ww) * ww;
|
||||
|
||||
float marginStart;
|
||||
switch(getSlope(winx, 0, ww)) {
|
||||
case UNDERCURL_SLOPE_ASCENDING:
|
||||
marginStart = winx - wx;
|
||||
break;
|
||||
case UNDERCURL_SLOPE_TOP_CAP:
|
||||
marginStart = winx - (wx + (ww * (2.f/6.f)));
|
||||
break;
|
||||
case UNDERCURL_SLOPE_DESCENDING:
|
||||
marginStart = winx - (wx + (ww * (3.f/6.f)));
|
||||
break;
|
||||
case UNDERCURL_SLOPE_BOTTOM_CAP:
|
||||
marginStart = winx - (wx + (ww * (5.f/6.f)));
|
||||
break;
|
||||
}
|
||||
|
||||
// Calculate number of points with floating precision
|
||||
float n = width; // Width of word in pixels
|
||||
// ._.
|
||||
n = (n / ww) * 4; // Number of points (./ \.)
|
||||
n += 2; // Add two last points
|
||||
int npoints = n; // Convert to int
|
||||
|
||||
// Position of the pen to draw the lines
|
||||
float penX = 0;
|
||||
float penY = 0;
|
||||
|
||||
if (npoints >= 3) {
|
||||
XPoint *points = xmalloc(sizeof(XPoint) * (npoints + 1));
|
||||
|
||||
// First point (Starts with the word bounds)
|
||||
penX = winx;
|
||||
switch (getSlope(winx, 0, ww)) {
|
||||
case UNDERCURL_SLOPE_ASCENDING:
|
||||
penY = wy + wh/2.f - marginStart;
|
||||
break;
|
||||
case UNDERCURL_SLOPE_TOP_CAP:
|
||||
penY = wy;
|
||||
break;
|
||||
case UNDERCURL_SLOPE_DESCENDING:
|
||||
penY = wy + marginStart;
|
||||
break;
|
||||
case UNDERCURL_SLOPE_BOTTOM_CAP:
|
||||
penY = wy + wh/2.f;
|
||||
break;
|
||||
}
|
||||
points[0].x = penX;
|
||||
points[0].y = penY;
|
||||
|
||||
// Second point (Goes back to the absolute point coordinates)
|
||||
switch (getSlope(winx, 1, ww)) {
|
||||
case UNDERCURL_SLOPE_ASCENDING:
|
||||
penX += ww * (1.f/6.f) - marginStart;
|
||||
penY += 0;
|
||||
break;
|
||||
case UNDERCURL_SLOPE_TOP_CAP:
|
||||
penX += ww * (2.f/6.f) - marginStart;
|
||||
penY += -wh/2.f + marginStart;
|
||||
break;
|
||||
case UNDERCURL_SLOPE_DESCENDING:
|
||||
penX += ww * (1.f/6.f) - marginStart;
|
||||
penY += 0;
|
||||
break;
|
||||
case UNDERCURL_SLOPE_BOTTOM_CAP:
|
||||
penX += ww * (2.f/6.f) - marginStart;
|
||||
penY += -marginStart + wh/2.f;
|
||||
break;
|
||||
}
|
||||
points[1].x = penX;
|
||||
points[1].y = penY;
|
||||
|
||||
// The rest of the points
|
||||
for (int i = 2; i < npoints; i++) {
|
||||
switch (getSlope(winx, i, ww)) {
|
||||
case UNDERCURL_SLOPE_ASCENDING:
|
||||
case UNDERCURL_SLOPE_DESCENDING:
|
||||
penX += ww * (1.f/6.f);
|
||||
penY += 0;
|
||||
break;
|
||||
case UNDERCURL_SLOPE_TOP_CAP:
|
||||
penX += ww * (2.f/6.f);
|
||||
penY += -wh / 2.f;
|
||||
break;
|
||||
case UNDERCURL_SLOPE_BOTTOM_CAP:
|
||||
penX += ww * (2.f/6.f);
|
||||
penY += wh / 2.f;
|
||||
break;
|
||||
}
|
||||
points[i].x = penX;
|
||||
points[i].y = penY;
|
||||
}
|
||||
|
||||
// End
|
||||
float waveLength = penX - winx;
|
||||
if (waveLength < width) { // Add a bonus point?
|
||||
int marginEnd = width - waveLength;
|
||||
penX += marginEnd;
|
||||
switch(getSlope(winx, npoints, ww)) {
|
||||
case UNDERCURL_SLOPE_ASCENDING:
|
||||
case UNDERCURL_SLOPE_DESCENDING:
|
||||
//penY += 0;
|
||||
break;
|
||||
case UNDERCURL_SLOPE_TOP_CAP:
|
||||
penY += -marginEnd;
|
||||
break;
|
||||
case UNDERCURL_SLOPE_BOTTOM_CAP:
|
||||
penY += marginEnd;
|
||||
break;
|
||||
}
|
||||
|
||||
points[npoints].x = penX;
|
||||
points[npoints].y = penY;
|
||||
|
||||
npoints++;
|
||||
} else if (waveLength > width) { // Is last point too far?
|
||||
int marginEnd = waveLength - width;
|
||||
points[npoints-1].x -= marginEnd;
|
||||
switch(getSlope(winx, npoints-1, ww)) {
|
||||
case UNDERCURL_SLOPE_TOP_CAP:
|
||||
points[npoints-1].y += marginEnd;
|
||||
break;
|
||||
case UNDERCURL_SLOPE_BOTTOM_CAP:
|
||||
points[npoints-1].y -= marginEnd;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Draw the lines
|
||||
XDrawLines(xw.dpy, XftDrawDrawable(xw.draw), ugc, points, npoints,
|
||||
CoordModeOrigin);
|
||||
|
||||
// Draw a second underline with an offset of 1 pixel
|
||||
if ( ((win.ch / (widthThreshold/2)) % 2)) {
|
||||
for (int i = 0; i < npoints; i++)
|
||||
points[i].x++;
|
||||
|
||||
XDrawLines(xw.dpy, XftDrawDrawable(xw.draw), ugc, points,
|
||||
npoints, CoordModeOrigin);
|
||||
}
|
||||
|
||||
// Free resources
|
||||
free(points);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
XFreeGC(xw.dpy, ugc);
|
||||
}
|
||||
|
||||
if (base.mode & ATTR_STRUCK) {
|
Loading…
Reference in New Issue