Code formatting + st refactoring.
This commit is contained in:
parent
b5878fc205
commit
e15f7fb669
28 changed files with 5853 additions and 6321 deletions
250
_suckless/st/FAQ
250
_suckless/st/FAQ
|
@ -1,250 +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 doesn’t 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 they’re running in xterm i.e. they don’t rely on
|
|
||||||
terminfo. What you see is the current state of the “xterm compliance”.
|
|
||||||
* Some programs don’t 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.
|
|
|
@ -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
|
|
||||||
|
|
34
_suckless/st/LICENSE
Normal file
34
_suckless/st/LICENSE
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
MIT/X Consortium License
|
||||||
|
|
||||||
|
© 2014-2022 Hiltjo Posthuma <hiltjo at codemadness dot org>
|
||||||
|
© 2018 Devin J. Pohly <djpohly at gmail dot com>
|
||||||
|
© 2014-2017 Quentin Rameau <quinq at fifth dot space>
|
||||||
|
© 2009-2012 Aurélien APTEL <aurelien dot aptel at gmail dot com>
|
||||||
|
© 2008-2017 Anselm R Garbe <garbeam at gmail dot com>
|
||||||
|
© 2012-2017 Roberto E. Vargas Caballero <k0ga at shike2 dot com>
|
||||||
|
© 2012-2016 Christoph Lohmann <20h at r-36 dot net>
|
||||||
|
© 2013 Eon S. Jeon <esjeon at hyunmu dot am>
|
||||||
|
© 2013 Alexander Sedov <alex0player at gmail dot com>
|
||||||
|
© 2013 Mark Edgar <medgar123 at gmail dot com>
|
||||||
|
© 2013-2014 Eric Pruitt <eric.pruitt at gmail dot com>
|
||||||
|
© 2013 Michael Forney <mforney at mforney dot org>
|
||||||
|
© 2013-2014 Markus Teich <markus dot teich at stusta dot mhn dot de>
|
||||||
|
© 2014-2015 Laslo Hunhold <dev at frign dot de>
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
to deal in the Software without restriction, including without limitation
|
||||||
|
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
DEALINGS IN THE SOFTWARE.
|
|
@ -4,8 +4,8 @@
|
||||||
|
|
||||||
These patches from suckless.org were applied from the newest versions, in order:
|
These patches from suckless.org were applied from the newest versions, in order:
|
||||||
|
|
||||||
1. `st-w3m-0.8.3.diff`
|
|
||||||
1. `st-font2-20190416-ba72400.diff`
|
1. `st-font2-20190416-ba72400.diff`
|
||||||
1. `st-scrollback-0.8.4.diff`
|
1. `st-hidecursor-0.8.3.diff`
|
||||||
|
1. `st-scrollback-0.8.5.diff`
|
||||||
1. `st-externalpipe-0.8.4.diff`
|
1. `st-externalpipe-0.8.4.diff`
|
||||||
1. `fix-wide-glyphs.diff (local, see _patches/)`
|
1. `st-glyph-wide-support-20220411-ef05519.diff`
|
||||||
|
|
|
@ -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
|
|
||||||
|
|
|
@ -1,204 +0,0 @@
|
||||||
diff --git a/st.h b/st.h
|
|
||||||
index a25605c..96b285c 100644
|
|
||||||
--- a/st.h
|
|
||||||
+++ b/st.h
|
|
||||||
@@ -36,6 +36,12 @@ enum glyph_attribute {
|
|
||||||
ATTR_BOLD_FAINT = ATTR_BOLD | ATTR_FAINT,
|
|
||||||
};
|
|
||||||
|
|
||||||
+enum drawing_mode {
|
|
||||||
+ DRAW_NONE = 0,
|
|
||||||
+ DRAW_BG = 1 << 0,
|
|
||||||
+ DRAW_FG = 1 << 1,
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
enum selection_mode {
|
|
||||||
SEL_IDLE = 0,
|
|
||||||
SEL_EMPTY = 1,
|
|
||||||
diff --git a/x.c b/x.c
|
|
||||||
index 12008ef..b668c83 100644
|
|
||||||
--- a/x.c
|
|
||||||
+++ b/x.c
|
|
||||||
@@ -142,7 +142,7 @@ typedef struct {
|
|
||||||
|
|
||||||
static inline ushort sixd_to_16bit(int);
|
|
||||||
static int xmakeglyphfontspecs(XftGlyphFontSpec *, const Glyph *, int, int, int);
|
|
||||||
-static void xdrawglyphfontspecs(const XftGlyphFontSpec *, Glyph, int, int, int);
|
|
||||||
+static void xdrawglyphfontspecs(const XftGlyphFontSpec *, Glyph, int, int, int, int);
|
|
||||||
static void xdrawglyph(Glyph, int, int);
|
|
||||||
static void xclear(int, int, int, int);
|
|
||||||
static int xgeommasktogravity(int);
|
|
||||||
@@ -1457,14 +1457,13 @@ xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
-xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, int y)
|
|
||||||
+xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, int y, int dmode)
|
|
||||||
{
|
|
||||||
int charlen = len * ((base.mode & ATTR_WIDE) ? 2 : 1);
|
|
||||||
int winx = borderpx + x * win.cw, winy = borderpx + y * win.ch,
|
|
||||||
width = charlen * win.cw;
|
|
||||||
Color *fg, *bg, *temp, revfg, revbg, truefg, truebg;
|
|
||||||
XRenderColor colfg, colbg;
|
|
||||||
- XRectangle r;
|
|
||||||
|
|
||||||
/* Fallback on color display for attributes not supported by the font */
|
|
||||||
if (base.mode & ATTR_ITALIC && base.mode & ATTR_BOLD) {
|
|
||||||
@@ -1548,47 +1547,47 @@ xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, i
|
|
||||||
if (base.mode & ATTR_INVISIBLE)
|
|
||||||
fg = bg;
|
|
||||||
|
|
||||||
- /* Intelligent cleaning up of the borders. */
|
|
||||||
- if (x == 0) {
|
|
||||||
- xclear(0, (y == 0)? 0 : winy, borderpx,
|
|
||||||
- winy + win.ch +
|
|
||||||
- ((winy + win.ch >= borderpx + win.th)? win.h : 0));
|
|
||||||
- }
|
|
||||||
- if (winx + width >= borderpx + win.tw) {
|
|
||||||
- xclear(winx + width, (y == 0)? 0 : winy, win.w,
|
|
||||||
- ((winy + win.ch >= borderpx + 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, winy + win.ch, winx + width, win.h);
|
|
||||||
-
|
|
||||||
- /* Clean up the region we want to draw to. */
|
|
||||||
- XftDrawRect(xw.draw, bg, winx, winy, width, win.ch);
|
|
||||||
-
|
|
||||||
- /* Set the clip region because Xft is sometimes dirty. */
|
|
||||||
- r.x = 0;
|
|
||||||
- r.y = 0;
|
|
||||||
- r.height = win.ch;
|
|
||||||
- r.width = width;
|
|
||||||
- XftDrawSetClipRectangles(xw.draw, winx, winy, &r, 1);
|
|
||||||
-
|
|
||||||
- /* Render the glyphs. */
|
|
||||||
- XftDrawGlyphFontSpec(xw.draw, fg, specs, len);
|
|
||||||
-
|
|
||||||
- /* Render underline and strikethrough. */
|
|
||||||
- if (base.mode & ATTR_UNDERLINE) {
|
|
||||||
- XftDrawRect(xw.draw, fg, winx, winy + dc.font.ascent + 1,
|
|
||||||
- width, 1);
|
|
||||||
- }
|
|
||||||
+ if (dmode & DRAW_BG) {
|
|
||||||
+ /* Intelligent cleaning up of the borders. */
|
|
||||||
+ if (x == 0) {
|
|
||||||
+ xclear(0, (y == 0)? 0 : winy, borderpx,
|
|
||||||
+ winy + win.ch +
|
|
||||||
+ ((winy + win.ch >= borderpx + win.th)? win.h : 0));
|
|
||||||
+ }
|
|
||||||
+ if (winx + width >= borderpx + win.tw) {
|
|
||||||
+ xclear(winx + width, (y == 0)? 0 : winy, win.w,
|
|
||||||
+ ((winy + win.ch >= borderpx + 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, winy + win.ch, winx + width, win.h);
|
|
||||||
|
|
||||||
- if (base.mode & ATTR_STRUCK) {
|
|
||||||
- XftDrawRect(xw.draw, fg, winx, winy + 2 * dc.font.ascent / 3,
|
|
||||||
- width, 1);
|
|
||||||
+ /* Fill the background */
|
|
||||||
+ XftDrawRect(xw.draw, bg, winx, winy, width, win.ch);
|
|
||||||
}
|
|
||||||
|
|
||||||
- /* Reset clip to none. */
|
|
||||||
- XftDrawSetClip(xw.draw, 0);
|
|
||||||
+ if (dmode & DRAW_FG) {
|
|
||||||
+/*
|
|
||||||
+ 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) {
|
|
||||||
+ XftDrawRect(xw.draw, fg, winx, winy + dc.font.ascent + 1,
|
|
||||||
+ width, 1);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (base.mode & ATTR_STRUCK) {
|
|
||||||
+ XftDrawRect(xw.draw, fg, winx, winy + 2 * dc.font.ascent / 3,
|
|
||||||
+ width, 1);
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
@@ -1598,7 +1597,7 @@ xdrawglyph(Glyph g, int x, int y)
|
|
||||||
XftGlyphFontSpec spec;
|
|
||||||
|
|
||||||
numspecs = xmakeglyphfontspecs(&spec, &g, 1, x, y);
|
|
||||||
- xdrawglyphfontspecs(&spec, g, numspecs, x, y);
|
|
||||||
+ xdrawglyphfontspecs(&spec, g, numspecs, x, y, DRAW_BG | DRAW_FG);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
@@ -1735,32 +1734,39 @@ xstartdraw(void)
|
|
||||||
void
|
|
||||||
xdrawline(Line line, int x1, int y1, int x2)
|
|
||||||
{
|
|
||||||
- int i, x, ox, numspecs;
|
|
||||||
+ int i, x, ox, numspecs, numspecs_cached;
|
|
||||||
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++) {
|
|
||||||
- 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;
|
|
||||||
- i = 0;
|
|
||||||
- }
|
|
||||||
- if (i == 0) {
|
|
||||||
- ox = x;
|
|
||||||
- base = new;
|
|
||||||
+ XftGlyphFontSpec *specs;
|
|
||||||
+
|
|
||||||
+ numspecs_cached = xmakeglyphfontspecs(xw.specbuf, &line[x1], x2 - x1, x1, y1);
|
|
||||||
+
|
|
||||||
+ /* Draw line in 2 passes: background and foreground. This way wide glyphs
|
|
||||||
+ won't get truncated (#223) */
|
|
||||||
+ for (int dmode = DRAW_BG; dmode <= DRAW_FG; dmode <<= 1) {
|
|
||||||
+ specs = xw.specbuf;
|
|
||||||
+ numspecs = numspecs_cached;
|
|
||||||
+ i = ox = 0;
|
|
||||||
+ for (x = x1; x < x2 && i < numspecs; 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, dmode);
|
|
||||||
+ specs += i;
|
|
||||||
+ numspecs -= i;
|
|
||||||
+ i = 0;
|
|
||||||
+ }
|
|
||||||
+ if (i == 0) {
|
|
||||||
+ ox = x;
|
|
||||||
+ base = new;
|
|
||||||
+ }
|
|
||||||
+ i++;
|
|
||||||
}
|
|
||||||
- i++;
|
|
||||||
+ if (i > 0)
|
|
||||||
+ xdrawglyphfontspecs(specs, base, i, ox, y1, dmode);
|
|
||||||
}
|
|
||||||
- if (i > 0)
|
|
||||||
- xdrawglyphfontspecs(specs, base, i, ox, y1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
|
@ -9,7 +9,7 @@ static char *font = "Liberation Mono:pixelsize=12:antialias=true:autohint=true";
|
||||||
/* Spare fonts */
|
/* Spare fonts */
|
||||||
static char *font2[] = {
|
static char *font2[] = {
|
||||||
/* "Inconsolata for Powerline:pixelsize=12:antialias=true:autohint=true", */
|
/* "Inconsolata for Powerline:pixelsize=12:antialias=true:autohint=true", */
|
||||||
/* "Hack Nerd Font Mono:pixelsize=11:antialias=true:autohint=true", */
|
"Hack Nerd Font Mono:pixelsize=11:antialias=true:autohint=true",
|
||||||
};
|
};
|
||||||
|
|
||||||
static int borderpx = 2;
|
static int borderpx = 2;
|
||||||
|
|
|
@ -187,7 +187,6 @@ static MouseShortcut mshortcuts[] = {
|
||||||
#define MODKEY ControlMask
|
#define MODKEY ControlMask
|
||||||
#define SHTKEY (ControlMask|ShiftMask)
|
#define SHTKEY (ControlMask|ShiftMask)
|
||||||
|
|
||||||
//static char *openurlcmd[] = { "/bin/sh", "-c", "st-url -o", "externalpipe", NULL };
|
|
||||||
static char *openurlcmd[] = {"/bin/sh", "-c", "xurls | dmenu -c -l 20 -i | xargs -r $BROWSER",
|
static char *openurlcmd[] = {"/bin/sh", "-c", "xurls | dmenu -c -l 20 -i | xargs -r $BROWSER",
|
||||||
"externalpipe", NULL};
|
"externalpipe", NULL};
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,7 @@ STLDFLAGS = $(LIBS) $(LDFLAGS)
|
||||||
#LIBS = -L$(X11LIB) -lm -lX11 -lutil -lXft \
|
#LIBS = -L$(X11LIB) -lm -lX11 -lutil -lXft \
|
||||||
# `$(PKG_CONFIG) --libs fontconfig` \
|
# `$(PKG_CONFIG) --libs fontconfig` \
|
||||||
# `$(PKG_CONFIG) --libs freetype2`
|
# `$(PKG_CONFIG) --libs freetype2`
|
||||||
|
#MANPREFIX = ${PREFIX}/man
|
||||||
|
|
||||||
# compiler and linker
|
# compiler and linker
|
||||||
# CC = c99
|
# CC = c99
|
||||||
|
|
|
@ -168,6 +168,7 @@ static void csidump(void);
|
||||||
static void csihandle(void);
|
static void csihandle(void);
|
||||||
static void csiparse(void);
|
static void csiparse(void);
|
||||||
static void csireset(void);
|
static void csireset(void);
|
||||||
|
static void osc_color_response(int, int, int);
|
||||||
static int eschandle(uchar);
|
static int eschandle(uchar);
|
||||||
static void strdump(void);
|
static void strdump(void);
|
||||||
static void strhandle(void);
|
static void strhandle(void);
|
||||||
|
@ -356,25 +357,10 @@ utf8validate(Rune *u, size_t i)
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char base64_digits[] = {
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 0, 0,
|
|
||||||
63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 0, 0, 0, -1, 0, 0, 0, 0, 1,
|
|
||||||
2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
|
|
||||||
22, 23, 24, 25, 0, 0, 0, 0, 0, 0, 26, 27, 28, 29, 30, 31, 32, 33, 34,
|
|
||||||
35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
|
||||||
};
|
|
||||||
|
|
||||||
char
|
char
|
||||||
base64dec_getc(const char **src)
|
base64dec_getc(const char **src)
|
||||||
{
|
{
|
||||||
while (**src && !isprint(**src))
|
while (**src && !isprint((unsigned char)**src))
|
||||||
(*src)++;
|
(*src)++;
|
||||||
return **src ? *((*src)++) : '='; /* emulate padding if string ends */
|
return **src ? *((*src)++) : '='; /* emulate padding if string ends */
|
||||||
}
|
}
|
||||||
|
@ -384,6 +370,13 @@ base64dec(const char *src)
|
||||||
{
|
{
|
||||||
size_t in_len = strlen(src);
|
size_t in_len = strlen(src);
|
||||||
char *result, *dst;
|
char *result, *dst;
|
||||||
|
static const char base64_digits[256] = {
|
||||||
|
[43] = 62, 0, 0, 0, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
|
||||||
|
0, 0, 0, -1, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
|
||||||
|
13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 0, 0, 0,
|
||||||
|
0, 0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
|
||||||
|
40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
|
||||||
|
};
|
||||||
|
|
||||||
if (in_len % 4)
|
if (in_len % 4)
|
||||||
in_len += 4 - (in_len % 4);
|
in_len += 4 - (in_len % 4);
|
||||||
|
@ -1117,7 +1110,6 @@ tscrolldown(int orig, int n, int copyhist)
|
||||||
Line temp;
|
Line temp;
|
||||||
|
|
||||||
LIMIT(n, 0, term.bot-orig+1);
|
LIMIT(n, 0, term.bot-orig+1);
|
||||||
|
|
||||||
if (copyhist) {
|
if (copyhist) {
|
||||||
term.histi = (term.histi - 1 + HISTSIZE) % HISTSIZE;
|
term.histi = (term.histi - 1 + HISTSIZE) % HISTSIZE;
|
||||||
temp = term.hist[term.histi];
|
temp = term.hist[term.histi];
|
||||||
|
@ -1125,6 +1117,7 @@ tscrolldown(int orig, int n, int copyhist)
|
||||||
term.line[term.bot] = temp;
|
term.line[term.bot] = temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
tsetdirt(orig, term.bot-n);
|
tsetdirt(orig, term.bot-n);
|
||||||
tclearregion(0, term.bot-n+1, term.col-1, term.bot);
|
tclearregion(0, term.bot-n+1, term.col-1, term.bot);
|
||||||
|
|
||||||
|
@ -1911,39 +1904,28 @@ csireset(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
osc4_color_response(int num)
|
osc_color_response(int num, int index, int is_osc4)
|
||||||
{
|
{
|
||||||
int n;
|
int n;
|
||||||
char buf[32];
|
char buf[32];
|
||||||
unsigned char r, g, b;
|
unsigned char r, g, b;
|
||||||
|
|
||||||
if (xgetcolor(num, &r, &g, &b)) {
|
if (xgetcolor(is_osc4 ? num : index, &r, &g, &b)) {
|
||||||
fprintf(stderr, "erresc: failed to fetch osc4 color %d\n", num);
|
fprintf(stderr, "erresc: failed to fetch %s color %d\n",
|
||||||
|
is_osc4 ? "osc4" : "osc",
|
||||||
|
is_osc4 ? num : index);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
n = snprintf(buf, sizeof buf, "\033]4;%d;rgb:%02x%02x/%02x%02x/%02x%02x\007",
|
n = snprintf(buf, sizeof buf, "\033]%s%d;rgb:%02x%02x/%02x%02x/%02x%02x\007",
|
||||||
num, r, r, g, g, b, b);
|
is_osc4 ? "4;" : "", num, r, r, g, g, b, b);
|
||||||
|
if (n < 0 || n >= sizeof(buf)) {
|
||||||
|
fprintf(stderr, "error: %s while printing %s response\n",
|
||||||
|
n < 0 ? "snprintf failed" : "truncation occurred",
|
||||||
|
is_osc4 ? "osc4" : "osc");
|
||||||
|
} else {
|
||||||
ttywrite(buf, n, 1);
|
ttywrite(buf, n, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
osc_color_response(int index, int num)
|
|
||||||
{
|
|
||||||
int n;
|
|
||||||
char buf[32];
|
|
||||||
unsigned char r, g, b;
|
|
||||||
|
|
||||||
if (xgetcolor(index, &r, &g, &b)) {
|
|
||||||
fprintf(stderr, "erresc: failed to fetch osc color %d\n", index);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
n = snprintf(buf, sizeof buf, "\033]%d;rgb:%02x%02x/%02x%02x/%02x%02x\007",
|
|
||||||
num, r, r, g, g, b, b);
|
|
||||||
|
|
||||||
ttywrite(buf, n, 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -1951,6 +1933,11 @@ strhandle(void)
|
||||||
{
|
{
|
||||||
char *p = NULL, *dec;
|
char *p = NULL, *dec;
|
||||||
int j, narg, par;
|
int j, narg, par;
|
||||||
|
const struct { int idx; char *str; } osc_table[] = {
|
||||||
|
{ defaultfg, "foreground" },
|
||||||
|
{ defaultbg, "background" },
|
||||||
|
{ defaultcs, "cursor" }
|
||||||
|
};
|
||||||
|
|
||||||
term.esc &= ~(ESC_STR_END|ESC_STR);
|
term.esc &= ~(ESC_STR_END|ESC_STR);
|
||||||
strparse();
|
strparse();
|
||||||
|
@ -1985,43 +1972,22 @@ strhandle(void)
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
case 10:
|
case 10:
|
||||||
if (narg < 2)
|
|
||||||
break;
|
|
||||||
|
|
||||||
p = strescseq.args[1];
|
|
||||||
|
|
||||||
if (!strcmp(p, "?"))
|
|
||||||
osc_color_response(defaultfg, 10);
|
|
||||||
else if (xsetcolorname(defaultfg, p))
|
|
||||||
fprintf(stderr, "erresc: invalid foreground color: %s\n", p);
|
|
||||||
else
|
|
||||||
redraw();
|
|
||||||
return;
|
|
||||||
case 11:
|
case 11:
|
||||||
if (narg < 2)
|
|
||||||
break;
|
|
||||||
|
|
||||||
p = strescseq.args[1];
|
|
||||||
|
|
||||||
if (!strcmp(p, "?"))
|
|
||||||
osc_color_response(defaultbg, 11);
|
|
||||||
else if (xsetcolorname(defaultbg, p))
|
|
||||||
fprintf(stderr, "erresc: invalid background color: %s\n", p);
|
|
||||||
else
|
|
||||||
redraw();
|
|
||||||
return;
|
|
||||||
case 12:
|
case 12:
|
||||||
if (narg < 2)
|
if (narg < 2)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
p = strescseq.args[1];
|
p = strescseq.args[1];
|
||||||
|
if ((j = par - 10) < 0 || j >= LEN(osc_table))
|
||||||
|
break; /* shouldn't be possible */
|
||||||
|
|
||||||
if (!strcmp(p, "?"))
|
if (!strcmp(p, "?")) {
|
||||||
osc_color_response(defaultcs, 12);
|
osc_color_response(par, osc_table[j].idx, 0);
|
||||||
else if (xsetcolorname(defaultcs, p))
|
} else if (xsetcolorname(osc_table[j].idx, p)) {
|
||||||
fprintf(stderr, "erresc: invalid cursor color: %s\n", p);
|
fprintf(stderr, "erresc: invalid %s color: %s\n",
|
||||||
else
|
osc_table[j].str, p);
|
||||||
redraw();
|
} else {
|
||||||
|
tfulldirt();
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
case 4: /* color set */
|
case 4: /* color set */
|
||||||
if (narg < 3)
|
if (narg < 3)
|
||||||
|
@ -2031,9 +1997,9 @@ strhandle(void)
|
||||||
case 104: /* color reset */
|
case 104: /* color reset */
|
||||||
j = (narg > 1) ? atoi(strescseq.args[1]) : -1;
|
j = (narg > 1) ? atoi(strescseq.args[1]) : -1;
|
||||||
|
|
||||||
if (p && !strcmp(p, "?"))
|
if (p && !strcmp(p, "?")) {
|
||||||
osc4_color_response(j);
|
osc_color_response(j, 0, 1);
|
||||||
else if (xsetcolorname(j, p)) {
|
} else if (xsetcolorname(j, p)) {
|
||||||
if (par == 104 && narg <= 1)
|
if (par == 104 && narg <= 1)
|
||||||
return; /* color reset without parameter */
|
return; /* color reset without parameter */
|
||||||
fprintf(stderr, "erresc: invalid color j=%d, p=%s\n",
|
fprintf(stderr, "erresc: invalid color j=%d, p=%s\n",
|
||||||
|
@ -2043,7 +2009,7 @@ strhandle(void)
|
||||||
* TODO if defaultbg color is changed, borders
|
* TODO if defaultbg color is changed, borders
|
||||||
* are dirty
|
* are dirty
|
||||||
*/
|
*/
|
||||||
redraw();
|
tfulldirt();
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -87,9 +87,9 @@ void die(const char *, ...);
|
||||||
void redraw(void);
|
void redraw(void);
|
||||||
void draw(void);
|
void draw(void);
|
||||||
|
|
||||||
|
void externalpipe(const Arg *);
|
||||||
void kscrolldown(const Arg *);
|
void kscrolldown(const Arg *);
|
||||||
void kscrollup(const Arg *);
|
void kscrollup(const Arg *);
|
||||||
void externalpipe(const Arg *);
|
|
||||||
void printscreen(const Arg *);
|
void printscreen(const Arg *);
|
||||||
void printsel(const Arg *);
|
void printsel(const Arg *);
|
||||||
void sendbreak(const Arg *);
|
void sendbreak(const Arg *);
|
||||||
|
@ -120,8 +120,6 @@ void *xmalloc(size_t);
|
||||||
void *xrealloc(void *, size_t);
|
void *xrealloc(void *, size_t);
|
||||||
char *xstrdup(const char *);
|
char *xstrdup(const char *);
|
||||||
|
|
||||||
int xgetcolor(int x, unsigned char *r, unsigned char *g, unsigned char *b);
|
|
||||||
|
|
||||||
/* config.h globals */
|
/* config.h globals */
|
||||||
extern char *utmp;
|
extern char *utmp;
|
||||||
extern char *scroll;
|
extern char *scroll;
|
||||||
|
|
|
@ -30,6 +30,7 @@ void xdrawline(Line, int, int, int);
|
||||||
void xfinishdraw(void);
|
void xfinishdraw(void);
|
||||||
void xloadcols(void);
|
void xloadcols(void);
|
||||||
int xsetcolorname(int, const char *);
|
int xsetcolorname(int, const char *);
|
||||||
|
int xgetcolor(int, unsigned char *, unsigned char *, unsigned char *);
|
||||||
void xseticontitle(char *);
|
void xseticontitle(char *);
|
||||||
void xsettitle(char *);
|
void xsettitle(char *);
|
||||||
int xsetcursor(int);
|
int xsetcursor(int);
|
||||||
|
|
126
_suckless/st/x.c
126
_suckless/st/x.c
|
@ -103,6 +103,11 @@ typedef struct {
|
||||||
Draw draw;
|
Draw draw;
|
||||||
Visual *vis;
|
Visual *vis;
|
||||||
XSetWindowAttributes attrs;
|
XSetWindowAttributes attrs;
|
||||||
|
/* Here, we use the term *pointer* to differentiate the cursor
|
||||||
|
* one sees when hovering the mouse over the terminal from, e.g.,
|
||||||
|
* a green rectangle where text would be entered. */
|
||||||
|
Cursor vpointer, bpointer; /* visible and hidden pointers */
|
||||||
|
int pointerisvisible;
|
||||||
int scr;
|
int scr;
|
||||||
int isfixed; /* is fixed geometry? */
|
int isfixed; /* is fixed geometry? */
|
||||||
int l, t; /* left and top offset */
|
int l, t; /* left and top offset */
|
||||||
|
@ -254,7 +259,7 @@ static char *opt_line = NULL;
|
||||||
static char *opt_name = NULL;
|
static char *opt_name = NULL;
|
||||||
static char *opt_title = NULL;
|
static char *opt_title = NULL;
|
||||||
|
|
||||||
static int oldbutton = 3; /* button event on startup: 3 = release */
|
static uint buttons; /* bit field of pressed buttons */
|
||||||
|
|
||||||
void
|
void
|
||||||
clipcopy(const Arg *dummy)
|
clipcopy(const Arg *dummy)
|
||||||
|
@ -367,61 +372,68 @@ mousesel(XEvent *e, int done)
|
||||||
void
|
void
|
||||||
mousereport(XEvent *e)
|
mousereport(XEvent *e)
|
||||||
{
|
{
|
||||||
int len, x = evcol(e), y = evrow(e),
|
int len, btn, code;
|
||||||
button = e->xbutton.button, state = e->xbutton.state;
|
int x = evcol(e), y = evrow(e);
|
||||||
|
int state = e->xbutton.state;
|
||||||
char buf[40];
|
char buf[40];
|
||||||
static int ox, oy;
|
static int ox, oy;
|
||||||
|
|
||||||
/* from urxvt */
|
if (e->type == MotionNotify) {
|
||||||
if (e->xbutton.type == MotionNotify) {
|
|
||||||
if (x == ox && y == oy)
|
if (x == ox && y == oy)
|
||||||
return;
|
return;
|
||||||
if (!IS_SET(MODE_MOUSEMOTION) && !IS_SET(MODE_MOUSEMANY))
|
if (!IS_SET(MODE_MOUSEMOTION) && !IS_SET(MODE_MOUSEMANY))
|
||||||
return;
|
return;
|
||||||
/* MOUSE_MOTION: no reporting if no button is pressed */
|
/* MODE_MOUSEMOTION: no reporting if no button is pressed */
|
||||||
if (IS_SET(MODE_MOUSEMOTION) && oldbutton == 3)
|
if (IS_SET(MODE_MOUSEMOTION) && buttons == 0)
|
||||||
return;
|
return;
|
||||||
|
/* Set btn to lowest-numbered pressed button, or 12 if no
|
||||||
button = oldbutton + 32;
|
* buttons are pressed. */
|
||||||
ox = x;
|
for (btn = 1; btn <= 11 && !(buttons & (1<<(btn-1))); btn++)
|
||||||
oy = y;
|
;
|
||||||
|
code = 32;
|
||||||
} else {
|
} else {
|
||||||
if (!IS_SET(MODE_MOUSESGR) && e->xbutton.type == ButtonRelease) {
|
btn = e->xbutton.button;
|
||||||
button = 3;
|
/* Only buttons 1 through 11 can be encoded */
|
||||||
} else {
|
if (btn < 1 || btn > 11)
|
||||||
button -= Button1;
|
return;
|
||||||
if (button >= 7)
|
if (e->type == ButtonRelease) {
|
||||||
button += 128 - 7;
|
|
||||||
else if (button >= 3)
|
|
||||||
button += 64 - 3;
|
|
||||||
}
|
|
||||||
if (e->xbutton.type == ButtonPress) {
|
|
||||||
oldbutton = button;
|
|
||||||
ox = x;
|
|
||||||
oy = y;
|
|
||||||
} else if (e->xbutton.type == ButtonRelease) {
|
|
||||||
oldbutton = 3;
|
|
||||||
/* MODE_MOUSEX10: no button release reporting */
|
/* MODE_MOUSEX10: no button release reporting */
|
||||||
if (IS_SET(MODE_MOUSEX10))
|
if (IS_SET(MODE_MOUSEX10))
|
||||||
return;
|
return;
|
||||||
if (button == 64 || button == 65)
|
/* Don't send release events for the scroll wheel */
|
||||||
|
if (btn == 4 || btn == 5)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
code = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ox = x;
|
||||||
|
oy = y;
|
||||||
|
|
||||||
|
/* Encode btn into code. If no button is pressed for a motion event in
|
||||||
|
* MODE_MOUSEMANY, then encode it as a release. */
|
||||||
|
if ((!IS_SET(MODE_MOUSESGR) && e->type == ButtonRelease) || btn == 12)
|
||||||
|
code += 3;
|
||||||
|
else if (btn >= 8)
|
||||||
|
code += 128 + btn - 8;
|
||||||
|
else if (btn >= 4)
|
||||||
|
code += 64 + btn - 4;
|
||||||
|
else
|
||||||
|
code += btn - 1;
|
||||||
|
|
||||||
if (!IS_SET(MODE_MOUSEX10)) {
|
if (!IS_SET(MODE_MOUSEX10)) {
|
||||||
button += ((state & ShiftMask ) ? 4 : 0)
|
code += ((state & ShiftMask ) ? 4 : 0)
|
||||||
+ ((state & Mod4Mask ) ? 8 : 0)
|
+ ((state & Mod1Mask ) ? 8 : 0) /* meta key: alt */
|
||||||
+ ((state & ControlMask) ? 16 : 0);
|
+ ((state & ControlMask) ? 16 : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IS_SET(MODE_MOUSESGR)) {
|
if (IS_SET(MODE_MOUSESGR)) {
|
||||||
len = snprintf(buf, sizeof(buf), "\033[<%d;%d;%d%c",
|
len = snprintf(buf, sizeof(buf), "\033[<%d;%d;%d%c",
|
||||||
button, x+1, y+1,
|
code, x+1, y+1,
|
||||||
e->xbutton.type == ButtonRelease ? 'm' : 'M');
|
e->type == ButtonRelease ? 'm' : 'M');
|
||||||
} else if (x < 223 && y < 223) {
|
} else if (x < 223 && y < 223) {
|
||||||
len = snprintf(buf, sizeof(buf), "\033[M%c%c%c",
|
len = snprintf(buf, sizeof(buf), "\033[M%c%c%c",
|
||||||
32+button, 32+x+1, 32+y+1);
|
32+code, 32+x+1, 32+y+1);
|
||||||
} else {
|
} else {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -464,9 +476,13 @@ mouseaction(XEvent *e, uint release)
|
||||||
void
|
void
|
||||||
bpress(XEvent *e)
|
bpress(XEvent *e)
|
||||||
{
|
{
|
||||||
|
int btn = e->xbutton.button;
|
||||||
struct timespec now;
|
struct timespec now;
|
||||||
int snap;
|
int snap;
|
||||||
|
|
||||||
|
if (1 <= btn && btn <= 11)
|
||||||
|
buttons |= 1 << (btn-1);
|
||||||
|
|
||||||
if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forcemousemod)) {
|
if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forcemousemod)) {
|
||||||
mousereport(e);
|
mousereport(e);
|
||||||
return;
|
return;
|
||||||
|
@ -475,7 +491,7 @@ bpress(XEvent *e)
|
||||||
if (mouseaction(e, 0))
|
if (mouseaction(e, 0))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (e->xbutton.button == Button1) {
|
if (btn == Button1) {
|
||||||
/*
|
/*
|
||||||
* If the user clicks below predefined timeouts specific
|
* If the user clicks below predefined timeouts specific
|
||||||
* snapping behaviour is exposed.
|
* snapping behaviour is exposed.
|
||||||
|
@ -689,6 +705,11 @@ xsetsel(char *str)
|
||||||
void
|
void
|
||||||
brelease(XEvent *e)
|
brelease(XEvent *e)
|
||||||
{
|
{
|
||||||
|
int btn = e->xbutton.button;
|
||||||
|
|
||||||
|
if (1 <= btn && btn <= 11)
|
||||||
|
buttons &= ~(1 << (btn-1));
|
||||||
|
|
||||||
if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forcemousemod)) {
|
if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forcemousemod)) {
|
||||||
mousereport(e);
|
mousereport(e);
|
||||||
return;
|
return;
|
||||||
|
@ -696,13 +717,20 @@ brelease(XEvent *e)
|
||||||
|
|
||||||
if (mouseaction(e, 1))
|
if (mouseaction(e, 1))
|
||||||
return;
|
return;
|
||||||
if (e->xbutton.button == Button1)
|
if (btn == Button1)
|
||||||
mousesel(e, 1);
|
mousesel(e, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
bmotion(XEvent *e)
|
bmotion(XEvent *e)
|
||||||
{
|
{
|
||||||
|
if (!xw.pointerisvisible) {
|
||||||
|
XDefineCursor(xw.dpy, xw.win, xw.vpointer);
|
||||||
|
xw.pointerisvisible = 1;
|
||||||
|
if (!IS_SET(MODE_MOUSEMANY))
|
||||||
|
xsetpointermotion(0);
|
||||||
|
}
|
||||||
|
|
||||||
if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forcemousemod)) {
|
if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forcemousemod)) {
|
||||||
mousereport(e);
|
mousereport(e);
|
||||||
return;
|
return;
|
||||||
|
@ -1212,10 +1240,10 @@ void
|
||||||
xinit(int cols, int rows)
|
xinit(int cols, int rows)
|
||||||
{
|
{
|
||||||
XGCValues gcvalues;
|
XGCValues gcvalues;
|
||||||
Cursor cursor;
|
|
||||||
Window parent;
|
Window parent;
|
||||||
pid_t thispid = getpid();
|
pid_t thispid = getpid();
|
||||||
XColor xmousefg, xmousebg;
|
XColor xmousefg, xmousebg;
|
||||||
|
Pixmap blankpm;
|
||||||
|
|
||||||
if (!(xw.dpy = XOpenDisplay(NULL)))
|
if (!(xw.dpy = XOpenDisplay(NULL)))
|
||||||
die("can't open display\n");
|
die("can't open display\n");
|
||||||
|
@ -1282,8 +1310,9 @@ xinit(int cols, int rows)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* white cursor, black outline */
|
/* white cursor, black outline */
|
||||||
cursor = XCreateFontCursor(xw.dpy, mouseshape);
|
xw.pointerisvisible = 1;
|
||||||
XDefineCursor(xw.dpy, xw.win, cursor);
|
xw.vpointer = XCreateFontCursor(xw.dpy, mouseshape);
|
||||||
|
XDefineCursor(xw.dpy, xw.win, xw.vpointer);
|
||||||
|
|
||||||
if (XParseColor(xw.dpy, xw.cmap, colorname[mousefg], &xmousefg) == 0) {
|
if (XParseColor(xw.dpy, xw.cmap, colorname[mousefg], &xmousefg) == 0) {
|
||||||
xmousefg.red = 0xffff;
|
xmousefg.red = 0xffff;
|
||||||
|
@ -1297,7 +1326,10 @@ xinit(int cols, int rows)
|
||||||
xmousebg.blue = 0x0000;
|
xmousebg.blue = 0x0000;
|
||||||
}
|
}
|
||||||
|
|
||||||
XRecolorCursor(xw.dpy, cursor, &xmousefg, &xmousebg);
|
XRecolorCursor(xw.dpy, xw.vpointer, &xmousefg, &xmousebg);
|
||||||
|
blankpm = XCreateBitmapFromData(xw.dpy, xw.win, &(char){0}, 1, 1);
|
||||||
|
xw.bpointer = XCreatePixmapCursor(xw.dpy, blankpm, blankpm,
|
||||||
|
&xmousefg, &xmousebg, 0, 0);
|
||||||
|
|
||||||
xw.xembed = XInternAtom(xw.dpy, "_XEMBED", False);
|
xw.xembed = XInternAtom(xw.dpy, "_XEMBED", False);
|
||||||
xw.wmdeletewin = XInternAtom(xw.dpy, "WM_DELETE_WINDOW", False);
|
xw.wmdeletewin = XInternAtom(xw.dpy, "WM_DELETE_WINDOW", False);
|
||||||
|
@ -1464,6 +1496,7 @@ xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, i
|
||||||
width = charlen * win.cw;
|
width = charlen * win.cw;
|
||||||
Color *fg, *bg, *temp, revfg, revbg, truefg, truebg;
|
Color *fg, *bg, *temp, revfg, revbg, truefg, truebg;
|
||||||
XRenderColor colfg, colbg;
|
XRenderColor colfg, colbg;
|
||||||
|
XRectangle r;
|
||||||
|
|
||||||
/* Fallback on color display for attributes not supported by the font */
|
/* Fallback on color display for attributes not supported by the font */
|
||||||
if (base.mode & ATTR_ITALIC && base.mode & ATTR_BOLD) {
|
if (base.mode & ATTR_ITALIC && base.mode & ATTR_BOLD) {
|
||||||
|
@ -1562,20 +1595,13 @@ xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, i
|
||||||
xclear(winx, 0, winx + width, borderpx);
|
xclear(winx, 0, winx + width, borderpx);
|
||||||
if (winy + win.ch >= borderpx + win.th)
|
if (winy + win.ch >= borderpx + win.th)
|
||||||
xclear(winx, winy + win.ch, winx + width, win.h);
|
xclear(winx, winy + win.ch, winx + width, win.h);
|
||||||
|
|
||||||
/* Fill the background */
|
/* Fill the background */
|
||||||
XftDrawRect(xw.draw, bg, winx, winy, width, win.ch);
|
XftDrawRect(xw.draw, bg, winx, winy, width, win.ch);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dmode & DRAW_FG) {
|
if (dmode & DRAW_FG) {
|
||||||
/*
|
|
||||||
if (base.mode & ATTR_BOXDRAW) {
|
|
||||||
drawboxes(winx, winy, width / len, win.ch, fg, bg, specs, len);
|
|
||||||
} else {
|
|
||||||
*/
|
|
||||||
/* Render the glyphs. */
|
/* Render the glyphs. */
|
||||||
XftDrawGlyphFontSpec(xw.draw, fg, specs, len);
|
XftDrawGlyphFontSpec(xw.draw, fg, specs, len);
|
||||||
// }
|
|
||||||
|
|
||||||
/* Render underline and strikethrough. */
|
/* Render underline and strikethrough. */
|
||||||
if (base.mode & ATTR_UNDERLINE) {
|
if (base.mode & ATTR_UNDERLINE) {
|
||||||
|
@ -1726,8 +1752,6 @@ xsettitle(char *p)
|
||||||
int
|
int
|
||||||
xstartdraw(void)
|
xstartdraw(void)
|
||||||
{
|
{
|
||||||
if (IS_SET(MODE_VISIBLE))
|
|
||||||
XCopyArea(xw.dpy, xw.win, xw.buf, dc.gc, 0, 0, win.w, win.h, 0, 0);
|
|
||||||
return IS_SET(MODE_VISIBLE);
|
return IS_SET(MODE_VISIBLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1814,6 +1838,8 @@ unmap(XEvent *ev)
|
||||||
void
|
void
|
||||||
xsetpointermotion(int set)
|
xsetpointermotion(int set)
|
||||||
{
|
{
|
||||||
|
if (!set && !xw.pointerisvisible)
|
||||||
|
return;
|
||||||
MODBIT(xw.attrs.event_mask, set, PointerMotionMask);
|
MODBIT(xw.attrs.event_mask, set, PointerMotionMask);
|
||||||
XChangeWindowAttributes(xw.dpy, xw.win, CWEventMask, &xw.attrs);
|
XChangeWindowAttributes(xw.dpy, xw.win, CWEventMask, &xw.attrs);
|
||||||
}
|
}
|
||||||
|
@ -1933,6 +1959,12 @@ kpress(XEvent *ev)
|
||||||
Status status;
|
Status status;
|
||||||
Shortcut *bp;
|
Shortcut *bp;
|
||||||
|
|
||||||
|
if (xw.pointerisvisible) {
|
||||||
|
XDefineCursor(xw.dpy, xw.win, xw.bpointer);
|
||||||
|
xsetpointermotion(1);
|
||||||
|
xw.pointerisvisible = 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (IS_SET(MODE_KBDLOCK))
|
if (IS_SET(MODE_KBDLOCK))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue