Compare commits

...

12 Commits

Author SHA1 Message Date
ba36c16af4 README.md 2024-05-01 11:11:17 +02:00
1ea1329c35 st 0.9 source code 2022-11-20 23:51:44 +01:00
ce0cbe1aa8 st 0.9 source code 2022-11-20 23:51:37 +01:00
d71cd9d4a7 README.md (Update clone URL) 2022-10-22 17:31:38 +02:00
q3aql
bb3f873aae change size of default window 2022-07-30 18:21:05 +02:00
q3aql
968ae5300b README.md (2022-07-21) 2022-07-21 01:34:19 +02:00
q3aql
691e3eb825 Increase/Decrease with Ctrl++/- 2022-07-21 01:31:26 +02:00
q3aql
6625527be7 README.md (2022-07-16) 2022-07-16 13:16:24 +02:00
q3aql
0e0f3eedc9 Update Name for Desktop File 2022-07-14 01:09:34 +02:00
q3aql
b9d19676f0 README.md 2022-07-13 18:59:38 +02:00
q3aql
1b63f9d89f Add shortcuts keys for zoom 2022-07-13 18:57:52 +02:00
q3aql
5ef7a11461 README.md (2022-07-11) 2022-07-11 00:18:41 +02:00
11 changed files with 122 additions and 122 deletions

3
FAQ
View File

@ -248,3 +248,6 @@ fonts:
Please don't bother reporting this bug to st, but notify the upstream Xft Please don't bother reporting this bug to st, but notify the upstream Xft
developers about fixing this bug. developers about fixing this bug.
As of 2022-09-05 this now seems to be finally fixed in libXft 2.3.5:
https://gitlab.freedesktop.org/xorg/lib/libxft/-/blob/libXft-2.3.5/NEWS

View File

@ -1,6 +1,6 @@
MIT/X Consortium License MIT/X Consortium License
© 2014-2020 Hiltjo Posthuma <hiltjo at codemadness dot org> © 2014-2022 Hiltjo Posthuma <hiltjo at codemadness dot org>
© 2018 Devin J. Pohly <djpohly at gmail dot com> © 2018 Devin J. Pohly <djpohly at gmail dot com>
© 2014-2017 Quentin Rameau <quinq at fifth dot space> © 2014-2017 Quentin Rameau <quinq at fifth dot space>
© 2009-2012 Aurélien APTEL <aurelien dot aptel at gmail dot com> © 2009-2012 Aurélien APTEL <aurelien dot aptel at gmail dot com>

View File

@ -14,23 +14,28 @@ st-config - My configuration of st suckless simple terminal
* `Support for scroll with Alt+j and Alt+k` * `Support for scroll with Alt+j and Alt+k`
* `Support for scroll with Alt+Up and Alt+Down` * `Support for scroll with Alt+Up and Alt+Down`
* `Support for scroll block with Alt+PageUp and Alt+PageDown` * `Support for scroll block with Alt+PageUp and Alt+PageDown`
* `Set font size with -z parameter`
* `Increase/Decrease/Reset zoom with Ctrl+9/8/0`
* `Increase/Decrease zoom with Ctrl+Plus/Minus`
* `Patch autocomplete applied` * `Patch autocomplete applied`
* `Includes shortcut installation` * `Includes shortcut installation`
<img src="examples/st.png" /> <img src="https://git.q3aql.dev/q3aql/st-config/raw/branch/master/examples/st.png" />
### Dependencies: ### Dependencies:
* **Arch Linux:** * **Arch Linux:**
```shell ```shell
$ sudo pacman -S gcc make coreutils freetype2 libxinerama fontconfig libx11 libxrender $ sudo pacman -S gcc git make coreutils freetype2 libxinerama fontconfig libx11 \
libxrender libxft --noconfirm
```` ````
* **Debian/Ubuntu:** * **Debian/Ubuntu:**
```shell ```shell
$ sudo apt install gcc make coreutils libfreetype-dev libxinerama-dev libfreetype6-dev libfontconfig1-dev libxrender-dev $ sudo apt install gcc git make coreutils libfreetype-dev libxinerama-dev libxft-dev \
libfreetype6-dev libfontconfig1-dev libxrender-dev -y
```` ````
### Build and install: ### Build and install:
@ -38,7 +43,7 @@ st-config - My configuration of st suckless simple terminal
* Open terminal and run the following commands: * Open terminal and run the following commands:
```shell ```shell
$ git clone https://github.com/q3aql/st-config $ git clone https://git.q3aql.dev/q3aql/st-config
$ cd st-config $ cd st-config
$ sudo make install clean $ sudo make install clean
```` ````

