Add new wip build, should be fairly stable.

This commit is contained in:
speediegq 2022-08-16 22:45:40 +02:00
parent 252811a29d
commit cfc0713137
19 changed files with 1849 additions and 2041 deletions

View file

@ -32,64 +32,34 @@ st: $(OBJ)
$(CC) -o $@ $(OBJ) $(STLDFLAGS)
clean:
rm -f st $(OBJ) st-spde-$(VERSION).tar.gz
rm -f st $(OBJ) st-$(VERSION).tar.gz
dist: clean
mkdir -p st-spde-$(VERSION)
cp -R arg.h autocomplete.h boxdraw.c boxdraw_data.h config.def.h config.mk st.png st.desktop docs hb.c hb.h Makefile st.1 st-autocomplete st.c st.h st.info win.h x.c docs/st-keybinds st-spde-$(VERSION)
tar -cf - st-spde-$(VERSION) | gzip > st-spde-$(VERSION).tar.gz
rm -rf st-spde-$(VERSION)
mkdir -p st-$(VERSION)
cp -R FAQ LEGACY TODO LICENSE Makefile README config.mk\
config.def.h st.info st.1 arg.h st.h win.h st.png st.desktop $(SRC)\
st-$(VERSION)
tar -cf - st-$(VERSION) | gzip > st-$(VERSION).tar.gz
rm -rf st-$(VERSION)
install: st
touch config.h boxdraw.o hb.o st.o x.o
mkdir -p $(DESTDIR)$(PREFIX)/bin
cp -f st $(DESTDIR)$(PREFIX)/bin
cp -f docs/bindlist $(DESTDIR)$(PREFIX)/bin/stbindlist
cp -f docs/st-keybinds $(DESTDIR)$(PREFIX)/bin
chmod +x $(DESTDIR)$(PREFIX)/bin/st-keybinds
chmod 755 $(DESTDIR)$(PREFIX)/bin/st
cp -f st-autocomplete $(DESTDIR)$(PREFIX)/bin
chmod 755 $(DESTDIR)$(PREFIX)/bin/st-autocomplete
mkdir -p $(DESTDIR)$(MANPREFIX)/man1
sed "s/VERSION/$(VERSION)/g" < st.1 > $(DESTDIR)$(MANPREFIX)/man1/st.1
chmod 644 $(DESTDIR)$(MANPREFIX)/man1/st.1
rm -f config.h boxdraw.o hb.o st.o x.o
tic -sx st.info
@echo Please see the README file regarding the terminfo entry of st.
mkdir -p $(DESTDIR)$(ICONPREFIX)
[ -f $(ICONNAME) ] && cp -f $(ICONNAME) $(DESTDIR)$(ICONPREFIX) || :
mkdir -p $(DESTDIR)$(APPPREFIX)
cp -f st.desktop $(DESTDIR)$(APPPREFIX)
[ -f $(ICONNAME) ] && cp -f $(ICONNAME) $(DESTDIR)$(ICONPREFIX) || :
uninstall:
rm -f $(DESTDIR)$(PREFIX)/bin/st
rm -f $(DESTDIR)$(APPPREFIX)/st.desktop
rm -f $(DESTDIR)$(PREFIX)/bin/st-autocomplete
rm -f $(DESTDIR)$(MANPREFIX)/man1/st.1
rm -f $(DESTDIR)$(ICONPREFIX)/$(ICONNAME)
libxftfix:
git clone https://github.com/uditkarode/libxft-bgra && cd libxft-bgra
sh autogen.sh --sysconfdir=/etc --prefix=/usr --mandir=/usr/share/man
make install
cd .. && rm -r libxft-bgra
gentoo-libxftfix:
mkdir -pv /etc/portage/patches/x11-libs/libXft
curl -o /etc/portage/patches/x11-libs/libXft/bgra.diff https://gitlab.freedesktop.org/xorg/lib/libxft/-/merge_requests/1.patch
emerge x11-libs/libXft
arch-libxftfix:
git clone https://aur.archlinux.org/libxft-bgra
cd libxft-bgra
makepkg -i
help:
@echo install: Installs st. You may need to run this as root.
@echo uninstall: Uninstalls st. You may need to run this as root.
@echo libxftfix: This option compiles and installs libXft-bgra which is necessary to prevent st from crashing.
@echo gentoo-libxftfix: This option installs libXft-bgra by patching it for Gentoo only.
@echo arch-libxftfix: This option installs libXft-bgra using the AUR on Arch Linux only.
@echo help: Displays this help sheet.
.PHONY: all options clean dist install uninstall libxftfix arch-libxftfix gentoo-libxftfix help
.PHONY: all options clean dist install uninstall

129
README.md
View file

