Compare commits
1 Commits
feat/under
...
feat/sync
Author | SHA1 | Date | |
---|---|---|---|
037931b193 |
24
config.def.h
24
config.def.h
@ -473,27 +473,3 @@ static char ascii_printable[] =
|
|||||||
" !\"#$%&'()*+,-./0123456789:;<=>?"
|
" !\"#$%&'()*+,-./0123456789:;<=>?"
|
||||||
"@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_"
|
"@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_"
|
||||||
"`abcdefghijklmnopqrstuvwxyz{|}~";
|
"`abcdefghijklmnopqrstuvwxyz{|}~";
|
||||||
|
|
||||||
/**
|
|
||||||
* Undercurl style. Set UNDERCURL_STYLE to one of the available styles.
|
|
||||||
*
|
|
||||||
* Curly: Dunno how to draw it *shrug*
|
|
||||||
* _ _ _ _
|
|
||||||
* ( ) ( ) ( ) ( )
|
|
||||||
* (_) (_) (_) (_)
|
|
||||||
*
|
|
||||||
* Spiky:
|
|
||||||
* /\ /\ /\ /\
|
|
||||||
* \/ \/ \/
|
|
||||||
*
|
|
||||||
* Capped:
|
|
||||||
* _ _ _
|
|
||||||
* / \ / \ / \
|
|
||||||
* \_/ \_/
|
|
||||||
*/
|
|
||||||
// Available styles
|
|
||||||
#define UNDERCURL_CURLY 0
|
|
||||||
#define UNDERCURL_SPIKY 1
|
|
||||||
#define UNDERCURL_CAPPED 2
|
|
||||||
// Active style
|
|
||||||
#define UNDERCURL_STYLE UNDERCURL_SPIKY
|
|
||||||
|
83
st.c
83
st.c
@ -33,7 +33,6 @@
|
|||||||
#define UTF_SIZ 4
|
#define UTF_SIZ 4
|
||||||
#define ESC_BUF_SIZ (128*UTF_SIZ)
|
#define ESC_BUF_SIZ (128*UTF_SIZ)
|
||||||
#define ESC_ARG_SIZ 16
|
#define ESC_ARG_SIZ 16
|
||||||
#define CAR_PER_ARG 4
|
|
||||||
#define STR_BUF_SIZ ESC_BUF_SIZ
|
#define STR_BUF_SIZ ESC_BUF_SIZ
|
||||||
#define STR_ARG_SIZ ESC_ARG_SIZ
|
#define STR_ARG_SIZ ESC_ARG_SIZ
|
||||||
|
|
||||||
@ -43,8 +42,6 @@
|
|||||||
#define ISCONTROLC1(c) (BETWEEN(c, 0x80, 0x9f))
|
#define ISCONTROLC1(c) (BETWEEN(c, 0x80, 0x9f))
|
||||||
#define ISCONTROL(c) (ISCONTROLC0(c) || ISCONTROLC1(c))
|
#define ISCONTROL(c) (ISCONTROLC0(c) || ISCONTROLC1(c))
|
||||||
#define ISDELIM(u) (u && wcschr(worddelimiters, u))
|
#define ISDELIM(u) (u && wcschr(worddelimiters, u))
|
||||||
#define STRESCARGREST(n) ((n) == 0 ? strescseq.buf : strescseq.argp[(n)-1] + 1)
|
|
||||||
#define STRESCARGJUST(n) (*(strescseq.argp[n]) = '\0', STRESCARGREST(n))
|
|
||||||
|
|
||||||
enum term_mode {
|
enum term_mode {
|
||||||
MODE_WRAP = 1 << 0,
|
MODE_WRAP = 1 << 0,
|
||||||
@ -142,7 +139,6 @@ typedef struct {
|
|||||||
int arg[ESC_ARG_SIZ];
|
int arg[ESC_ARG_SIZ];
|
||||||
int narg; /* nb of args */
|
int narg; /* nb of args */
|
||||||
char mode[2];
|
char mode[2];
|
||||||
int carg[ESC_ARG_SIZ][CAR_PER_ARG]; /* colon args */
|
|
||||||
} CSIEscape;
|
} CSIEscape;
|
||||||
|
|
||||||
/* STR Escape sequence structs */
|
/* STR Escape sequence structs */
|
||||||
@ -152,7 +148,7 @@ typedef struct {
|
|||||||
char *buf; /* allocated raw string */
|
char *buf; /* allocated raw string */
|
||||||
size_t siz; /* allocation size */
|
size_t siz; /* allocation size */
|
||||||
size_t len; /* raw string length */
|
size_t len; /* raw string length */
|
||||||
char *argp[STR_ARG_SIZ]; /* pointers to the end of nth argument */
|
char *args[STR_ARG_SIZ];
|
||||||
int narg; /* nb of args */
|
int narg; /* nb of args */
|
||||||
} STREscape;
|
} STREscape;
|
||||||
|
|
||||||
@ -163,7 +159,6 @@ static void ttywriteraw(const char *, size_t);
|
|||||||
|
|
||||||
static void csidump(void);
|
static void csidump(void);
|
||||||
static void csihandle(void);
|
static void csihandle(void);
|
||||||
static void readcolonargs(char **, int, int[][CAR_PER_ARG]);
|
|
||||||
static void csiparse(void);
|
static void csiparse(void);
|
||||||
static void csireset(void);
|
static void csireset(void);
|
||||||
static void osc_color_response(int, int, int);
|
static void osc_color_response(int, int, int);
|
||||||
@ -1163,28 +1158,6 @@ tnewline(int first_col)
|
|||||||
tmoveto(first_col ? 0 : term.c.x, y);
|
tmoveto(first_col ? 0 : term.c.x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
readcolonargs(char **p, int cursor, int params[][CAR_PER_ARG])
|
|
||||||
{
|
|
||||||
int i = 0;
|
|
||||||
for (; i < CAR_PER_ARG; i++)
|
|
||||||
params[cursor][i] = -1;
|
|
||||||
|
|
||||||
if (**p != ':')
|
|
||||||
return;
|
|
||||||
|
|
||||||
char *np = NULL;
|
|
||||||
i = 0;
|
|
||||||
|
|
||||||
while (**p == ':' && i < CAR_PER_ARG) {
|
|
||||||
while (**p == ':')
|
|
||||||
(*p)++;
|
|
||||||
params[cursor][i] = strtol(*p, &np, 10);
|
|
||||||
*p = np;
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
csiparse(void)
|
csiparse(void)
|
||||||
{
|
{
|
||||||
@ -1207,7 +1180,6 @@ csiparse(void)
|
|||||||
v = -1;
|
v = -1;
|
||||||
csiescseq.arg[csiescseq.narg++] = v;
|
csiescseq.arg[csiescseq.narg++] = v;
|
||||||
p = np;
|
p = np;
|
||||||
readcolonargs(&p, csiescseq.narg-1, csiescseq.carg);
|
|
||||||
if (*p != ';' || csiescseq.narg == ESC_ARG_SIZ)
|
if (*p != ';' || csiescseq.narg == ESC_ARG_SIZ)
|
||||||
break;
|
break;
|
||||||
p++;
|
p++;
|
||||||
@ -1424,10 +1396,6 @@ tsetattr(const int *attr, int l)
|
|||||||
ATTR_STRUCK );
|
ATTR_STRUCK );
|
||||||
term.c.attr.fg = defaultfg;
|
term.c.attr.fg = defaultfg;
|
||||||
term.c.attr.bg = defaultbg;
|
term.c.attr.bg = defaultbg;
|
||||||
term.c.attr.ustyle = -1;
|
|
||||||
term.c.attr.ucolor[0] = -1;
|
|
||||||
term.c.attr.ucolor[1] = -1;
|
|
||||||
term.c.attr.ucolor[2] = -1;
|
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
term.c.attr.mode |= ATTR_BOLD;
|
term.c.attr.mode |= ATTR_BOLD;
|
||||||
@ -1439,14 +1407,7 @@ tsetattr(const int *attr, int l)
|
|||||||
term.c.attr.mode |= ATTR_ITALIC;
|
term.c.attr.mode |= ATTR_ITALIC;
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
term.c.attr.ustyle = csiescseq.carg[i][0];
|
|
||||||
|
|
||||||
if (term.c.attr.ustyle != 0)
|
|
||||||
term.c.attr.mode |= ATTR_UNDERLINE;
|
term.c.attr.mode |= ATTR_UNDERLINE;
|
||||||
else
|
|
||||||
term.c.attr.mode &= ~ATTR_UNDERLINE;
|
|
||||||
|
|
||||||
term.c.attr.mode ^= ATTR_DIRTYUNDERLINE;
|
|
||||||
break;
|
break;
|
||||||
case 5: /* slow blink */
|
case 5: /* slow blink */
|
||||||
/* FALLTHROUGH */
|
/* FALLTHROUGH */
|
||||||
@ -1497,18 +1458,6 @@ tsetattr(const int *attr, int l)
|
|||||||
case 49:
|
case 49:
|
||||||
term.c.attr.bg = defaultbg;
|
term.c.attr.bg = defaultbg;
|
||||||
break;
|
break;
|
||||||
case 58:
|
|
||||||
term.c.attr.ucolor[0] = csiescseq.carg[i][1];
|
|
||||||
term.c.attr.ucolor[1] = csiescseq.carg[i][2];
|
|
||||||
term.c.attr.ucolor[2] = csiescseq.carg[i][3];
|
|
||||||
term.c.attr.mode ^= ATTR_DIRTYUNDERLINE;
|
|
||||||
break;
|
|
||||||
case 59:
|
|
||||||
term.c.attr.ucolor[0] = -1;
|
|
||||||
term.c.attr.ucolor[1] = -1;
|
|
||||||
term.c.attr.ucolor[2] = -1;
|
|
||||||
term.c.attr.mode ^= ATTR_DIRTYUNDERLINE;
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
if (BETWEEN(attr[i], 30, 37)) {
|
if (BETWEEN(attr[i], 30, 37)) {
|
||||||
term.c.attr.fg = attr[i] - 30;
|
term.c.attr.fg = attr[i] - 30;
|
||||||
@ -1961,30 +1910,29 @@ strhandle(void)
|
|||||||
};
|
};
|
||||||
|
|
||||||
term.esc &= ~(ESC_STR_END|ESC_STR);
|
term.esc &= ~(ESC_STR_END|ESC_STR);
|
||||||
strescseq.buf[strescseq.len] = '\0';
|
strparse();
|
||||||
|
par = (narg = strescseq.narg) ? atoi(strescseq.args[0]) : 0;
|
||||||
|
|
||||||
switch (strescseq.type) {
|
switch (strescseq.type) {
|
||||||
case ']': /* OSC -- Operating System Command */
|
case ']': /* OSC -- Operating System Command */
|
||||||
strparse();
|
|
||||||
par = (narg = strescseq.narg) ? atoi(STRESCARGJUST(0)) : 0;
|
|
||||||
switch (par) {
|
switch (par) {
|
||||||
case 0:
|
case 0:
|
||||||
if (narg > 1) {
|
if (narg > 1) {
|
||||||
xsettitle(STRESCARGREST(1));
|
xsettitle(strescseq.args[1]);
|
||||||
xseticontitle(STRESCARGREST(1));
|
xseticontitle(strescseq.args[1]);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
case 1:
|
case 1:
|
||||||
if (narg > 1)
|
if (narg > 1)
|
||||||
xseticontitle(STRESCARGREST(1));
|
xseticontitle(strescseq.args[1]);
|
||||||
return;
|
return;
|
||||||
case 2:
|
case 2:
|
||||||
if (narg > 1)
|
if (narg > 1)
|
||||||
xsettitle(STRESCARGREST(1));
|
xsettitle(strescseq.args[1]);
|
||||||
return;
|
return;
|
||||||
case 52:
|
case 52:
|
||||||
if (narg > 2 && allowwindowops) {
|
if (narg > 2 && allowwindowops) {
|
||||||
dec = base64dec(STRESCARGJUST(2));
|
dec = base64dec(strescseq.args[2]);
|
||||||
if (dec) {
|
if (dec) {
|
||||||
xsetsel(dec);
|
xsetsel(dec);
|
||||||
xclipcopy();
|
xclipcopy();
|
||||||
@ -1998,7 +1946,7 @@ strhandle(void)
|
|||||||
case 12:
|
case 12:
|
||||||
if (narg < 2)
|
if (narg < 2)
|
||||||
break;
|
break;
|
||||||
p = STRESCARGREST(1);
|
p = strescseq.args[1];
|
||||||
if ((j = par - 10) < 0 || j >= LEN(osc_table))
|
if ((j = par - 10) < 0 || j >= LEN(osc_table))
|
||||||
break; /* shouldn't be possible */
|
break; /* shouldn't be possible */
|
||||||
|
|
||||||
@ -2014,10 +1962,10 @@ strhandle(void)
|
|||||||
case 4: /* color set */
|
case 4: /* color set */
|
||||||
if (narg < 3)
|
if (narg < 3)
|
||||||
break;
|
break;
|
||||||
p = STRESCARGJUST(2);
|
p = strescseq.args[2];
|
||||||
/* FALLTHROUGH */
|
/* FALLTHROUGH */
|
||||||
case 104: /* color reset */
|
case 104: /* color reset */
|
||||||
j = (narg > 1) ? atoi(STRESCARGJUST(1)) : -1;
|
j = (narg > 1) ? atoi(strescseq.args[1]) : -1;
|
||||||
|
|
||||||
if (p && !strcmp(p, "?")) {
|
if (p && !strcmp(p, "?")) {
|
||||||
osc_color_response(j, 0, 1);
|
osc_color_response(j, 0, 1);
|
||||||
@ -2039,7 +1987,7 @@ strhandle(void)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'k': /* old title set compatibility */
|
case 'k': /* old title set compatibility */
|
||||||
xsettitle(strescseq.buf);
|
xsettitle(strescseq.args[0]);
|
||||||
return;
|
return;
|
||||||
case 'P': /* DCS -- Device Control String */
|
case 'P': /* DCS -- Device Control String */
|
||||||
/* https://gitlab.com/gnachman/iterm2/-/wikis/synchronized-updates-spec */
|
/* https://gitlab.com/gnachman/iterm2/-/wikis/synchronized-updates-spec */
|
||||||
@ -2064,17 +2012,18 @@ strparse(void)
|
|||||||
char *p = strescseq.buf;
|
char *p = strescseq.buf;
|
||||||
|
|
||||||
strescseq.narg = 0;
|
strescseq.narg = 0;
|
||||||
|
strescseq.buf[strescseq.len] = '\0';
|
||||||
|
|
||||||
if (*p == '\0')
|
if (*p == '\0')
|
||||||
return;
|
return;
|
||||||
|
|
||||||
while (strescseq.narg < STR_ARG_SIZ) {
|
while (strescseq.narg < STR_ARG_SIZ) {
|
||||||
|
strescseq.args[strescseq.narg++] = p;
|
||||||
while ((c = *p) != ';' && c != '\0')
|
while ((c = *p) != ';' && c != '\0')
|
||||||
p++;
|
++p;
|
||||||
strescseq.argp[strescseq.narg++] = p;
|
|
||||||
if (c == '\0')
|
if (c == '\0')
|
||||||
return;
|
return;
|
||||||
p++;
|
*p++ = '\0';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
3
st.h
3
st.h
@ -34,7 +34,6 @@ enum glyph_attribute {
|
|||||||
ATTR_WIDE = 1 << 9,
|
ATTR_WIDE = 1 << 9,
|
||||||
ATTR_WDUMMY = 1 << 10,
|
ATTR_WDUMMY = 1 << 10,
|
||||||
ATTR_BOLD_FAINT = ATTR_BOLD | ATTR_FAINT,
|
ATTR_BOLD_FAINT = ATTR_BOLD | ATTR_FAINT,
|
||||||
ATTR_DIRTYUNDERLINE = 1 << 15,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum selection_mode {
|
enum selection_mode {
|
||||||
@ -66,8 +65,6 @@ typedef struct {
|
|||||||
ushort mode; /* attribute flags */
|
ushort mode; /* attribute flags */
|
||||||
uint32_t fg; /* foreground */
|
uint32_t fg; /* foreground */
|
||||||
uint32_t bg; /* background */
|
uint32_t bg; /* background */
|
||||||
int ustyle; /* underline style */
|
|
||||||
int ucolor[3]; /* underline color */
|
|
||||||
} Glyph;
|
} Glyph;
|
||||||
|
|
||||||
typedef Glyph *Line;
|
typedef Glyph *Line;
|
||||||
|
1
st.info
1
st.info
@ -1,5 +1,4 @@
|
|||||||
st-mono| simpleterm monocolor,
|
st-mono| simpleterm monocolor,
|
||||||
Su,
|
|
||||||
acsc=+C\,D-A.B0E``aaffgghFiGjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~,
|
acsc=+C\,D-A.B0E``aaffgghFiGjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~,
|
||||||
am,
|
am,
|
||||||
bce,
|
bce,
|
||||||
|
406
x.c
406
x.c
@ -45,14 +45,6 @@ typedef struct {
|
|||||||
signed char appcursor; /* application cursor */
|
signed char appcursor; /* application cursor */
|
||||||
} Key;
|
} Key;
|
||||||
|
|
||||||
/* Undercurl slope types */
|
|
||||||
enum undercurl_slope_type {
|
|
||||||
UNDERCURL_SLOPE_ASCENDING = 0,
|
|
||||||
UNDERCURL_SLOPE_TOP_CAP = 1,
|
|
||||||
UNDERCURL_SLOPE_DESCENDING = 2,
|
|
||||||
UNDERCURL_SLOPE_BOTTOM_CAP = 3
|
|
||||||
};
|
|
||||||
|
|
||||||
/* X modifiers */
|
/* X modifiers */
|
||||||
#define XK_ANY_MOD UINT_MAX
|
#define XK_ANY_MOD UINT_MAX
|
||||||
#define XK_NO_MOD 0
|
#define XK_NO_MOD 0
|
||||||
@ -1404,51 +1396,6 @@ xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x
|
|||||||
return numspecs;
|
return numspecs;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int isSlopeRising (int x, int iPoint, int waveWidth)
|
|
||||||
{
|
|
||||||
// . . . .
|
|
||||||
// / \ / \ / \ / \
|
|
||||||
// / \ / \ / \ / \
|
|
||||||
// . . . . .
|
|
||||||
|
|
||||||
// Find absolute `x` of point
|
|
||||||
x += iPoint * (waveWidth/2);
|
|
||||||
|
|
||||||
// Find index of absolute wave
|
|
||||||
int absSlope = x / ((float)waveWidth/2);
|
|
||||||
|
|
||||||
return (absSlope % 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int getSlope (int x, int iPoint, int waveWidth)
|
|
||||||
{
|
|
||||||
// Sizes: Caps are half width of slopes
|
|
||||||
// 1_2 1_2 1_2 1_2
|
|
||||||
// / \ / \ / \ / \
|
|
||||||
// / \ / \ / \ / \
|
|
||||||
// 0 3_0 3_0 3_0 3_
|
|
||||||
// <2-> <1> <---6---->
|
|
||||||
|
|
||||||
// Find type of first point
|
|
||||||
int firstType;
|
|
||||||
x -= (x / waveWidth) * waveWidth;
|
|
||||||
if (x < (waveWidth * (2.f/6.f)))
|
|
||||||
firstType = UNDERCURL_SLOPE_ASCENDING;
|
|
||||||
else if (x < (waveWidth * (3.f/6.f)))
|
|
||||||
firstType = UNDERCURL_SLOPE_TOP_CAP;
|
|
||||||
else if (x < (waveWidth * (5.f/6.f)))
|
|
||||||
firstType = UNDERCURL_SLOPE_DESCENDING;
|
|
||||||
else
|
|
||||||
firstType = UNDERCURL_SLOPE_BOTTOM_CAP;
|
|
||||||
|
|
||||||
// Find type of given point
|
|
||||||
int pointType = (iPoint % 4);
|
|
||||||
pointType += firstType;
|
|
||||||
pointType %= 4;
|
|
||||||
|
|
||||||
return pointType;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
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)
|
||||||
{
|
{
|
||||||
@ -1567,357 +1514,8 @@ xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, i
|
|||||||
|
|
||||||
/* Render underline and strikethrough. */
|
/* Render underline and strikethrough. */
|
||||||
if (base.mode & ATTR_UNDERLINE) {
|
if (base.mode & ATTR_UNDERLINE) {
|
||||||
// Underline Color
|
XftDrawRect(xw.draw, fg, winx, winy + dc.font.ascent * chscale + 1,
|
||||||
const int widthThreshold = 28; // +1 width every widthThreshold px of font
|
width, 1);
|
||||||
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) {
|
if (base.mode & ATTR_STRUCK) {
|
||||||
|
Reference in New Issue
Block a user