View File

@ -208,8 +208,13 @@ static Shortcut shortcuts[] = {
{ ShiftMask, XK_Print, printscreen, {.i = 0} }, { ShiftMask, XK_Print, printscreen, {.i = 0} },
{ XK_ANY_MOD, XK_Print, printsel, {.i = 0} }, { XK_ANY_MOD, XK_Print, printsel, {.i = 0} },
{ TERMMOD, XK_Prior, zoom, {.f = +1} }, { TERMMOD, XK_Prior, zoom, {.f = +1} },
{ ControlMask, XK_9, zoom, {.f = +1} },
{ ControlMask, XK_plus, zoom, {.f = +1} },
{ TERMMOD, XK_Next, zoom, {.f = -1} }, { TERMMOD, XK_Next, zoom, {.f = -1} },
{ ControlMask, XK_8, zoom, {.f = -1} },
{ ControlMask, XK_minus, zoom, {.f = -1} },
{ TERMMOD, XK_Home, zoomreset, {.f = 0} }, { TERMMOD, XK_Home, zoomreset, {.f = 0} },
{ ControlMask, XK_0, zoomreset, {.f = 0} },
{ TERMMOD, XK_C, clipcopy, {.i = 0} }, { TERMMOD, XK_C, clipcopy, {.i = 0} },
{ TERMMOD, XK_V, clippaste, {.i = 0} }, { TERMMOD, XK_V, clippaste, {.i = 0} },
{ TERMMOD, XK_Y, selpaste, {.i = 0} }, { TERMMOD, XK_Y, selpaste, {.i = 0} },

View File

@ -208,8 +208,13 @@ static Shortcut shortcuts[] = {
{ ShiftMask, XK_Print, printscreen, {.i = 0} }, { ShiftMask, XK_Print, printscreen, {.i = 0} },
{ XK_ANY_MOD, XK_Print, printsel, {.i = 0} }, { XK_ANY_MOD, XK_Print, printsel, {.i = 0} },
{ TERMMOD, XK_Prior, zoom, {.f = +1} }, { TERMMOD, XK_Prior, zoom, {.f = +1} },
{ ControlMask, XK_9, zoom, {.f = +1} },
{ ControlMask, XK_plus, zoom, {.f = +1} },
{ TERMMOD, XK_Next, zoom, {.f = -1} }, { TERMMOD, XK_Next, zoom, {.f = -1} },
{ ControlMask, XK_8, zoom, {.f = -1} },
{ ControlMask, XK_minus, zoom, {.f = -1} },
{ TERMMOD, XK_Home, zoomreset, {.f = 0} }, { TERMMOD, XK_Home, zoomreset, {.f = 0} },
{ ControlMask, XK_0, zoomreset, {.f = 0} },
{ TERMMOD, XK_C, clipcopy, {.i = 0} }, { TERMMOD, XK_C, clipcopy, {.i = 0} },
{ TERMMOD, XK_V, clippaste, {.i = 0} }, { TERMMOD, XK_V, clippaste, {.i = 0} },
{ TERMMOD, XK_Y, selpaste, {.i = 0} }, { TERMMOD, XK_Y, selpaste, {.i = 0} },

View File

@ -1,5 +1,5 @@
# st version # st version
VERSION = 0.8.5 VERSION = 0.9
# Customize below to fit your system # Customize below to fit your system
@ -30,6 +30,7 @@ STLDFLAGS = $(LIBS) $(LDFLAGS)
#LIBS = -L$(X11LIB) -lm -lX11 -lutil -lXft \ #LIBS = -L$(X11LIB) -lm -lX11 -lutil -lXft \
# `$(PKG_CONFIG) --libs fontconfig` \ # `$(PKG_CONFIG) --libs fontconfig` \
# `$(PKG_CONFIG) --libs freetype2` # `$(PKG_CONFIG) --libs freetype2`
#MANPREFIX = ${PREFIX}/man
# compiler and linker # compiler and linker
# CC = c99 # CC = c99

118
st.c
View File

@ -169,6 +169,7 @@ static void csidump(void);
static void csihandle(void); static void csihandle(void);
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 int eschandle(uchar); static int eschandle(uchar);
static void strdump(void); static void strdump(void);
static void strhandle(void); static void strhandle(void);
@ -357,25 +358,10 @@ utf8validate(Rune *u, size_t i)
return i; return i;
} }
static const char base64_digits[] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 0, 0,
63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 0, 0, 0, -1, 0, 0, 0, 0, 1,
2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
22, 23, 24, 25, 0, 0, 0, 0, 0, 0, 26, 27, 28, 29, 30, 31, 32, 33, 34,
35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
char char
base64dec_getc(const char **src) base64dec_getc(const char **src)
{ {
while (**src && !isprint(**src)) while (**src && !isprint((unsigned char)**src))
(*src)++; (*src)++;
return **src ? *((*src)++) : '='; /* emulate padding if string ends */ return **src ? *((*src)++) : '='; /* emulate padding if string ends */
} }
@ -385,6 +371,13 @@ base64dec(const char *src)
{ {
size_t in_len = strlen(src); size_t in_len = strlen(src);
char *result, *dst; char *result, *dst;
static const char base64_digits[256] = {
[43] = 62, 0, 0, 0, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
0, 0, 0, -1, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 0, 0, 0,
0, 0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
};
if (in_len % 4) if (in_len % 4)
in_len += 4 - (in_len % 4); in_len += 4 - (in_len % 4);
@ -957,7 +950,7 @@ ttyresize(int tw, int th)
} }
void void
ttyhangup() ttyhangup(void)
{ {
/* Send SIGHUP to shell */ /* Send SIGHUP to shell */
kill(pid, SIGHUP); kill(pid, SIGHUP);
@ -1906,39 +1899,28 @@ csireset(void)
} }
void void
osc4_color_response(int num) osc_color_response(int num, int index, int is_osc4)
{ {
int n; int n;
char buf[32]; char buf[32];
unsigned char r, g, b; unsigned char r, g, b;
if (xgetcolor(num, &r, &g, &b)) { if (xgetcolor(is_osc4 ? num : index, &r, &g, &b)) {
fprintf(stderr, "erresc: failed to fetch osc4 color %d\n", num); fprintf(stderr, "erresc: failed to fetch %s color %d\n",
is_osc4 ? "osc4" : "osc",
is_osc4 ? num : index);
return; return;
} }
n = snprintf(buf, sizeof buf, "\033]4;%d;rgb:%02x%02x/%02x%02x/%02x%02x\007", n = snprintf(buf, sizeof buf, "\033]%s%d;rgb:%02x%02x/%02x%02x/%02x%02x\007",
num, r, r, g, g, b, b); is_osc4 ? "4;" : "", num, r, r, g, g, b, b);
if (n < 0 || n >= sizeof(buf)) {
ttywrite(buf, n, 1); fprintf(stderr, "error: %s while printing %s response\n",
} n < 0 ? "snprintf failed" : "truncation occurred",
is_osc4 ? "osc4" : "osc");
void } else {
osc_color_response(int index, int num) ttywrite(buf, n, 1);
{
int n;
char buf[32];
unsigned char r, g, b;
if (xgetcolor(index, &r, &g, &b)) {
fprintf(stderr, "erresc: failed to fetch osc color %d\n", index);
return;
} }
n = snprintf(buf, sizeof buf, "\033]%d;rgb:%02x%02x/%02x%02x/%02x%02x\007",
num, r, r, g, g, b, b);
ttywrite(buf, n, 1);
} }
void void
@ -1946,6 +1928,11 @@ strhandle(void)
{ {
char *p = NULL, *dec; char *p = NULL, *dec;
int j, narg, par; int j, narg, par;
const struct { int idx; char *str; } osc_table[] = {
{ defaultfg, "foreground" },
{ defaultbg, "background" },
{ defaultcs, "cursor" }
};
term.esc &= ~(ESC_STR_END|ESC_STR); term.esc &= ~(ESC_STR_END|ESC_STR);
strparse(); strparse();
@ -1980,43 +1967,22 @@ strhandle(void)
} }
return; return;
case 10: case 10:
if (narg < 2)
break;
p = strescseq.args[1];
if (!strcmp(p, "?"))
osc_color_response(defaultfg, 10);
else if (xsetcolorname(defaultfg, p))
fprintf(stderr, "erresc: invalid foreground color: %s\n", p);
else
redraw();
return;
case 11: case 11:
if (narg < 2)
break;
p = strescseq.args[1];
if (!strcmp(p, "?"))
osc_color_response(defaultbg, 11);
else if (xsetcolorname(defaultbg, p))
fprintf(stderr, "erresc: invalid background color: %s\n", p);
else
redraw();
return;
case 12: case 12:
if (narg < 2) if (narg < 2)
break; break;
p = strescseq.args[1]; p = strescseq.args[1];
if ((j = par - 10) < 0 || j >= LEN(osc_table))
break; /* shouldn't be possible */
if (!strcmp(p, "?")) if (!strcmp(p, "?")) {
osc_color_response(defaultcs, 12); osc_color_response(par, osc_table[j].idx, 0);
else if (xsetcolorname(defaultcs, p)) } else if (xsetcolorname(osc_table[j].idx, p)) {
fprintf(stderr, "erresc: invalid cursor color: %s\n", p); fprintf(stderr, "erresc: invalid %s color: %s\n",
else osc_table[j].str, p);
redraw(); } else {
tfulldirt();
}
return; return;
case 4: /* color set */ case 4: /* color set */
if (narg < 3) if (narg < 3)
@ -2026,9 +1992,9 @@ strhandle(void)
case 104: /* color reset */ case 104: /* color reset */
j = (narg > 1) ? atoi(strescseq.args[1]) : -1; j = (narg > 1) ? atoi(strescseq.args[1]) : -1;
if (p && !strcmp(p, "?")) if (p && !strcmp(p, "?")) {
osc4_color_response(j); osc_color_response(j, 0, 1);
else if (xsetcolorname(j, p)) { } else if (xsetcolorname(j, p)) {
if (par == 104 && narg <= 1) if (par == 104 && narg <= 1)
return; /* color reset without parameter */ return; /* color reset without parameter */
fprintf(stderr, "erresc: invalid color j=%d, p=%s\n", fprintf(stderr, "erresc: invalid color j=%d, p=%s\n",
@ -2038,7 +2004,7 @@ strhandle(void)
* TODO if defaultbg color is changed, borders * TODO if defaultbg color is changed, borders
* are dirty * are dirty
*/ */
redraw(); tfulldirt();
} }
return; return;
} }

