diff options
Diffstat (limited to 'st')
| -rw-r--r-- | st/st/.Xdefaults | 124 | ||||
| -rw-r--r-- | st/st/.gitignore | 5 | ||||
| -rw-r--r-- | st/st/FAQ | 167 | ||||
| -rw-r--r-- | st/st/LEGACY | 17 | ||||
| -rw-r--r-- | st/st/Makefile | 5 | ||||
| -rw-r--r-- | st/st/PKGBUILD | 45 | ||||
| -rw-r--r-- | st/st/README.md | 85 | ||||
| -rw-r--r-- | st/st/TODO | 28 | ||||
| -rw-r--r-- | st/st/config.h | 131 | ||||
| -rw-r--r-- | st/st/config.mk | 27 | ||||
| -rw-r--r-- | st/st/solarized-alpha-toggle.patch | 20 | ||||
| -rwxr-xr-x | st/st/st | bin | 104768 -> 115616 bytes | |||
| -rwxr-xr-x | st/st/st-copyout | 12 | ||||
| -rw-r--r-- | st/st/st.1 | 54 | ||||
| -rw-r--r-- | st/st/st.c | 164 | ||||
| -rw-r--r-- | st/st/st.h | 15 | ||||
| -rw-r--r-- | st/st/win.h | 5 | ||||
| -rw-r--r-- | st/st/x.c | 464 |
18 files changed, 847 insertions, 521 deletions
diff --git a/st/st/.Xdefaults b/st/st/.Xdefaults new file mode 100644 index 0000000..05b5e2e --- /dev/null +++ b/st/st/.Xdefaults @@ -0,0 +1,124 @@ +!! Transparency (0-1): +st.alpha: 0.92 + +!! Set a default font and font size as below: +st.font: Monospace-11; + +! st.termname: st-256color +! st.borderpx: 2 + +!! Set the background, foreground and cursor colors as below: +*.background: #282828 +*.foreground: white +*.cursorColor: white + +/* !! gruvbox: */ +/* *.color0: #1d2021 */ +/* *.color1: #cc241d */ +/* *.color2: #98971a */ +/* *.color3: #d79921 */ +/* *.color4: #458588 */ +/* *.color5: #b16286 */ +/* *.color6: #689d6a */ +/* *.color7: #a89984 */ +/* *.color8: #928374 */ +/* *.color9: #fb4934 */ +/* *.color10: #b8bb26 */ +/* *.color11: #fabd2f */ +/* *.color12: #83a598 */ +/* *.color13: #d3869b */ +/* *.color14: #8ec07c */ +/* *.color15: #ebdbb2 */ + +/* !! gruvbox light: */ +/* *.color0: #fbf1c7 */ +/* *.color1: #cc241d */ +/* *.color2: #98971a */ +/* *.color3: #d79921 */ +/* *.color4: #458588 */ +/* *.color5: #b16286 */ +/* *.color6: #689d6a */ +/* *.color7: #7c6f64 */ +/* *.color8: #928374 */ +/* *.color9: #9d0006 */ +/* *.color10: #79740e */ +/* *.color11: #b57614 */ +/* *.color12: #076678 */ +/* *.color13: #8f3f71 */ +/* *.color14: #427b58 */ +/* *.color15: #3c3836 */ + +/* !! brogrammer: */ +/* *.foreground: #d6dbe5 */ +/* *.background: #131313 */ +/* *.color0: #1f1f1f */ +/* *.color8: #d6dbe5 */ +/* *.color1: #f81118 */ +/* *.color9: #de352e */ +/* *.color2: #2dc55e */ +/* *.color10: #1dd361 */ +/* *.color3: #ecba0f */ +/* *.color11: #f3bd09 */ +/* *.color4: #2a84d2 */ +/* *.color12: #1081d6 */ +/* *.color5: #4e5ab7 */ +/* *.color13: #5350b9 */ +/* *.color6: #1081d6 */ +/* *.color14: #0f7ddb */ +/* *.color7: #d6dbe5 */ +/* *.color15: #ffffff */ +/* *.colorBD: #d6dbe5 */ + +/* ! base16 */ +/* *.color0: #181818 */ +/* *.color1: #ab4642 */ +/* *.color2: #a1b56c */ +/* *.color3: #f7ca88 */ +/* *.color4: #7cafc2 */ +/* *.color5: #ba8baf */ +/* *.color6: #86c1b9 */ +/* *.color7: #d8d8d8 */ +/* *.color8: #585858 */ +/* *.color9: #ab4642 */ +/* *.color10: #a1b56c */ +/* *.color11: #f7ca88 */ +/* *.color12: #7cafc2 */ +/* *.color13: #ba8baf */ +/* *.color14: #86c1b9 */ +/* *.color15: #f8f8f8 */ + +/* !! solarized */ +/* *.color0: #073642 */ +/* *.color1: #dc322f */ +/* *.color2: #859900 */ +/* *.color3: #b58900 */ +/* *.color4: #268bd2 */ +/* *.color5: #d33682 */ +/* *.color6: #2aa198 */ +/* *.color7: #eee8d5 */ +/* *.color9: #cb4b16 */ +/* *.color8: #fdf6e3 */ +/* *.color10: #586e75 */ +/* *.color11: #657b83 */ +/* *.color12: #839496 */ +/* *.color13: #6c71c4 */ +/* *.color14: #93a1a1 */ +/* *.color15: #fdf6e3 */ + +/* !! xterm */ +/* *.color0: #000000 */ +/* *.color1: #cd0000 */ +/* *.color2: #00cd00 */ +/* *.color3: #cdcd00 */ +/* *.color4: #0000cd */ +/* *.color5: #cd00cd */ +/* *.color6: #00cdcd */ +/* *.color7: #e5e5e5 */ +/* *.color8: #4d4d4d */ +/* *.color9: #ff0000 */ +/* *.color10: #00ff00 */ +/* *.color11: #ffff00 */ +/* *.color12: #0000ff */ +/* *.color13: #ff00ff */ +/* *.color14: #00ffff */ +/* *.color15: #aabac8 */ diff --git a/st/st/.gitignore b/st/st/.gitignore new file mode 100644 index 0000000..18c21b0 --- /dev/null +++ b/st/st/.gitignore @@ -0,0 +1,5 @@ +st +st.o +x.o +pkg/ +*.pkg.tar.xz diff --git a/st/st/FAQ b/st/st/FAQ deleted file mode 100644 index 921c493..0000000 --- a/st/st/FAQ +++ /dev/null @@ -1,167 +0,0 @@ -## Why does st not handle utmp entries? - -Use the excellent tool of [utmp](http://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. - -## I get some weird glitches/visual bug on _random program_! - -Try launching it with a different TERM: $ TERM=xterm myapp. toe(1) will give -you a list of available terminals, but you’ll most likely switch between xterm, -st or st-256color. The default value for TERM can be changed in config.h -(TNAME). - -## How do I scroll back up? - -Using a terminal multiplexer. - -* `st -e tmux` using C-b [ -* `st -e screen` using C-a ESC - -## 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 -<http://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] http://st.suckless.org/patches/delkey - diff --git a/st/st/LEGACY b/st/st/LEGACY deleted file mode 100644 index bf28b1e..0000000 --- a/st/st/LEGACY +++ /dev/null @@ -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 - diff --git a/st/st/Makefile b/st/st/Makefile index 0b3cecd..a836907 100644 --- a/st/st/Makefile +++ b/st/st/Makefile @@ -22,7 +22,7 @@ config.h: $(CC) $(STCFLAGS) -c $< st.o: config.h st.h win.h -x.o: arg.h st.h win.h +x.o: arg.h config.h st.h win.h $(OBJ): config.h config.mk @@ -43,7 +43,9 @@ dist: clean install: st mkdir -p $(DESTDIR)$(PREFIX)/bin cp -f st $(DESTDIR)$(PREFIX)/bin + cp -f st-copyout $(DESTDIR)$(PREFIX)/bin chmod 755 $(DESTDIR)$(PREFIX)/bin/st + chmod 755 $(DESTDIR)$(PREFIX)/bin/st-copyout mkdir -p $(DESTDIR)$(MANPREFIX)/man1 sed "s/VERSION/$(VERSION)/g" < st.1 > $(DESTDIR)$(MANPREFIX)/man1/st.1 chmod 644 $(DESTDIR)$(MANPREFIX)/man1/st.1 @@ -52,6 +54,7 @@ install: st uninstall: rm -f $(DESTDIR)$(PREFIX)/bin/st + rm -f $(DESTDIR)$(PREFIX)/bin/st-copyout rm -f $(DESTDIR)$(MANPREFIX)/man1/st.1 .PHONY: all options clean dist install uninstall diff --git a/st/st/PKGBUILD b/st/st/PKGBUILD new file mode 100644 index 0000000..98a057d --- /dev/null +++ b/st/st/PKGBUILD @@ -0,0 +1,45 @@ +# Maintainer: + +pkgname=st-luke-git +_pkgname=st +pkgver=0.8.2.r1062.2087ab9 +pkgrel=1 +epoch=1 +pkgdesc="Luke's simple (suckless) terminal with vim-bindings, transparency, xresources, etc. " +url='https://github.com/LukeSmithxyz/st' +arch=('i686' 'x86_64') +license=('MIT') +options=('zipman') +depends=('libxft') +makedepends=('ncurses' 'libxext' 'git') +optdepends=('dmenu: feed urls to dmenu') +source=('git://github.com/LukeSmithxyz/st') +sha1sums=('SKIP') + +provides=("${_pkgname}") +conflicts=("${_pkgname}") + +pkgver() { + cd "${_pkgname}" + printf "%s.r%s.%s" "$(awk '/^VERSION =/ {print $3}' config.mk)" \ + "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)" +} + +prepare() { + cd $srcdir/${_pkgname} + # skip terminfo which conflicts with ncurses + sed -i '/tic /d' Makefile +} + +build() { + cd "${_pkgname}" + make X11INC=/usr/include/X11 X11LIB=/usr/lib/X11 +} + +package() { + cd "${_pkgname}" + make PREFIX=/usr DESTDIR="${pkgdir}" install + install -Dm644 LICENSE "${pkgdir}/usr/share/licenses/${pkgname}/LICENSE" + install -Dm644 README.md "${pkgdir}/usr/share/doc/${pkgname}/README.md" + install -Dm644 .Xdefaults "${pkgdir}/usr/share/doc/${pkgname}/Xdefaults.example" +} diff --git a/st/st/README.md b/st/st/README.md index 9a6c849..c7a1d9b 100644 --- a/st/st/README.md +++ b/st/st/README.md @@ -1,55 +1,76 @@ # Luke's build of st - the simple (suckless) terminal -Forked from [https://github.com/shiva/st](https://github.com/shiva/st) for simplicity's sake, which is the [suckless terminal (st)](https://st.suckless.org/) with some patches added: -+ transparency -+ copy to clipboard (alt-shift-c) -+ Solarized colors (light and dark toggleable) -+ vertcenter -+ scrollback with keyboard -+ scrollback with mouse -+ updated to latest version 0.8.1 +The [suckless terminal (st)](https://st.suckless.org/) with some additional features that make it literally the best terminal emulator ever: -## My own additions +## Unique features (using dmenu) -+ Default font is system "mono" at 14pt, meaning the font will match your system font. -+ Hold alt and press either ↑/↓ or the vim keys k/j to move up/down in the terminal. -+ Alt-u and Alt-d scroll back/foward in history a page at a time. -+ Alt-PageUp and Alt-PageDown scroll back/foward in history a page at a time. -+ Transparency with solarized colors by default. -+ Zoom in/out with Alt+Shift+k/j or u/d for larger intervals. ++ **follow urls** by pressing `alt-l` ++ **copy urls** in the same way with `alt-y` ++ **copy the output of commands** with `alt-o` -## Terminal-specific mappings +## Bindings for -(Additions before me.) ++ **scrollback** with `alt-↑/↓` or `alt-pageup/down` or `shift` while scrolling the mouse ++ OR **vim-bindings**: scroll up/down in history with `alt-k` and `alt-j`. Faster with `alt-u`/`alt-d`. ++ **zoom/change font size**: same bindings as above, but holding down shift as well. `alt-home` returns to default ++ **copy text** with `alt-c`, **paste** is `alt-v` or `shift-insert` -+ Scroll through history -- Shift+PageUp/PageDown or Shift+Mouse wheel -+ Increase/decrease font size -- Shift+Alt+PageUp/PageDown -+ Return to default font size -- Shift+Alt+Home -+ Paste -- Shift+Insert +## Pretty stuff + ++ Compatibility with `Xresources` and `pywal` for dynamic colors. The `Xdefaults` file shows a usage example. ++ Default [gruvbox](https://github.com/morhetz/gruvbox) colors otherwise. ++ Transparency/alpha, which is also adjustable from your `Xresources`. ++ Default font is system "mono" at 16pt, meaning the font will match your system font. + +## Other st patches + ++ Vertcenter ++ Scrollback ++ font2 ++ updated to latest version 0.8.2 ## Installation for newbs ``` -make +git clone https://github.com/LukeSmithxyz/st +cd st sudo make install ``` +Users of Arch-based distros can also install it from the AUR as [st-luke-git](https://aur.archlinux.org/packages/st-luke-git/). + Obviously, `make` is required to build. `fontconfig` is required for the default build, since it asks `fontconfig` for your system monospace font. It might be obvious, but `libX11` and `libXft` are required as well. Chances are, you have all of this installed already. -## Custom changes (`config.def.h` or `config.h`) +On OpenBSD, be sure to edit `config.mk` first and remove `-lrt` from the `$LIBS` before compiling. + +Be sure to have a composite manager (`xcompmgr`, `compton`, etc.) running if you want transparency. + +## How to configure dynamically with Xresources -By default, the terminal is transparent with a blackish background. There's a patch file `solarized-alpha-toggle.patch` which you can use to remove the transparency and give it a typical deep, dark blue solarized background. Just run: +For many key variables, this build of `st` will look for X settings set in either `~/.Xdefaults` or `~/.Xresources`. You must run `xrdb` on one of these files to load the settings. + +For example, you can define your desired fonts, transparency or colors: ``` -patch < solarized-alpha-toggle.patch +*.font: Liberation Mono:pixelsize=12:antialias=true:autohint=true; +*.alpha: 0.9 +*.color0: #111 +... ``` -Then, run `make` & `sudo make install` again to install the new build. You make reverse the solarized background by running the same command as above, but giving `patch` the `-R` option as well. +The `alpha` value (for transparency) goes from `0` (transparent) to `1` (opaque). + +### Colors + +To be clear about the color settings: + +- This build will use gruvbox colors by default and as a fallback. +- If there are Xresources colors defined, those will take priority. +- But if `wal` has run in your session, its colors will take priority. + +Note that when you run `wal`, it will negate the transparency of existing windows, but new windows will continue with the previously defined transparency. -## Explore `config.h` +## Contact -+ Change `colorname[]` array values (88 LOC), default colours are solarized. -+ Numbers of 0 - 15 are usual terminal colors. Change them to your liking. -+ Change `bg` to your desired terminal background color. -+ Change `fg` to your desired terminal foreground color. -+ Change `cursor` to your desired terminal cursor color. +- Luke Smith <luke@lukesmith.xyz> +- [https://lukesmith.xyz](https://lukesmith.xyz) diff --git a/st/st/TODO b/st/st/TODO deleted file mode 100644 index 5f74cd5..0000000 --- a/st/st/TODO +++ /dev/null @@ -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 - diff --git a/st/st/config.h b/st/st/config.h index 57cc5a6..22e9d21 100644 --- a/st/st/config.h +++ b/st/st/config.h @@ -5,7 +5,8 @@ * * font: see http://freedesktop.org/software/fontconfig/fontconfig-user.html */ -static char *font = "mono:pixelsize=18:antialias=true:autohint=true"; +static char *font = "mono:pixelsize=16:antialias=true:autohint=true"; +static char *font2[] = { "Inconsolata for Powerline:pixelsize=16:antialias=true:autohint=true" }; static int borderpx = 2; /* @@ -30,9 +31,9 @@ static float chscale = 1.0; /* * word delimiter string * - * More advanced example: " `'\"()[]{}" + * More advanced example: L" `'\"()[]{}" */ -char *worddelimiters = " "; +wchar_t *worddelimiters = L" "; /* selection timeouts (in milliseconds) */ static unsigned int doubleclicktimeout = 300; @@ -83,15 +84,42 @@ char *termname = "st-256color"; unsigned int tabspaces = 8; /* bg opacity */ -//unsigned int alpha = 0xe6; //230 -unsigned int alpha = 0xff; //205 +float alpha = 0.92; + +/* Terminal colors (16 first used in escape sequence) */ +static const char *colorname[] = { + "#282828", /* hard contrast: #1d2021 / soft contrast: #32302f */ + "#cc241d", + "#98971a", + "#d79921", + "#458588", + "#b16286", + "#689d6a", + "#a89984", + "#928374", + "#fb4934", + "#b8bb26", + "#fabd2f", + "#83a598", + "#d3869b", + "#8ec07c", + "#ebdbb2", + [255] = 0, + /* more colors can be added after 255 to use with DefaultXX */ + "#282828", /* 256 -> bg */ + "#ebdbb2", /* 257 -> fg */ + "#add8e6", /* 258 -> cursor */ +}; -#include "/home/kdam0/.cache/wal/colors-wal-st.h" /* * Default colors (colorname index) * foreground, background, cursor, reverse cursor */ +unsigned int defaultfg = 257; +unsigned int defaultbg = 256; +static unsigned int defaultcs = 258; +static unsigned int defaultrcs = 0; /* * Default shape of cursor @@ -123,6 +151,44 @@ static unsigned int mousebg = 0; static unsigned int defaultattr = 11; /* + * Xresources preferences to load at startup + */ +ResourcePref resources[] = { + { "font", STRING, &font }, + { "fontalt0", STRING, &font2[0] }, + { "color0", STRING, &colorname[0] }, + { "color1", STRING, &colorname[1] }, + { "color2", STRING, &colorname[2] }, + { "color3", STRING, &colorname[3] }, + { "color4", STRING, &colorname[4] }, + { "color5", STRING, &colorname[5] }, + { "color6", STRING, &colorname[6] }, + { "color7", STRING, &colorname[7] }, + { "color8", STRING, &colorname[8] }, + { "color9", STRING, &colorname[9] }, + { "color10", STRING, &colorname[10] }, + { "color11", STRING, &colorname[11] }, + { "color12", STRING, &colorname[12] }, + { "color13", STRING, &colorname[13] }, + { "color14", STRING, &colorname[14] }, + { "color15", STRING, &colorname[15] }, + { "background", STRING, &colorname[256] }, + { "foreground", STRING, &colorname[257] }, + { "cursorColor", STRING, &colorname[258] }, + { "termname", STRING, &termname }, + { "shell", STRING, &shell }, + { "xfps", INTEGER, &xfps }, + { "actionfps", INTEGER, &actionfps }, + { "blinktimeout", INTEGER, &blinktimeout }, + { "bellvolume", INTEGER, &bellvolume }, + { "tabspaces", INTEGER, &tabspaces }, + { "borderpx", INTEGER, &borderpx }, + { "cwscale", FLOAT, &cwscale }, + { "chscale", FLOAT, &chscale }, + { "alpha", FLOAT, &alpha }, +}; + +/* * Internal mouse shortcuts. * Beware that overloading Button1 will disable the selection. */ @@ -132,15 +198,29 @@ static MouseShortcut mshortcuts[] = { { Button5, XK_NO_MOD, "\005" }, }; +/* Internal keyboard shortcuts. */ +#define MODKEY Mod1Mask +#define TERMMOD (Mod1Mask|ShiftMask) + MouseKey mkeys[] = { /* button mask function argument */ { Button4, ShiftMask, kscrollup, {.i = 1} }, { Button5, ShiftMask, kscrolldown, {.i = 1} }, + { Button4, MODKEY, kscrollup, {.i = 1} }, + { Button5, MODKEY, kscrolldown, {.i = 1} }, + { Button4, TERMMOD, zoom, {.f = +1} }, + { Button5, TERMMOD, zoom, {.f = -1} }, }; -/* Internal keyboard shortcuts. */ -#define MODKEY Mod1Mask -#define TERMMOD (ControlMask|ShiftMask) +static char *openurlcmd[] = { "/bin/sh", "-c", + "sed 's/.*│//g' | tr -d '\n' | grep -aEo '(((http|https)://|www\\.)[a-zA-Z0-9.]*[:]?[a-zA-Z0-9./&%?#=_-]*)|((magnet:\\?xt=urn:btih:)[a-zA-Z0-9]*)'| uniq | sed 's/^www./http:\\/\\/www\\./g' | dmenu -i -p 'Follow which url?' -l 10 | xargs -r xdg-open", + "externalpipe", NULL }; + +static char *copyurlcmd[] = { "/bin/sh", "-c", + "sed 's/.*│//g' | tr -d '\n' | grep -aEo '(((http|https)://|www\\.)[a-zA-Z0-9.]*[:]?[a-zA-Z0-9./&%?#=_-]*)|((magnet:\\?xt=urn:btih:)[a-zA-Z0-9]*)' | uniq | sed 's/^www./http:\\/\\/www\\./g' | dmenu -i -p 'Copy which url?' -l 10 | tr -d '\n' | xclip -selection clipboard", + "externalpipe", NULL }; + +static char *copyoutput[] = { "/bin/sh", "-c", "st-copyout", "externalpipe", NULL }; static Shortcut shortcuts[] = { /* mask keysym function argument */ @@ -148,14 +228,14 @@ static Shortcut shortcuts[] = { { ControlMask, XK_Print, toggleprinter, {.i = 0} }, { ShiftMask, XK_Print, printscreen, {.i = 0} }, { XK_ANY_MOD, XK_Print, printsel, {.i = 0} }, - { MODKEY|ShiftMask, XK_Prior, zoom, {.f = +1} }, - { MODKEY|ShiftMask, XK_Next, zoom, {.f = -1} }, - { MODKEY|ShiftMask, XK_Home, zoomreset, {.f = 0} }, - { ShiftMask, XK_Insert, selpaste, {.i = 0} }, - { MODKEY|ShiftMask, XK_Insert, clippaste, {.i = 0} }, - { MODKEY|ShiftMask, XK_C, clipcopy, {.i = 0} }, - { MODKEY|ShiftMask, XK_V, clippaste, {.i = 0} }, - { TERMMOD, XK_Num_Lock, numlock, {.i = 0} }, + { TERMMOD, XK_Prior, zoom, {.f = +1} }, + { TERMMOD, XK_Next, zoom, {.f = -1} }, + { MODKEY, XK_Home, zoomreset, {.f = 0} }, + { ShiftMask, XK_Insert, clippaste, {.i = 0} }, + { MODKEY, XK_c, clipcopy, {.i = 0} }, + { MODKEY, XK_v, clippaste, {.i = 0} }, + { MODKEY, XK_p, selpaste, {.i = 0} }, + { MODKEY, XK_Num_Lock, numlock, {.i = 0} }, { MODKEY, XK_Control_L, iso14755, {.i = 0} }, { ShiftMask, XK_Page_Up, kscrollup, {.i = -1} }, { ShiftMask, XK_Page_Down, kscrolldown, {.i = -1} }, @@ -165,12 +245,17 @@ static Shortcut shortcuts[] = { { MODKEY, XK_j, kscrolldown, {.i = 1} }, { MODKEY, XK_Up, kscrollup, {.i = 1} }, { MODKEY, XK_Down, kscrolldown, {.i = 1} }, - { MODKEY, XK_u, kscrollup, {.i = 1} }, - { MODKEY, XK_d, kscrolldown, {.i = 1} }, - { MODKEY|ShiftMask, XK_K, zoom, {.f = +1} }, - { MODKEY|ShiftMask, XK_J, zoom, {.f = -1} }, - { MODKEY|ShiftMask, XK_U, zoom, {.f = +2} }, - { MODKEY|ShiftMask, XK_D, zoom, {.f = -2} }, + { MODKEY, XK_u, kscrollup, {.i = -1} }, + { MODKEY, XK_d, kscrolldown, {.i = -1} }, + { TERMMOD, XK_Up, zoom, {.f = +1} }, + { TERMMOD, XK_Down, zoom, {.f = -1} }, + { TERMMOD, XK_K, zoom, {.f = +1} }, + { TERMMOD, XK_J, zoom, {.f = -1} }, + { TERMMOD, XK_U, zoom, {.f = +2} }, + { TERMMOD, XK_D, zoom, {.f = -2} }, + { MODKEY, XK_l, externalpipe, {.v = openurlcmd } }, + { MODKEY, XK_y, externalpipe, {.v = copyurlcmd } }, + { MODKEY, XK_o, externalpipe, {.v = copyoutput } }, }; /* diff --git a/st/st/config.mk b/st/st/config.mk index 3b00d7e..eba98c3 100644 --- a/st/st/config.mk +++ b/st/st/config.mk @@ -1,28 +1,35 @@ # st version -VERSION = 0.8.1 +VERSION = 0.8.2 # Customize below to fit your system # paths -PREFIX = /usr/local +PREFIX ?= /usr/local MANPREFIX = $(PREFIX)/share/man X11INC = /usr/X11R6/include X11LIB = /usr/X11R6/lib +PKG_CONFIG = pkg-config + # includes and libs INCS = -I$(X11INC) \ - `pkg-config --cflags fontconfig` \ - `pkg-config --cflags freetype2` -LIBS = -L${X11LIB} -lm -lrt -lX11 -lutil -lXft -lXrender \ - `pkg-config --libs fontconfig` \ - `pkg-config --libs freetype2` + `$(PKG_CONFIG) --cflags fontconfig` \ + `$(PKG_CONFIG) --cflags freetype2` +LIBS = -L$(X11LIB) -lm -lrt -lX11 -lutil -lXft -lXrender \ + `$(PKG_CONFIG) --libs fontconfig` \ + `$(PKG_CONFIG) --libs freetype2` # flags -CPPFLAGS = -DVERSION=\"$(VERSION)\" -D_XOPEN_SOURCE=600 -STCFLAGS = $(INCS) $(CPPFLAGS) $(CFLAGS) +STCPPFLAGS = -DVERSION=\"$(VERSION)\" -D_XOPEN_SOURCE=600 +STCFLAGS = $(INCS) $(STCPPFLAGS) $(CPPFLAGS) $(CFLAGS) STLDFLAGS = $(LIBS) $(LDFLAGS) +# OpenBSD: +#CPPFLAGS = -DVERSION=\"$(VERSION)\" -D_XOPEN_SOURCE=600 -D_BSD_SOURCE +#LIBS = -L$(X11LIB) -lm -lX11 -lutil -lXft \ +# `pkg-config --libs fontconfig` \ +# `pkg-config --libs freetype2` + # compiler and linker # CC = c99 - diff --git a/st/st/solarized-alpha-toggle.patch b/st/st/solarized-alpha-toggle.patch deleted file mode 100644 index 901c392..0000000 --- a/st/st/solarized-alpha-toggle.patch +++ /dev/null @@ -1,20 +0,0 @@ ---- config.h 2018-05-01 14:09:36.752813283 -0700 -+++ config.sol.h 2018-05-01 14:10:20.132810913 -0700 -@@ -83,7 +83,7 @@ - unsigned int tabspaces = 8; - - /* bg opacity */ --unsigned int alpha = 0xcd; -+unsigned int alpha = 0xff; - - static const char *colorname[] = { - "#073642", /* 0: black */ -@@ -114,7 +114,7 @@ - * foreground, background, cursor, reverse cursor - */ - unsigned int defaultfg = 12; --unsigned int defaultbg = 256; -+unsigned int defaultbg = 0; - static unsigned int defaultcs = 14; - static unsigned int defaultrcs = 15; - Binary files differdiff --git a/st/st/st-copyout b/st/st/st-copyout new file mode 100755 index 0000000..8eafc58 --- /dev/null +++ b/st/st/st-copyout @@ -0,0 +1,12 @@ +#!/bin/sh +# Using external pipe with st, give a dmenu prompt of recent commands, +# allowing the user to copy the output of one. +# xclip required for this script. +# By Jaywalker and Luke +tmpfile=$(mktemp /tmp/st-cmd-output.XXXXXX) +trap 'rm "$tmpfile"' 0 1 15 +sed -n "w $tmpfile" +ps1="$(grep "\S" "$tmpfile" | tail -n 1 | sed 's/^\s*//' | cut -d' ' -f1)" +chosen="$(grep -F "$ps1" "$tmpfile" | sed '$ d' | tac | dmenu -p "Copy which command's output?" -i -l 10 | sed 's/[^^]/[&]/g; s/\^/\\^/g')" +eps1="$(echo "$ps1" | sed 's/[^^]/[&]/g; s/\^/\\^/g')" +awk "/^$chosen$/{p=1;print;next} p&&/$eps1/{p=0};p" "$tmpfile" | xclip -selection clipboard @@ -1,6 +1,6 @@ .TH ST 1 st\-VERSION .SH NAME -st \- simple terminal +st \- simple terminal (Luke Smith (https://lukesmith.xyz)'s build) .SH SYNOPSIS .B st .RB [ \-aiv ] @@ -125,6 +125,38 @@ and all the remaining arguments are used as a command even without it. .SH SHORTCUTS .TP +.B Alt-j/k or Alt-Up/Down or Alt-Mouse Wheel +Scroll up/down one line at a time. +.TP +.B Alt-u/d or Alt-Page Up/Page Down +Scroll up/down one screen at a time. +.TP +.B Alt-Shift-k/j or Alt-Shift-Page Up/Page Down or Alt-Shift-Mouse Wheel +Increase or decrease font size. +.TP +.B Alt-Home +Reset to default font size. +.TP +.B Shift-Insert or Alt-v +Paste from clipboard. +.TP +.B Alt-c +Copy to clipboard. +.TP +.B Alt-p +Paste/input primary selection. +.TP +.B Alt-l +Show dmenu menu of all URLs on screen and choose one to open. +.TP +.B Alt-y +Show dmenu menu of all URLs on screen and choose one to copy. +.TP +.B Alt-o +Show dmenu menu of all recently run commands and copy the output of the chosen command to the clipboard. +.I xclip +required. +.TP .B Break Send a break in the serial line. Break key is obtained in PC keyboards @@ -142,25 +174,7 @@ Print the full screen to the Print the selection to the .I iofile. .TP -.B Ctrl-Shift-Page Up -Increase font size. -.TP -.B Ctrl-Shift-Page Down -Decrease font size. -.TP -.B Ctrl-Shift-Home -Reset to default font size. -.TP -.B Ctrl-Shift-y -Paste from primary selection (middle mouse button). -.TP -.B Ctrl-Shift-c -Copy the selected text to the clipboard selection. -.TP -.B Ctrl-Shift-v -Paste from the clipboard selection. -.TP -.B Ctrl-Shift-i +.B Alt-Ctrl Launch dmenu to enter a unicode codepoint and send the corresponding glyph to st. .SH CUSTOMIZATION @@ -35,6 +35,7 @@ #define ESC_ARG_SIZ 16 #define STR_BUF_SIZ ESC_BUF_SIZ #define STR_ARG_SIZ ESC_ARG_SIZ +#define HISTSIZE 2000 /* macros */ #define IS_SET(flag) ((term.mode & (flag)) != 0) @@ -42,7 +43,12 @@ #define ISCONTROLC0(c) (BETWEEN(c, 0, 0x1f) || (c) == '\177') #define ISCONTROLC1(c) (BETWEEN(c, 0x80, 0x9f)) #define ISCONTROL(c) (ISCONTROLC0(c) || ISCONTROLC1(c)) -#define ISDELIM(u) (utf8strchr(worddelimiters, u) != NULL) +#define ISDELIM(u) (u && wcschr(worddelimiters, u)) +#define TLINE(y) ((y) < term.scr ? term.hist[((y) + term.histi - \ + term.scr + HISTSIZE + 1) % HISTSIZE] : \ + term.line[(y) - term.scr]) + +#define TLINE_HIST(y) ((y) <= HISTSIZE-term.row+2 ? term.hist[(y)] : term.line[(y-HISTSIZE+term.row-3)]) /* constants */ #define ISO14755CMD "dmenu -w \"$WINDOWID\" -p codepoint: </dev/null" @@ -217,7 +223,6 @@ static void selsnap(int *, int *, int); static size_t utf8decode(const char *, Rune *, size_t); static Rune utf8decodebyte(char, size_t *); static char utf8encodebyte(Rune, size_t); -static char *utf8strchr(char *, Rune); static size_t utf8validate(Rune *, size_t); static char *base64dec(const char *); @@ -259,10 +264,10 @@ xwrite(int fd, const char *s, size_t len) void * xmalloc(size_t len) { - void *p = malloc(len); + void *p; - if (!p) - die("Out of memory\n"); + if (!(p = malloc(len))) + die("malloc: %s\n", strerror(errno)); return p; } @@ -271,7 +276,7 @@ void * xrealloc(void *p, size_t len) { if ((p = realloc(p, len)) == NULL) - die("Out of memory\n"); + die("realloc: %s\n", strerror(errno)); return p; } @@ -280,7 +285,7 @@ char * xstrdup(char *s) { if ((s = strdup(s)) == NULL) - die("Out of memory\n"); + die("strdup: %s\n", strerror(errno)); return s; } @@ -344,23 +349,6 @@ utf8encodebyte(Rune u, size_t i) return utfbyte[i] | (u & ~utfmask[i]); } -char * -utf8strchr(char *s, Rune u) -{ - Rune r; - size_t i, j, len; - - len = strlen(s); - for (i = 0, j = 0; i < len; i += j) { - if (!(j = utf8decode(&s[i], &r, len - i))) - break; - if (r == u) - return &(s[i]); - } - - return NULL; -} - size_t utf8validate(Rune *u, size_t i) { @@ -443,12 +431,27 @@ tlinelen(int y) return i; } +int +tlinehistlen(int y) +{ + int i = term.col; + + if (TLINE_HIST(y)[i - 1].mode & ATTR_WRAP) + return i; + + while (i > 0 && TLINE_HIST(y)[i - 1].u == ' ') + --i; + + return i; +} + void selstart(int col, int row, int snap) { selclear(); sel.mode = SEL_EMPTY; sel.type = SEL_REGULAR; + sel.alt = IS_SET(MODE_ALTSCREEN); sel.snap = snap; sel.oe.x = sel.ob.x = col; sel.oe.y = sel.ob.y = row; @@ -477,13 +480,12 @@ selextend(int col, int row, int type, int done) oldsey = sel.ne.y; oldtype = sel.type; - sel.alt = IS_SET(MODE_ALTSCREEN); sel.oe.x = col; sel.oe.y = row; selnormalize(); sel.type = type; - if (oldey != sel.oe.y || oldex != sel.oe.x || oldtype != sel.type) + if (oldey != sel.oe.y || oldex != sel.oe.x || oldtype != sel.type || sel.mode == SEL_EMPTY) tsetdirt(MIN(sel.nb.y, oldsby), MAX(sel.ne.y, oldsey)); sel.mode = done ? SEL_IDLE : SEL_READY; @@ -690,7 +692,7 @@ execsh(char *cmd, char **args) errno = 0; if ((pw = getpwuid(getuid())) == NULL) { if (errno) - die("getpwuid:%s\n", strerror(errno)); + die("getpwuid: %s\n", strerror(errno)); else die("who are you?\n"); } @@ -733,13 +735,15 @@ sigchld(int a) pid_t p; if ((p = waitpid(pid, &stat, WNOHANG)) < 0) - die("Waiting for pid %hd failed: %s\n", pid, strerror(errno)); + die("waiting for pid %hd failed: %s\n", pid, strerror(errno)); if (pid != p) return; - if (!WIFEXITED(stat) || WEXITSTATUS(stat)) - die("child finished with error '%d'\n", stat); + if (WIFEXITED(stat) && WEXITSTATUS(stat)) + die("child exited with status %d\n", WEXITSTATUS(stat)); + else if (WIFSIGNALED(stat)) + die("child terminated due to signal %d\n", WTERMSIG(stat)); exit(0); } @@ -784,7 +788,8 @@ ttynew(char *line, char *cmd, char *out, char **args) if (line) { if ((cmdfd = open(line, O_RDWR)) < 0) - die("open line failed: %s\n", strerror(errno)); + die("open line '%s' failed: %s\n", + line, strerror(errno)); dup2(cmdfd, 0); stty(args); return cmdfd; @@ -796,7 +801,7 @@ ttynew(char *line, char *cmd, char *out, char **args) switch (pid = fork()) { case -1: - die("fork failed\n"); + die("fork failed: %s\n", strerror(errno)); break; case 0: close(iofd); @@ -808,9 +813,17 @@ ttynew(char *line, char *cmd, char *out, char **args) die("ioctl TIOCSCTTY failed: %s\n", strerror(errno)); close(s); close(m); +#ifdef __OpenBSD__ + if (pledge("stdio getpw proc exec", NULL) == -1) + die("pledge\n"); +#endif execsh(cmd, args); break; default: +#ifdef __OpenBSD__ + if (pledge("stdio rpath tty proc", NULL) == -1) + die("pledge\n"); +#endif close(s); cmdfd = m; signal(SIGCHLD, sigchld); @@ -829,7 +842,7 @@ ttyread(void) /* append read bytes to unprocessed bytes */ if ((ret = read(cmdfd, buf+buflen, LEN(buf)-buflen)) < 0) - die("Couldn't read from shell: %s\n", strerror(errno)); + die("couldn't read from shell: %s\n", strerror(errno)); buflen += ret; written = twrite(buf, buflen, 0); @@ -838,9 +851,6 @@ ttyread(void) if (buflen > 0) memmove(buf, buf + written, buflen); - if (term.scr > 0 && term.scr < HISTSIZE-1) - term.scr++; - return ret; } @@ -1094,7 +1104,6 @@ kscrollup(const Arg* a) } } - void tscrolldown(int orig, int n, int copyhist) { @@ -1137,6 +1146,9 @@ tscrollup(int orig, int n, int copyhist) term.line[orig] = temp; } + if (term.scr > 0 && term.scr < HISTSIZE) + term.scr = MIN(term.scr + n, HISTSIZE-1); + tclearregion(0, orig, term.col-1, orig+n-1); tsetdirt(orig+n, term.bot); @@ -1504,7 +1516,8 @@ tsetattr(int *attr, int l) } else { fprintf(stderr, "erresc(default): gfx attr %d unknown\n", - attr[i]), csidump(); + attr[i]); + csidump(); } break; } @@ -1624,6 +1637,7 @@ tsetmode(int priv, int set, int *args, int narg) case 1015: /* urxvt mangled mouse mode; incompatible and can be mistaken for other control codes. */ + break; default: fprintf(stderr, "erresc: unknown private set/reset mode %d\n", @@ -1895,7 +1909,7 @@ csireset(void) void strhandle(void) { - char *p = NULL; + char *p = NULL, *dec; int j, narg, par; term.esc &= ~(ESC_STR_END|ESC_STR); @@ -1913,8 +1927,6 @@ strhandle(void) return; case 52: if (narg > 2) { - char *dec; - dec = base64dec(strescseq.args[2]); if (dec) { xsetsel(dec); @@ -1932,7 +1944,10 @@ strhandle(void) case 104: /* color reset, here p = NULL */ j = (narg > 1) ? atoi(strescseq.args[1]) : -1; if (xsetcolorname(j, p)) { - fprintf(stderr, "erresc: invalid color %s\n", p); + if (par == 104 && narg <= 1) + return; /* color reset without parameter */ + fprintf(stderr, "erresc: invalid color j=%d, p=%s\n", + j, p ? p : "(null)"); } else { /* * TODO if defaultbg color is changed, borders @@ -2030,6 +2045,62 @@ tprinter(char *s, size_t len) } void +externalpipe(const Arg *arg) +{ + int to[2]; + char buf[UTF_SIZ]; + void (*oldsigpipe)(int); + Glyph *bp, *end; + int lastpos, n, newline; + + if (pipe(to) == -1) + return; + + switch (fork()) { + case -1: + close(to[0]); + close(to[1]); + return; + case 0: + dup2(to[0], STDIN_FILENO); + close(to[0]); + close(to[1]); + execvp(((char **)arg->v)[0], (char **)arg->v); + fprintf(stderr, "st: execvp %s\n", ((char **)arg->v)[0]); + perror("failed"); + exit(0); + } + + close(to[0]); + /* ignore sigpipe for now, in case child exists early */ + oldsigpipe = signal(SIGPIPE, SIG_IGN); + newline = 0; + /* modify externalpipe patch to pipe history too */ + for (n = 0; n <= HISTSIZE + 2; n++) { + bp = TLINE_HIST(n); + lastpos = MIN(tlinehistlen(n) +1, term.col) - 1; + if (lastpos < 0) + break; + if (lastpos == 0) + continue; + end = &bp[lastpos + 1]; + for (; bp < end; ++bp) + if (xwrite(to[1], buf, utf8encode(bp->u, buf)) < 0) + break; + if ((newline = TLINE_HIST(n)[lastpos].mode & ATTR_WRAP)) + continue; + if (xwrite(to[1], "\n", 1) < 0) + break; + newline = 0; + } + if (newline) + (void)xwrite(to[1], "\n", 1); + close(to[1]); + /* restore */ + signal(SIGPIPE, oldsigpipe); +} + +void iso14755(const Arg *arg) { FILE *p; @@ -2335,7 +2406,7 @@ eschandle(uchar ascii) case 'Z': /* DECID -- Identify Terminal */ ttywrite(vtiden, strlen(vtiden), 0); break; - case 'c': /* RIS -- Reset to inital state */ + case 'c': /* RIS -- Reset to initial state */ treset(); resettitle(); xloadcols(); @@ -2406,7 +2477,6 @@ tputc(Rune u) goto check_control_code; } - if (IS_SET(MODE_SIXEL)) { /* TODO: implement sixel mode */ return; @@ -2591,7 +2661,7 @@ tresize(int col, int row) } } - /* resize each r w to new width, zero-pad if needed */ + /* resize each row to new width, zero-pad if needed */ for (i = 0; i < minrow; i++) { term.line[i] = xrealloc(term.line[i], col * sizeof(Glyph)); term.alt[i] = xrealloc(term.alt[i], col * sizeof(Glyph)); @@ -2669,12 +2739,12 @@ draw(void) cx--; drawregion(0, 0, term.col, term.row); - if (term.scr == 0) { + if (term.scr == 0) xdrawcursor(cx, term.c.y, term.line[term.c.y][cx], term.ocx, term.ocy, term.line[term.ocy][term.ocx]); - } term.ocx = cx, term.ocy = term.c.y; xfinishdraw(); + xximspot(term.ocx, term.ocy); } void @@ -3,9 +3,6 @@ #include <stdint.h> #include <sys/types.h> -/* Arbitrary size */ -#define HISTSIZE 2000 - /* macros */ #define MIN(a, b) ((a) < (b) ? (a) : (b)) #define MAX(a, b) ((a) < (b) ? (b) : (a)) @@ -22,8 +19,6 @@ #define TRUECOLOR(r,g,b) (1 << 24 | (r) << 16 | (g) << 8 | (b)) #define IS_TRUECOL(x) (1 << 24 & (x)) -#define TLINE(y) ((y) < term.scr ? term.hist[((y) + term.histi - term.scr \ - + HISTSIZE + 1) % HISTSIZE] : term.line[(y) - term.scr]) enum glyph_attribute { ATTR_NULL = 0, @@ -92,7 +87,10 @@ void die(const char *, ...); void redraw(void); void draw(void); +void externalpipe(const Arg *); void iso14755(const Arg *); +void kscrolldown(const Arg *); +void kscrollup(const Arg *); void printscreen(const Arg *); void printsel(const Arg *); void sendbreak(const Arg *); @@ -123,18 +121,15 @@ void *xmalloc(size_t); void *xrealloc(void *, size_t); char *xstrdup(char *); -void kscrolldown(const Arg *); -void kscrollup(const Arg *); - /* config.h globals */ extern char *utmp; extern char *stty_args; extern char *vtiden; -extern char *worddelimiters; +extern wchar_t *worddelimiters; extern int allowaltscreen; extern char *termname; extern unsigned int tabspaces; -extern unsigned int alpha; extern unsigned int defaultfg; extern unsigned int defaultbg; +extern float alpha; extern MouseKey mkeys[]; diff --git a/st/st/win.h b/st/st/win.h index d277477..a6ef1b9 100644 --- a/st/st/win.h +++ b/st/st/win.h @@ -23,10 +23,6 @@ enum win_mode { |MODE_MOUSEMANY, }; -/* alpha */ -#define OPAQUE 0Xff -#define USE_ARGB (alpha != OPAQUE && opt_embed == NULL) - void xbell(void); void xclipcopy(void); void xdrawcursor(int, int, Glyph, int, int, Glyph); @@ -40,3 +36,4 @@ void xsetmode(int, unsigned int); void xsetpointermotion(int); void xsetsel(char *); int xstartdraw(void); +void xximspot(int, int); @@ -14,6 +14,7 @@ #include <X11/keysym.h> #include <X11/Xft/Xft.h> #include <X11/XKBlib.h> +#include <X11/Xresource.h> static char *argv0; #include "arg.h" @@ -43,6 +44,19 @@ typedef struct { signed char appcursor; /* application cursor */ } Key; +/* Xresources preferences */ +enum resource_type { + STRING = 0, + INTEGER = 1, + FLOAT = 2 +}; + +typedef struct { + char *name; + enum resource_type type; + void *dst; +} ResourcePref; + /* X modifiers */ #define XK_ANY_MOD UINT_MAX #define XK_NO_MOD 0 @@ -78,6 +92,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 cyo; /* char y offset */ @@ -141,6 +156,9 @@ 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); +static void ximopen(Display *); +static void ximinstantiate(Display *, XPointer, XPointer); +static void ximdestroy(XIM, XPointer, XPointer); static void xinit(int, int); static void cresize(int, int); static void xresize(int, int); @@ -148,6 +166,8 @@ static void xhints(void); static int xloadcolor(int, const char *, Color *); static int xloadfont(Font *, FcPattern *); static void xloadfonts(char *, double); +static int xloadsparefont(FcPattern *, int); +static void xloadsparefonts(void); static void xunloadfont(Font *); static void xunloadfonts(void); static void xsetenv(void); @@ -225,12 +245,14 @@ typedef struct { } Fontcache; /* Fontcache is an array now. A new font will be appended to the array. */ -static Fontcache frc[16]; +static Fontcache *frc = NULL; static int frclen = 0; +static int frccap = 0; static char *usedfont = NULL; static double usedfontsize = 0; static double defaultfontsize = 0; +static char *opt_alpha = NULL; static char *opt_class = NULL; static char **opt_cmd = NULL; static char *opt_embed = NULL; @@ -294,6 +316,7 @@ zoomabs(const Arg *arg) { xunloadfonts(); xloadfonts(usedfont, arg->f); + xloadsparefonts(); cresize(0, 0); redraw(); xhints(); @@ -313,7 +336,7 @@ zoomreset(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; } @@ -321,7 +344,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; } @@ -639,7 +662,7 @@ setsel(char *str, Time t) if (XGetSelectionOwner(xw.dpy, XA_PRIMARY) != xw.win) selclear(); - xclipcopy(); + clipcopy(NULL); } void @@ -657,7 +680,7 @@ brelease(XEvent *e) } if (e->xbutton.button == Button2) - selpaste(NULL); + clippaste(NULL); else if (e->xbutton.button == Button1) mousesel(e, 1); } @@ -685,6 +708,11 @@ cresize(int width, int height) col = (win.w - 2 * borderpx) / win.cw; row = (win.h - 2 * borderpx) / win.ch; + 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); @@ -694,8 +722,8 @@ cresize(int width, int height) void xresize(int col, int row) { - win.tw = MAX(1, col * win.cw); - win.th = MAX(1, row * win.ch); + 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, @@ -744,28 +772,34 @@ xloadcols(void) static int loaded; Color *cp; - dc.collen = MAX(LEN(colorname), 256); - dc.col = xmalloc(dc.collen * sizeof(Color)); - if (loaded) { for (cp = dc.col; cp < &dc.col[dc.collen]; ++cp) XftColorFree(xw.dpy, xw.vis, xw.cmap, cp); + } else { + dc.collen = MAX(LEN(colorname), 256); + dc.col = xmalloc(dc.collen * sizeof(Color)); } for (i = 0; i < dc.collen; i++) if (!xloadcolor(i, NULL, &dc.col[i])) { if (colorname[i]) - die("Could not allocate color '%s'\n", colorname[i]); + die("could not allocate color '%s'\n", colorname[i]); else - die("Could not allocate color %d\n", i); + die("could not allocate color %d\n", i); } /* set alpha value of bg color */ - if (USE_ARGB) { - dc.col[defaultbg].color.alpha = (0xffff * alpha) / OPAQUE; - dc.col[defaultbg].pixel &= 0x00111111; - dc.col[defaultbg].pixel |= alpha << 24; - } + if (opt_alpha) + alpha = strtof(opt_alpha, NULL); + dc.col[defaultbg].color.alpha = (unsigned short)(0xffff * alpha); + dc.col[defaultbg].color.red = + ((unsigned short)(dc.col[defaultbg].color.red * alpha)) & 0xff00; + dc.col[defaultbg].color.green = + ((unsigned short)(dc.col[defaultbg].color.green * alpha)) & 0xff00; + dc.col[defaultbg].color.blue = + ((unsigned short)(dc.col[defaultbg].color.blue * alpha)) & 0xff00; + dc.col[defaultbg].pixel &= 0x00FFFFFF; + dc.col[defaultbg].pixel |= (unsigned char)(0xff * alpha) << 24; loaded = 1; } @@ -777,7 +811,6 @@ xsetcolorname(int x, const char *name) if (!BETWEEN(x, 0, dc.collen)) return 1; - if (!xloadcolor(x, name, &ncolor)) return 1; @@ -787,17 +820,6 @@ xsetcolorname(int x, const char *name) return 0; } -void -xtermclear(int col1, int row1, int col2, int row2) -{ - XftDrawRect(xw.draw, - &dc.col[IS_SET(MODE_REVERSE) ? defaultfg : defaultbg], - borderpx + col1 * win.cw, - borderpx + row1 * win.ch, - (col2-col1+1) * win.cw, - (row2-row1+1) * win.ch); -} - /* * Absolute coordinates. */ @@ -812,22 +834,24 @@ xclear(int x1, int y1, int x2, int y2) void xhints(void) { - XClassHint class = {opt_name ? opt_name : termname, - opt_class ? opt_class : termname}; + XClassHint class = {opt_name ? opt_name : "st", + opt_class ? opt_class : "St"}; XWMHints wm = {.flags = InputHint, .input = 1}; XSizeHints *sizeh; sizeh = XAllocSizeHints(); - sizeh->flags = PSize | PResizeInc | PBaseSize; + 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; + sizeh->min_width = win.cw + 2 * borderpx; if (xw.isfixed) { - sizeh->flags |= PMaxSize | PMinSize; + sizeh->flags |= PMaxSize; sizeh->min_width = sizeh->max_width = win.w; sizeh->min_height = sizeh->max_height = win.h; } @@ -900,7 +924,7 @@ xloadfont(Font *f, FcPattern *pattern) if ((XftPatternGetInteger(f->match->pattern, "slant", 0, &haveattr) != XftResultMatch) || haveattr < wantattr) { f->badslant = 1; - fputs("st: font slant does not match\n", stderr); + fputs("font slant does not match\n", stderr); } } @@ -909,7 +933,7 @@ xloadfont(Font *f, FcPattern *pattern) if ((XftPatternGetInteger(f->match->pattern, "weight", 0, &haveattr) != XftResultMatch) || haveattr != wantattr) { f->badweight = 1; - fputs("st: font weight does not match\n", stderr); + fputs("font weight does not match\n", stderr); } } @@ -937,14 +961,13 @@ xloadfonts(char *fontstr, double fontsize) FcPattern *pattern; double fontval; - if (fontstr[0] == '-') { + if (fontstr[0] == '-') pattern = XftXlfdParse(fontstr, False, False); - } else { + else pattern = FcNameParse((FcChar8 *)fontstr); - } if (!pattern) - die("st: can't open font %s\n", fontstr); + die("can't open font %s\n", fontstr); if (fontsize > 1) { FcPatternDel(pattern, FC_PIXEL_SIZE); @@ -970,7 +993,7 @@ xloadfonts(char *fontstr, double fontsize) } if (xloadfont(&dc.font, pattern)) - die("st: can't open font %s\n", fontstr); + die("can't open font %s\n", fontstr); if (usedfontsize < 0) { FcPatternGetDouble(dc.font.match->pattern, @@ -988,21 +1011,116 @@ xloadfonts(char *fontstr, double fontsize) FcPatternDel(pattern, FC_SLANT); FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ITALIC); if (xloadfont(&dc.ifont, pattern)) - die("st: can't open font %s\n", fontstr); + die("can't open font %s\n", fontstr); FcPatternDel(pattern, FC_WEIGHT); FcPatternAddInteger(pattern, FC_WEIGHT, FC_WEIGHT_BOLD); if (xloadfont(&dc.ibfont, pattern)) - die("st: can't open font %s\n", fontstr); + die("can't open font %s\n", fontstr); FcPatternDel(pattern, FC_SLANT); FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ROMAN); if (xloadfont(&dc.bfont, pattern)) - die("st: can't open font %s\n", fontstr); + die("can't open font %s\n", fontstr); FcPatternDestroy(pattern); } +int +xloadsparefont(FcPattern *pattern, int flags) +{ + FcPattern *match; + FcResult result; + + match = FcFontMatch(NULL, pattern, &result); + if (!match) { + return 1; + } + + if (!(frc[frclen].font = XftFontOpenPattern(xw.dpy, match))) { + FcPatternDestroy(match); + return 1; + } + + frc[frclen].flags = flags; + /* Believe U+0000 glyph will present in each default font */ + frc[frclen].unicodep = 0; + frclen++; + + return 0; +} + +void +xloadsparefonts(void) +{ + FcPattern *pattern; + double sizeshift, fontval; + int fc; + char **fp; + + if (frclen != 0) + die("can't embed spare fonts. cache isn't empty"); + + /* Calculate count of spare fonts */ + fc = sizeof(font2) / sizeof(*font2); + if (fc == 0) + return; + + /* Allocate memory for cache entries. */ + if (frccap < 4 * fc) { + frccap += 4 * fc - frccap; + frc = xrealloc(frc, frccap * sizeof(Fontcache)); + } + + for (fp = font2; fp - font2 < fc; ++fp) { + + if (**fp == '-') + pattern = XftXlfdParse(*fp, False, False); + else + pattern = FcNameParse((FcChar8 *)*fp); + + if (!pattern) + die("can't open spare font %s\n", *fp); + + if (defaultfontsize > 0) { + sizeshift = usedfontsize - defaultfontsize; + if (sizeshift != 0 && + FcPatternGetDouble(pattern, FC_PIXEL_SIZE, 0, &fontval) == + FcResultMatch) { + fontval += sizeshift; + FcPatternDel(pattern, FC_PIXEL_SIZE); + FcPatternDel(pattern, FC_SIZE); + FcPatternAddDouble(pattern, FC_PIXEL_SIZE, fontval); + } + } + + FcPatternAddBool(pattern, FC_SCALABLE, 1); + + FcConfigSubstitute(NULL, pattern, FcMatchPattern); + XftDefaultSubstitute(xw.dpy, xw.scr, pattern); + + if (xloadsparefont(pattern, FRC_NORMAL)) + die("can't open spare font %s\n", *fp); + + FcPatternDel(pattern, FC_SLANT); + FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ITALIC); + if (xloadsparefont(pattern, FRC_ITALIC)) + die("can't open spare font %s\n", *fp); + + FcPatternDel(pattern, FC_WEIGHT); + FcPatternAddInteger(pattern, FC_WEIGHT, FC_WEIGHT_BOLD); + if (xloadsparefont(pattern, FRC_ITALICBOLD)) + die("can't open spare font %s\n", *fp); + + FcPatternDel(pattern, FC_SLANT); + FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ROMAN); + if (xloadsparefont(pattern, FRC_BOLD)) + die("can't open spare font %s\n", *fp); + + FcPatternDestroy(pattern); + } +} + void xunloadfont(Font *f) { @@ -1026,6 +1144,43 @@ xunloadfonts(void) } void +ximopen(Display *dpy) +{ + XIMCallback destroy = { .client_data = NULL, .callback = ximdestroy }; + + if ((xw.xim = XOpenIM(xw.dpy, NULL, NULL, NULL)) == NULL) { + XSetLocaleModifiers("@im=local"); + if ((xw.xim = XOpenIM(xw.dpy, NULL, NULL, NULL)) == NULL) { + XSetLocaleModifiers("@im="); + if ((xw.xim = XOpenIM(xw.dpy, NULL, NULL, NULL)) == NULL) + die("XOpenIM failed. Could not open input device.\n"); + } + } + if (XSetIMValues(xw.xim, XNDestroyCallback, &destroy, NULL) != NULL) + die("XSetIMValues failed. Could not set input method value.\n"); + xw.xic = XCreateIC(xw.xim, XNInputStyle, XIMPreeditNothing | XIMStatusNothing, + XNClientWindow, xw.win, XNFocusWindow, xw.win, NULL); + if (xw.xic == NULL) + die("XCreateIC failed. Could not obtain input method.\n"); +} + +void +ximinstantiate(Display *dpy, XPointer client, XPointer call) +{ + ximopen(dpy); + XUnregisterIMInstantiateCallback(xw.dpy, NULL, NULL, NULL, + ximinstantiate, NULL); +} + +void +ximdestroy(XIM xim, XPointer client, XPointer call) +{ + xw.xim = NULL; + XRegisterIMInstantiateCallback(xw.dpy, NULL, NULL, NULL, + ximinstantiate, NULL); +} + +void xinit(int cols, int rows) { XGCValues gcvalues; @@ -1033,63 +1188,39 @@ xinit(int cols, int rows) Window parent; pid_t thispid = getpid(); XColor xmousefg, xmousebg; + XWindowAttributes attr; + XVisualInfo vis; - if (!(xw.dpy = XOpenDisplay(NULL))) - die("Can't open display\n"); xw.scr = XDefaultScreen(xw.dpy); - xw.depth = (USE_ARGB) ? 32: XDefaultDepth(xw.dpy, xw.scr); - if (!USE_ARGB) - xw.vis = XDefaultVisual(xw.dpy, xw.scr); - else { - XVisualInfo *vis; - XRenderPictFormat *fmt; - int nvi; - int i; - - XVisualInfo tpl = { - .screen = xw.scr, - .depth = 32, - .class = TrueColor - }; - - vis = XGetVisualInfo(xw.dpy, - VisualScreenMask | VisualDepthMask | VisualClassMask, - &tpl, &nvi); - xw.vis = NULL; - for (i = 0; i < nvi; i++) { - fmt = XRenderFindVisualFormat(xw.dpy, vis[i].visual); - if (fmt->type == PictTypeDirect && fmt->direct.alphaMask) { - xw.vis = vis[i].visual; - break; - } - } - - XFree(vis); - if (!xw.vis) { - fprintf(stderr, "Couldn't find ARGB visual.\n"); - exit(1); - } + if (!(opt_embed && (parent = strtol(opt_embed, NULL, 0)))) { + parent = XRootWindow(xw.dpy, xw.scr); + xw.depth = 32; + } else { + XGetWindowAttributes(xw.dpy, parent, &attr); + xw.depth = attr.depth; } + XMatchVisualInfo(xw.dpy, xw.scr, xw.depth, TrueColor, &vis); + xw.vis = vis.visual; + /* font */ if (!FcInit()) - die("Could not init fontconfig.\n"); + die("could not init fontconfig.\n"); usedfont = (opt_font == NULL)? font : opt_font; xloadfonts(usedfont, 0); + /* spare fonts */ + xloadsparefonts(); + /* colors */ - if (!USE_ARGB) - xw.cmap = XDefaultColormap(xw.dpy, xw.scr); - else - xw.cmap = XCreateColormap(xw.dpy, XRootWindow(xw.dpy, xw.scr), - xw.vis, None); + xw.cmap = XCreateColormap(xw.dpy, parent, xw.vis, None); xloadcols(); /* adjust fixed window geometry */ - win.w = 2 * borderpx + cols * win.cw; - win.h = 2 * borderpx + rows * win.ch; + win.w = 2 * win.hborderpx + cols * win.cw; + win.h = 2 * win.vborderpx + rows * win.ch; if (xw.gm & XNegative) xw.l += DisplayWidth(xw.dpy, xw.scr) - win.w - 2; if (xw.gm & YNegative) @@ -1099,13 +1230,11 @@ xinit(int cols, int rows) xw.attrs.background_pixel = dc.col[defaultbg].pixel; xw.attrs.border_pixel = dc.col[defaultbg].pixel; xw.attrs.bit_gravity = NorthWestGravity; - xw.attrs.event_mask = FocusChangeMask | KeyPressMask + xw.attrs.event_mask = FocusChangeMask | KeyPressMask | KeyReleaseMask | ExposureMask | VisibilityChangeMask | StructureNotifyMask | ButtonMotionMask | ButtonPressMask | ButtonReleaseMask; xw.attrs.colormap = xw.cmap; - if (!(opt_embed && (parent = strtol(opt_embed, NULL, 0)))) - parent = XRootWindow(xw.dpy, xw.scr); xw.win = XCreateWindow(xw.dpy, parent, xw.l, xw.t, win.w, win.h, 0, xw.depth, InputOutput, xw.vis, CWBackPixel | CWBorderPixel | CWBitGravity @@ -1114,8 +1243,7 @@ xinit(int cols, int rows) memset(&gcvalues, 0, sizeof(gcvalues)); gcvalues.graphics_exposures = False; xw.buf = XCreatePixmap(xw.dpy, xw.win, win.w, win.h, xw.depth); - dc.gc = XCreateGC(xw.dpy, (USE_ARGB) ? xw.buf: parent, - GCGraphicsExposures, &gcvalues); + dc.gc = XCreateGC(xw.dpy, xw.buf, GCGraphicsExposures, &gcvalues); XSetForeground(xw.dpy, dc.gc, dc.col[defaultbg].pixel); XFillRectangle(xw.dpy, xw.buf, dc.gc, 0, 0, win.w, win.h); @@ -1126,22 +1254,7 @@ xinit(int cols, int rows) xw.draw = XftDrawCreate(xw.dpy, xw.buf, xw.vis, xw.cmap); /* input methods */ - if ((xw.xim = XOpenIM(xw.dpy, NULL, NULL, NULL)) == NULL) { - XSetLocaleModifiers("@im=local"); - if ((xw.xim = XOpenIM(xw.dpy, NULL, NULL, NULL)) == NULL) { - XSetLocaleModifiers("@im="); - if ((xw.xim = XOpenIM(xw.dpy, - NULL, NULL, NULL)) == NULL) { - die("XOpenIM failed. Could not open input" - " device.\n"); - } - } - } - xw.xic = XCreateIC(xw.xim, XNInputStyle, XIMPreeditNothing - | XIMStatusNothing, XNClientWindow, xw.win, - XNFocusWindow, xw.win, NULL); - if (xw.xic == NULL) - die("XCreateIC failed. Could not obtain input method.\n"); + ximopen(xw.dpy); /* white cursor, black outline */ cursor = XCreateFontCursor(xw.dpy, mouseshape); @@ -1188,7 +1301,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; @@ -1283,13 +1396,10 @@ xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x fontpattern = FcFontSetMatch(0, fcsets, 1, fcpattern, &fcres); - /* - * Overwrite or create the new cache entry. - */ - if (frclen >= LEN(frc)) { - frclen = LEN(frc) - 1; - XftFontClose(xw.dpy, frc[frclen].font); - frc[frclen].unicodep = 0; + /* Allocate memory for the new cache entry. */ + if (frclen >= frccap) { + frccap += 16; + frc = xrealloc(frc, frccap * sizeof(Fontcache)); } frc[frclen].font = XftFontOpenPattern(xw.dpy, @@ -1324,7 +1434,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; @@ -1361,10 +1471,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]; - if (IS_SET(MODE_REVERSE)) { if (fg == &dc.col[defaultfg]) { fg = &dc.col[defaultbg]; @@ -1414,17 +1520,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.vborderpx, 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.hborderpx); + 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. */ @@ -1438,7 +1544,11 @@ xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, i XftDrawSetClipRectangles(xw.draw, winx, winy, &r, 1); /* Render the glyphs. */ - XftDrawGlyphFontSpec(xw.draw, fg, specs, len); + FcBool b = FcFalse; + FcPatternGetBool(specs->font->pattern, FC_COLOR, 0, &b); + if (!b) { + XftDrawGlyphFontSpec(xw.draw, fg, specs, len); + } /* Render underline and strikethrough. */ if (base.mode & ATTR_UNDERLINE) { @@ -1517,35 +1627,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); } } @@ -1620,6 +1730,16 @@ xfinishdraw(void) } void +xximspot(int x, int y) +{ + XPoint spot = { borderpx + x * win.cw, borderpx + (y + 1) * win.ch }; + XVaNestedList attr = XVaCreateNestedList(0, XNSpotLocation, &spot, NULL); + + XSetICValues(xw.xic, XNPreeditAttributes, attr, NULL); + XFree(attr); +} + +void expose(XEvent *ev) { redraw(); @@ -1796,7 +1916,6 @@ kpress(XEvent *ev) ttywrite(buf, len, 1); } - void cmessage(XEvent *e) { @@ -1935,6 +2054,59 @@ run(void) } } +int +resource_load(XrmDatabase db, char *name, enum resource_type rtype, void *dst) +{ + char **sdst = dst; + int *idst = dst; + float *fdst = dst; + + char fullname[256]; + char fullclass[256]; + char *type; + XrmValue ret; + + snprintf(fullname, sizeof(fullname), "%s.%s", + opt_name ? opt_name : "st", name); + snprintf(fullclass, sizeof(fullclass), "%s.%s", + opt_class ? opt_class : "St", name); + fullname[sizeof(fullname) - 1] = fullclass[sizeof(fullclass) - 1] = '\0'; + + XrmGetResource(db, fullname, fullclass, &type, &ret); + if (ret.addr == NULL || strncmp("String", type, 64)) + return 1; + + switch (rtype) { + case STRING: + *sdst = ret.addr; + break; + case INTEGER: + *idst = strtoul(ret.addr, NULL, 10); + break; + case FLOAT: + *fdst = strtof(ret.addr, NULL); + break; + } + return 0; +} + +void +config_init(void) +{ + char *resm; + XrmDatabase db; + ResourcePref *p; + + XrmInitialize(); + resm = XResourceManagerString(xw.dpy); + if (!resm) + return; + + db = XrmGetStringDatabase(resm); + for (p = resources; p < resources + LEN(resources); p++) + resource_load(db, p->name, p->type, p->dst); +} + void usage(void) { @@ -1959,6 +2131,9 @@ main(int argc, char *argv[]) case 'a': allowaltscreen = 0; break; + case 'A': + opt_alpha = EARGF(usage()); + break; case 'c': opt_class = EARGF(usage()); break; @@ -1993,7 +2168,7 @@ main(int argc, char *argv[]) opt_embed = EARGF(usage()); break; case 'v': - die("%s " VERSION " (c) 2010-2016 st engineers\n", argv0); + die("%s " VERSION "\n", argv0); break; default: usage(); @@ -2008,6 +2183,11 @@ run: setlocale(LC_CTYPE, ""); XSetLocaleModifiers(""); + + if(!(xw.dpy = XOpenDisplay(NULL))) + die("Can't open display\n"); + + config_init(); cols = MAX(cols, 1); rows = MAX(rows, 1); tnew(cols, rows); |