@ -1,129 +0,0 @@
# st
speedie's simple terminal configuration
![image](https://user-images.githubusercontent.com/71722170/163290759-e171e5f0-3e9b-4c23-85bf-b45f19a37b34.png)
This is my personal always-changing build of [suckless.org](https://suckless.org)'s simple terminal or [st](https://st.suckless.org).
It features many different patches and tweaks to enhance the experience.
### Important
- This build REQUIRES libXft-bgra. If you don't know what that is, it's a patched build of libXft which fixes a bug which causes st to crash when displaying certain characters.
- This build does not keep object files or config.h. Those are automatically deleted after a successful compile. If a compile is not successful, they will not be deleted. If that's the case, do NOT edit config.h because if you do and it compiles successfully then your changes will be lost.
### Installation
- Install dev-vcs/git using your favorite package manager
- git clone <this-url>
- cd st
- sudo make install
- Follow "Installing libXft-bgra"
### Installation (Package manager)
If you're running Gentoo Linux, you can add my overlay and then simply emerge it.
- emerge layman
- layman -o https://raw.githubusercontent.com/spoverlay/splay/main/splay.xml -f -a splay
- emerge st-spde
### Installing libXft-bgra
Thankfully, I made this process a bit easier by building it into the Makefile.
- cd st
- make libxftfix # For all distros except Gentoo
- make gentoo-libxftfix # For Gentoo
- make arch-libxftfix # For Arch
### Features
This build of dwm has been patched pretty heavily with the following patches
- st-alpha
- st-anysize
- st-autocomplete
- st-bold-is-not-bright
- st-boxdraw
- st-charoffsets
- st-clipboard
- st-delkey
- st-externalpipe
- st-font2
- st-fontfix
- st-glyph-wide-support-boxdraw
- st-ligatures-alpha-scrollback
- st-newterm
- st-nobadweight
- st-scrollback
- st-scrollback-mouse
- st-spoiler
- st-w3m
- st-xclearwin
- st-xresources
- st-keyboard-select
- st-undercurl
- st-csi
- st-copyurl
- st-dynamic-cursor-color
This build of st has full compatibility with .Xresources and allows defining these options:
- !! st resources
- ! special
- *.foreground: #e7e7e7
- *.background: #202020
- *.cursorColor: #e7e7e7
- ! black
- *.color0: #262626
- *.color8: #737373
- ! red
- *.color1: #ff3534
- *.color9: #ff4f4c
- ! green
- *.color2: #35b723
- *.color10: #82ff6e
- ! yellow
- *.color3: #eae804
- *.color11: #dfff52
- ! blue
- *.color4: #362be4
- *.color12: #5767ff
- ! magenta
- *.color5: #fa9cf8
- *.color13: #cf89cf
- ! cyan
- *.color6: #4ed4d4
- *.color14: #68efef
- ! white
- *.color7: #bebebe
- *.color15: #f7f5f5
- ! alpha
- *.alpha: 0.7
- ! font
- *.font: Terminus:pixelsize=15.5:antialias=true:autohint=true;
- *.font2: JoyPixels:pixelsize=12
- *.cols: 80
- *.rows: 24
- *.mousefg: 7
- *.mousebg: 0
- *.defaultattr: 11
- *.cwscale: 1.0
- *.chscale: 1.0
Pywal support is also a thing and will automatically be used. No special scripts like my build of dmenu requires.
It also supports color emojis as long as libXft is patched, otherwise it will CRASH. It has an emoji picker. To use it, add a keybind to your build of dwm which runs /usr/bin/emojilist (Requires dmenu). It allows copying the output of a command. To use it, add a keybind to your build of dwm which runs /usr/bin/copyout (Requires dmenu) Keep in mind if you're using my build of dwm, these binds are already added.
### Keybinds (not complete)
- CTRL+y | Copy to the clipboard
- CTRL+p | Paste from the clipboard
- CTRL+= | Increase font size
- CTRL+- | Decrease font size
- CTRL+0 | Reset font size to default
- CTRL+j | Scroll down
- CTRL+k | Scroll up
- CTRL+Shift+k| Copy the last URL
- CTRL+Enter | Opens a new terminal window in the same directory
- Scroll+up | Scroll up (Mouse scrollback support)
- Scroll+down | Scroll down (Mouse scrollback support)
- Shift+Esc | Select mode
-
- If you're using my zsh config:
- I | Enter Insert mode
- Esc | Enter Normal mode
- Tab | Autocomplete

View file

@ -1,16 +0,0 @@
# ifndef __ST_AUTOCOMPLETE_H
# define __ST_AUTOCOMPLETE_H
enum {
ACMPL_DEACTIVATE,
ACMPL_WORD,
ACMPL_WWORD,
ACMPL_FUZZY_WORD,
ACMPL_FUZZY_WWORD,
ACMPL_FUZZY,
ACMPL_SUFFIX,
ACMPL_SURROUND,
ACMPL_UNDO,
};
# endif // __ST_AUTOCOMPLETE_H

File diff suppressed because it is too large Load diff

View file

@ -4,11 +4,11 @@ VERSION = 0.8.5
# Customize below to fit your system
# paths
PREFIX = /usr
PREFIX = /usr/local
APPPREFIX = $(PREFIX)/share/applications
MANPREFIX = $(PREFIX)/share/man
ICONPREFIX = $(PREFIX)/share/pixmaps
ICONNAME = st.png
APPPREFIX = $(PREFIX)/share/applications
X11INC = /usr/X11R6/include
X11LIB = /usr/X11R6/lib
@ -17,12 +17,11 @@ PKG_CONFIG = pkg-config
# includes and libs
INCS = -I$(X11INC) \
`$(PKG_CONFIG) --cflags glib-2.0` \
`$(PKG_CONFIG) --cflags fontconfig` \
`$(PKG_CONFIG) --cflags freetype2` \
`$(PKG_CONFIG) --cflags harfbuzz`
LIBS = -L$(X11LIB) -lm -lrt -lX11 -lutil -lXft -lXrender -lgd \
`$(PKG_CONFIG) --libs glib-2.0` \
LIBS = -L$(X11LIB) -lm -lrt -lX11 -lutil -lXft -lgd \
`$(PKG_CONFIG) --libs fontconfig` \
`$(PKG_CONFIG) --libs freetype2` \
`$(PKG_CONFIG) --libs harfbuzz`
@ -37,6 +36,7 @@ STLDFLAGS = $(LIBS) $(LDFLAGS)
#LIBS = -L$(X11LIB) -lm -lX11 -lutil -lXft \
# `$(PKG_CONFIG) --libs fontconfig` \
# `$(PKG_CONFIG) --libs freetype2`
#MANPREFIX = ${PREFIX}/man
# compiler and linker
# CC = c99

View file

@ -1,17 +0,0 @@
CTRL+y | Copy to the clipboard
CTRL+p | Paste from the clipboard
CTRL+= | Increase font size
CTRL+- | Decrease font size
CTRL+0 | Reset font size to default
CTRL+j | Scroll down
CTRL+k | Scroll up
CTRL+Shift+k| Copy the last URL
CTRL+Enter | Opens a new terminal window in the same directory
Scroll+up | Scroll up (Mouse scrollback support)
Scroll+down | Scroll down (Mouse scrollback support)
Shift+Esc | Select mode
If you're using my zsh config:
I | Enter Insert mode
Esc | Enter Normal mode
Tab | Autocomplete

View file

@ -1,33 +0,0 @@
!! st resources
! special
*.foreground: #e7e7e7
*.background: #202020
*.cursorColor: #e7e7e7
! black
*.color0: #262626
*.color8: #737373
! red
*.color1: #ff3534
*.color9: #ff4f4c
! green
*.color2: #35b723
*.color10: #82ff6e
! yellow
*.color3: #eae804
*.color11: #dfff52
! blue
*.color4: #362be4
*.color12: #5767ff
! magenta
*.color5: #fa9cf8
*.color13: #cf89cf
! cyan
*.color6: #4ed4d4
*.color14: #68efef
! white
*.color7: #bebebe
*.color15: #f7f5f5
! alpha
*.alpha: 0.9
! font
*.font: DejaVu Sans Mono:pixelsize=12:antialias=true:autohint=true;

View file

@ -1,23 +0,0 @@
Here's an (unfinished) list of keybinds my build of st comes with
NOTE: May me slightly out of date.
For more information, read the 'man' page.
CTRL+y | Copy (yank) to the clipboard
CTRL+p | Paste from the clipboard
CTRL+= | Increase font size
CTRL+- | Decrease font size
CTRL+0 | Reset font size to default
CTRL+j | Scroll down
CTRL+k | Scroll up
CTRL+Enter | Opens a new terminal window in the same directory
Scroll+up | Scroll up (Mouse scrollback support)
Scroll+down | Scroll down (Mouse scrollback support)
If you're using my zsh config (szsh):
I | Enter Insert mode
Esc | Enter Normal mode
Tab | Autocomplete
If you're using my build of dwm:
Alt+Shift+e | Open emoji picker
Alt+Shift+c | Open copyout selection

View file

@ -1,28 +0,0 @@
st-alpha
st-anysize
st-autocomplete
st-bold-is-not-bright
st-boxdraw
st-charoffsets
st-clipboard
st-delkey
st-externalpipe
st-font2
st-fontfix
st-glyph-wide-support-boxdraw
st-ligatures-alpha-scrollback
st-newterm
st-nobadweight
st-scrollback
st-scrollback-mouse
st-spoiler
st-w3m
st-xclearwin
st-xresources
st-keyboard-select
st-undercurl
st-csi
st-copyurl
st-dynamic-cursor-color
st-desktopentry
st-netwmicon

View file

@ -1,4 +0,0 @@
#!/bin/sh
# Simple script which allows you to read all st keybinds
less /usr/bin/stbindlist

9
hb.c
View file

@ -21,7 +21,8 @@ static int hbfontslen = 0;
static HbFontMatch *hbfontcache = NULL;
/*
* Replace 0 with a list of font features, wrapped in FEATURE macro, e.g.
* 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[] = { 0 };
@ -96,6 +97,10 @@ hbtransform(XftGlyphFontSpec *specs, const Glyph *glyphs, size_t len, int x, int
for (int i = 0, specidx = 0; i < len; i++) {
if (glyphs[i].mode & ATTR_WDUMMY)
continue;
if (glyphs[i].mode & ATTR_BOXDRAW) {
specidx++;
continue;
}
if (codepoints[i] != specs[specidx].glyph)
((Glyph *)glyphs)[i].mode |= ATTR_LIGA;
@ -128,7 +133,7 @@ hbtransformsegment(XftFont *xfont, const Glyph *string, hb_codepoint_t *codepoin
}
/* Shape the segment. */
hb_shape(font, buffer, features, sizeof(features));
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, NULL);

BIN
st

Binary file not shown.

View file

@ -1,300 +0,0 @@
#!/usr/bin/perl
#########################################################################
# Copyright (C) 2012-2021 Wojciech Siewierski, Gaspar Vardanyan #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
#########################################################################
my ($cmd, $cursor_row, $cursor_column) = @ARGV;
# A reference to a function that transforms the completed word
# into a regex matching the completions. Usually generated by
# generate_matcher().
#
# For example
# $fun = generate_matcher(".*");
# $fun->("foo");
# would return "f.*o.*o"
#
# In other words, indirectly decides which characters can
# appear in the completion.
my $matcher;
# A regular expression matching a character before each match.
# For example, it you want to match the text after a
# whitespace, set it to "\s".
my $char_class_before;
# A regular expression matching every character in the entered
# text that will be used to find matching completions. Usually
# "\w" or similar.
my $char_class_to_complete;
# A regular expression matching every allowed last character
# of the completion (uses greedy matching).
my $char_class_at_end;
if ($cmd eq 'word-complete') {
# Basic word completion. Completes the current word
# without any special matching.
$char_class_before = '[^-\w]';
$matcher = sub { quotemeta shift }; # identity
$char_class_at_end = '[-\w]';
$char_class_to_complete = '[-\w]';
} elsif ($cmd eq 'WORD-complete') {
# The same as above but in the Vim meaning of a "WORD" --
# whitespace delimited.
$char_class_before = '\s';
$matcher = sub { quotemeta shift };
$char_class_at_end = '\S';
$char_class_to_complete = '\S';
} elsif ($cmd eq 'fuzzy-word-complete' ||
$cmd eq 'skeleton-word-complete') {
# Fuzzy completion of the current word.
$char_class_before = '[^-\w]';
$matcher = generate_matcher('[-\w]*');
$char_class_at_end = '[-\w]';
$char_class_to_complete = '[-\w]';
} elsif ($cmd eq 'fuzzy-WORD-complete') {
# Fuzzy completion of the current WORD.
$char_class_before = '\s';
$matcher = generate_matcher('\S*');
$char_class_at_end = '\S';
$char_class_to_complete = '\S';
} elsif ($cmd eq 'fuzzy-complete' ||
$cmd eq 'skeleton-complete') {
# Fuzzy completion of an arbitrary text.
$char_class_before = '\W';
$matcher = generate_matcher('.*?');
$char_class_at_end = '\w';
$char_class_to_complete = '\S';
} elsif ($cmd eq 'suffix-complete') {
# Fuzzy completion of an completing suffixes, like
# completing test=hello from /blah/hello.
$char_class_before = '\S';
$matcher = generate_matcher('\S*');
$char_class_at_end = '\S';
$char_class_to_complete = '\S';
} elsif ($cmd eq 'surround-complete') {
# Completing contents of quotes and braces.
# Here we are using three named groups: s, b, p for quotes, braces
# and parenthesis.
$char_class_before = '((?<q>["\'`])|(?<b>\[)|(?<p>\())';
$matcher = generate_matcher('.*?');
# Here we match text till enclosing pair, using perl conditionals in
# regexps (?(condition)yes-expression|no-expression).
# \0 is used to hack concatenation with '*' later in the code.
$char_class_at_end = '.*?(.(?=(?(<b>)\]|((?(<p>)\)|\g{q})))))\0';
$char_class_to_complete = '\S';
}
my $lines = [];
my $last_line = -1;
my $lines_after_cursor = 0;
while (<STDIN>)
{
$last_line++;
if ($last_line <= $cursor_row)
{
push @{$lines}, $_;
}
else
{
unshift @{$lines}, $_;
$lines_after_cursor++;
}
}
$cursor_row = $last_line;
# read the word behind the cursor
$_ = substr(@{$lines} [$cursor_row], 0, $cursor_column); # get the current line up to the cursor...
s/.*?($char_class_to_complete*)$/$1/; # ...and read the last word from it
my $word_to_complete = quotemeta;
# ignore the completed word itself
$self->{already_completed}{$word_to_complete} = 1;
print stdout "$word_to_complete\n";
# search for matches
while (my $completion = find_match($self,
$word_to_complete,
$self->{next_row} // $cursor_row,
$matcher->($word_to_complete),
$char_class_before,
$char_class_at_end)
) {
calc_match_coords($self,
$self->{next_row}+1,
$completion);
print stdout "$completion @{$self->{highlight}}\n";
}
leave($self);
######################################################################
# Finds the next matching completion in the row current row or above
# while skipping duplicates using skip_duplicates().
sub find_match {
my ($self, $word_to_match, $current_row, $regexp, $char_class_before, $char_class_at_end) = @_;
$self->{matches_in_row} //= [];
# cycle through all the matches in the current row if not starting a new search
if (@{$self->{matches_in_row}}) {
return skip_duplicates($self, $word_to_match, $current_row, $regexp, $char_class_before, $char_class_at_end);
}
my $i;
# search through all the rows starting with current one or one above the last checked
for ($i = $current_row; $i >= 0; --$i) {
my $line = @{$lines} [$i]; # get the line of text from the row
if ($i == $cursor_row) {
$line = substr $line, 0, $cursor_column;
}
$_ = $line;
# find all the matches in the current line
my $match;
push @{$self->{matches_in_row}}, $+{match} while ($_, $match) = /
(.*${char_class_before})
(?<match>
${regexp}
${char_class_at_end}*
)
/ix;
# corner case: match at the very beginning of line
push @{$self->{matches_in_row}}, $+{match} if $line =~ /^(${char_class_before}){0}(?<match>$regexp$char_class_at_end*)/i;
if (@{$self->{matches_in_row}}) {
# remember which row should be searched next
$self->{next_row} = --$i;
# arguments needed for find_match() mutual recursion
return skip_duplicates($self, $word_to_match, $i, $regexp, $char_class_before, $char_class_at_end);
}
}
# no more possible completions, revert to the original word
$self->{next_row} = -1 if $i < 0;
return undef;
}
######################################################################
# Checks whether the completion found by find_match() was already
# found and if it was, calls find_match() again to find the next
# completion.
#
# Takes all the arguments that find_match() would take, to make a
# mutually recursive call.
sub skip_duplicates {
my $self = $_[0];
my $current_row = $_[2];
my $completion;
if ($current_row >= $lines_after_cursor)
{
$completion = shift @{$self->{matches_in_row}}; # get the rightmost one
}
else
{
$completion = pop @{$self->{matches_in_row}}; # get the rightmost one
}
# check for duplicates
if (exists $self->{already_completed}{$completion}) {
# skip this completion
return find_match(@_);
} else {
$self->{already_completed}{$completion} = 1;
return $completion;
}
}
######################################################################
# Returns a function that takes a string and returns that string with
# this function's argument inserted between its every two characters.
# The resulting string is used as a regular expression matching the
# completion candidates.
sub generate_matcher {
my $regex_between = shift;
sub {
$_ = shift;
# sorry for this lispy code, I couldn't resist ;)
(join "$regex_between",
(map quotemeta,
(split //)))
}
}
######################################################################
sub calc_match_coords {
my ($self, $linenum, $completion) = @_;
my $line = @{$lines} [$linenum];
my $re = quotemeta $completion;
$line =~ /$re/;
#my ($beg_row, $beg_col) = $line->coord_of($-[0]);
#my ($end_row, $end_col) = $line->coord_of($+[0]);
my $beg = $-[0];
my $end = $+[0];
if (exists $self->{highlight}) {
delete $self->{highlight};
}
# () # TODO: what does () do in perl ????
if ($linenum >= $lines_after_cursor)
{
$linenum -= $lines_after_cursor;
}
else
{
$linenum = $last_line - $linenum;
}
# ACMPL_ISSUE: multi-line completions don't work
# $self->{highlight} = [$beg_row, $beg_col, $end_row, $end_col];
$self->{highlight} = [$linenum, $beg, $end];
}
######################################################################
sub leave {
my ($self) = @_;
delete $self->{next_row};
delete $self->{matches_in_row};
delete $self->{already_completed};
delete $self->{highlight};
}

1786
st.c

File diff suppressed because it is too large Load diff

View file

@ -3,7 +3,7 @@ Type=Application
Exec=st
TryExec=st
Icon=st
Terminal=true
Terminal=false
Categories=System;TerminalEmulator;
Name=st

49
st.h
View file

@ -4,9 +4,10 @@
#include <sys/types.h>
#include <gd.h>
#include <glib.h>
/* macros */
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#define MAX(a, b) ((a) < (b) ? (b) : (a))
#define LEN(a) (sizeof(a) / sizeof(a)[0])
#define BETWEEN(x, a, b) ((a) <= (x) && (x) <= (b))
#define DIVCEIL(n, d) (((n) + ((d) - 1)) / (d))
@ -24,29 +25,25 @@
enum glyph_attribute {
ATTR_NULL = 0,
ATTR_BOLD = 1 << 0,
ATTR_FAINT = 1 << 1,
ATTR_ITALIC = 1 << 2,
ATTR_UNDERLINE = 1 << 3,
ATTR_BLINK = 1 << 4,
ATTR_REVERSE = 1 << 5,
ATTR_INVISIBLE = 1 << 6,
ATTR_STRUCK = 1 << 7,
ATTR_WRAP = 1 << 8,
ATTR_WIDE = 1 << 9,
ATTR_WDUMMY = 1 << 10,
ATTR_LIGA = 1 << 11,
ATTR_BOXDRAW = 1 << 11,
ATTR_SET = 1 << 0,
ATTR_BOLD = 1 << 1,
ATTR_FAINT = 1 << 2,
ATTR_ITALIC = 1 << 3,
ATTR_UNDERLINE = 1 << 4,
ATTR_BLINK = 1 << 5,
ATTR_REVERSE = 1 << 6,
ATTR_INVISIBLE = 1 << 7,
ATTR_STRUCK = 1 << 8,
ATTR_WRAP = 1 << 9,
ATTR_WIDE = 1 << 10,
ATTR_WDUMMY = 1 << 11,
ATTR_BOXDRAW = 1 << 12,
ATTR_LIGA = 1 << 13,
ATTR_SELECTED = 1 << 14,
ATTR_BOLD_FAINT = ATTR_BOLD | ATTR_FAINT,
ATTR_DIRTYUNDERLINE = 1 << 15,
};
enum drawing_mode {
DRAW_NONE = 0,
DRAW_BG = 1 << 0,
DRAW_FG = 1 << 1,
};
enum selection_mode {
SEL_IDLE = 0,
SEL_EMPTY = 1,
@ -90,25 +87,20 @@ typedef union {
const char *s;
} Arg;
void autocomplete (const Arg *);
void die(const char *, ...);
void redraw(void);
void draw(void);
void kscrolldown(const Arg *);
void kscrollup(const Arg *);
void newterm(const Arg *);
void externalpipe(const Arg *);
void printscreen(const Arg *);
void printsel(const Arg *);
void sendbreak(const Arg *);
void toggleprinter(const Arg *);
void copyurl(const Arg *);
int tattrset(int);
int trt_kbdselect(KeySym, char *, int);
void tnew(int, int);
int tisaltscreen(void);
void tresize(int, int);
void tsetdirtattr(int);
void ttyhangup(void);
@ -132,7 +124,7 @@ void *xmalloc(size_t);
void *xrealloc(void *, size_t);
char *xstrdup(const char *);
int xgetcolor(int x, unsigned char *r, unsigned char *g, unsigned char *b);
void openUrlOnClick(int, int, char *);
int isboxdraw(Rune);
ushort boxdrawindex(const Glyph *);
@ -154,6 +146,5 @@ extern char *termname;
extern unsigned int tabspaces;
extern unsigned int defaultfg;
extern unsigned int defaultbg;
static unsigned int defaultcs;
extern unsigned int defaultcs;
extern const int boxdraw, boxdraw_bold, boxdraw_braille;
extern float alpha;

View file

@ -162,7 +162,7 @@ st-mono| simpleterm monocolor,
rin=\E[%p1%dT,
ritm=\E[23m,
rmacs=\E(B,
rmcup=\E[?1049l\E[23;0;0t,
rmcup=\E[?1049l,
rmir=\E[4l,
rmkx=\E[?1l\E>,
rmso=\E[27m,
@ -173,7 +173,7 @@ st-mono| simpleterm monocolor,
sitm=\E[3m,
sgr0=\E[0m,
smacs=\E(0,
smcup=\E[?1049h\E[22;0;0t,
smcup=\E[?1049h,
smir=\E[4h,
smkx=\E[?1h\E=,
smso=\E[7m,
@ -192,6 +192,7 @@ st-mono| simpleterm monocolor,
Ms=\E]52;%p1%s;%p2%s\007,
Se=\E[2 q,
Ss=\E[%p1%d q,
Sync=\EP=%p1%ds\E\\,
st| simpleterm,
use=st-mono,

8
win.h
View file

@ -21,7 +21,6 @@ enum win_mode {
MODE_NUMLOCK = 1 << 17,
MODE_MOUSE = MODE_MOUSEBTN|MODE_MOUSEMOTION|MODE_MOUSEX10\
|MODE_MOUSEMANY,
MODE_KBDSELECT = 1 << 18,
};
void xbell(void);
@ -31,16 +30,13 @@ 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 xfreetitlestack(void);
void xsettitle(char *, int);
void xpushtitle(void);
void xsettitle(char *);
int xsetcursor(int);
void xsetmode(int, unsigned int);
void xsetpointermotion(int);
void xsetsel(char *);
int xstartdraw(void);
void toggle_winmode(int);
void keyboard_select(const Arg *);
void xximspot(int, int);
void xclearwin(void);

257
x.c
View file

@ -73,6 +73,8 @@ enum undercurl_slope_type {
#define XK_NO_MOD 0
#define XK_SWITCH_MOD (1<<13|1<<14)
static int cursorblinks = 0;
/* function definitions used in config.h */
static void clipcopy(const Arg *);
static void clippaste(const Arg *);
@ -86,9 +88,6 @@ 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
@ -103,8 +102,6 @@ typedef XftDraw *Draw;
typedef XftColor Color;
typedef XftGlyphFontSpec GlyphFontSpec;
typedef unsigned long int CARD32;
/* Purely graphic info */
typedef struct {
int tw, th; /* tty width and height */
@ -136,6 +133,7 @@ typedef struct {
int depth; /* bit depth */
int l, t; /* left and top offset */
int gm; /* geometry mask */
int cyo;
} XWindow;
typedef struct {
@ -171,7 +169,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, int);
static void xdrawglyphfontspecs(const XftGlyphFontSpec *, Glyph, int, int, int);
static void xdrawglyph(Glyph, int, int);
static void xclear(int, int, int, int);
static int xgeommasktogravity(int);
@ -186,14 +184,15 @@ static void xhints(void);
static int xloadcolor(int, const char *, Color *);
static int xloadfont(Font *, FcPattern *);
static void xloadfonts(const char *, double);
static int xloadsparefont(FcPattern *, int);
static void xloadsparefonts(void);
static void xunloadfont(Font *);
static void xunloadfonts(void);
static void xsetenv(void);
static void xseturgency(int);
static int evcol(XEvent *);
static int evrow(XEvent *);
static int xloadsparefont(FcPattern *, int);
static void xloadsparefonts(void);
static void expose(XEvent *);
static void visibility(XEvent *);
static void unmap(XEvent *);
@ -250,8 +249,6 @@ 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 {
@ -275,8 +272,6 @@ static char *usedfont = NULL;
static double usedfontsize = 0;
static double defaultfontsize = 0;
static int cursorblinks = 0;
static char *opt_alpha = NULL;
static char *opt_class = NULL;
static char **opt_cmd = NULL;
static char *opt_embed = NULL;
@ -747,6 +742,7 @@ brelease(XEvent *e)
return;
if (btn == Button1)
mousesel(e, 1);
openUrlOnClick(evcol(e), evrow(e), url_opener);
}
void
@ -849,9 +845,6 @@ xloadcols(void)
die("could not allocate color %d\n", i);
}
/* set alpha value of bg color */
if (opt_alpha)
alpha = strtof(opt_alpha, NULL);
dc.col[defaultbg].color.alpha = (unsigned short)(0xffff * alpha);
dc.col[defaultbg].pixel &= 0x00FFFFFF;
dc.col[defaultbg].pixel |= (unsigned char)(0xff * alpha) << 24;
@ -885,6 +878,12 @@ xsetcolorname(int x, const char *name)
XftColorFree(xw.dpy, xw.vis, xw.cmap, &dc.col[x]);
dc.col[x] = ncolor;
if (x == defaultbg) {
dc.col[defaultbg].color.alpha = (unsigned short)(0xffff * alpha);
dc.col[defaultbg].pixel &= 0x00FFFFFF;
dc.col[defaultbg].pixel |= (unsigned char)(0xff * alpha) << 24;
}
return 0;
}
@ -1006,6 +1005,7 @@ xloadfont(Font *f, FcPattern *pattern)
XftResultMatch)) {
if ((XftPatternGetInteger(f->match->pattern, "weight", 0,
&haveattr) != XftResultMatch) || haveattr != wantattr) {
f->badweight = 1;
fputs("font weight does not match\n", stderr);
}
}
@ -1079,6 +1079,7 @@ xloadfonts(const char *fontstr, double fontsize)
/* Setting character width and height. */
win.cw = ceilf(dc.font.width * cwscale);
win.ch = ceilf(dc.font.height * chscale);
xw.cyo = ceilf(dc.font.height * (chscale - 1) / 2);
FcPatternDel(pattern, FC_SLANT);
FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ITALIC);
@ -1272,51 +1273,6 @@ xicdestroy(XIC xim, XPointer client, XPointer call)
return 1;
}
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
xinit(int cols, int rows)
{
@ -1423,27 +1379,28 @@ xinit(int cols, int rows)
/* use a png-image to set _NET_WM_ICON */
FILE* file = fopen(ICON, "r");
if (file) {
/* inititialize variables */
/* load image in rgba-format */
const gdImagePtr icon_rgba = gdImageCreateFromPng(file);
fclose(file);
/* declare icon-variable which will store the image in argb-format */
const int width = gdImageSX(icon_rgba);
const int height = gdImageSY(icon_rgba);
const int icon_n = width * height + 2;
CARD32 *icon_argb = g_new0(CARD32, icon_n);
long icon_argb[icon_n];
/* set width and height of the icon */
int i = 0;
icon_argb[i++] = width;
icon_argb[i++] = height;
/* RGBA -> ARGB */
/* rgba -> argb */
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
const int pixel_rgba = gdImageGetPixel(icon_rgba, x, y);
guint8* pixel_argb = (guint8*) &icon_argb[i++];
unsigned char *pixel_argb = (unsigned char *) &icon_argb[i++];
pixel_argb[0] = gdImageBlue(icon_rgba, pixel_rgba);
pixel_argb[1] = gdImageGreen(icon_rgba, pixel_rgba);
pixel_argb[2] = gdImageRed(icon_rgba, pixel_rgba);
/* scale alpha from 0-127 to 0-255 */
const int alpha = 127 - gdImageAlpha(icon_rgba, pixel_rgba);
const unsigned char alpha = 127 - gdImageAlpha(icon_rgba, pixel_rgba);
pixel_argb[3] = alpha == 127 ? 255 : alpha * 2;
}
}
@ -1516,7 +1473,7 @@ xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x
font = &dc.bfont;
frcflags = FRC_BOLD;
}
yp = winy + font->ascent;
yp = winy + font->ascent + xw.cyo;
}
if (mode & ATTR_BOXDRAW) {
@ -1529,8 +1486,8 @@ xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x
if (glyphidx) {
specs[numspecs].font = font->match;
specs[numspecs].glyph = glyphidx;
specs[numspecs].x = (short)xp + cxoffset;
specs[numspecs].y = (short)yp + cyoffset;
specs[numspecs].x = (short)xp;
specs[numspecs].y = (short)yp;
xp += runewidth;
numspecs++;
continue;
@ -1615,8 +1572,53 @@ 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, int dmode)
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,
@ -1656,6 +1658,10 @@ 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];
@ -1692,15 +1698,10 @@ xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, i
}
if (base.mode & ATTR_REVERSE) {
if (bg == fg) {
bg = &dc.col[defaultfg];
fg = &dc.col[defaultbg];
} else {
temp = fg;
fg = bg;
bg = temp;
}
}
if (base.mode & ATTR_BLINK && win.mode & MODE_BLINK)
fg = bg;
@ -1742,6 +1743,8 @@ 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 * chscale + 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
@ -1837,7 +1840,7 @@ xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, i
*/
wh *= 2;
// Set the angle of the slope to 45°
// Set the angle of the slope to 45°
ww = wh;
// Position of wave is independent of word, it's absolute
@ -1937,7 +1940,7 @@ xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, i
// Make the underline corridor larger
wh *= 2;
// Set the angle of the slope to 45°
// Set the angle of the slope to 45°
ww = wh;
ww *= 1 + capRatio; // Add a bit of width for the cap
@ -2096,7 +2099,7 @@ xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, i
}
if (base.mode & ATTR_STRUCK) {
XftDrawRect(xw.draw, fg, winx, winy + 2 * dc.font.ascent / 3,
XftDrawRect(xw.draw, fg, winx, winy + xw.cyo + 2 * dc.font.ascent * chscale / 3,
width, 1);
}
@ -2111,7 +2114,7 @@ xdrawglyph(Glyph g, int x, int y)
XftGlyphFontSpec spec;
numspecs = xmakeglyphfontspecs(&spec, &g, 1, x, y);
xdrawglyphfontspecs(&spec, g, numspecs, x, y, DRAW_BG | DRAW_FG);
xdrawglyphfontspecs(&spec, g, numspecs, x, y);
}
void
@ -2123,9 +2126,7 @@ xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og, Line line, int le
/* remove the old cursor */
if (selected(ox, oy))
og.mode ^= ATTR_REVERSE;
/* Redraw the line where cursor was previously.
* It will restore the ligatures broken by the cursor. */
//xdrawglyph(og, ox, oy);
xdrawline(line, 0, oy, len);
if (IS_SET(MODE_HIDE))
@ -2257,30 +2258,10 @@ xseticontitle(char *p)
}
void
xfreetitlestack(void)
{
for (int i = 0; i < LEN(titlestack); i++) {
free(titlestack[i]);
titlestack[i] = NULL;
}
}
void
xsettitle(char *p, int pop)
xsettitle(char *p)
{
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;
}
DEFAULT(p, opt_title);
if (Xutf8TextListToTextProperty(xw.dpy, &p, 1, XUTF8StringStyle,
&prop) != Success)
@ -2290,16 +2271,6 @@ xsettitle(char *p, int pop)
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)
{
@ -2311,17 +2282,11 @@ xstartdraw(void)
void
xdrawline(Line line, int x1, int y1, int x2)
{
int i, x, ox, numspecs, numspecs_cached;
int i, x, ox, numspecs;
Glyph base, new;
XftGlyphFontSpec *specs;
XftGlyphFontSpec *specs = xw.specbuf;
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;
numspecs = xmakeglyphfontspecs(specs, &line[x1], x2 - x1, x1, y1);
i = ox = 0;
for (x = x1; x < x2 && i < numspecs; x++) {
new = line[x];
@ -2330,7 +2295,7 @@ xdrawline(Line line, int x1, int y1, int x2)
if (selected(x, y1))
new.mode ^= ATTR_REVERSE;
if (i > 0 && ATTRCMP(base, new)) {
xdrawglyphfontspecs(specs, base, i, ox, y1, dmode);
xdrawglyphfontspecs(specs, base, i, ox, y1);
specs += i;
numspecs -= i;
i = 0;
@ -2342,8 +2307,7 @@ xdrawline(Line line, int x1, int y1, int x2)
i++;
}
if (i > 0)
xdrawglyphfontspecs(specs, base, i, ox, y1, dmode);
}
xdrawglyphfontspecs(specs, base, i, ox, y1);
}
void
@ -2520,24 +2484,14 @@ kpress(XEvent *ev)
len = XmbLookupString(xw.ime.xic, e, buf, sizeof buf, &ksym, &status);
else
len = XLookupString(e, buf, sizeof buf, &ksym, NULL);
if ( IS_SET(MODE_KBDSELECT) ) {
if ( match(XK_NO_MOD, e->state) ||
(XK_Shift_L | XK_Shift_R) & e->state )
win.mode ^= trt_kbdselect(ksym, buf, len);
return;
}
/* 1. shortcuts */
for (bp = shortcuts; bp < shortcuts + LEN(shortcuts); bp++) {
if (ksym == bp->keysym && match(bp->mod, e->state)) {
if (bp -> func != autocomplete)
autocomplete ((const Arg []) { ACMPL_DEACTIVATE });
bp->func(&(bp->arg));
return;
}
}
autocomplete ((const Arg []) { ACMPL_DEACTIVATE });
/* 2. custom keys from config.h */
if ((customkey = kmap(ksym, e->state))) {
ttywrite(customkey, strlen(customkey), 1);
@ -2591,6 +2545,9 @@ resize(XEvent *e)
cresize(e->xconfigure.width, e->xconfigure.height);
}
int tinsync(uint);
int ttyread_pending();
void
run(void)
{
@ -2625,7 +2582,7 @@ run(void)
FD_SET(ttyfd, &rfd);
FD_SET(xfd, &rfd);
if (XPending(xw.dpy))
if (XPending(xw.dpy) || ttyread_pending())
timeout = 0; /* existing events might not set xfd */
seltv.tv_sec = timeout / 1E3;
@ -2639,7 +2596,8 @@ run(void)
}
clock_gettime(CLOCK_MONOTONIC, &now);
if (FD_ISSET(ttyfd, &rfd))
int ttyin = FD_ISSET(ttyfd, &rfd) || ttyread_pending();
if (ttyin)
ttyread();
xev = 0;
@ -2663,7 +2621,7 @@ run(void)
* maximum latency intervals during `cat huge.txt`, and perfect
* sync with periodic updates from animations/key-repeats/etc.
*/
if (FD_ISSET(ttyfd, &rfd) || xev) {
if (ttyin || xev) {
if (!drawing) {
trigger = now;
if (IS_SET(MODE_BLINK)) {
@ -2678,6 +2636,18 @@ run(void)
continue; /* we have time, try to find idle */
}
if (tinsync(su_timeout)) {
/*
* on synchronized-update draw-suspension: don't reset
* drawing so that we draw ASAP once we can (just after
* ESU). it won't be too soon because we already can
* draw now but we skip. we set timeout > 0 to draw on
* SU-timeout even without new content.
*/
timeout = minlatency;
continue;
}
/* idle detected or maxlatency exhausted -> draw */
timeout = -1;
if (blinktimeout && (cursorblinks || tattrset(ATTR_BLINK))) {
@ -2764,14 +2734,6 @@ usage(void)
" [stty_args ...]\n", argv0, argv0);
}
void toggle_winmode(int flag) {
win.mode ^= flag;
}
void keyboard_select(const Arg *dummy) {
win.mode ^= trt_kbdselect(-1, NULL, 0);
}
int
main(int argc, char *argv[])
{
@ -2784,7 +2746,8 @@ main(int argc, char *argv[])
allowaltscreen = 0;
break;
case 'A':
opt_alpha = EARGF(usage());
alpha = strtof(EARGF(usage()), NULL);
LIMIT(alpha, 0.0, 1.0);
break;
case 'c':
opt_class = EARGF(usage());