View File

@ -5,7 +5,7 @@ TryExec=st
Icon=utilities-terminal Icon=utilities-terminal
Terminal=false Terminal=false
Categories=System;TerminalEmulator; Categories=System;TerminalEmulator;
Name=st Name=st Simple Terminal (Suckless)
GenericName=Terminal GenericName=Terminal
Comment=st is a simple terminal implementation for X Comment=st is a simple terminal implementation for X
StartupWMClass=st-256color StartupWMClass=st-256color

2
st.h
View File

@ -115,8 +115,6 @@ void *xmalloc(size_t);
void *xrealloc(void *, size_t); void *xrealloc(void *, size_t);
char *xstrdup(const char *); char *xstrdup(const char *);
int xgetcolor(int x, unsigned char *r, unsigned char *g, unsigned char *b);
/* config.h globals */ /* config.h globals */
extern char *utmp; extern char *utmp;
extern char *scroll; extern char *scroll;

1
win.h
View File

@ -30,6 +30,7 @@ void xdrawline(Line, int, int, int);
void xfinishdraw(void); void xfinishdraw(void);
void xloadcols(void); void xloadcols(void);
int xsetcolorname(int, const char *); int xsetcolorname(int, const char *);
int xgetcolor(int, unsigned char *, unsigned char *, unsigned char *);
void xseticontitle(char *); void xseticontitle(char *);
void xsettitle(char *); void xsettitle(char *);
int xsetcursor(int); int xsetcursor(int);

