Compare commits

...

10 Commits

Author SHA1 Message Date
Luca Bilke 7c84da62e7 small changes 2023-06-13 23:24:28 +02:00
Luca Bilke d53df10eea selection colors 2023-06-13 23:11:40 +02:00
Luca Bilke 6d789d8231 add missing bracket, write config 2023-06-13 23:04:39 +02:00
Luca Bilke fc861f2167 working dir 2023-06-13 22:15:42 +02:00
Luca Bilke 6e5103528d csi 22/23 2023-06-13 22:15:23 +02:00
Luca Bilke e763dcc73d anysize 2023-06-13 22:04:16 +02:00
Luca Bilke 5f395b1016 bold is not bright 2023-06-13 22:00:16 +02:00
Luca Bilke d3881a0437 blinking cursor 2023-06-13 21:59:31 +02:00
Luca Bilke 27af760f77 undercurl 2023-06-13 21:57:23 +02:00
Luca Bilke 1865c95a26 boxdraw + ligatures 2023-06-13 21:41:39 +02:00
27 changed files with 4043 additions and 574 deletions

253
FAQ
View File

@ -1,253 +0,0 @@
## Why does st not handle utmp entries?
Use the excellent tool of [utmp](https://git.suckless.org/utmp/) for this task.
## Some _random program_ complains that st is unknown/not recognised/unsupported/whatever!
It means that st doesnt have any terminfo entry on your system. Chances are
you did not `make install`. If you just want to test it without installing it,
you can manually run `tic -sx st.info`.
## Nothing works, and nothing is said about an unknown terminal!
* Some programs just assume theyre running in xterm i.e. they dont rely on
terminfo. What you see is the current state of the “xterm compliance”.
* Some programs dont complain about the lacking st description and default to
another terminal. In that case see the question about terminfo.
## How do I scroll back up?
* Using a terminal multiplexer.
* `st -e tmux` using C-b [
* `st -e screen` using C-a ESC
* Using the excellent tool of [scroll](https://git.suckless.org/scroll/).
* Using the scrollback [patch](https://st.suckless.org/patches/scrollback/).
## I would like to have utmp and/or scroll functionality by default
You can add the absolute path of both programs in your config.h file. You only
have to modify the value of utmp and scroll variables.
## Why doesn't the Del key work in some programs?
Taken from the terminfo manpage:
If the terminal has a keypad that transmits codes when the keys
are pressed, this information can be given. Note that it is not
possible to handle terminals where the keypad only works in
local (this applies, for example, to the unshifted HP 2621 keys).
If the keypad can be set to transmit or not transmit, give these
codes as smkx and rmkx. Otherwise the keypad is assumed to
always transmit.
In the st case smkx=E[?1hE= and rmkx=E[?1lE>, so it is mandatory that
applications which want to test against keypad keys send these
sequences.
But buggy applications (like bash and irssi, for example) don't do this. A fast
solution for them is to use the following command:
$ printf '\033[?1h\033=' >/dev/tty
or
$ tput smkx
In the case of bash, readline is used. Readline has a different note in its
manpage about this issue:
enable-keypad (Off)
When set to On, readline will try to enable the
application keypad when it is called. Some systems
need this to enable arrow keys.
Adding this option to your .inputrc will fix the keypad problem for all
applications using readline.
If you are using zsh, then read the zsh FAQ
<http://zsh.sourceforge.net/FAQ/zshfaq03.html#l25>:
It should be noted that the O / [ confusion can occur with other keys
such as Home and End. Some systems let you query the key sequences
sent by these keys from the system's terminal database, terminfo.
Unfortunately, the key sequences given there typically apply to the
mode that is not the one zsh uses by default (it's the "application"
mode rather than the "raw" mode). Explaining the use of terminfo is
outside of the scope of this FAQ, but if you wish to use the key
sequences given there you can tell the line editor to turn on
"application" mode when it starts and turn it off when it stops:
function zle-line-init () { echoti smkx }
function zle-line-finish () { echoti rmkx }
zle -N zle-line-init
zle -N zle-line-finish
Putting these lines into your .zshrc will fix the problems.
## How can I use meta in 8bit mode?
St supports meta in 8bit mode, but the default terminfo entry doesn't
use this capability. If you want it, you have to use the 'st-meta' value
in TERM.
## I cannot compile st in OpenBSD
OpenBSD lacks librt, despite it being mandatory in POSIX
<http://pubs.opengroup.org/onlinepubs/9699919799/utilities/c99.html#tag_20_11_13>.
If you want to compile st for OpenBSD you have to remove -lrt from config.mk, and
st will compile without any loss of functionality, because all the functions are
included in libc on this platform.
## The Backspace Case
St is emulating the Linux way of handling backspace being delete and delete being
backspace.
This is an issue that was discussed in suckless mailing list
<https://lists.suckless.org/dev/1404/20697.html>. Here is why some old grumpy
terminal users wants its backspace to be how he feels it:
Well, I am going to comment why I want to change the behaviour
of this key. When ASCII was defined in 1968, communication
with computers was done using punched cards, or hardcopy
terminals (basically a typewriter machine connected with the
computer using a serial port). ASCII defines DELETE as 7F,
because, in punched-card terms, it means all the holes of the
card punched; it is thus a kind of 'physical delete'. In the
same way, the BACKSPACE key was a non-destructive backspace,
as on a typewriter. So, if you wanted to delete a character,
you had to BACKSPACE and then DELETE. Another use of BACKSPACE
was to type accented characters, for example 'a BACKSPACE `'.
The VT100 had no BACKSPACE key; it was generated using the
CONTROL key as another control character (CONTROL key sets to
0 b7 b6 b5, so it converts H (code 0x48) into BACKSPACE (code
0x08)), but it had a DELETE key in a similar position where
the BACKSPACE key is located today on common PC keyboards.
All the terminal emulators emulated the difference between
these keys correctly: the backspace key generated a BACKSPACE
(^H) and delete key generated a DELETE (^?).
But a problem arose when Linus Torvalds wrote Linux. Unlike
earlier terminals, the Linux virtual terminal (the terminal
emulator integrated in the kernel) returned a DELETE when
backspace was pressed, due to the VT100 having a DELETE key in
the same position. This created a lot of problems (see [1]
and [2]). Since Linux has become the king, a lot of terminal
emulators today generate a DELETE when the backspace key is
pressed in order to avoid problems with Linux. The result is
that the only way of generating a BACKSPACE on these systems
is by using CONTROL + H. (I also think that emacs had an
important point here because the CONTROL + H prefix is used
in emacs in some commands (help commands).)
From point of view of the kernel, you can change the key
for deleting a previous character with stty erase. When you
connect a real terminal into a machine you describe the type
of terminal, so getty configures the correct value of stty
erase for this terminal. In the case of terminal emulators,
however, you don't have any getty that can set the correct
value of stty erase, so you always get the default value.
For this reason, it is necessary to add 'stty erase ^H' to your
profile if you have changed the value of the backspace key.
Of course, another solution is for st itself to modify the
value of stty erase. I usually have the inverse problem:
when I connect to non-Unix machines, I have to press CONTROL +
h to get a BACKSPACE. The inverse problem occurs when a user
connects to my Unix machines from a different system with a
correct backspace key.
[1] http://www.ibb.net/~anne/keyboard.html
[2] http://www.tldp.org/HOWTO/Keyboard-and-Console-HOWTO-5.html
## But I really want the old grumpy behaviour of my terminal
Apply [1].
[1] https://st.suckless.org/patches/delkey
## Why do images not work in st using the w3m image hack?
w3mimg uses a hack that draws an image on top of the terminal emulator Drawable
window. The hack relies on the terminal to use a single buffer to draw its
contents directly.
st uses double-buffered drawing so the image is quickly replaced and may show a
short flicker effect.
Below is a patch example to change st double-buffering to a single Drawable
buffer.
diff --git a/x.c b/x.c
--- a/x.c
+++ b/x.c
@@ -732,10 +732,6 @@ xresize(int col, int row)
win.tw = col * win.cw;
win.th = row * win.ch;
- XFreePixmap(xw.dpy, xw.buf);
- xw.buf = XCreatePixmap(xw.dpy, xw.win, win.w, win.h,
- DefaultDepth(xw.dpy, xw.scr));
- XftDrawChange(xw.draw, xw.buf);
xclear(0, 0, win.w, win.h);
/* resize to new width */
@@ -1148,8 +1144,7 @@ xinit(int cols, int rows)
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 = xw.win;
XSetForeground(xw.dpy, dc.gc, dc.col[defaultbg].pixel);
XFillRectangle(xw.dpy, xw.buf, dc.gc, 0, 0, win.w, win.h);
@@ -1632,8 +1627,6 @@ xdrawline(Line line, int x1, int y1, int x2)
void
xfinishdraw(void)
{
- XCopyArea(xw.dpy, xw.buf, xw.win, dc.gc, 0, 0, win.w,
- win.h, 0, 0);
XSetForeground(xw.dpy, dc.gc,
dc.col[IS_SET(MODE_REVERSE)?
defaultfg : defaultbg].pixel);
## BadLength X error in Xft when trying to render emoji
Xft makes st crash when rendering color emojis with the following error:
"X Error of failed request: BadLength (poly request too large or internal Xlib length error)"
Major opcode of failed request: 139 (RENDER)
Minor opcode of failed request: 20 (RenderAddGlyphs)
Serial number of failed request: 1595
Current serial number in output stream: 1818"
This is a known bug in Xft (not st) which happens on some platforms and
combination of particular fonts and fontconfig settings.
See also:
https://gitlab.freedesktop.org/xorg/lib/libxft/issues/6
https://bugs.freedesktop.org/show_bug.cgi?id=107534
https://bugzilla.redhat.com/show_bug.cgi?id=1498269
The solution is to remove color emoji fonts or disable this in the fontconfig
XML configuration. As an ugly workaround (which may work only on newer
fontconfig versions (FC_COLOR)), the following code can be used to mask color
fonts:
FcPatternAddBool(fcpattern, FC_COLOR, FcFalse);
Please don't bother reporting this bug to st, but notify the upstream Xft
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

17
LEGACY
View File

@ -1,17 +0,0 @@
A STATEMENT ON LEGACY SUPPORT
In the terminal world there is much cruft that comes from old and unsup
ported terminals that inherit incompatible modes and escape sequences
which noone is able to know, except when he/she comes from that time and
developed a graphical vt100 emulator at that time.
One goal of st is to only support what is really needed. When you en
counter a sequence which you really need, implement it. But while you
are at it, do not add the other cruft you might encounter while sneek
ing at other terminal emulators. History has bloated them and there is
no real evidence that most of the sequences are used today.
Christoph Lohmann <20h@r-36.net>
2012-09-13T07:00:36.081271045+02:00

View File

@ -4,7 +4,7 @@
include config.mk
SRC = st.c x.c
SRC = st.c x.c boxdraw.c hb.c
OBJ = $(SRC:.c=.o)
all: options st
@ -22,7 +22,9 @@ config.h:
$(CC) $(STCFLAGS) -c $<
st.o: config.h st.h win.h
x.o: arg.h config.h st.h win.h
x.o: arg.h config.h st.h win.h hb.h
boxdraw.o: config.h st.h boxdraw_data.h
hb.o: st.h
$(OBJ): config.h config.mk

34
README
View File

@ -1,34 +0,0 @@
st - simple terminal
--------------------
st is a simple terminal emulator for X which sucks less.
Requirements
------------
In order to build st you need the Xlib header files.
Installation
------------
Edit config.mk to match your local setup (st is installed into
the /usr/local namespace by default).
Afterwards enter the following command to build and install st (if
necessary as root):
make clean install
Running st
----------
If you did not install st with make clean install, you must compile
the st terminfo entry with the following command:
tic -sx st.info
See the man page for additional details.
Credits
-------
Based on Aurélien APTEL <aurelien dot aptel at gmail dot com> bt source code.

28
TODO
View File

@ -1,28 +0,0 @@
vt emulation
------------
* double-height support
code & interface
----------------
* add a simple way to do multiplexing
drawing
-------
* add diacritics support to xdraws()
* switch to a suckless font drawing library
* make the font cache simpler
* add better support for brightening of the upper colors
bugs
----
* fix shift up/down (shift selection in emacs)
* remove DEC test sequence when appropriate
misc
----
$ grep -nE 'XXX|TODO' st.c

2
TODO.md Normal file
View File

@ -0,0 +1,2 @@
# TODO
- [ ] Make undercurl more subtle

194
boxdraw.c Normal file
View File

@ -0,0 +1,194 @@
/*
* Copyright 2018 Avi Halachmi (:avih) avihpit@yahoo.com https://github.com/avih
* MIT/X Consortium License
*/
#include <X11/Xft/Xft.h>
#include "st.h"
#include "boxdraw_data.h"
/* Rounded non-negative integers division of n / d */
#define DIV(n, d) (((n) + (d) / 2) / (d))
static Display *xdpy;
static Colormap xcmap;
static XftDraw *xd;
static Visual *xvis;
static void drawbox(int, int, int, int, XftColor *, XftColor *, ushort);
static void drawboxlines(int, int, int, int, XftColor *, ushort);
/* public API */
void
boxdraw_xinit(Display *dpy, Colormap cmap, XftDraw *draw, Visual *vis)
{
xdpy = dpy; xcmap = cmap; xd = draw, xvis = vis;
}
int
isboxdraw(Rune u)
{
Rune block = u & ~0xff;
return (boxdraw && block == 0x2500 && boxdata[(uint8_t)u]) ||
(boxdraw_braille && block == 0x2800);
}
/* the "index" is actually the entire shape data encoded as ushort */
ushort
boxdrawindex(const Glyph *g)
{
if (boxdraw_braille && (g->u & ~0xff) == 0x2800)
return BRL | (uint8_t)g->u;
if (boxdraw_bold && (g->mode & ATTR_BOLD))
return BDB | boxdata[(uint8_t)g->u];
return boxdata[(uint8_t)g->u];
}
void
drawboxes(int x, int y, int cw, int ch, XftColor *fg, XftColor *bg,
const XftGlyphFontSpec *specs, int len)
{
for ( ; len-- > 0; x += cw, specs++)
drawbox(x, y, cw, ch, fg, bg, (ushort)specs->glyph);
}
/* implementation */
void
drawbox(int x, int y, int w, int h, XftColor *fg, XftColor *bg, ushort bd)
{
ushort cat = bd & ~(BDB | 0xff); /* mask out bold and data */
if (bd & (BDL | BDA)) {
/* lines (light/double/heavy/arcs) */
drawboxlines(x, y, w, h, fg, bd);
} else if (cat == BBD) {
/* lower (8-X)/8 block */
int d = DIV((uint8_t)bd * h, 8);
XftDrawRect(xd, fg, x, y + d, w, h - d);
} else if (cat == BBU) {
/* upper X/8 block */
XftDrawRect(xd, fg, x, y, w, DIV((uint8_t)bd * h, 8));
} else if (cat == BBL) {
/* left X/8 block */
XftDrawRect(xd, fg, x, y, DIV((uint8_t)bd * w, 8), h);
} else if (cat == BBR) {
/* right (8-X)/8 block */
int d = DIV((uint8_t)bd * w, 8);
XftDrawRect(xd, fg, x + d, y, w - d, h);
} else if (cat == BBQ) {
/* Quadrants */
int w2 = DIV(w, 2), h2 = DIV(h, 2);
if (bd & TL)
XftDrawRect(xd, fg, x, y, w2, h2);
if (bd & TR)
XftDrawRect(xd, fg, x + w2, y, w - w2, h2);
if (bd & BL)
XftDrawRect(xd, fg, x, y + h2, w2, h - h2);
if (bd & BR)
XftDrawRect(xd, fg, x + w2, y + h2, w - w2, h - h2);
} else if (bd & BBS) {
/* Shades - data is 1/2/3 for 25%/50%/75% alpha, respectively */
int d = (uint8_t)bd;
XftColor xfc;
XRenderColor xrc = { .alpha = 0xffff };
xrc.red = DIV(fg->color.red * d + bg->color.red * (4 - d), 4);
xrc.green = DIV(fg->color.green * d + bg->color.green * (4 - d), 4);
xrc.blue = DIV(fg->color.blue * d + bg->color.blue * (4 - d), 4);
XftColorAllocValue(xdpy, xvis, xcmap, &xrc, &xfc);
XftDrawRect(xd, &xfc, x, y, w, h);
XftColorFree(xdpy, xvis, xcmap, &xfc);
} else if (cat == BRL) {
/* braille, each data bit corresponds to one dot at 2x4 grid */
int w1 = DIV(w, 2);
int h1 = DIV(h, 4), h2 = DIV(h, 2), h3 = DIV(3 * h, 4);
if (bd & 1) XftDrawRect(xd, fg, x, y, w1, h1);
if (bd & 2) XftDrawRect(xd, fg, x, y + h1, w1, h2 - h1);
if (bd & 4) XftDrawRect(xd, fg, x, y + h2, w1, h3 - h2);
if (bd & 8) XftDrawRect(xd, fg, x + w1, y, w - w1, h1);
if (bd & 16) XftDrawRect(xd, fg, x + w1, y + h1, w - w1, h2 - h1);
if (bd & 32) XftDrawRect(xd, fg, x + w1, y + h2, w - w1, h3 - h2);
if (bd & 64) XftDrawRect(xd, fg, x, y + h3, w1, h - h3);
if (bd & 128) XftDrawRect(xd, fg, x + w1, y + h3, w - w1, h - h3);
}
}
void
drawboxlines(int x, int y, int w, int h, XftColor *fg, ushort bd)
{
/* s: stem thickness. width/8 roughly matches underscore thickness. */
/* We draw bold as 1.5 * normal-stem and at least 1px thicker. */
/* doubles draw at least 3px, even when w or h < 3. bold needs 6px. */
int mwh = MIN(w, h);
int base_s = MAX(1, DIV(mwh, 8));
int bold = (bd & BDB) && mwh >= 6; /* possibly ignore boldness */
int s = bold ? MAX(base_s + 1, DIV(3 * base_s, 2)) : base_s;
int w2 = DIV(w - s, 2), h2 = DIV(h - s, 2);
/* the s-by-s square (x + w2, y + h2, s, s) is the center texel. */
/* The base length (per direction till edge) includes this square. */
int light = bd & (LL | LU | LR | LD);
int double_ = bd & (DL | DU | DR | DD);
if (light) {
/* d: additional (negative) length to not-draw the center */
/* texel - at arcs and avoid drawing inside (some) doubles */
int arc = bd & BDA;
int multi_light = light & (light - 1);
int multi_double = double_ & (double_ - 1);
/* light crosses double only at DH+LV, DV+LH (ref. shapes) */
int d = arc || (multi_double && !multi_light) ? -s : 0;
if (bd & LL)
XftDrawRect(xd, fg, x, y + h2, w2 + s + d, s);
if (bd & LU)
XftDrawRect(xd, fg, x + w2, y, s, h2 + s + d);
if (bd & LR)
XftDrawRect(xd, fg, x + w2 - d, y + h2, w - w2 + d, s);
if (bd & LD)
XftDrawRect(xd, fg, x + w2, y + h2 - d, s, h - h2 + d);
}
/* double lines - also align with light to form heavy when combined */
if (double_) {
/*
* going clockwise, for each double-ray: p is additional length
* to the single-ray nearer to the previous direction, and n to
* the next. p and n adjust from the base length to lengths
* which consider other doubles - shorter to avoid intersections
* (p, n), or longer to draw the far-corner texel (n).
*/
int dl = bd & DL, du = bd & DU, dr = bd & DR, dd = bd & DD;
if (dl) {
int p = dd ? -s : 0, n = du ? -s : dd ? s : 0;
XftDrawRect(xd, fg, x, y + h2 + s, w2 + s + p, s);
XftDrawRect(xd, fg, x, y + h2 - s, w2 + s + n, s);
}
if (du) {
int p = dl ? -s : 0, n = dr ? -s : dl ? s : 0;
XftDrawRect(xd, fg, x + w2 - s, y, s, h2 + s + p);
XftDrawRect(xd, fg, x + w2 + s, y, s, h2 + s + n);
}
if (dr) {
int p = du ? -s : 0, n = dd ? -s : du ? s : 0;
XftDrawRect(xd, fg, x + w2 - p, y + h2 - s, w - w2 + p, s);
XftDrawRect(xd, fg, x + w2 - n, y + h2 + s, w - w2 + n, s);
}
if (dd) {
int p = dr ? -s : 0, n = dl ? -s : dr ? s : 0;
XftDrawRect(xd, fg, x + w2 + s, y + h2 - p, s, h - h2 + p);
XftDrawRect(xd, fg, x + w2 - s, y + h2 - n, s, h - h2 + n);
}
}
}

214
boxdraw_data.h Normal file
View File

@ -0,0 +1,214 @@
/*
* Copyright 2018 Avi Halachmi (:avih) avihpit@yahoo.com https://github.com/avih
* MIT/X Consortium License
*/
/*
* U+25XX codepoints data
*
* References:
* http://www.unicode.org/charts/PDF/U2500.pdf
* http://www.unicode.org/charts/PDF/U2580.pdf
*
* Test page:
* https://github.com/GNOME/vte/blob/master/doc/boxes.txt
*/
/* Each shape is encoded as 16-bits. Higher bits are category, lower are data */
/* Categories (mutually exclusive except BDB): */
/* For convenience, BDL/BDA/BBS/BDB are 1 bit each, the rest are enums */
#define BDL (1<<8) /* Box Draw Lines (light/double/heavy) */
#define BDA (1<<9) /* Box Draw Arc (light) */
#define BBD (1<<10) /* Box Block Down (lower) X/8 */
#define BBL (2<<10) /* Box Block Left X/8 */
#define BBU (3<<10) /* Box Block Upper X/8 */
#define BBR (4<<10) /* Box Block Right X/8 */
#define BBQ (5<<10) /* Box Block Quadrants */
#define BRL (6<<10) /* Box Braille (data is lower byte of U28XX) */
#define BBS (1<<14) /* Box Block Shades */
#define BDB (1<<15) /* Box Draw is Bold */
/* (BDL/BDA) Light/Double/Heavy x Left/Up/Right/Down/Horizontal/Vertical */
/* Heavy is light+double (literally drawing light+double align to form heavy) */
#define LL (1<<0)
#define LU (1<<1)
#define LR (1<<2)
#define LD (1<<3)
#define LH (LL+LR)
#define LV (LU+LD)
#define DL (1<<4)
#define DU (1<<5)
#define DR (1<<6)
#define DD (1<<7)
#define DH (DL+DR)
#define DV (DU+DD)
#define HL (LL+DL)
#define HU (LU+DU)
#define HR (LR+DR)
#define HD (LD+DD)
#define HH (HL+HR)
#define HV (HU+HD)
/* (BBQ) Quadrants Top/Bottom x Left/Right */
#define TL (1<<0)
#define TR (1<<1)
#define BL (1<<2)
#define BR (1<<3)
/* Data for U+2500 - U+259F except dashes/diagonals */
static const unsigned short boxdata[256] = {
/* light lines */
[0x00] = BDL + LH, /* light horizontal */
[0x02] = BDL + LV, /* light vertical */
[0x0c] = BDL + LD + LR, /* light down and right */
[0x10] = BDL + LD + LL, /* light down and left */
[0x14] = BDL + LU + LR, /* light up and right */
[0x18] = BDL + LU + LL, /* light up and left */
[0x1c] = BDL + LV + LR, /* light vertical and right */
[0x24] = BDL + LV + LL, /* light vertical and left */
[0x2c] = BDL + LH + LD, /* light horizontal and down */
[0x34] = BDL + LH + LU, /* light horizontal and up */
[0x3c] = BDL + LV + LH, /* light vertical and horizontal */
[0x74] = BDL + LL, /* light left */
[0x75] = BDL + LU, /* light up */
[0x76] = BDL + LR, /* light right */
[0x77] = BDL + LD, /* light down */
/* heavy [+light] lines */
[0x01] = BDL + HH,
[0x03] = BDL + HV,
[0x0d] = BDL + HR + LD,
[0x0e] = BDL + HD + LR,
[0x0f] = BDL + HD + HR,
[0x11] = BDL + HL + LD,
[0x12] = BDL + HD + LL,
[0x13] = BDL + HD + HL,
[0x15] = BDL + HR + LU,
[0x16] = BDL + HU + LR,
[0x17] = BDL + HU + HR,
[0x19] = BDL + HL + LU,
[0x1a] = BDL + HU + LL,
[0x1b] = BDL + HU + HL,
[0x1d] = BDL + HR + LV,
[0x1e] = BDL + HU + LD + LR,
[0x1f] = BDL + HD + LR + LU,
[0x20] = BDL + HV + LR,
[0x21] = BDL + HU + HR + LD,
[0x22] = BDL + HD + HR + LU,
[0x23] = BDL + HV + HR,
[0x25] = BDL + HL + LV,
[0x26] = BDL + HU + LD + LL,
[0x27] = BDL + HD + LU + LL,
[0x28] = BDL + HV + LL,
[0x29] = BDL + HU + HL + LD,
[0x2a] = BDL + HD + HL + LU,
[0x2b] = BDL + HV + HL,
[0x2d] = BDL + HL + LD + LR,
[0x2e] = BDL + HR + LL + LD,
[0x2f] = BDL + HH + LD,
[0x30] = BDL + HD + LH,
[0x31] = BDL + HD + HL + LR,
[0x32] = BDL + HR + HD + LL,
[0x33] = BDL + HH + HD,
[0x35] = BDL + HL + LU + LR,
[0x36] = BDL + HR + LU + LL,
[0x37] = BDL + HH + LU,
[0x38] = BDL + HU + LH,
[0x39] = BDL + HU + HL + LR,
[0x3a] = BDL + HU + HR + LL,
[0x3b] = BDL + HH + HU,
[0x3d] = BDL + HL + LV + LR,
[0x3e] = BDL + HR + LV + LL,
[0x3f] = BDL + HH + LV,
[0x40] = BDL + HU + LH + LD,
[0x41] = BDL + HD + LH + LU,
[0x42] = BDL + HV + LH,
[0x43] = BDL + HU + HL + LD + LR,
[0x44] = BDL + HU + HR + LD + LL,
[0x45] = BDL + HD + HL + LU + LR,
[0x46] = BDL + HD + HR + LU + LL,
[0x47] = BDL + HH + HU + LD,
[0x48] = BDL + HH + HD + LU,
[0x49] = BDL + HV + HL + LR,
[0x4a] = BDL + HV + HR + LL,
[0x4b] = BDL + HV + HH,
[0x78] = BDL + HL,
[0x79] = BDL + HU,
[0x7a] = BDL + HR,
[0x7b] = BDL + HD,
[0x7c] = BDL + HR + LL,
[0x7d] = BDL + HD + LU,
[0x7e] = BDL + HL + LR,
[0x7f] = BDL + HU + LD,
/* double [+light] lines */
[0x50] = BDL + DH,
[0x51] = BDL + DV,
[0x52] = BDL + DR + LD,
[0x53] = BDL + DD + LR,
[0x54] = BDL + DR + DD,
[0x55] = BDL + DL + LD,
[0x56] = BDL + DD + LL,
[0x57] = BDL + DL + DD,
[0x58] = BDL + DR + LU,
[0x59] = BDL + DU + LR,
[0x5a] = BDL + DU + DR,
[0x5b] = BDL + DL + LU,
[0x5c] = BDL + DU + LL,
[0x5d] = BDL + DL + DU,
[0x5e] = BDL + DR + LV,
[0x5f] = BDL + DV + LR,
[0x60] = BDL + DV + DR,
[0x61] = BDL + DL + LV,
[0x62] = BDL + DV + LL,
[0x63] = BDL + DV + DL,
[0x64] = BDL + DH + LD,
[0x65] = BDL + DD + LH,
[0x66] = BDL + DD + DH,
[0x67] = BDL + DH + LU,
[0x68] = BDL + DU + LH,
[0x69] = BDL + DH + DU,
[0x6a] = BDL + DH + LV,
[0x6b] = BDL + DV + LH,
[0x6c] = BDL + DH + DV,
/* (light) arcs */
[0x6d] = BDA + LD + LR,
[0x6e] = BDA + LD + LL,
[0x6f] = BDA + LU + LL,
[0x70] = BDA + LU + LR,
/* Lower (Down) X/8 block (data is 8 - X) */
[0x81] = BBD + 7, [0x82] = BBD + 6, [0x83] = BBD + 5, [0x84] = BBD + 4,
[0x85] = BBD + 3, [0x86] = BBD + 2, [0x87] = BBD + 1, [0x88] = BBD + 0,
/* Left X/8 block (data is X) */
[0x89] = BBL + 7, [0x8a] = BBL + 6, [0x8b] = BBL + 5, [0x8c] = BBL + 4,
[0x8d] = BBL + 3, [0x8e] = BBL + 2, [0x8f] = BBL + 1,
/* upper 1/2 (4/8), 1/8 block (X), right 1/2, 1/8 block (8-X) */
[0x80] = BBU + 4, [0x94] = BBU + 1,
[0x90] = BBR + 4, [0x95] = BBR + 7,
/* Quadrants */
[0x96] = BBQ + BL,
[0x97] = BBQ + BR,
[0x98] = BBQ + TL,
[0x99] = BBQ + TL + BL + BR,
[0x9a] = BBQ + TL + BR,
[0x9b] = BBQ + TL + TR + BL,
[0x9c] = BBQ + TL + TR + BR,
[0x9d] = BBQ + TR,
[0x9e] = BBQ + BL + TR,
[0x9f] = BBQ + BL + TR + BR,
/* Shades, data is an alpha value in 25% units (1/4, 1/2, 3/4) */
[0x91] = BBS + 1, [0x92] = BBS + 2, [0x93] = BBS + 3,
/* U+2504 - U+250B, U+254C - U+254F: unsupported (dashes) */
/* U+2571 - U+2573: unsupported (diagonals) */
};

View File

@ -1,13 +1,15 @@
/* See LICENSE file for copyright and license details. */
/*
* appearance
*
* font: see http://freedesktop.org/software/fontconfig/fontconfig-user.html
*/
static char *font = "Liberation Mono:pixelsize=12:antialias=true:autohint=true";
static char *font = "FiraCode Nerd Font Mono:pixelsize=14";
static int borderpx = 2;
/* Underline curl style
* CURLY 0
* SPIKY 1
* CAPPED 2
*/
#define UNDERCURL_STYLE 2
/*
* What program is execed by st depends of these precedence rules:
* 1: program passed with -e
@ -60,13 +62,25 @@ static double maxlatency = 33;
* blinking timeout (set to 0 to disable blinking) for the terminal blinking
* attribute.
*/
static unsigned int blinktimeout = 800;
static unsigned int blinktimeout = 600;
/*
* thickness of underline and bar cursors
*/
static unsigned int cursorthickness = 2;
/*
* 1: render most of the lines/blocks characters without using the font for
* perfect alignment between cells (U2500 - U259F except dashes/diagonals).
* Bold affects lines thickness if boxdraw_bold is not 0. Italic is ignored.
* 0: disable (render all U25XX glyphs normally from the font).
*/
const int boxdraw = 1;
const int boxdraw_bold = 0;
/* braille (U28XX): 1: render as adjacent "pixels", 0: use font */
const int boxdraw_braille = 0;
/*
* bell volume. It must be a value between -100 and 100. Use 0 for disabling
* it
@ -96,52 +110,61 @@ unsigned int tabspaces = 8;
/* Terminal colors (16 first used in escape sequence) */
static const char *colorname[] = {
/* 8 normal colors */
"black",
"red3",
"green3",
"yellow3",
"blue2",
"magenta3",
"cyan3",
"gray90",
"#15161E",
"#f7768e",
"#9ece6a",
"#e0af68",
"#7aa2f7",
"#bb9af7",
"#7dcfff",
"#a9b1d6",
/* 8 bright colors */
"gray50",
"red",
"green",
"yellow",
"#5c5cff",
"magenta",
"cyan",
"white",
"#414868",
"#f7768e",
"#9ece6a",
"#e0af68",
"#7aa2f7",
"#bb9af7",
"#7dcfff",
"#c0caf5",
[255] = 0,
/* more colors can be added after 255 to use with DefaultXX */
"#cccccc",
"#555555",
"gray90", /* default foreground colour */
"black", /* default background colour */
// indexes beyond 255 are used for internal colors
"#c0caf5", /* default cursor colour */
"#1a1b26", /* default inverted cursor colour */
"#c0caf5", /* default foreground colour */
"#1a1b26", /* default background colour */
"#c0caf5", /* default selection foreground colour */
"#33467C", /* default selection background colour */
};
/*
* Default colors (colorname index)
* foreground, background, cursor, reverse cursor
*/
unsigned int defaultfg = 258;
unsigned int defaultbg = 259;
unsigned int defaultcs = 256;
static unsigned int defaultrcs = 257;
unsigned int defaultfg = 258;
unsigned int defaultbg = 259;
unsigned int selectionfg = 260;
unsigned int selectionbg = 261;
/* If 0 use selectionfg as foreground in order to have a uniform foreground-color */
/* Else if 1 keep original foreground-color of each cell => more colors :) */
static int ignoreselfg = 1;
/*
* 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
@ -278,7 +301,7 @@ static Key key[] = {
{ XK_KP_Delete, ControlMask, "\033[3;5~", +1, 0},
{ XK_KP_Delete, ShiftMask, "\033[2K", -1, 0},
{ XK_KP_Delete, ShiftMask, "\033[3;2~", +1, 0},
{ XK_KP_Delete, XK_ANY_MOD, "\033[P", -1, 0},
{ XK_KP_Delete, XK_ANY_MOD, "\033[3~", -1, 0},
{ XK_KP_Delete, XK_ANY_MOD, "\033[3~", +1, 0},
{ XK_KP_Multiply, XK_ANY_MOD, "\033Oj", +2, 0},
{ XK_KP_Add, XK_ANY_MOD, "\033Ok", +2, 0},
@ -346,7 +369,7 @@ static Key key[] = {
{ XK_Delete, ControlMask, "\033[3;5~", +1, 0},
{ XK_Delete, ShiftMask, "\033[2K", -1, 0},
{ XK_Delete, ShiftMask, "\033[3;2~", +1, 0},
{ XK_Delete, XK_ANY_MOD, "\033[P", -1, 0},
{ XK_Delete, XK_ANY_MOD, "\033[3~", -1, 0},
{ XK_Delete, XK_ANY_MOD, "\033[3~", +1, 0},
{ XK_BackSpace, XK_NO_MOD, "\177", 0, 0},
{ XK_BackSpace, Mod1Mask, "\033\177", 0, 0},

View File

@ -15,10 +15,12 @@ PKG_CONFIG = pkg-config
# includes and libs
INCS = -I$(X11INC) \
`$(PKG_CONFIG) --cflags fontconfig` \
`$(PKG_CONFIG) --cflags freetype2`
`$(PKG_CONFIG) --cflags freetype2` \
`$(PKG_CONFIG) --cflags harfbuzz`
LIBS = -L$(X11LIB) -lm -lrt -lX11 -lutil -lXft \
`$(PKG_CONFIG) --libs fontconfig` \
`$(PKG_CONFIG) --libs freetype2`
`$(PKG_CONFIG) --libs freetype2` \
`$(PKG_CONFIG) --libs harfbuzz`
# flags
STCPPFLAGS = -DVERSION=\"$(VERSION)\" -D_XOPEN_SOURCE=600

124
hb.c Normal file
View File

@ -0,0 +1,124 @@
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <X11/Xft/Xft.h>
#include <X11/cursorfont.h>
#include <hb.h>
#include <hb-ft.h>
#include "st.h"
#include "hb.h"
#define FEATURE(c1,c2,c3,c4) { .tag = HB_TAG(c1,c2,c3,c4), .value = 1, .start = HB_FEATURE_GLOBAL_START, .end = HB_FEATURE_GLOBAL_END }
#define BUFFER_STEP 256
hb_font_t *hbfindfont(XftFont *match);
typedef struct {
XftFont *match;
hb_font_t *font;
} HbFontMatch;
typedef struct {
size_t capacity;
HbFontMatch *fonts;
} HbFontCache;
static HbFontCache hbfontcache = { 0, NULL };
typedef struct {
size_t capacity;
Rune *runes;
} RuneBuffer;
static RuneBuffer hbrunebuffer = { 0, NULL };
/*
* Poplulate the array with a list of font features, wrapped in FEATURE macro,
* e. g.
* FEATURE('c', 'a', 'l', 't'), FEATURE('d', 'l', 'i', 'g')
*/
hb_feature_t features[] = { };
void
hbunloadfonts()
{
for (int i = 0; i < hbfontcache.capacity; i++) {
hb_font_destroy(hbfontcache.fonts[i].font);
XftUnlockFace(hbfontcache.fonts[i].match);
}
if (hbfontcache.fonts != NULL) {
free(hbfontcache.fonts);
hbfontcache.fonts = NULL;
}
hbfontcache.capacity = 0;
}
hb_font_t *
hbfindfont(XftFont *match)
{
for (int i = 0; i < hbfontcache.capacity; i++) {
if (hbfontcache.fonts[i].match == match)
return hbfontcache.fonts[i].font;
}
/* Font not found in cache, caching it now. */
hbfontcache.fonts = realloc(hbfontcache.fonts, sizeof(HbFontMatch) * (hbfontcache.capacity + 1));
FT_Face face = XftLockFace(match);
hb_font_t *font = hb_ft_font_create(face, NULL);
if (font == NULL)
die("Failed to load Harfbuzz font.");
hbfontcache.fonts[hbfontcache.capacity].match = match;
hbfontcache.fonts[hbfontcache.capacity].font = font;
hbfontcache.capacity += 1;
return font;
}
void hbtransform(HbTransformData *data, XftFont *xfont, const Glyph *glyphs, int start, int length) {
ushort mode = USHRT_MAX;
unsigned int glyph_count;
int rune_idx, glyph_idx, end = start + length;
hb_font_t *font = hbfindfont(xfont);
if (font == NULL)
return;
hb_buffer_t *buffer = hb_buffer_create();
hb_buffer_set_direction(buffer, HB_DIRECTION_LTR);
/* Resize the buffer if required length is larger. */
if (hbrunebuffer.capacity < length) {
hbrunebuffer.capacity = (length / BUFFER_STEP + 1) * BUFFER_STEP;
hbrunebuffer.runes = realloc(hbrunebuffer.runes, hbrunebuffer.capacity * sizeof(Rune));
}
/* Fill buffer with codepoints. */
for (rune_idx = 0, glyph_idx = start; glyph_idx < end; glyph_idx++, rune_idx++) {
hbrunebuffer.runes[rune_idx] = glyphs[glyph_idx].u;
mode = glyphs[glyph_idx].mode;
if (mode & ATTR_WDUMMY)
hbrunebuffer.runes[rune_idx] = 0x0020;
}
hb_buffer_add_codepoints(buffer, hbrunebuffer.runes, length, 0, length);
/* Shape the segment. */
hb_shape(font, buffer, features, sizeof(features)/sizeof(hb_feature_t));
/* Get new glyph info. */
hb_glyph_info_t *info = hb_buffer_get_glyph_infos(buffer, &glyph_count);
hb_glyph_position_t *pos = hb_buffer_get_glyph_positions(buffer, &glyph_count);
/* Fill the output. */
data->buffer = buffer;
data->glyphs = info;
data->positions = pos;
data->count = glyph_count;
}
void hbcleanup(HbTransformData *data) {
hb_buffer_destroy(data->buffer);
memset(data, 0, sizeof(HbTransformData));
}

14
hb.h Normal file
View File

@ -0,0 +1,14 @@
#include <X11/Xft/Xft.h>
#include <hb.h>
#include <hb-ft.h>
typedef struct {
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 *);

View File

@ -0,0 +1,164 @@
From 8dcdc4b21a73268e167d98aa30f24315c7f3b7ff Mon Sep 17 00:00:00 2001
From: Bakkeby <bakkeby@gmail.com>
Date: Mon, 18 Jul 2022 16:52:03 +0200
Subject: [PATCH] Adding anysize patch
---
x.c | 56 ++++++++++++++++++++++++++++++--------------------------
1 file changed, 30 insertions(+), 26 deletions(-)
diff --git a/x.c b/x.c
index 2a3bd38..f534347 100644
--- a/x.c
+++ b/x.c
@@ -81,6 +81,7 @@ typedef XftGlyphFontSpec GlyphFontSpec;
typedef struct {
int tw, th; /* tty width and height */
int w, h; /* window width and height */
+ int hborderpx, vborderpx;
int ch; /* char height */
int cw; /* char width */
int mode; /* window state/mode flags */
@@ -331,7 +332,7 @@ ttysend(const Arg *arg)
int
evcol(XEvent *e)
{
- int x = e->xbutton.x - borderpx;
+ int x = e->xbutton.x - win.hborderpx;
LIMIT(x, 0, win.tw - 1);
return x / win.cw;
}
@@ -339,7 +340,7 @@ evcol(XEvent *e)
int
evrow(XEvent *e)
{
- int y = e->xbutton.y - borderpx;
+ int y = e->xbutton.y - win.vborderpx;
LIMIT(y, 0, win.th - 1);
return y / win.ch;
}
@@ -739,6 +740,9 @@ cresize(int width, int height)
col = MAX(1, col);
row = MAX(1, row);
+ win.hborderpx = (win.w - col * win.cw) / 2;
+ win.vborderpx = (win.h - row * win.ch) / 2;
+
tresize(col, row);
xresize(col, row);
ttyresize(win.tw, win.th);
@@ -869,8 +873,8 @@ xhints(void)
sizeh->flags = PSize | PResizeInc | PBaseSize | PMinSize;
sizeh->height = win.h;
sizeh->width = win.w;
- sizeh->height_inc = win.ch;
- sizeh->width_inc = win.cw;
+ sizeh->height_inc = 1;
+ sizeh->width_inc = 1;
sizeh->base_height = 2 * borderpx;
sizeh->base_width = 2 * borderpx;
sizeh->min_height = win.ch + 2 * borderpx;
@@ -1152,8 +1156,8 @@ xinit(int cols, int rows)
xloadcols();
/* adjust fixed window geometry */
- win.w = 2 * borderpx + cols * win.cw;
- win.h = 2 * borderpx + rows * win.ch;
+ win.w = 2 * win.hborderpx + 2 * borderpx + cols * win.cw;
+ win.h = 2 * win.vborderpx + 2 * borderpx + rows * win.ch;
if (xw.gm & XNegative)
xw.l += DisplayWidth(xw.dpy, xw.scr) - win.w - 2;
if (xw.gm & YNegative)
@@ -1242,7 +1246,7 @@ xinit(int cols, int rows)
int
xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x, int y)
{
- float winx = borderpx + x * win.cw, winy = borderpx + y * win.ch, xp, yp;
+ float winx = win.hborderpx + x * win.cw, winy = win.vborderpx + y * win.ch, xp, yp;
ushort mode, prevmode = USHRT_MAX;
Font *font = &dc.font;
int frcflags = FRC_NORMAL;
@@ -1375,7 +1379,7 @@ void
xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, int y)
{
int charlen = len * ((base.mode & ATTR_WIDE) ? 2 : 1);
- int winx = borderpx + x * win.cw, winy = borderpx + y * win.ch,
+ int winx = win.hborderpx + x * win.cw, winy = win.vborderpx + y * win.ch,
width = charlen * win.cw;
Color *fg, *bg, *temp, revfg, revbg, truefg, truebg;
XRenderColor colfg, colbg;
@@ -1465,17 +1469,17 @@ xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, i
/* Intelligent cleaning up of the borders. */
if (x == 0) {
- xclear(0, (y == 0)? 0 : winy, borderpx,
+ xclear(0, (y == 0)? 0 : winy, win.hborderpx,
winy + win.ch +
- ((winy + win.ch >= borderpx + win.th)? win.h : 0));
+ ((winy + win.ch >= win.vborderpx + win.th)? win.h : 0));
}
- if (winx + width >= borderpx + win.tw) {
+ if (winx + width >= win.hborderpx + win.tw) {
xclear(winx + width, (y == 0)? 0 : winy, win.w,
- ((winy + win.ch >= borderpx + win.th)? win.h : (winy + win.ch)));
+ ((winy + win.ch >= win.vborderpx + win.th)? win.h : (winy + win.ch)));
}
if (y == 0)
- xclear(winx, 0, winx + width, borderpx);
- if (winy + win.ch >= borderpx + win.th)
+ xclear(winx, 0, winx + width, win.vborderpx);
+ if (winy + win.ch >= win.vborderpx + win.th)
xclear(winx, winy + win.ch, winx + width, win.h);
/* Clean up the region we want to draw to. */
@@ -1569,35 +1573,35 @@ xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og)
case 3: /* Blinking Underline */
case 4: /* Steady Underline */
XftDrawRect(xw.draw, &drawcol,
- borderpx + cx * win.cw,
- borderpx + (cy + 1) * win.ch - \
+ win.hborderpx + cx * win.cw,
+ win.vborderpx + (cy + 1) * win.ch - \
cursorthickness,
win.cw, cursorthickness);
break;
case 5: /* Blinking bar */
case 6: /* Steady bar */
XftDrawRect(xw.draw, &drawcol,
- borderpx + cx * win.cw,
- borderpx + cy * win.ch,
+ win.hborderpx + cx * win.cw,
+ win.vborderpx + cy * win.ch,
cursorthickness, win.ch);
break;
}
} else {
XftDrawRect(xw.draw, &drawcol,
- borderpx + cx * win.cw,
- borderpx + cy * win.ch,
+ win.hborderpx + cx * win.cw,
+ win.vborderpx + cy * win.ch,
win.cw - 1, 1);
XftDrawRect(xw.draw, &drawcol,
- borderpx + cx * win.cw,
- borderpx + cy * win.ch,
+ win.hborderpx + cx * win.cw,
+ win.vborderpx + cy * win.ch,
1, win.ch - 1);
XftDrawRect(xw.draw, &drawcol,
- borderpx + (cx + 1) * win.cw - 1,
- borderpx + cy * win.ch,
+ win.hborderpx + (cx + 1) * win.cw - 1,
+ win.vborderpx + cy * win.ch,
1, win.ch - 1);
XftDrawRect(xw.draw, &drawcol,
- borderpx + cx * win.cw,
- borderpx + (cy + 1) * win.ch - 1,
+ win.hborderpx + cx * win.cw,
+ win.vborderpx + (cy + 1) * win.ch - 1,
win.cw, 1);
}
}
--
2.37.1

View File

@ -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

View File

@ -0,0 +1,27 @@
From e8f3c86d93613eef5af187dfd2dba9ae9919a2ee Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Rapha=C3=ABl=20Proust?= <code@bnwr.net>
Date: Sun, 27 Jan 2019 13:31:28 +0800
Subject: [PATCH] Show bold not as bright
---
x.c | 4 ----
1 file changed, 4 deletions(-)
diff --git a/x.c b/x.c
index 0422421..904e1dc 100644
--- a/x.c
+++ b/x.c
@@ -1296,10 +1296,6 @@ xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, i
bg = &dc.col[base.bg];
}
- /* Change basic system colors [0-7] to bright system colors [8-15] */
- if ((base.mode & ATTR_BOLD_FAINT) == ATTR_BOLD && BETWEEN(base.fg, 0, 7))
- fg = &dc.col[base.fg + 8];
-
if (IS_SET(MODE_REVERSE)) {
if (fg == &dc.col[defaultfg]) {
fg = &dc.col[defaultbg];
--
2.20.1

View File

@ -0,0 +1,583 @@
From 46a1124957b8de5e7f827656b64bfc3baeaa097f Mon Sep 17 00:00:00 2001
From: wael <40663@protonmail.com>
Date: Mon, 11 Apr 2022 17:04:30 +0300
Subject: [PATCH] [st][patch][boxdraw] update to 0.8.5
---
Makefile | 3 +-
boxdraw.c | 194 ++++++++++++++++++++++++++++++++++++++++++++
boxdraw_data.h | 214 +++++++++++++++++++++++++++++++++++++++++++++++++
config.def.h | 12 +++
st.c | 3 +
st.h | 10 +++
x.c | 21 +++--
7 files changed, 451 insertions(+), 6 deletions(-)
create mode 100644 boxdraw.c
create mode 100644 boxdraw_data.h
diff --git a/Makefile b/Makefile
index 470ac86..6dfa212 100644
--- a/Makefile
+++ b/Makefile
@@ -4,7 +4,7 @@
include config.mk
-SRC = st.c x.c
+SRC = st.c x.c boxdraw.c
OBJ = $(SRC:.c=.o)
all: options st
@@ -23,6 +23,7 @@ config.h:
st.o: config.h st.h win.h
x.o: arg.h config.h st.h win.h
+boxdraw.o: config.h st.h boxdraw_data.h
$(OBJ): config.h config.mk
diff --git a/boxdraw.c b/boxdraw.c
new file mode 100644
index 0000000..28a92d0
--- /dev/null
+++ b/boxdraw.c
@@ -0,0 +1,194 @@
+/*
+ * Copyright 2018 Avi Halachmi (:avih) avihpit@yahoo.com https://github.com/avih
+ * MIT/X Consortium License
+ */
+
+#include <X11/Xft/Xft.h>
+#include "st.h"
+#include "boxdraw_data.h"
+
+/* Rounded non-negative integers division of n / d */
+#define DIV(n, d) (((n) + (d) / 2) / (d))
+
+static Display *xdpy;
+static Colormap xcmap;
+static XftDraw *xd;
+static Visual *xvis;
+
+static void drawbox(int, int, int, int, XftColor *, XftColor *, ushort);
+static void drawboxlines(int, int, int, int, XftColor *, ushort);
+
+/* public API */
+
+void
+boxdraw_xinit(Display *dpy, Colormap cmap, XftDraw *draw, Visual *vis)
+{
+ xdpy = dpy; xcmap = cmap; xd = draw, xvis = vis;
+}
+
+int
+isboxdraw(Rune u)
+{
+ Rune block = u & ~0xff;
+ return (boxdraw && block == 0x2500 && boxdata[(uint8_t)u]) ||
+ (boxdraw_braille && block == 0x2800);
+}
+
+/* the "index" is actually the entire shape data encoded as ushort */
+ushort
+boxdrawindex(const Glyph *g)
+{
+ if (boxdraw_braille && (g->u & ~0xff) == 0x2800)
+ return BRL | (uint8_t)g->u;
+ if (boxdraw_bold && (g->mode & ATTR_BOLD))
+ return BDB | boxdata[(uint8_t)g->u];
+ return boxdata[(uint8_t)g->u];
+}
+
+void
+drawboxes(int x, int y, int cw, int ch, XftColor *fg, XftColor *bg,
+ const XftGlyphFontSpec *specs, int len)
+{
+ for ( ; len-- > 0; x += cw, specs++)
+ drawbox(x, y, cw, ch, fg, bg, (ushort)specs->glyph);
+}
+
+/* implementation */
+
+void
+drawbox(int x, int y, int w, int h, XftColor *fg, XftColor *bg, ushort bd)
+{
+ ushort cat = bd & ~(BDB | 0xff); /* mask out bold and data */
+ if (bd & (BDL | BDA)) {
+ /* lines (light/double/heavy/arcs) */
+ drawboxlines(x, y, w, h, fg, bd);
+
+ } else if (cat == BBD) {
+ /* lower (8-X)/8 block */
+ int d = DIV((uint8_t)bd * h, 8);
+ XftDrawRect(xd, fg, x, y + d, w, h - d);
+
+ } else if (cat == BBU) {
+ /* upper X/8 block */
+ XftDrawRect(xd, fg, x, y, w, DIV((uint8_t)bd * h, 8));
+
+ } else if (cat == BBL) {
+ /* left X/8 block */
+ XftDrawRect(xd, fg, x, y, DIV((uint8_t)bd * w, 8), h);
+
+ } else if (cat == BBR) {
+ /* right (8-X)/8 block */
+ int d = DIV((uint8_t)bd * w, 8);
+ XftDrawRect(xd, fg, x + d, y, w - d, h);
+
+ } else if (cat == BBQ) {
+ /* Quadrants */
+ int w2 = DIV(w, 2), h2 = DIV(h, 2);
+ if (bd & TL)
+ XftDrawRect(xd, fg, x, y, w2, h2);
+ if (bd & TR)
+ XftDrawRect(xd, fg, x + w2, y, w - w2, h2);
+ if (bd & BL)
+ XftDrawRect(xd, fg, x, y + h2, w2, h - h2);
+ if (bd & BR)
+ XftDrawRect(xd, fg, x + w2, y + h2, w - w2, h - h2);
+
+ } else if (bd & BBS) {
+ /* Shades - data is 1/2/3 for 25%/50%/75% alpha, respectively */
+ int d = (uint8_t)bd;
+ XftColor xfc;
+ XRenderColor xrc = { .alpha = 0xffff };
+
+ xrc.red = DIV(fg->color.red * d + bg->color.red * (4 - d), 4);
+ xrc.green = DIV(fg->color.green * d + bg->color.green * (4 - d), 4);
+ xrc.blue = DIV(fg->color.blue * d + bg->color.blue * (4 - d), 4);
+
+ XftColorAllocValue(xdpy, xvis, xcmap, &xrc, &xfc);
+ XftDrawRect(xd, &xfc, x, y, w, h);
+ XftColorFree(xdpy, xvis, xcmap, &xfc);
+
+ } else if (cat == BRL) {
+ /* braille, each data bit corresponds to one dot at 2x4 grid */
+ int w1 = DIV(w, 2);
+ int h1 = DIV(h, 4), h2 = DIV(h, 2), h3 = DIV(3 * h, 4);
+
+ if (bd & 1) XftDrawRect(xd, fg, x, y, w1, h1);
+ if (bd & 2) XftDrawRect(xd, fg, x, y + h1, w1, h2 - h1);
+ if (bd & 4) XftDrawRect(xd, fg, x, y + h2, w1, h3 - h2);
+ if (bd & 8) XftDrawRect(xd, fg, x + w1, y, w - w1, h1);
+ if (bd & 16) XftDrawRect(xd, fg, x + w1, y + h1, w - w1, h2 - h1);
+ if (bd & 32) XftDrawRect(xd, fg, x + w1, y + h2, w - w1, h3 - h2);
+ if (bd & 64) XftDrawRect(xd, fg, x, y + h3, w1, h - h3);
+ if (bd & 128) XftDrawRect(xd, fg, x + w1, y + h3, w - w1, h - h3);
+
+ }
+}
+
+void
+drawboxlines(int x, int y, int w, int h, XftColor *fg, ushort bd)
+{
+ /* s: stem thickness. width/8 roughly matches underscore thickness. */
+ /* We draw bold as 1.5 * normal-stem and at least 1px thicker. */
+ /* doubles draw at least 3px, even when w or h < 3. bold needs 6px. */
+ int mwh = MIN(w, h);
+ int base_s = MAX(1, DIV(mwh, 8));
+ int bold = (bd & BDB) && mwh >= 6; /* possibly ignore boldness */
+ int s = bold ? MAX(base_s + 1, DIV(3 * base_s, 2)) : base_s;
+ int w2 = DIV(w - s, 2), h2 = DIV(h - s, 2);
+ /* the s-by-s square (x + w2, y + h2, s, s) is the center texel. */
+ /* The base length (per direction till edge) includes this square. */
+
+ int light = bd & (LL | LU | LR | LD);
+ int double_ = bd & (DL | DU | DR | DD);
+
+ if (light) {
+ /* d: additional (negative) length to not-draw the center */
+ /* texel - at arcs and avoid drawing inside (some) doubles */
+ int arc = bd & BDA;
+ int multi_light = light & (light - 1);
+ int multi_double = double_ & (double_ - 1);
+ /* light crosses double only at DH+LV, DV+LH (ref. shapes) */
+ int d = arc || (multi_double && !multi_light) ? -s : 0;
+
+ if (bd & LL)
+ XftDrawRect(xd, fg, x, y + h2, w2 + s + d, s);
+ if (bd & LU)
+ XftDrawRect(xd, fg, x + w2, y, s, h2 + s + d);
+ if (bd & LR)
+ XftDrawRect(xd, fg, x + w2 - d, y + h2, w - w2 + d, s);
+ if (bd & LD)
+ XftDrawRect(xd, fg, x + w2, y + h2 - d, s, h - h2 + d);
+ }
+
+ /* double lines - also align with light to form heavy when combined */
+ if (double_) {
+ /*
+ * going clockwise, for each double-ray: p is additional length
+ * to the single-ray nearer to the previous direction, and n to
+ * the next. p and n adjust from the base length to lengths
+ * which consider other doubles - shorter to avoid intersections
+ * (p, n), or longer to draw the far-corner texel (n).
+ */
+ int dl = bd & DL, du = bd & DU, dr = bd & DR, dd = bd & DD;
+ if (dl) {
+ int p = dd ? -s : 0, n = du ? -s : dd ? s : 0;
+ XftDrawRect(xd, fg, x, y + h2 + s, w2 + s + p, s);
+ XftDrawRect(xd, fg, x, y + h2 - s, w2 + s + n, s);
+ }
+ if (du) {
+ int p = dl ? -s : 0, n = dr ? -s : dl ? s : 0;
+ XftDrawRect(xd, fg, x + w2 - s, y, s, h2 + s + p);
+ XftDrawRect(xd, fg, x + w2 + s, y, s, h2 + s + n);
+ }
+ if (dr) {
+ int p = du ? -s : 0, n = dd ? -s : du ? s : 0;
+ XftDrawRect(xd, fg, x + w2 - p, y + h2 - s, w - w2 + p, s);
+ XftDrawRect(xd, fg, x + w2 - n, y + h2 + s, w - w2 + n, s);
+ }
+ if (dd) {
+ int p = dr ? -s : 0, n = dl ? -s : dr ? s : 0;
+ XftDrawRect(xd, fg, x + w2 + s, y + h2 - p, s, h - h2 + p);
+ XftDrawRect(xd, fg, x + w2 - s, y + h2 - n, s, h - h2 + n);
+ }
+ }
+}
diff --git a/boxdraw_data.h b/boxdraw_data.h
new file mode 100644
index 0000000..7890500
--- /dev/null
+++ b/boxdraw_data.h
@@ -0,0 +1,214 @@
+/*
+ * Copyright 2018 Avi Halachmi (:avih) avihpit@yahoo.com https://github.com/avih
+ * MIT/X Consortium License
+ */
+
+/*
+ * U+25XX codepoints data
+ *
+ * References:
+ * http://www.unicode.org/charts/PDF/U2500.pdf
+ * http://www.unicode.org/charts/PDF/U2580.pdf
+ *
+ * Test page:
+ * https://github.com/GNOME/vte/blob/master/doc/boxes.txt
+ */
+
+/* Each shape is encoded as 16-bits. Higher bits are category, lower are data */
+/* Categories (mutually exclusive except BDB): */
+/* For convenience, BDL/BDA/BBS/BDB are 1 bit each, the rest are enums */
+#define BDL (1<<8) /* Box Draw Lines (light/double/heavy) */
+#define BDA (1<<9) /* Box Draw Arc (light) */
+
+#define BBD (1<<10) /* Box Block Down (lower) X/8 */
+#define BBL (2<<10) /* Box Block Left X/8 */
+#define BBU (3<<10) /* Box Block Upper X/8 */
+#define BBR (4<<10) /* Box Block Right X/8 */
+#define BBQ (5<<10) /* Box Block Quadrants */
+#define BRL (6<<10) /* Box Braille (data is lower byte of U28XX) */
+
+#define BBS (1<<14) /* Box Block Shades */
+#define BDB (1<<15) /* Box Draw is Bold */
+
+/* (BDL/BDA) Light/Double/Heavy x Left/Up/Right/Down/Horizontal/Vertical */
+/* Heavy is light+double (literally drawing light+double align to form heavy) */
+#define LL (1<<0)
+#define LU (1<<1)
+#define LR (1<<2)
+#define LD (1<<3)
+#define LH (LL+LR)
+#define LV (LU+LD)
+
+#define DL (1<<4)
+#define DU (1<<5)
+#define DR (1<<6)
+#define DD (1<<7)
+#define DH (DL+DR)
+#define DV (DU+DD)
+
+#define HL (LL+DL)
+#define HU (LU+DU)
+#define HR (LR+DR)
+#define HD (LD+DD)
+#define HH (HL+HR)
+#define HV (HU+HD)
+
+/* (BBQ) Quadrants Top/Bottom x Left/Right */
+#define TL (1<<0)
+#define TR (1<<1)
+#define BL (1<<2)
+#define BR (1<<3)
+
+/* Data for U+2500 - U+259F except dashes/diagonals */
+static const unsigned short boxdata[256] = {
+ /* light lines */
+ [0x00] = BDL + LH, /* light horizontal */
+ [0x02] = BDL + LV, /* light vertical */
+ [0x0c] = BDL + LD + LR, /* light down and right */
+ [0x10] = BDL + LD + LL, /* light down and left */
+ [0x14] = BDL + LU + LR, /* light up and right */
+ [0x18] = BDL + LU + LL, /* light up and left */
+ [0x1c] = BDL + LV + LR, /* light vertical and right */
+ [0x24] = BDL + LV + LL, /* light vertical and left */
+ [0x2c] = BDL + LH + LD, /* light horizontal and down */
+ [0x34] = BDL + LH + LU, /* light horizontal and up */
+ [0x3c] = BDL + LV + LH, /* light vertical and horizontal */
+ [0x74] = BDL + LL, /* light left */
+ [0x75] = BDL + LU, /* light up */
+ [0x76] = BDL + LR, /* light right */
+ [0x77] = BDL + LD, /* light down */
+
+ /* heavy [+light] lines */
+ [0x01] = BDL + HH,
+ [0x03] = BDL + HV,
+ [0x0d] = BDL + HR + LD,
+ [0x0e] = BDL + HD + LR,
+ [0x0f] = BDL + HD + HR,
+ [0x11] = BDL + HL + LD,
+ [0x12] = BDL + HD + LL,
+ [0x13] = BDL + HD + HL,
+ [0x15] = BDL + HR + LU,
+ [0x16] = BDL + HU + LR,
+ [0x17] = BDL + HU + HR,
+ [0x19] = BDL + HL + LU,
+ [0x1a] = BDL + HU + LL,
+ [0x1b] = BDL + HU + HL,
+ [0x1d] = BDL + HR + LV,
+ [0x1e] = BDL + HU + LD + LR,
+ [0x1f] = BDL + HD + LR + LU,
+ [0x20] = BDL + HV + LR,
+ [0x21] = BDL + HU + HR + LD,
+ [0x22] = BDL + HD + HR + LU,
+ [0x23] = BDL + HV + HR,
+ [0x25] = BDL + HL + LV,
+ [0x26] = BDL + HU + LD + LL,
+ [0x27] = BDL + HD + LU + LL,
+ [0x28] = BDL + HV + LL,
+ [0x29] = BDL + HU + HL + LD,
+ [0x2a] = BDL + HD + HL + LU,
+ [0x2b] = BDL + HV + HL,
+ [0x2d] = BDL + HL + LD + LR,
+ [0x2e] = BDL + HR + LL + LD,
+ [0x2f] = BDL + HH + LD,
+ [0x30] = BDL + HD + LH,
+ [0x31] = BDL + HD + HL + LR,
+ [0x32] = BDL + HR + HD + LL,
+ [0x33] = BDL + HH + HD,
+ [0x35] = BDL + HL + LU + LR,
+ [0x36] = BDL + HR + LU + LL,
+ [0x37] = BDL + HH + LU,
+ [0x38] = BDL + HU + LH,
+ [0x39] = BDL + HU + HL + LR,
+ [0x3a] = BDL + HU + HR + LL,
+ [0x3b] = BDL + HH + HU,
+ [0x3d] = BDL + HL + LV + LR,
+ [0x3e] = BDL + HR + LV + LL,
+ [0x3f] = BDL + HH + LV,
+ [0x40] = BDL + HU + LH + LD,
+ [0x41] = BDL + HD + LH + LU,
+ [0x42] = BDL + HV + LH,
+ [0x43] = BDL + HU + HL + LD + LR,
+ [0x44] = BDL + HU + HR + LD + LL,
+ [0x45] = BDL + HD + HL + LU + LR,
+ [0x46] = BDL + HD + HR + LU + LL,
+ [0x47] = BDL + HH + HU + LD,
+ [0x48] = BDL + HH + HD + LU,
+ [0x49] = BDL + HV + HL + LR,
+ [0x4a] = BDL + HV + HR + LL,
+ [0x4b] = BDL + HV + HH,
+ [0x78] = BDL + HL,
+ [0x79] = BDL + HU,
+ [0x7a] = BDL + HR,
+ [0x7b] = BDL + HD,
+ [0x7c] = BDL + HR + LL,
+ [0x7d] = BDL + HD + LU,
+ [0x7e] = BDL + HL + LR,
+ [0x7f] = BDL + HU + LD,
+
+ /* double [+light] lines */
+ [0x50] = BDL + DH,
+ [0x51] = BDL + DV,
+ [0x52] = BDL + DR + LD,
+ [0x53] = BDL + DD + LR,
+ [0x54] = BDL + DR + DD,
+ [0x55] = BDL + DL + LD,
+ [0x56] = BDL + DD + LL,
+ [0x57] = BDL + DL + DD,
+ [0x58] = BDL + DR + LU,
+ [0x59] = BDL + DU + LR,
+ [0x5a] = BDL + DU + DR,
+ [0x5b] = BDL + DL + LU,
+ [0x5c] = BDL + DU + LL,
+ [0x5d] = BDL + DL + DU,
+ [0x5e] = BDL + DR + LV,
+ [0x5f] = BDL + DV + LR,
+ [0x60] = BDL + DV + DR,
+ [0x61] = BDL + DL + LV,
+ [0x62] = BDL + DV + LL,
+ [0x63] = BDL + DV + DL,
+ [0x64] = BDL + DH + LD,
+ [0x65] = BDL + DD + LH,
+ [0x66] = BDL + DD + DH,
+ [0x67] = BDL + DH + LU,
+ [0x68] = BDL + DU + LH,
+ [0x69] = BDL + DH + DU,
+ [0x6a] = BDL + DH + LV,
+ [0x6b] = BDL + DV + LH,
+ [0x6c] = BDL + DH + DV,
+
+ /* (light) arcs */
+ [0x6d] = BDA + LD + LR,
+ [0x6e] = BDA + LD + LL,
+ [0x6f] = BDA + LU + LL,
+ [0x70] = BDA + LU + LR,
+
+ /* Lower (Down) X/8 block (data is 8 - X) */
+ [0x81] = BBD + 7, [0x82] = BBD + 6, [0x83] = BBD + 5, [0x84] = BBD + 4,
+ [0x85] = BBD + 3, [0x86] = BBD + 2, [0x87] = BBD + 1, [0x88] = BBD + 0,
+
+ /* Left X/8 block (data is X) */
+ [0x89] = BBL + 7, [0x8a] = BBL + 6, [0x8b] = BBL + 5, [0x8c] = BBL + 4,
+ [0x8d] = BBL + 3, [0x8e] = BBL + 2, [0x8f] = BBL + 1,
+
+ /* upper 1/2 (4/8), 1/8 block (X), right 1/2, 1/8 block (8-X) */
+ [0x80] = BBU + 4, [0x94] = BBU + 1,
+ [0x90] = BBR + 4, [0x95] = BBR + 7,
+
+ /* Quadrants */
+ [0x96] = BBQ + BL,
+ [0x97] = BBQ + BR,
+ [0x98] = BBQ + TL,
+ [0x99] = BBQ + TL + BL + BR,
+ [0x9a] = BBQ + TL + BR,
+ [0x9b] = BBQ + TL + TR + BL,
+ [0x9c] = BBQ + TL + TR + BR,
+ [0x9d] = BBQ + TR,
+ [0x9e] = BBQ + BL + TR,
+ [0x9f] = BBQ + BL + TR + BR,
+
+ /* Shades, data is an alpha value in 25% units (1/4, 1/2, 3/4) */
+ [0x91] = BBS + 1, [0x92] = BBS + 2, [0x93] = BBS + 3,
+
+ /* U+2504 - U+250B, U+254C - U+254F: unsupported (dashes) */
+ /* U+2571 - U+2573: unsupported (diagonals) */
+};
diff --git a/config.def.h b/config.def.h
index 91ab8ca..7bb3ff7 100644
--- a/config.def.h
+++ b/config.def.h
@@ -67,6 +67,18 @@ static unsigned int blinktimeout = 800;
*/
static unsigned int cursorthickness = 2;
+/*
+ * 1: render most of the lines/blocks characters without using the font for
+ * perfect alignment between cells (U2500 - U259F except dashes/diagonals).
+ * Bold affects lines thickness if boxdraw_bold is not 0. Italic is ignored.
+ * 0: disable (render all U25XX glyphs normally from the font).
+ */
+const int boxdraw = 0;
+const int boxdraw_bold = 0;
+
+/* braille (U28XX): 1: render as adjacent "pixels", 0: use font */
+const int boxdraw_braille = 0;
+
/*
* bell volume. It must be a value between -100 and 100. Use 0 for disabling
* it
diff --git a/st.c b/st.c
index f43cfd3..baa2bed 100644
--- a/st.c
+++ b/st.c
@@ -1214,6 +1214,9 @@ tsetchar(Rune u, const Glyph *attr, int x, int y)
term.dirty[y] = 1;
term.line[y][x] = *attr;
term.line[y][x].u = u;
+
+ if (isboxdraw(u))
+ term.line[y][x].mode |= ATTR_BOXDRAW;
}
void
diff --git a/st.h b/st.h
index 519b9bd..07a7c66 100644
--- a/st.h
+++ b/st.h
@@ -33,6 +33,7 @@ enum glyph_attribute {
ATTR_WRAP = 1 << 8,
ATTR_WIDE = 1 << 9,
ATTR_WDUMMY = 1 << 10,
+ ATTR_BOXDRAW = 1 << 11,
ATTR_BOLD_FAINT = ATTR_BOLD | ATTR_FAINT,
};
@@ -113,6 +114,14 @@ char *xstrdup(const char *);
int xgetcolor(int x, unsigned char *r, unsigned char *g, unsigned char *b);
+int isboxdraw(Rune);
+ushort boxdrawindex(const Glyph *);
+#ifdef XFT_VERSION
+/* only exposed to x.c, otherwise we'll need Xft.h for the types */
+void boxdraw_xinit(Display *, Colormap, XftDraw *, Visual *);
+void drawboxes(int, int, int, int, XftColor *, XftColor *, const XftGlyphFontSpec *, int);
+#endif
+
/* config.h globals */
extern char *utmp;
extern char *scroll;
@@ -126,3 +135,4 @@ extern unsigned int tabspaces;
extern unsigned int defaultfg;
extern unsigned int defaultbg;
extern unsigned int defaultcs;
+extern const int boxdraw, boxdraw_bold, boxdraw_braille;
diff --git a/x.c b/x.c
index 2a3bd38..bf6bbf9 100644
--- a/x.c
+++ b/x.c
@@ -1237,6 +1237,8 @@ xinit(int cols, int rows)
xsel.xtarget = XInternAtom(xw.dpy, "UTF8_STRING", 0);
if (xsel.xtarget == None)
xsel.xtarget = XA_STRING;
+
+ boxdraw_xinit(xw.dpy, xw.cmap, xw.draw, xw.vis);
}
int
@@ -1283,8 +1285,13 @@ xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x
yp = winy + font->ascent;
}
- /* Lookup character index with default font. */
- glyphidx = XftCharIndex(xw.dpy, font->match, rune);
+ if (mode & ATTR_BOXDRAW) {
+ /* minor shoehorning: boxdraw uses only this ushort */
+ glyphidx = boxdrawindex(&glyphs[i]);
+ } else {
+ /* Lookup character index with default font. */
+ glyphidx = XftCharIndex(xw.dpy, font->match, rune);
+ }
if (glyphidx) {
specs[numspecs].font = font->match;
specs[numspecs].glyph = glyphidx;
@@ -1488,8 +1495,12 @@ xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, i
r.width = width;
XftDrawSetClipRectangles(xw.draw, winx, winy, &r, 1);
- /* Render the glyphs. */
- XftDrawGlyphFontSpec(xw.draw, fg, specs, len);
+ if (base.mode & ATTR_BOXDRAW) {
+ drawboxes(winx, winy, width / len, win.ch, fg, bg, specs, len);
+ } else {
+ /* Render the glyphs. */
+ XftDrawGlyphFontSpec(xw.draw, fg, specs, len);
+ }
/* Render underline and strikethrough. */
if (base.mode & ATTR_UNDERLINE) {
@@ -1532,7 +1543,7 @@ xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og)
/*
* Select the right color for the right mode.
*/
- g.mode &= ATTR_BOLD|ATTR_ITALIC|ATTR_UNDERLINE|ATTR_STRUCK|ATTR_WIDE;
+ g.mode &= ATTR_BOLD|ATTR_ITALIC|ATTR_UNDERLINE|ATTR_STRUCK|ATTR_WIDE|ATTR_BOXDRAW;
if (IS_SET(MODE_REVERSE)) {
g.mode |= ATTR_REVERSE;
--
2.35.1

View File

@ -0,0 +1,208 @@
From c90af45228c1100377d64ad021fa3f0cff9a1df4 Mon Sep 17 00:00:00 2001
From: wael <40663@protonmail.com>
Date: Mon, 11 Apr 2022 21:28:43 +0300
Subject: [PATCH] [st][patch][csi 22 23] update to 0.8.5
---
st.c | 36 ++++++++++++++++++++++++++++++++----
st.info | 4 ++--
win.h | 4 +++-
x.c | 41 ++++++++++++++++++++++++++++++++++++++---
4 files changed, 75 insertions(+), 10 deletions(-)
diff --git a/st.c b/st.c
index f43cfd3..2802381 100644
--- a/st.c
+++ b/st.c
@@ -1801,6 +1801,33 @@ csihandle(void)
goto unknown;
}
break;
+ case 't': /* title stack operations */
+ switch (csiescseq.arg[0]) {
+ case 22: /* pust current title on stack */
+ switch (csiescseq.arg[1]) {
+ case 0:
+ case 1:
+ case 2:
+ xpushtitle();
+ break;
+ default:
+ goto unknown;
+ }
+ break;
+ case 23: /* pop last title from stack */
+ switch (csiescseq.arg[1]) {
+ case 0:
+ case 1:
+ case 2:
+ xsettitle(NULL, 1);
+ break;
+ default:
+ goto unknown;
+ }
+ break;
+ default:
+ goto unknown;
+ }
}
}
@@ -1885,7 +1912,7 @@ strhandle(void)
switch (par) {
case 0:
if (narg > 1) {
- xsettitle(strescseq.args[1]);
+ xsettitle(strescseq.args[1], 0);
xseticontitle(strescseq.args[1]);
}
return;
@@ -1895,7 +1922,7 @@ strhandle(void)
return;
case 2:
if (narg > 1)
- xsettitle(strescseq.args[1]);
+ xsettitle(strescseq.args[1], 0);
return;
case 52:
if (narg > 2 && allowwindowops) {
@@ -1973,7 +2000,7 @@ strhandle(void)
}
break;
case 'k': /* old title set compatibility */
- xsettitle(strescseq.args[0]);
+ xsettitle(strescseq.args[0], 0);
return;
case 'P': /* DCS -- Device Control String */
case '_': /* APC -- Application Program Command */
@@ -2345,6 +2372,7 @@ eschandle(uchar ascii)
break;
case 'c': /* RIS -- Reset to initial state */
treset();
+ xfreetitlestack();
resettitle();
xloadcols();
break;
@@ -2631,7 +2659,7 @@ tresize(int col, int row)
void
resettitle(void)
{
- xsettitle(NULL);
+ xsettitle(NULL, 0);
}
void
diff --git a/st.info b/st.info
index 8201ad6..aeef606 100644
--- a/st.info
+++ b/st.info
@@ -161,7 +161,7 @@ st-mono| simpleterm monocolor,
rin=\E[%p1%dT,
ritm=\E[23m,
rmacs=\E(B,
- rmcup=\E[?1049l,
+ rmcup=\E[?1049l\E[23;0;0t,
rmir=\E[4l,
rmkx=\E[?1l\E>,
rmso=\E[27m,
@@ -172,7 +172,7 @@ st-mono| simpleterm monocolor,
sitm=\E[3m,
sgr0=\E[0m,
smacs=\E(0,
- smcup=\E[?1049h,
+ smcup=\E[?1049h\E[22;0;0t,
smir=\E[4h,
smkx=\E[?1h\E=,
smso=\E[7m,
diff --git a/win.h b/win.h
index e6e4369..ef67fd6 100644
--- a/win.h
+++ b/win.h
@@ -31,7 +31,9 @@ void xfinishdraw(void);
void xloadcols(void);
int xsetcolorname(int, const char *);
void xseticontitle(char *);
-void xsettitle(char *);
+void xfreetitlestack(void);
+void xsettitle(char *, int);
+void xpushtitle(void);
int xsetcursor(int);
void xsetmode(int, unsigned int);
void xsetpointermotion(int);
diff --git a/x.c b/x.c
index 2a3bd38..babb04c 100644
--- a/x.c
+++ b/x.c
@@ -63,6 +63,9 @@ static void ttysend(const Arg *);
/* config.h for applying patches and the configuration. */
#include "config.h"
+/* size of title stack */
+#define TITLESTACKSIZE 8
+
/* XEMBED messages */
#define XEMBED_FOCUS_IN 4
#define XEMBED_FOCUS_OUT 5
@@ -220,6 +223,8 @@ static DC dc;
static XWindow xw;
static XSelection xsel;
static TermWindow win;
+static int tstki; /* title stack index */
+static char *titlestack[TITLESTACKSIZE]; /* title stack */
/* Font Ring Cache */
enum {
@@ -1626,10 +1631,30 @@ xseticontitle(char *p)
}
void
-xsettitle(char *p)
+xfreetitlestack(void)
{
- XTextProperty prop;
- DEFAULT(p, opt_title);
+ for (int i = 0; i < LEN(titlestack); i++) {
+ free(titlestack[i]);
+ titlestack[i] = NULL;
+ }
+}
+
+void
+xsettitle(char *p, int pop)
+{
+ XTextProperty prop;
+
+ free(titlestack[tstki]);
+ if (pop) {
+ titlestack[tstki] = NULL;
+ tstki = (tstki - 1 + TITLESTACKSIZE) % TITLESTACKSIZE;
+ p = titlestack[tstki] ? titlestack[tstki] : opt_title;
+ } else if (p) {
+ titlestack[tstki] = xstrdup(p);
+ } else {
+ titlestack[tstki] = NULL;
+ p = opt_title;
+ }
if (Xutf8TextListToTextProperty(xw.dpy, &p, 1, XUTF8StringStyle,
&prop) != Success)
@@ -1639,6 +1664,16 @@ xsettitle(char *p)
XFree(prop.value);
}
+void
+xpushtitle(void)
+{
+ int tstkin = (tstki + 1) % TITLESTACKSIZE;
+
+ free(titlestack[tstkin]);
+ titlestack[tstkin] = titlestack[tstki] ? xstrdup(titlestack[tstki]) : NULL;
+ tstki = tstkin;
+}
+
int
xstartdraw(void)
{
--
2.35.1

View File

@ -0,0 +1,624 @@
diff --git a/Makefile b/Makefile
index 6dfa212..adfa07a 100644
--- a/Makefile
+++ b/Makefile
@@ -4,7 +4,7 @@
include config.mk
-SRC = st.c x.c boxdraw.c
+SRC = st.c x.c boxdraw.c hb.c
OBJ = $(SRC:.c=.o)
all: options st
@@ -22,8 +22,9 @@ config.h:
$(CC) $(STCFLAGS) -c $<
st.o: config.h st.h win.h
-x.o: arg.h config.h st.h win.h
+x.o: arg.h config.h st.h win.h hb.h
boxdraw.o: config.h st.h boxdraw_data.h
+hb.o: st.h
$(OBJ): config.h config.mk
diff --git a/config.mk b/config.mk
index 1e306f8..3e13e53 100644
--- a/config.mk
+++ b/config.mk
@@ -15,10 +15,12 @@ PKG_CONFIG = pkg-config
# includes and libs
INCS = -I$(X11INC) \
`$(PKG_CONFIG) --cflags fontconfig` \
- `$(PKG_CONFIG) --cflags freetype2`
+ `$(PKG_CONFIG) --cflags freetype2` \
+ `$(PKG_CONFIG) --cflags harfbuzz`
LIBS = -L$(X11LIB) -lm -lrt -lX11 -lutil -lXft \
`$(PKG_CONFIG) --libs fontconfig` \
- `$(PKG_CONFIG) --libs freetype2`
+ `$(PKG_CONFIG) --libs freetype2` \
+ `$(PKG_CONFIG) --libs harfbuzz`
# flags
STCPPFLAGS = -DVERSION=\"$(VERSION)\" -D_XOPEN_SOURCE=600
diff --git a/hb.c b/hb.c
new file mode 100644
index 0000000..528c040
--- /dev/null
+++ b/hb.c
@@ -0,0 +1,124 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+#include <X11/Xft/Xft.h>
+#include <X11/cursorfont.h>
+#include <hb.h>
+#include <hb-ft.h>
+
+#include "st.h"
+#include "hb.h"
+
+#define FEATURE(c1,c2,c3,c4) { .tag = HB_TAG(c1,c2,c3,c4), .value = 1, .start = HB_FEATURE_GLOBAL_START, .end = HB_FEATURE_GLOBAL_END }
+#define BUFFER_STEP 256
+
+hb_font_t *hbfindfont(XftFont *match);
+
+typedef struct {
+ XftFont *match;
+ hb_font_t *font;
+} HbFontMatch;
+
+typedef struct {
+ size_t capacity;
+ HbFontMatch *fonts;
+} HbFontCache;
+
+static HbFontCache hbfontcache = { 0, NULL };
+
+typedef struct {
+ size_t capacity;
+ Rune *runes;
+} RuneBuffer;
+
+static RuneBuffer hbrunebuffer = { 0, NULL };
+
+/*
+ * Poplulate the array with a list of font features, wrapped in FEATURE macro,
+ * e. g.
+ * FEATURE('c', 'a', 'l', 't'), FEATURE('d', 'l', 'i', 'g')
+ */
+hb_feature_t features[] = { };
+
+void
+hbunloadfonts()
+{
+ for (int i = 0; i < hbfontcache.capacity; i++) {
+ hb_font_destroy(hbfontcache.fonts[i].font);
+ XftUnlockFace(hbfontcache.fonts[i].match);
+ }
+
+ if (hbfontcache.fonts != NULL) {
+ free(hbfontcache.fonts);
+ hbfontcache.fonts = NULL;
+ }
+ hbfontcache.capacity = 0;
+}
+
+hb_font_t *
+hbfindfont(XftFont *match)
+{
+ for (int i = 0; i < hbfontcache.capacity; i++) {
+ if (hbfontcache.fonts[i].match == match)
+ return hbfontcache.fonts[i].font;
+ }
+
+ /* Font not found in cache, caching it now. */
+ hbfontcache.fonts = realloc(hbfontcache.fonts, sizeof(HbFontMatch) * (hbfontcache.capacity + 1));
+ FT_Face face = XftLockFace(match);
+ hb_font_t *font = hb_ft_font_create(face, NULL);
+ if (font == NULL)
+ die("Failed to load Harfbuzz font.");
+
+ hbfontcache.fonts[hbfontcache.capacity].match = match;
+ hbfontcache.fonts[hbfontcache.capacity].font = font;
+ hbfontcache.capacity += 1;
+
+ return font;
+}
+
+void hbtransform(HbTransformData *data, XftFont *xfont, const Glyph *glyphs, int start, int length) {
+ ushort mode = USHRT_MAX;
+ unsigned int glyph_count;
+ int rune_idx, glyph_idx, end = start + length;
+
+ hb_font_t *font = hbfindfont(xfont);
+ if (font == NULL)
+ return;
+
+ hb_buffer_t *buffer = hb_buffer_create();
+ hb_buffer_set_direction(buffer, HB_DIRECTION_LTR);
+
+ /* Resize the buffer if required length is larger. */
+ if (hbrunebuffer.capacity < length) {
+ hbrunebuffer.capacity = (length / BUFFER_STEP + 1) * BUFFER_STEP;
+ hbrunebuffer.runes = realloc(hbrunebuffer.runes, hbrunebuffer.capacity * sizeof(Rune));
+ }
+
+ /* Fill buffer with codepoints. */
+ for (rune_idx = 0, glyph_idx = start; glyph_idx < end; glyph_idx++, rune_idx++) {
+ hbrunebuffer.runes[rune_idx] = glyphs[glyph_idx].u;
+ mode = glyphs[glyph_idx].mode;
+ if (mode & ATTR_WDUMMY)
+ hbrunebuffer.runes[rune_idx] = 0x0020;
+ }
+ hb_buffer_add_codepoints(buffer, hbrunebuffer.runes, length, 0, length);
+
+ /* Shape the segment. */
+ hb_shape(font, buffer, features, sizeof(features)/sizeof(hb_feature_t));
+
+ /* Get new glyph info. */
+ hb_glyph_info_t *info = hb_buffer_get_glyph_infos(buffer, &glyph_count);
+ hb_glyph_position_t *pos = hb_buffer_get_glyph_positions(buffer, &glyph_count);
+
+ /* Fill the output. */
+ data->buffer = buffer;
+ data->glyphs = info;
+ data->positions = pos;
+ data->count = glyph_count;
+}
+
+void hbcleanup(HbTransformData *data) {
+ hb_buffer_destroy(data->buffer);
+ memset(data, 0, sizeof(HbTransformData));
+}
diff --git a/hb.h b/hb.h
new file mode 100644
index 0000000..88de9bd
--- /dev/null
+++ b/hb.h
@@ -0,0 +1,14 @@
+#include <X11/Xft/Xft.h>
+#include <hb.h>
+#include <hb-ft.h>
+
+typedef struct {
+ 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 41d5ace..1c2edd6 100644
--- a/st.c
+++ b/st.c
@@ -2643,7 +2643,8 @@ draw(void)
drawregion(0, 0, term.col, term.row);
xdrawcursor(cx, term.c.y, term.line[term.c.y][cx],
- term.ocx, term.ocy, term.line[term.ocy][term.ocx]);
+ term.ocx, term.ocy, term.line[term.ocy][term.ocx],
+ term.line[term.ocy], term.col);
term.ocx = cx;
term.ocy = term.c.y;
xfinishdraw();
diff --git a/st.h b/st.h
index 808f5f7..ae41368 100644
--- a/st.h
+++ b/st.h
@@ -11,7 +11,8 @@
#define DIVCEIL(n, d) (((n) + ((d) - 1)) / (d))
#define DEFAULT(a, b) (a) = (a) ? (a) : (b)
#define LIMIT(x, a, b) (x) = (x) < (a) ? (a) : (x) > (b) ? (b) : (x)
-#define ATTRCMP(a, b) ((a).mode != (b).mode || (a).fg != (b).fg || \
+#define ATTRCMP(a, b) (((a).mode & (~ATTR_WRAP)) != ((b).mode & (~ATTR_WRAP)) || \
+ (a).fg != (b).fg || \
(a).bg != (b).bg)
#define TIMEDIFF(t1, t2) ((t1.tv_sec-t2.tv_sec)*1000 + \
(t1.tv_nsec-t2.tv_nsec)/1E6)
diff --git a/win.h b/win.h
index 6de960d..94679e4 100644
--- a/win.h
+++ b/win.h
@@ -25,7 +25,7 @@ enum win_mode {
void xbell(void);
void xclipcopy(void);
-void xdrawcursor(int, int, Glyph, int, int, Glyph);
+void xdrawcursor(int, int, Glyph, int, int, Glyph, Line, int);
void xdrawline(Line, int, int, int);
void xfinishdraw(void);
void xloadcols(void);
diff --git a/x.c b/x.c
index bf6bbf9..929a59a 100644
--- a/x.c
+++ b/x.c
@@ -19,6 +19,7 @@ char *argv0;
#include "arg.h"
#include "st.h"
#include "win.h"
+#include "hb.h"
/* types used in config.h */
typedef struct {
@@ -141,6 +142,7 @@ 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 xdrawglyph(Glyph, int, int);
@@ -757,7 +759,7 @@ xresize(int col, int row)
xclear(0, 0, win.w, win.h);
/* resize to new width */
- xw.specbuf = xrealloc(xw.specbuf, col * sizeof(GlyphFontSpec));
+ xw.specbuf = xrealloc(xw.specbuf, col * sizeof(GlyphFontSpec) * 4);
}
ushort
@@ -1062,6 +1064,9 @@ xunloadfont(Font *f)
void
xunloadfonts(void)
{
+ /* Clear Harfbuzz font cache. */
+ hbunloadfonts();
+
/* Free the loaded fonts in the font cache. */
while (frclen > 0)
XftFontClose(xw.dpy, frc[--frclen].font);
@@ -1185,7 +1190,7 @@ xinit(int cols, int rows)
XFillRectangle(xw.dpy, xw.buf, dc.gc, 0, 0, win.w, win.h);
/* font spec buffer */
- xw.specbuf = xmalloc(cols * sizeof(GlyphFontSpec));
+ xw.specbuf = xmalloc(cols * sizeof(GlyphFontSpec) * 4);
/* Xft rendering context */
xw.draw = XftDrawCreate(xw.dpy, xw.buf, xw.vis, xw.cmap);
@@ -1241,6 +1246,22 @@ xinit(int cols, int rows)
boxdraw_xinit(xw.dpy, xw.cmap, xw.draw, xw.vis);
}
+void
+xresetfontsettings(ushort mode, Font **font, int *frcflags)
+{
+ *font = &dc.font;
+ if ((mode & ATTR_ITALIC) && (mode & ATTR_BOLD)) {
+ *font = &dc.ibfont;
+ *frcflags = FRC_ITALICBOLD;
+ } else if (mode & ATTR_ITALIC) {
+ *font = &dc.ifont;
+ *frcflags = FRC_ITALIC;
+ } else if (mode & ATTR_BOLD) {
+ *font = &dc.bfont;
+ *frcflags = FRC_BOLD;
+ }
+}
+
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
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;
+ HbTransformData shaped = { 0 };
+
+ /* Initial values. */
+ mode = prevmode = glyphs[0].mode;
+ xresetfontsettings(mode, &font, &frcflags);
for (i = 0, xp = winx, yp = winy + font->ascent; i < len; ++i) {
- /* Fetch rune and mode for current glyph. */
- rune = glyphs[i].u;
mode = glyphs[i].mode;
/* Skip dummy wide-character spacing. */
- if (mode == ATTR_WDUMMY)
+ if (mode & ATTR_WDUMMY && i < (len - 1))
continue;
- /* Determine font for glyph if different from previous glyph. */
- if (prevmode != mode) {
- prevmode = mode;
- font = &dc.font;
- frcflags = FRC_NORMAL;
- runewidth = win.cw * ((mode & ATTR_WIDE) ? 2.0f : 1.0f);
- if ((mode & ATTR_ITALIC) && (mode & ATTR_BOLD)) {
- font = &dc.ibfont;
- frcflags = FRC_ITALICBOLD;
- } else if (mode & ATTR_ITALIC) {
- font = &dc.ifont;
- frcflags = FRC_ITALIC;
- } else if (mode & ATTR_BOLD) {
- font = &dc.bfont;
- frcflags = FRC_BOLD;
+ if (
+ prevmode != mode
+ || ATTRCMP(glyphs[start], glyphs[i])
+ || selected(x + i, y) != selected(x + start, y)
+ || i == (len - 1)
+ ) {
+ /* Handle 1-character wide segments and end of line */
+ length = i - start;
+ if (i == start) {
+ length = 1;
+ } else if (i == (len - 1)) {
+ length = (i - start + 1);
}
- yp = winy + font->ascent;
- }
- if (mode & ATTR_BOXDRAW) {
- /* minor shoehorning: boxdraw uses only this ushort */
- glyphidx = boxdrawindex(&glyphs[i]);
- } else {
- /* Lookup character index with default font. */
- glyphidx = XftCharIndex(xw.dpy, font->match, rune);
- }
- if (glyphidx) {
- specs[numspecs].font = font->match;
- specs[numspecs].glyph = glyphidx;
- specs[numspecs].x = (short)xp;
- specs[numspecs].y = (short)yp;
- xp += runewidth;
- 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);
- /* Everything correct. */
- if (glyphidx && frc[f].flags == frcflags)
- break;
- /* We got a default font for a not found glyph. */
- if (!glyphidx && frc[f].flags == frcflags
- && frc[f].unicodep == rune) {
- break;
+ /* Shape the segment. */
+ hbtransform(&shaped, font->match, glyphs, start, length);
+ runewidth = win.cw * ((glyphs[start].mode & ATTR_WIDE) ? 2.0f : 1.0f);
+ cluster_xp = xp; cluster_yp = yp;
+ for (int code_idx = 0; code_idx < shaped.count; code_idx++) {
+ int idx = shaped.glyphs[code_idx].cluster;
+
+ if (glyphs[start + idx].mode & ATTR_WDUMMY)
+ continue;
+
+ /* Advance the drawing cursor if we've moved to a new cluster */
+ if (code_idx > 0 && idx != shaped.glyphs[code_idx - 1].cluster) {
+ xp += runewidth;
+ cluster_xp = xp;
+ cluster_yp = yp;
+ runewidth = win.cw * ((glyphs[start + idx].mode & ATTR_WIDE) ? 2.0f : 1.0f);
+ }
+
+ if (glyphs[start + code_idx].mode & ATTR_BOXDRAW) {
+ /* minor shoehorning: boxdraw uses only this ushort */
+ specs[numspecs].font = font->match;
+ specs[numspecs].glyph = boxdrawindex(&glyphs[start + code_idx]);
+ specs[numspecs].x = xp;
+ specs[numspecs].y = yp;
+ numspecs++;
+ } else if (shaped.glyphs[code_idx].codepoint != 0) {
+ /* If symbol is found, put it into the specs. */
+ specs[numspecs].font = font->match;
+ specs[numspecs].glyph = shaped.glyphs[code_idx].codepoint;
+ specs[numspecs].x = cluster_xp + (short)(shaped.positions[code_idx].x_offset / 64.);
+ specs[numspecs].y = cluster_yp - (short)(shaped.positions[code_idx].y_offset / 64.);
+ cluster_xp += shaped.positions[code_idx].x_advance / 64.;
+ cluster_yp += shaped.positions[code_idx].y_advance / 64.;
+ numspecs++;
+ } else {
+ /* If it's not found, try to fetch it through the font cache. */
+ rune = glyphs[start + idx].u;
+ for (f = 0; f < frclen; f++) {
+ glyphidx = XftCharIndex(xw.dpy, frc[f].font, rune);
+ /* Everything correct. */
+ if (glyphidx && frc[f].flags == frcflags)
+ break;
+ /* We got a default font for a not found glyph. */
+ if (!glyphidx && frc[f].flags == frcflags
+ && frc[f].unicodep == rune) {
+ break;
+ }
+ }
+
+ /* 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;
+
+ /*
+ * Nothing was found in the cache. Now use
+ * some dozen of Fontconfig calls to get the
+ * font for one single character.
+ *
+ * Xft and fontconfig are design failures.
+ */
+ fcpattern = FcPatternDuplicate(font->pattern);
+ fccharset = FcCharSetCreate();
+
+ FcCharSetAddChar(fccharset, rune);
+ FcPatternAddCharSet(fcpattern, FC_CHARSET,
+ fccharset);
+ FcPatternAddBool(fcpattern, FC_SCALABLE, 1);
+
+ FcConfigSubstitute(0, fcpattern,
+ FcMatchPattern);
+ FcDefaultSubstitute(fcpattern);
+
+ fontpattern = FcFontSetMatch(0, fcsets, 1,
+ fcpattern, &fcres);
+
+ /* Allocate memory for the new cache entry. */
+ if (frclen >= frccap) {
+ frccap += 16;
+ frc = xrealloc(frc, frccap * sizeof(Fontcache));
+ }
+
+ frc[frclen].font = XftFontOpenPattern(xw.dpy,
+ fontpattern);
+ if (!frc[frclen].font)
+ die("XftFontOpenPattern failed seeking fallback font: %s\n",
+ strerror(errno));
+ frc[frclen].flags = frcflags;
+ frc[frclen].unicodep = rune;
+
+ glyphidx = XftCharIndex(xw.dpy, frc[frclen].font, rune);
+
+ f = frclen;
+ frclen++;
+
+ FcPatternDestroy(fcpattern);
+ FcCharSetDestroy(fccharset);
+ }
+
+ specs[numspecs].font = frc[f].font;
+ specs[numspecs].glyph = glyphidx;
+ specs[numspecs].x = (short)xp;
+ specs[numspecs].y = (short)yp;
+ numspecs++;
+ }
}
- }
- /* 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
- * some dozen of Fontconfig calls to get the
- * font for one single character.
- *
- * Xft and fontconfig are design failures.
- */
- fcpattern = FcPatternDuplicate(font->pattern);
- fccharset = FcCharSetCreate();
-
- FcCharSetAddChar(fccharset, rune);
- FcPatternAddCharSet(fcpattern, FC_CHARSET,
- fccharset);
- FcPatternAddBool(fcpattern, FC_SCALABLE, 1);
-
- FcConfigSubstitute(0, fcpattern,
- FcMatchPattern);
- FcDefaultSubstitute(fcpattern);
-
- fontpattern = FcFontSetMatch(0, fcsets, 1,
- fcpattern, &fcres);
-
- /* Allocate memory for the new cache entry. */
- if (frclen >= frccap) {
- frccap += 16;
- frc = xrealloc(frc, frccap * sizeof(Fontcache));
+ /* Determine font for glyph if different from previous glyph. */
+ if (prevmode != mode) {
+ prevmode = mode;
+ xresetfontsettings(mode, &font, &frcflags);
+ yp = winy + font->ascent;
}
-
- frc[frclen].font = XftFontOpenPattern(xw.dpy,
- fontpattern);
- if (!frc[frclen].font)
- die("XftFontOpenPattern failed seeking fallback font: %s\n",
- strerror(errno));
- frc[frclen].flags = frcflags;
- frc[frclen].unicodep = rune;
-
- glyphidx = XftCharIndex(xw.dpy, frc[frclen].font, rune);
-
- f = frclen;
- frclen++;
-
- FcPatternDestroy(fcpattern);
- FcCharSetDestroy(fccharset);
}
-
- specs[numspecs].font = frc[f].font;
- specs[numspecs].glyph = glyphidx;
- specs[numspecs].x = (short)xp;
- specs[numspecs].y = (short)yp;
- xp += runewidth;
- numspecs++;
}
+ hbcleanup(&shaped);
return numspecs;
}
@@ -1528,14 +1581,17 @@ xdrawglyph(Glyph g, int x, int y)
}
void
-xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og)
+xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og, Line line, int len)
{
Color drawcol;
/* remove the old cursor */
if (selected(ox, oy))
og.mode ^= ATTR_REVERSE;
- xdrawglyph(og, ox, oy);
+
+ /* Redraw the line where cursor was previously.
+ * It will restore the ligatures broken by the cursor. */
+ xdrawline(line, 0, oy, len);
if (IS_SET(MODE_HIDE))
return;
@@ -1663,18 +1719,16 @@ xdrawline(Line line, int x1, int y1, int x2)
Glyph base, new;
XftGlyphFontSpec *specs = xw.specbuf;
- numspecs = xmakeglyphfontspecs(specs, &line[x1], x2 - x1, x1, y1);
i = ox = 0;
- for (x = x1; x < x2 && i < numspecs; x++) {
+ for (x = x1; x < x2; x++) {
new = line[x];
if (new.mode == ATTR_WDUMMY)
continue;
if (selected(x, y1))
new.mode ^= ATTR_REVERSE;
- if (i > 0 && ATTRCMP(base, new)) {
- xdrawglyphfontspecs(specs, base, i, ox, y1);
- specs += i;
- numspecs -= i;
+ if ((i > 0) && ATTRCMP(base, new)) {
+ numspecs = xmakeglyphfontspecs(specs, &line[ox], x - ox, ox, y1);
+ xdrawglyphfontspecs(specs, base, numspecs, ox, y1);
i = 0;
}
if (i == 0) {
@@ -1683,8 +1737,10 @@ xdrawline(Line line, int x1, int y1, int x2)
}
i++;
}
- if (i > 0)
- xdrawglyphfontspecs(specs, base, i, ox, y1);
+ if (i > 0) {
+ numspecs = xmakeglyphfontspecs(specs, &line[ox], x2 - ox, ox, y1);
+ xdrawglyphfontspecs(specs, base, numspecs, ox, y1);
+ }
}
void

View File

@ -0,0 +1,130 @@
From 0750c0b8c91579ec871c70c8990527bebc86a56e Mon Sep 17 00:00:00 2001
From: Ashish Kumar Yadav <ashishkumar.yadav@students.iiserpune.ac.in>
Date: Sat, 31 Jul 2021 22:21:11 +0530
Subject: [PATCH] Add settings for selection-colors
This patch adds the two color-settings *selectionfg* and *selectionbg* to
config.def.h. Those define the fore- and background colors which are used when
text on the screen is selected with the mouse. This removes the default
behaviour which would simply reverse the colors.
Additionally, a third setting *ingnoreselfg* exists. If true then the setting
*selectionfg* is ignored and the original foreground-colors of each cell are
not changed during selection. Basically only the background-color would change.
This might be more visually appealing to some folks.
---
config.def.h | 11 ++++++++---
st.h | 1 +
x.c | 30 +++++++++++++-----------------
3 files changed, 22 insertions(+), 20 deletions(-)
diff --git a/config.def.h b/config.def.h
index 6f05dce..3679af8 100644
--- a/config.def.h
+++ b/config.def.h
@@ -119,18 +119,23 @@ static const char *colorname[] = {
/* more colors can be added after 255 to use with DefaultXX */
"#cccccc",
- "#555555",
+ "#2e3440",
};
/*
* Default colors (colorname index)
- * foreground, background, cursor, reverse cursor
+ * foreground, background, cursor, reverse cursor, selection
*/
unsigned int defaultfg = 7;
unsigned int defaultbg = 0;
static unsigned int defaultcs = 256;
-static unsigned int defaultrcs = 257;
+static unsigned int defaultrcs = 256;
+unsigned int selectionbg = 257;
+unsigned int selectionfg = 7;
+/* If 0 use selectionfg as foreground in order to have a uniform foreground-color */
+/* Else if 1 keep original foreground-color of each cell => more colors :) */
+static int ignoreselfg = 1;
/*
* Default shape of cursor
diff --git a/st.h b/st.h
index 3d351b6..e1a28c3 100644
--- a/st.h
+++ b/st.h
@@ -33,6 +33,7 @@ enum glyph_attribute {
ATTR_WRAP = 1 << 8,
ATTR_WIDE = 1 << 9,
ATTR_WDUMMY = 1 << 10,
+ ATTR_SELECTED = 1 << 11,
ATTR_BOLD_FAINT = ATTR_BOLD | ATTR_FAINT,
};
diff --git a/x.c b/x.c
index 210f184..7a6c70e 100644
--- a/x.c
+++ b/x.c
@@ -1425,6 +1425,12 @@ xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, i
bg = temp;
}
+ if (base.mode & ATTR_SELECTED) {
+ bg = &dc.col[selectionbg];
+ if (!ignoreselfg)
+ fg = &dc.col[selectionfg];
+ }
+
if (base.mode & ATTR_BLINK && win.mode & MODE_BLINK)
fg = bg;
@@ -1491,7 +1497,7 @@ xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og)
/* remove the old cursor */
if (selected(ox, oy))
- og.mode ^= ATTR_REVERSE;
+ og.mode |= ATTR_SELECTED;
xdrawglyph(og, ox, oy);
if (IS_SET(MODE_HIDE))
@@ -1504,23 +1510,13 @@ xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og)
if (IS_SET(MODE_REVERSE)) {
g.mode |= ATTR_REVERSE;
+ g.fg = defaultcs;
g.bg = defaultfg;
- if (selected(cx, cy)) {
- drawcol = dc.col[defaultcs];
- g.fg = defaultrcs;
- } else {
- drawcol = dc.col[defaultrcs];
- g.fg = defaultcs;
- }
+ drawcol = dc.col[defaultrcs];
} else {
- if (selected(cx, cy)) {
- g.fg = defaultfg;
- g.bg = defaultrcs;
- } else {
- g.fg = defaultbg;
- g.bg = defaultcs;
- }
- drawcol = dc.col[g.bg];
+ g.fg = defaultbg;
+ g.bg = defaultcs;
+ drawcol = dc.col[defaultcs];
}
/* draw the new one */
@@ -1612,7 +1608,7 @@ xdrawline(Line line, int x1, int y1, int x2)
if (new.mode == ATTR_WDUMMY)
continue;
if (selected(x, y1))
- new.mode ^= ATTR_REVERSE;
+ new.mode |= ATTR_SELECTED;
if (i > 0 && ATTRCMP(base, new)) {
xdrawglyphfontspecs(specs, base, i, ox, y1);
specs += i;
--
2.32.0

View File

@ -0,0 +1,605 @@
diff --git a/config.def.h b/config.def.h
index 6f05dce..7ae1b92 100644
--- a/config.def.h
+++ b/config.def.h
@@ -470,3 +470,27 @@ static char ascii_printable[] =
" !\"#$%&'()*+,-./0123456789:;<=>?"
"@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
diff --git a/st.c b/st.c
index 76b7e0d..542ab3a 100644
--- a/st.c
+++ b/st.c
@@ -33,6 +33,7 @@
#define UTF_SIZ 4
#define ESC_BUF_SIZ (128*UTF_SIZ)
#define ESC_ARG_SIZ 16
+#define CAR_PER_ARG 4
#define STR_BUF_SIZ ESC_BUF_SIZ
#define STR_ARG_SIZ ESC_ARG_SIZ
@@ -139,6 +140,7 @@ typedef struct {
int arg[ESC_ARG_SIZ];
int narg; /* nb of args */
char mode[2];
+ int carg[ESC_ARG_SIZ][CAR_PER_ARG]; /* colon args */
} CSIEscape;
/* STR Escape sequence structs */
@@ -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);
@@ -1131,6 +1134,28 @@ tnewline(int first_col)
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
csiparse(void)
{
@@ -1153,6 +1178,7 @@ csiparse(void)
v = -1;
csiescseq.arg[csiescseq.narg++] = v;
p = np;
+ readcolonargs(&p, csiescseq.narg-1, csiescseq.carg);
if (*p != ';' || csiescseq.narg == ESC_ARG_SIZ)
break;
p++;
@@ -1369,6 +1395,10 @@ tsetattr(int *attr, int l)
ATTR_STRUCK );
term.c.attr.fg = defaultfg;
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;
case 1:
term.c.attr.mode |= ATTR_BOLD;
@@ -1380,7 +1410,14 @@ tsetattr(int *attr, int l)
term.c.attr.mode |= ATTR_ITALIC;
break;
case 4:
- term.c.attr.mode |= ATTR_UNDERLINE;
+ term.c.attr.ustyle = csiescseq.carg[i][0];
+
+ if (term.c.attr.ustyle != 0)
+ term.c.attr.mode |= ATTR_UNDERLINE;
+ else
+ term.c.attr.mode &= ~ATTR_UNDERLINE;
+
+ term.c.attr.mode ^= ATTR_DIRTYUNDERLINE;
break;
case 5: /* slow blink */
/* FALLTHROUGH */
@@ -1431,6 +1468,18 @@ tsetattr(int *attr, int l)
case 49:
term.c.attr.bg = defaultbg;
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:
if (BETWEEN(attr[i], 30, 37)) {
term.c.attr.fg = attr[i] - 30;
diff --git a/st.h b/st.h
index 3d351b6..95bdcbd 100644
--- a/st.h
+++ b/st.h
@@ -34,6 +34,7 @@ enum glyph_attribute {
ATTR_WIDE = 1 << 9,
ATTR_WDUMMY = 1 << 10,
ATTR_BOLD_FAINT = ATTR_BOLD | ATTR_FAINT,
+ ATTR_DIRTYUNDERLINE = 1 << 15,
};
enum selection_mode {
@@ -65,6 +66,8 @@ typedef struct {
ushort mode; /* attribute flags */
uint32_t fg; /* foreground */
uint32_t bg; /* background */
+ int ustyle; /* underline style */
+ int ucolor[3]; /* underline color */
} Glyph;
typedef Glyph *Line;
diff --git a/st.info b/st.info
index 8201ad6..659878c 100644
--- a/st.info
+++ b/st.info
@@ -1,4 +1,5 @@
st-mono| simpleterm monocolor,
+ Su,
acsc=+C\,D-A.B0E``aaffgghFiGjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~,
am,
bce,
diff --git a/x.c b/x.c
index 210f184..3a0e79e 100644
--- a/x.c
+++ b/x.c
@@ -45,6 +45,14 @@ typedef struct {
signed char appcursor; /* application cursor */
} 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 */
#define XK_ANY_MOD UINT_MAX
#define XK_NO_MOD 0
@@ -1339,6 +1347,51 @@ xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x
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
xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, int y)
{
@@ -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) {

View File

@ -0,0 +1,97 @@
From ae14b869d7bc0e0cd8ed16157837ad09aaacacc0 Mon Sep 17 00:00:00 2001
From: David Gricar <coppie@protonmail.com>
Date: Tue, 17 Mar 2020 13:38:05 +0100
Subject: [PATCH] Add switch to provide initial working directory
This patch adds -p switch which takes one argument 'path' and can be
used to set the initial working directory of the new st instance.
It acts the same as running 'cd path' command after starting the st
instance.
---
st.1 | 8 ++++++++
x.c | 13 +++++++++----
2 files changed, 17 insertions(+), 4 deletions(-)
diff --git a/st.1 b/st.1
index e8d6059..a901122 100644
--- a/st.1
+++ b/st.1
@@ -6,6 +6,8 @@ st \- simple terminal
.RB [ \-aiv ]
.RB [ \-c
.IR class ]
+.RB [ \-d
+.IR path ]
.RB [ \-f
.IR font ]
.RB [ \-g
@@ -30,6 +32,8 @@ st \- simple terminal
.RB [ \-aiv ]
.RB [ \-c
.IR class ]
+.RB [ \-d
+.IR path ]
.RB [ \-f
.IR font ]
.RB [ \-g
@@ -58,6 +62,10 @@ disable alternate screens in terminal
.BI \-c " class"
defines the window class (default $TERM).
.TP
+.BI \-d " path"
+changes the working directory to
+.IR path .
+.TP
.BI \-f " font"
defines the
.I font
diff --git a/x.c b/x.c
index 48a6676..fab2ddc 100644
--- a/x.c
+++ b/x.c
@@ -250,6 +250,7 @@ static char *opt_io = NULL;
static char *opt_line = NULL;
static char *opt_name = NULL;
static char *opt_title = NULL;
+static char *opt_dir = NULL;
static int oldbutton = 3; /* button event on startup: 3 = release */
@@ -1958,12 +1959,12 @@ run(void)
void
usage(void)
{
- die("usage: %s [-aiv] [-c class] [-f font] [-g geometry]"
- " [-n name] [-o file]\n"
+ die("usage: %s [-aiv] [-c class] [-d path] [-f font]"
+ " [-g geometry] [-n name] [-o file]\n"
" [-T title] [-t title] [-w windowid]"
" [[-e] command [args ...]]\n"
- " %s [-aiv] [-c class] [-f font] [-g geometry]"
- " [-n name] [-o file]\n"
+ " %s [-aiv] [-c class] [-d path] [-f font]"
+ " [-g geometry] [-n name] [-o file]\n"
" [-T title] [-t title] [-w windowid] -l line"
" [stty_args ...]\n", argv0, argv0);
}
@@ -2015,6 +2016,9 @@ main(int argc, char *argv[])
case 'v':
die("%s " VERSION "\n", argv0);
break;
+ case 'd':
+ opt_dir = EARGF(usage());
+ break;
default:
usage();
} ARGEND;
@@ -2034,6 +2038,7 @@ run:
xinit(cols, rows);
xsetenv();
selinit();
+ chdir(opt_dir);
run();
return 0;
--
2.25.1

8
st.1
View File

@ -6,6 +6,8 @@ st \- simple terminal
.RB [ \-aiv ]
.RB [ \-c
.IR class ]
.RB [ \-d
.IR path ]
.RB [ \-f
.IR font ]
.RB [ \-g
@ -30,6 +32,8 @@ st \- simple terminal
.RB [ \-aiv ]
.RB [ \-c
.IR class ]
.RB [ \-d
.IR path ]
.RB [ \-f
.IR font ]
.RB [ \-g
@ -58,6 +62,10 @@ disable alternate screens in terminal
.BI \-c " class"
defines the window class (default $TERM).
.TP
.BI \-d " path"
changes the working directory to
.IR path .
.TP
.BI \-f " font"
defines the
.I font

93
st.c
View File

@ -33,6 +33,7 @@
#define UTF_SIZ 4
#define ESC_BUF_SIZ (128*UTF_SIZ)
#define ESC_ARG_SIZ 16
#define CAR_PER_ARG 4
#define STR_BUF_SIZ ESC_BUF_SIZ
#define STR_ARG_SIZ ESC_ARG_SIZ
@ -139,6 +140,7 @@ typedef struct {
int arg[ESC_ARG_SIZ];
int narg; /* nb of args */
char mode[2];
int carg[ESC_ARG_SIZ][CAR_PER_ARG]; /* colon args */
} CSIEscape;
/* STR Escape sequence structs */
@ -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 void osc_color_response(int, int, int);
@ -1127,6 +1130,28 @@ tnewline(int first_col)
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
csiparse(void)
{
@ -1149,6 +1174,7 @@ csiparse(void)
v = -1;
csiescseq.arg[csiescseq.narg++] = v;
p = np;
readcolonargs(&p, csiescseq.narg-1, csiescseq.carg);
if (*p != ';' || csiescseq.narg == ESC_ARG_SIZ)
break;
p++;
@ -1215,6 +1241,9 @@ tsetchar(Rune u, const Glyph *attr, int x, int y)
term.dirty[y] = 1;
term.line[y][x] = *attr;
term.line[y][x].u = u;
if (isboxdraw(u))
term.line[y][x].mode |= ATTR_BOXDRAW;
}
void
@ -1365,6 +1394,10 @@ tsetattr(const int *attr, int l)
ATTR_STRUCK );
term.c.attr.fg = defaultfg;
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;
case 1:
term.c.attr.mode |= ATTR_BOLD;
@ -1376,7 +1409,14 @@ tsetattr(const int *attr, int l)
term.c.attr.mode |= ATTR_ITALIC;
break;
case 4:
term.c.attr.mode |= ATTR_UNDERLINE;
term.c.attr.ustyle = csiescseq.carg[i][0];
if (term.c.attr.ustyle != 0)
term.c.attr.mode |= ATTR_UNDERLINE;
else
term.c.attr.mode &= ~ATTR_UNDERLINE;
term.c.attr.mode ^= ATTR_DIRTYUNDERLINE;
break;
case 5: /* slow blink */
/* FALLTHROUGH */
@ -1427,6 +1467,18 @@ tsetattr(const int *attr, int l)
case 49:
term.c.attr.bg = defaultbg;
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:
if (BETWEEN(attr[i], 30, 37)) {
term.c.attr.fg = attr[i] - 30;
@ -1809,6 +1861,33 @@ csihandle(void)
goto unknown;
}
break;
case 't': /* title stack operations */
switch (csiescseq.arg[0]) {
case 22: /* pust current title on stack */
switch (csiescseq.arg[1]) {
case 0:
case 1:
case 2:
xpushtitle();
break;
default:
goto unknown;
}
break;
case 23: /* pop last title from stack */
switch (csiescseq.arg[1]) {
case 0:
case 1:
case 2:
xsettitle(NULL, 1);
break;
default:
goto unknown;
}
break;
default:
goto unknown;
}
}
}
@ -1887,7 +1966,7 @@ strhandle(void)
switch (par) {
case 0:
if (narg > 1) {
xsettitle(strescseq.args[1]);
xsettitle(strescseq.args[1], 0);
xseticontitle(strescseq.args[1]);
}
return;
@ -1897,7 +1976,7 @@ strhandle(void)
return;
case 2:
if (narg > 1)
xsettitle(strescseq.args[1]);
xsettitle(strescseq.args[1], 0);
return;
case 52:
if (narg > 2 && allowwindowops) {
@ -1956,7 +2035,7 @@ strhandle(void)
}
break;
case 'k': /* old title set compatibility */
xsettitle(strescseq.args[0]);
xsettitle(strescseq.args[0], 0);
return;
case 'P': /* DCS -- Device Control String */
case '_': /* APC -- Application Program Command */
@ -2328,6 +2407,7 @@ eschandle(uchar ascii)
break;
case 'c': /* RIS -- Reset to initial state */
treset();
xfreetitlestack();
resettitle();
xloadcols();
break;
@ -2617,7 +2697,7 @@ tresize(int col, int row)
void
resettitle(void)
{
xsettitle(NULL);
xsettitle(NULL, 0);
}
void
@ -2652,7 +2732,8 @@ draw(void)
drawregion(0, 0, term.col, term.row);
xdrawcursor(cx, term.c.y, term.line[term.c.y][cx],
term.ocx, term.ocy, term.line[term.ocy][term.ocx]);
term.ocx, term.ocy, term.line[term.ocy][term.ocx],
term.line[term.ocy], term.col);
term.ocx = cx;
term.ocy = term.c.y;
xfinishdraw();

17
st.h
View File

@ -11,7 +11,8 @@
#define DIVCEIL(n, d) (((n) + ((d) - 1)) / (d))
#define DEFAULT(a, b) (a) = (a) ? (a) : (b)
#define LIMIT(x, a, b) (x) = (x) < (a) ? (a) : (x) > (b) ? (b) : (x)
#define ATTRCMP(a, b) ((a).mode != (b).mode || (a).fg != (b).fg || \
#define ATTRCMP(a, b) (((a).mode & (~ATTR_WRAP)) != ((b).mode & (~ATTR_WRAP)) || \
(a).fg != (b).fg || \
(a).bg != (b).bg)
#define TIMEDIFF(t1, t2) ((t1.tv_sec-t2.tv_sec)*1000 + \
(t1.tv_nsec-t2.tv_nsec)/1E6)
@ -33,7 +34,10 @@ enum glyph_attribute {
ATTR_WRAP = 1 << 8,
ATTR_WIDE = 1 << 9,
ATTR_WDUMMY = 1 << 10,
ATTR_BOXDRAW = 1 << 11,
ATTR_SELECTED = 1 << 12,
ATTR_BOLD_FAINT = ATTR_BOLD | ATTR_FAINT,
ATTR_DIRTYUNDERLINE = 1 << 15,
};
enum selection_mode {
@ -65,6 +69,8 @@ typedef struct {
ushort mode; /* attribute flags */
uint32_t fg; /* foreground */
uint32_t bg; /* background */
int ustyle; /* underline style */
int ucolor[3]; /* underline color */
} Glyph;
typedef Glyph *Line;
@ -111,6 +117,14 @@ void *xmalloc(size_t);
void *xrealloc(void *, size_t);
char *xstrdup(const char *);
int isboxdraw(Rune);
ushort boxdrawindex(const Glyph *);
#ifdef XFT_VERSION
/* only exposed to x.c, otherwise we'll need Xft.h for the types */
void boxdraw_xinit(Display *, Colormap, XftDraw *, Visual *);
void drawboxes(int, int, int, int, XftColor *, XftColor *, const XftGlyphFontSpec *, int);
#endif
/* config.h globals */
extern char *utmp;
extern char *scroll;
@ -124,3 +138,4 @@ extern unsigned int tabspaces;
extern unsigned int defaultfg;
extern unsigned int defaultbg;
extern unsigned int defaultcs;
extern const int boxdraw, boxdraw_bold, boxdraw_braille;

View File

@ -1,4 +1,5 @@
st-mono| simpleterm monocolor,
Su,
acsc=+C\,D-A.B0E``aaffgghFiGjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~,
am,
bce,
@ -161,7 +162,7 @@ st-mono| simpleterm monocolor,
rin=\E[%p1%dT,
ritm=\E[23m,
rmacs=\E(B,
rmcup=\E[?1049l,
rmcup=\E[?1049l\E[23;0;0t,
rmir=\E[4l,
rmkx=\E[?1l\E>,
rmso=\E[27m,
@ -172,7 +173,7 @@ st-mono| simpleterm monocolor,
sitm=\E[3m,
sgr0=\E[0m,
smacs=\E(0,
smcup=\E[?1049h,
smcup=\E[?1049h\E[22;0;0t,
smir=\E[4h,
smkx=\E[?1h\E=,
smso=\E[7m,

6
win.h
View File

@ -25,14 +25,16 @@ enum win_mode {
void xbell(void);
void xclipcopy(void);
void xdrawcursor(int, int, Glyph, int, int, Glyph);
void xdrawcursor(int, int, Glyph, int, int, Glyph, Line, int);
void xdrawline(Line, int, int, int);
void xfinishdraw(void);
void xloadcols(void);
int xsetcolorname(int, const char *);
int xgetcolor(int, unsigned char *, unsigned char *, unsigned char *);
void xseticontitle(char *);
void xsettitle(char *);
void xfreetitlestack(void);
void xsettitle(char *, int);
void xpushtitle(void);
int xsetcursor(int);
void xsetmode(int, unsigned int);
void xsetpointermotion(int);

896
x.c

File diff suppressed because it is too large Load Diff