90
x.c
View File

@ -253,7 +253,7 @@ static char *opt_line = NULL;
static char *opt_name = NULL; static char *opt_name = NULL;
static char *opt_title = NULL; static char *opt_title = NULL;
static int oldbutton = 3; /* button event on startup: 3 = release */ static uint buttons; /* bit field of pressed buttons */
static int cursorblinks = 0; static int cursorblinks = 0;
void void
@ -366,61 +366,68 @@ mousesel(XEvent *e, int done)
void void
mousereport(XEvent *e) mousereport(XEvent *e)
{ {
int len, x = evcol(e), y = evrow(e), int len, btn, code;
button = e->xbutton.button, state = e->xbutton.state; int x = evcol(e), y = evrow(e);
int state = e->xbutton.state;
char buf[40]; char buf[40];
static int ox, oy; static int ox, oy;
/* from urxvt */ if (e->type == MotionNotify) {
if (e->xbutton.type == MotionNotify) {
if (x == ox && y == oy) if (x == ox && y == oy)
return; return;
if (!IS_SET(MODE_MOUSEMOTION) && !IS_SET(MODE_MOUSEMANY)) if (!IS_SET(MODE_MOUSEMOTION) && !IS_SET(MODE_MOUSEMANY))
return; return;
/* MOUSE_MOTION: no reporting if no button is pressed */ /* MODE_MOUSEMOTION: no reporting if no button is pressed */
if (IS_SET(MODE_MOUSEMOTION) && oldbutton == 3) if (IS_SET(MODE_MOUSEMOTION) && buttons == 0)
return; return;
/* Set btn to lowest-numbered pressed button, or 12 if no
button = oldbutton + 32; * buttons are pressed. */
ox = x; for (btn = 1; btn <= 11 && !(buttons & (1<<(btn-1))); btn++)
oy = y; ;
code = 32;
} else { } else {
if (!IS_SET(MODE_MOUSESGR) && e->xbutton.type == ButtonRelease) { btn = e->xbutton.button;
button = 3; /* Only buttons 1 through 11 can be encoded */
} else { if (btn < 1 || btn > 11)
button -= Button1; return;
if (button >= 7) if (e->type == ButtonRelease) {
button += 128 - 7;
else if (button >= 3)
button += 64 - 3;
}
if (e->xbutton.type == ButtonPress) {
oldbutton = button;
ox = x;
oy = y;
} else if (e->xbutton.type == ButtonRelease) {
oldbutton = 3;
/* MODE_MOUSEX10: no button release reporting */ /* MODE_MOUSEX10: no button release reporting */
if (IS_SET(MODE_MOUSEX10)) if (IS_SET(MODE_MOUSEX10))
return; return;
if (button == 64 || button == 65) /* Don't send release events for the scroll wheel */
if (btn == 4 || btn == 5)
return; return;
} }
code = 0;
} }
ox = x;
oy = y;
/* Encode btn into code. If no button is pressed for a motion event in
* MODE_MOUSEMANY, then encode it as a release. */
if ((!IS_SET(MODE_MOUSESGR) && e->type == ButtonRelease) || btn == 12)
code += 3;
else if (btn >= 8)
code += 128 + btn - 8;
else if (btn >= 4)
code += 64 + btn - 4;
else
code += btn - 1;
if (!IS_SET(MODE_MOUSEX10)) { if (!IS_SET(MODE_MOUSEX10)) {
button += ((state & ShiftMask ) ? 4 : 0) code += ((state & ShiftMask ) ? 4 : 0)
+ ((state & Mod4Mask ) ? 8 : 0) + ((state & Mod1Mask ) ? 8 : 0) /* meta key: alt */
+ ((state & ControlMask) ? 16 : 0); + ((state & ControlMask) ? 16 : 0);
} }
if (IS_SET(MODE_MOUSESGR)) { if (IS_SET(MODE_MOUSESGR)) {
len = snprintf(buf, sizeof(buf), "\033[<%d;%d;%d%c", len = snprintf(buf, sizeof(buf), "\033[<%d;%d;%d%c",
button, x+1, y+1, code, x+1, y+1,
e->xbutton.type == ButtonRelease ? 'm' : 'M'); e->type == ButtonRelease ? 'm' : 'M');
} else if (x < 223 && y < 223) { } else if (x < 223 && y < 223) {
len = snprintf(buf, sizeof(buf), "\033[M%c%c%c", len = snprintf(buf, sizeof(buf), "\033[M%c%c%c",
32+button, 32+x+1, 32+y+1); 32+code, 32+x+1, 32+y+1);
} else { } else {
return; return;
} }
@ -463,9 +470,13 @@ mouseaction(XEvent *e, uint release)
void void
bpress(XEvent *e) bpress(XEvent *e)
{ {
int btn = e->xbutton.button;
struct timespec now; struct timespec now;
int snap; int snap;
if (1 <= btn && btn <= 11)
buttons |= 1 << (btn-1);
if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forcemousemod)) { if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forcemousemod)) {
mousereport(e); mousereport(e);
return; return;
@ -474,7 +485,7 @@ bpress(XEvent *e)
if (mouseaction(e, 0)) if (mouseaction(e, 0))
return; return;
if (e->xbutton.button == Button1) { if (btn == Button1) {
/* /*
* If the user clicks below predefined timeouts specific * If the user clicks below predefined timeouts specific
* snapping behaviour is exposed. * snapping behaviour is exposed.
@ -688,6 +699,11 @@ xsetsel(char *str)
void void
brelease(XEvent *e) brelease(XEvent *e)
{ {
int btn = e->xbutton.button;
if (1 <= btn && btn <= 11)
buttons &= ~(1 << (btn-1));
if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forcemousemod)) { if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forcemousemod)) {
mousereport(e); mousereport(e);
return; return;
@ -695,7 +711,7 @@ brelease(XEvent *e)
if (mouseaction(e, 1)) if (mouseaction(e, 1))
return; return;
if (e->xbutton.button == Button1) if (btn == Button1)
mousesel(e, 1); mousesel(e, 1);
} }
@ -1479,12 +1495,12 @@ 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) {
XftDrawRect(xw.draw, fg, winx, winy + dc.font.ascent + 1, XftDrawRect(xw.draw, fg, winx, winy + dc.font.ascent * chscale + 1,
width, 1); width, 1);
} }
if (base.mode & ATTR_STRUCK) { if (base.mode & ATTR_STRUCK) {
XftDrawRect(xw.draw, fg, winx, winy + 2 * dc.font.ascent / 3, XftDrawRect(xw.draw, fg, winx, winy + 2 * dc.font.ascent * chscale / 3,
width, 1); width, 1);
} }