mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-04-27 06:46:44 -04:00
Merge branch 'master' of https://codeberg.org/dnkl/foot
This commit is contained in:
commit
8445da4853
103 changed files with 1655 additions and 579 deletions
112
.gitlab-ci.yml
112
.gitlab-ci.yml
|
|
@ -1,112 +0,0 @@
|
|||
stages:
|
||||
- build
|
||||
|
||||
variables:
|
||||
GIT_SUBMODULE_STRATEGY: normal
|
||||
|
||||
before_script:
|
||||
- apk update
|
||||
- apk add musl-dev linux-headers meson ninja gcc scdoc ncurses
|
||||
- apk add libxkbcommon-dev pixman-dev freetype-dev fontconfig-dev harfbuzz-dev utf8proc-dev
|
||||
- apk add wayland-dev wayland-protocols
|
||||
- apk add git
|
||||
- apk add check-dev
|
||||
- apk add ttf-hack font-noto-emoji
|
||||
|
||||
debug-x64:
|
||||
image: alpine:edge
|
||||
stage: build
|
||||
script:
|
||||
- cd subprojects
|
||||
- git clone https://codeberg.org/dnkl/fcft.git
|
||||
- cd ..
|
||||
- mkdir -p bld/debug
|
||||
- cd bld/debug
|
||||
- meson --buildtype=debug -Dgrapheme-clustering=enabled -Dfcft:grapheme-shaping=enabled -Dfcft:run-shaping=enabled -Dfcft:test-text-shaping=true ../../
|
||||
- ninja -v -k0
|
||||
- ninja -v test
|
||||
artifacts:
|
||||
reports:
|
||||
junit: bld/debug/meson-logs/testlog.junit.xml
|
||||
|
||||
debug-x64-no-grapheme-clustering:
|
||||
image: alpine:edge
|
||||
stage: build
|
||||
script:
|
||||
- apk del harfbuzz harfbuzz-dev utf8proc utf8proc-dev
|
||||
- cd subprojects
|
||||
- git clone https://codeberg.org/dnkl/fcft.git
|
||||
- cd ..
|
||||
- mkdir -p bld/debug
|
||||
- cd bld/debug
|
||||
- meson --buildtype=debug -Dgrapheme-clustering=disabled -Dfcft:grapheme-shaping=disabled -Dfcft:run-shaping=disabled -Dfcft:test-text-shaping=false ../../
|
||||
- ninja -v -k0
|
||||
- ninja -v test
|
||||
- ./foot --version
|
||||
- ./footclient --version
|
||||
artifacts:
|
||||
reports:
|
||||
junit: bld/debug/meson-logs/testlog.junit.xml
|
||||
|
||||
release-x64:
|
||||
image: alpine:edge
|
||||
stage: build
|
||||
script:
|
||||
- cd subprojects
|
||||
- git clone https://codeberg.org/dnkl/fcft.git
|
||||
- cd ..
|
||||
- mkdir -p bld/release
|
||||
- cd bld/release
|
||||
- meson --buildtype=release -Db_pgo=generate -Dgrapheme-clustering=enabled -Dfcft:grapheme-shaping=enabled -Dfcft:run-shaping=enabled -Dfcft:test-text-shaping=true ../../
|
||||
- ninja -v -k0
|
||||
- ninja -v test
|
||||
- ./foot --version
|
||||
- ./footclient --version
|
||||
artifacts:
|
||||
reports:
|
||||
junit: bld/release/meson-logs/testlog.junit.xml
|
||||
|
||||
debug-x86:
|
||||
image: i386/alpine:edge
|
||||
stage: build
|
||||
script:
|
||||
- cd subprojects
|
||||
- git clone https://codeberg.org/dnkl/fcft.git
|
||||
- cd ..
|
||||
- mkdir -p bld/debug
|
||||
- cd bld/debug
|
||||
- meson --buildtype=debug -Dgrapheme-clustering=enabled -Dfcft:grapheme-shaping=enabled -Dfcft:run-shaping=enabled -Dfcft:test-text-shaping=true ../../
|
||||
- ninja -v -k0
|
||||
- ninja -v test
|
||||
- ./foot --version
|
||||
- ./footclient --version
|
||||
artifacts:
|
||||
reports:
|
||||
junit: bld/debug/meson-logs/testlog.junit.xml
|
||||
|
||||
release-x86:
|
||||
image: i386/alpine:edge
|
||||
stage: build
|
||||
script:
|
||||
- cd subprojects
|
||||
- git clone https://codeberg.org/dnkl/fcft.git
|
||||
- cd ..
|
||||
- mkdir -p bld/release
|
||||
- cd bld/release
|
||||
- meson --buildtype=release -Db_pgo=generate -Dgrapheme-clustering=enabled -Dfcft:grapheme-shaping=enabled -Dfcft:run-shaping=enabled -Dfcft:test-text-shaping=true ../../
|
||||
- ninja -v -k0
|
||||
- ninja -v test
|
||||
- ./foot --version
|
||||
- ./footclient --version
|
||||
artifacts:
|
||||
reports:
|
||||
junit: bld/release/meson-logs/testlog.junit.xml
|
||||
|
||||
codespell:
|
||||
image: alpine:edge
|
||||
stage: build
|
||||
script:
|
||||
- apk add python3
|
||||
- apk add py3-pip
|
||||
- pip install codespell
|
||||
- codespell -Lser,doas,zar README.md INSTALL.md CHANGELOG.md *.c *.h doc/*.scd
|
||||
|
|
@ -33,7 +33,7 @@ pipeline:
|
|||
image: alpine:latest
|
||||
commands:
|
||||
- apk update
|
||||
- apk add musl-dev linux-headers meson ninja gcc scdoc ncurses
|
||||
- apk add musl-dev linux-headers meson ninja gcc clang scdoc ncurses
|
||||
- apk add libxkbcommon-dev pixman-dev freetype-dev fontconfig-dev harfbuzz-dev utf8proc-dev
|
||||
- apk add wayland-dev wayland-protocols
|
||||
- apk add git
|
||||
|
|
@ -50,7 +50,7 @@ pipeline:
|
|||
- ./footclient --version
|
||||
- cd ../..
|
||||
|
||||
# Release
|
||||
# Release (gcc)
|
||||
- mkdir -p bld/release-x64
|
||||
- cd bld/release-x64
|
||||
- meson --buildtype=release -Db_pgo=generate -Dgrapheme-clustering=enabled -Dfcft:grapheme-shaping=enabled -Dfcft:run-shaping=enabled -Dfcft:test-text-shaping=true ../..
|
||||
|
|
@ -60,6 +60,16 @@ pipeline:
|
|||
- ./footclient --version
|
||||
- cd ../..
|
||||
|
||||
# Release (clang)
|
||||
- mkdir -p bld/release-x64-clang
|
||||
- cd bld/release-x64-clang
|
||||
- CC=clang meson --buildtype=release -Dgrapheme-clustering=enabled -Dfcft:grapheme-shaping=enabled -Dfcft:run-shaping=enabled -Dfcft:test-text-shaping=true ../..
|
||||
- ninja -v -k0
|
||||
- ninja -v test
|
||||
- ./foot --version
|
||||
- ./footclient --version
|
||||
- cd ../..
|
||||
|
||||
# no grapheme clustering
|
||||
- apk del harfbuzz harfbuzz-dev utf8proc utf8proc-dev
|
||||
- mkdir -p bld/debug
|
||||
|
|
@ -80,7 +90,7 @@ pipeline:
|
|||
image: i386/alpine:latest
|
||||
commands:
|
||||
- apk update
|
||||
- apk add musl-dev linux-headers meson ninja gcc scdoc ncurses
|
||||
- apk add musl-dev linux-headers meson ninja gcc clang scdoc ncurses
|
||||
- apk add libxkbcommon-dev pixman-dev freetype-dev fontconfig-dev harfbuzz-dev utf8proc-dev
|
||||
- apk add wayland-dev wayland-protocols
|
||||
- apk add git
|
||||
|
|
@ -97,7 +107,7 @@ pipeline:
|
|||
- ./footclient --version
|
||||
- cd ../..
|
||||
|
||||
# Release
|
||||
# Release (gcc)
|
||||
- mkdir -p bld/release-x86
|
||||
- cd bld/release-x86
|
||||
- meson --buildtype=release -Db_pgo=generate -Dgrapheme-clustering=enabled -Dfcft:grapheme-shaping=enabled -Dfcft:run-shaping=enabled -Dfcft:test-text-shaping=true ../..
|
||||
|
|
@ -106,3 +116,13 @@ pipeline:
|
|||
- ./foot --version
|
||||
- ./footclient --version
|
||||
- cd ../..
|
||||
|
||||
# Release (clang)
|
||||
- mkdir -p bld/release-x86-clang
|
||||
- cd bld/release-x86-clang
|
||||
- CC=clang meson --buildtype=release -Dgrapheme-clustering=enabled -Dfcft:grapheme-shaping=enabled -Dfcft:run-shaping=enabled -Dfcft:test-text-shaping=true ../..
|
||||
- ninja -v -k0
|
||||
- ninja -v test
|
||||
- ./foot --version
|
||||
- ./footclient --version
|
||||
- cd ../..
|
||||
|
|
|
|||
110
CHANGELOG.md
110
CHANGELOG.md
|
|
@ -1,6 +1,7 @@
|
|||
# Changelog
|
||||
|
||||
* [Unreleased](#unreleased)
|
||||
* [1.14.0](#1-14-0)
|
||||
* [1.13.1](#1-13-1)
|
||||
* [1.13.0](#1-13-0)
|
||||
* [1.12.1](#1-12-1)
|
||||
|
|
@ -42,6 +43,24 @@
|
|||
|
||||
|
||||
## Unreleased
|
||||
### Added
|
||||
### Changed
|
||||
### Deprecated
|
||||
### Removed
|
||||
### Fixed
|
||||
|
||||
* Incorrect icon in dock and window switcher on Gnome ([#1317][1317])
|
||||
* Crash when scrolling after resizing the window with non-zero
|
||||
scrolling regions.
|
||||
|
||||
[1317]: https://codeberg.org/dnkl/foot/issues/1317
|
||||
|
||||
|
||||
### Security
|
||||
### Contributors
|
||||
|
||||
|
||||
## 1.14.0
|
||||
|
||||
### Added
|
||||
|
||||
|
|
@ -49,8 +68,24 @@
|
|||
* Support (optional) for utmp logging with libutempter.
|
||||
* `kxIN` and `kxOUT` (focus in/out events) to terminfo.
|
||||
* `name` capability to `XTGETTCAP`.
|
||||
* String values in `foot.ini` may now be quoted. This can be used to
|
||||
set a value to the empty string, for example.
|
||||
* Environment variables can now be **unset**, by setting
|
||||
`[environment].<variable>=""` (quotes are required) ([#1225][1225]).
|
||||
* `font-size-adjustment=N[px]` option, letting you configure how much
|
||||
to increment/decrement the font size when zooming in or out
|
||||
([#1188][1188]).
|
||||
* Bracketed paste terminfo entries (`BD`, `BE`, `PE` and `PS`, added
|
||||
to ncurses in 2022-12-24). Vim makes use of these.
|
||||
* “Report version” terminfo entries (`XR`/`xr`).
|
||||
* “Report DA2” terminfo entries (`RV`/`rv`).
|
||||
* `XF` terminfo capability (focus in/out events available).
|
||||
* `$TERM_PROGRAM` and `$TERM_PROGRAM_VERSION` environment variables
|
||||
set in the slave process.
|
||||
|
||||
[1136]: https://codeberg.org/dnkl/foot/issues/1136
|
||||
[1225]: https://codeberg.org/dnkl/foot/issues/1225
|
||||
[1188]: https://codeberg.org/dnkl/foot/issues/1188
|
||||
|
||||
|
||||
### Changed
|
||||
|
|
@ -64,13 +99,20 @@
|
|||
("permanently reset") instead of `2` ("reset") for DEC private
|
||||
modes that are known but unsupported.
|
||||
* Set `PWD` environment variable in the slave process ([#1179][1179]).
|
||||
* DPI is now forced to 96 when found to be unreasonably high.
|
||||
* Set default log level to warning ([#1215][1215]).
|
||||
* Default `grapheme-width-method` from `wcswidth` to `double-width`.
|
||||
* When determining initial font size, do FontConfig config
|
||||
substitution if the user-provided font pattern has no {pixel}size
|
||||
option ([#1287][1287]).
|
||||
* DECRST of DECCOLM and DECSCLM removed from terminfo.
|
||||
|
||||
[1166]: https://codeberg.org/dnkl/foot/issues/1166
|
||||
[1179]: https://codeberg.org/dnkl/foot/issues/1179
|
||||
[1215]: https://codeberg.org/dnkl/foot/pulls/1215
|
||||
[1287]: https://codeberg.org/dnkl/foot/issues/1287
|
||||
|
||||
|
||||
### Deprecated
|
||||
### Removed
|
||||
### Fixed
|
||||
|
||||
* Crash in `foot --server` on key press, after another `footclient`
|
||||
|
|
@ -80,16 +122,76 @@
|
|||
that does not allow Wayland buffer re-use (e.g. KDE/plasma)
|
||||
([#1173][1173])
|
||||
* Scrollback search matches not being highlighted correctly, on
|
||||
compositors that does now allow Wayland buffer re-use
|
||||
compositors that does not allow Wayland buffer re-use
|
||||
(e.g. KDE/plasma).
|
||||
* Nanosecs "overflow" when calculating timeout value for
|
||||
`resize-delay-ms` option.
|
||||
* Missing backslash in ST terminator in escape sequences in the
|
||||
built-in terminfo (accessed via XTGETTCAP).
|
||||
* Crash when interactively resizing the window with a very large
|
||||
scrollback.
|
||||
* Crash when a sixel image exceeds the current sixel max height.
|
||||
* Crash after reverse-scrolling (`CSI Ps T`) in the ‘normal’
|
||||
(non-alternate) screen ([#1190][1190]).
|
||||
* Background transparency being applied to the text "behind" the
|
||||
cursor. Only applies to block cursor using inversed fg/bg
|
||||
colors. ([#1205][1205]).
|
||||
* Crash when monitor’s physical size is "too small" ([#1209][1209]).
|
||||
* Line-height adjustment when incrementing/decrementing the font size
|
||||
with a user-set line-height ([#1218][1218]).
|
||||
* Scaling factor not being correctly applied when converting pt-or-px
|
||||
config values (e.g. letter offsets, line height etc).
|
||||
* Selection being stuck visually when `IL` and `DL`.
|
||||
* URL underlines sometimes still being visible after exiting URL mode.
|
||||
* Text-bindings, and pipe-* bindings, with multiple key mappings
|
||||
causing a crash (double-free) on exit ([#1259][1259]).
|
||||
* Double-width glyphs glitching when surrounded by glyphs overflowing
|
||||
into the double-width glyph ([#1256][1256]).
|
||||
* Wayland protocol violation when ack:ing a configure event for an
|
||||
unmapped surface ([#1249][1249]).
|
||||
* `xdg_toplevel::set_min_size()` not being called.
|
||||
* Key bindings with consumed modifiers masking other key bindings
|
||||
([#1280][1280]).
|
||||
* Multi-character compose sequences with the kitty keyboard protocol
|
||||
([#1288][1288]).
|
||||
* Crash when application output scrolls very fast, e.g. `yes`
|
||||
([#1305][1305]).
|
||||
* Crash when application scrolls **many** lines (> ~2³¹).
|
||||
* DECCOLM erasing the screen ([#1265][1265]).
|
||||
|
||||
[1173]: https://codeberg.org/dnkl/foot/issues/1173
|
||||
[1190]: https://codeberg.org/dnkl/foot/issues/1190
|
||||
[1205]: https://codeberg.org/dnkl/foot/issues/1205
|
||||
[1209]: https://codeberg.org/dnkl/foot/issues/1209
|
||||
[1218]: https://codeberg.org/dnkl/foot/issues/1218
|
||||
[1259]: https://codeberg.org/dnkl/foot/issues/1259
|
||||
[1256]: https://codeberg.org/dnkl/foot/issues/1256
|
||||
[1249]: https://codeberg.org/dnkl/foot/issues/1249
|
||||
[1280]: https://codeberg.org/dnkl/foot/issues/1280
|
||||
[1288]: https://codeberg.org/dnkl/foot/issues/1288
|
||||
[1305]: https://codeberg.org/dnkl/foot/issues/1305
|
||||
[1265]: https://codeberg.org/dnkl/foot/issues/1265
|
||||
|
||||
|
||||
### Security
|
||||
### Contributors
|
||||
|
||||
* Alexey Sakovets
|
||||
* Andrea Pappacoda
|
||||
* Antoine Beaupré
|
||||
* argosatcore
|
||||
* Craig Barnes
|
||||
* EuCaue
|
||||
* Grigory Kirillov
|
||||
* Harri Nieminen
|
||||
* Hugo Osvaldo Barrera
|
||||
* jaroeichler
|
||||
* Joakim Nohlgård
|
||||
* Nick Hastings
|
||||
* Soren A D
|
||||
* Torsten Trautwein
|
||||
* Vladimír Magyar
|
||||
* woojiq
|
||||
* Yorick Peterse
|
||||
|
||||
|
||||
## 1.13.1
|
||||
|
|
|
|||
18
INSTALL.md
18
INSTALL.md
|
|
@ -327,6 +327,7 @@ We will use the `pgo` binary along with input corpus generated by
|
|||
`scripts/generate-alt-random-writes.py`:
|
||||
|
||||
```sh
|
||||
./utils/xtgettcap
|
||||
./footclient --version
|
||||
./foot --version
|
||||
tmp_file=$(mktemp)
|
||||
|
|
@ -349,9 +350,10 @@ rm ${tmp_file}
|
|||
```
|
||||
|
||||
The first step, running `./foot --version` and `./footclient
|
||||
--version` might seem unnecessary, but is needed to ensure we have
|
||||
_some_ profiling data for functions not covered by the PGO helper
|
||||
binary. Without this, the final link phase will fail.
|
||||
--version` etc, might seem unnecessary, but is needed to ensure we
|
||||
have _some_ profiling data for functions not covered by the PGO helper
|
||||
binary, for **all** binaries. Without this, the final link phase will
|
||||
fail.
|
||||
|
||||
The snippet above then creates an (empty) temporary file. Then, it
|
||||
runs a script that generates random escape sequences (if you cat
|
||||
|
|
@ -371,6 +373,7 @@ This method requires a running Wayland session.
|
|||
We will use the script `scripts/generate-alt-random-writes.py`:
|
||||
|
||||
```sh
|
||||
./utils/xtgettcap
|
||||
./footclient --version
|
||||
foot_tmp_file=$(mktemp)
|
||||
./foot \
|
||||
|
|
@ -384,9 +387,10 @@ rm ${foot_tmp_file}
|
|||
You should see a foot window open up, with random colored text. The
|
||||
window should close after ~1-2s.
|
||||
|
||||
The first step, `./footclient --version` might seem unnecessary, but
|
||||
is needed to ensure we have _some_ profiling data for
|
||||
`footclient`. Without this, the final link phase will fail.
|
||||
The first step, `./utils/xtgettcap && ./footclient --version`
|
||||
might seem unnecessary, but is needed to ensure we have _some_
|
||||
profiling data for **all** binaries we build. Without this, the final
|
||||
link phase will fail.
|
||||
|
||||
|
||||
##### Use the generated PGO data
|
||||
|
|
@ -436,7 +440,7 @@ sed 's/@default_terminfo@/foot/g' foot.info | \
|
|||
Where _”output-directory”_ **must** match the value passed to
|
||||
`-Dcustom-terminfo-install-location` in the foot build. If
|
||||
`-Dcustom-terminfo-install-location` has not been set, `-o
|
||||
<output-directoty>` can simply be omitted.
|
||||
<output-directory>` can simply be omitted.
|
||||
|
||||
Or, if packaging:
|
||||
|
||||
|
|
|
|||
|
|
@ -569,7 +569,7 @@ reported the same issue.
|
|||
The report should contain the following:
|
||||
|
||||
- Foot version (`foot --version`).
|
||||
- Log output from foot (start foot from another terminal).
|
||||
- Log output from foot (run `foot -d info` from another terminal).
|
||||
- Which Wayland compositor (and version) you are running.
|
||||
- If reporting a crash, please try to provide a `bt full` backtrace
|
||||
with symbols.
|
||||
|
|
|
|||
4
client.c
4
client.c
|
|
@ -94,7 +94,7 @@ print_usage(const char *prog_name)
|
|||
" -N,--no-wait detach the client process from the running terminal, exiting immediately\n"
|
||||
" -o,--override=[section.]key=value override configuration option\n"
|
||||
" -E, --client-environment exec shell using footclient's environment, instead of the server's\n"
|
||||
" -d,--log-level={info|warning|error|none} log level (info)\n"
|
||||
" -d,--log-level={info|warning|error|none} log level (warning)\n"
|
||||
" -l,--log-colorize=[{never|always|auto}] enable/disable colorization of log output on stderr\n"
|
||||
" -v,--version show the version number and quit\n"
|
||||
" -e ignored (for compatibility with xterm -e)\n";
|
||||
|
|
@ -178,7 +178,7 @@ main(int argc, char *const *argv)
|
|||
|
||||
const char *custom_cwd = NULL;
|
||||
const char *server_socket_path = NULL;
|
||||
enum log_class log_level = LOG_CLASS_INFO;
|
||||
enum log_class log_level = LOG_CLASS_WARNING;
|
||||
enum log_colorize log_colorize = LOG_COLORIZE_AUTO;
|
||||
bool hold = false;
|
||||
bool client_environment = false;
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ _foot()
|
|||
cur=${COMP_WORDS[COMP_CWORD]}
|
||||
prev=${COMP_WORDS[COMP_CWORD-1]}
|
||||
|
||||
# check if positional argument is completed
|
||||
# Check if positional argument is completed
|
||||
previous_words=( "${COMP_WORDS[@]}" )
|
||||
unset previous_words[-1]
|
||||
commands=$(compgen -c | grep -vFx "$(compgen -k)" | grep -vE '^([.:[]|foot)$' | sort -u)
|
||||
|
|
@ -43,41 +43,45 @@ _foot()
|
|||
(( i++ ))
|
||||
continue
|
||||
fi
|
||||
# positional argument found
|
||||
# Positional argument found
|
||||
offset=$i
|
||||
fi
|
||||
(( i++ ))
|
||||
done
|
||||
|
||||
if [[ ! -z "$offset" ]] ; then
|
||||
# depends on bash_completion being available
|
||||
# Depends on bash_completion being available
|
||||
declare -F _command_offset >/dev/null || return 1
|
||||
_command_offset $offset
|
||||
return 0
|
||||
elif [[ ${cur} == --* ]] ; then
|
||||
COMPREPLY=( $(compgen -W "${flags}" -- ${cur}) )
|
||||
elif [[ ${prev} =~ ^(--config|--print-pid|--server)$ ]] ; then
|
||||
compopt -o default
|
||||
elif [[ ${prev} == '--working-directory' ]] ; then
|
||||
compopt -o dirnames
|
||||
elif [[ ${prev} == '--term' ]] ; then
|
||||
# check if toe is available
|
||||
which toe > /dev/null || return 1
|
||||
COMPREPLY=( $(compgen -W "$(toe -a | awk '$1 ~ /[+]/ {next}; {print $1}')" -- ${cur}) )
|
||||
elif [[ ${prev} == '--font' ]] ; then
|
||||
# check if fc-list is available
|
||||
which fc-list > /dev/null || return 1
|
||||
COMPREPLY=( $(compgen -W "$(fc-list : family | sed 's/,/\n/g' | uniq | tr -d ' ')" -- ${cur}) )
|
||||
elif [[ ${prev} == '--log-level' ]] ; then
|
||||
COMPREPLY=( $(compgen -W "none error warning info" -- ${cur}) )
|
||||
elif [[ ${prev} == '--log-colorize' ]] ; then
|
||||
COMPREPLY=( $(compgen -W "never always auto" -- ${cur}) )
|
||||
elif [[ ${prev} =~ ^(--app-id|--help|--override|--title|--version|--window-size-chars|--window-size-pixels|--check-config)$ ]] ; then
|
||||
: # don't autocomplete for these flags
|
||||
else
|
||||
# complete commands from $PATH
|
||||
COMPREPLY=( $(compgen -c -- ${cur}) )
|
||||
return 0
|
||||
fi
|
||||
|
||||
case "$prev" in
|
||||
--config|--print-pid|--server|-[cps])
|
||||
compopt -o default ;;
|
||||
--working-directory|-D)
|
||||
compopt -o dirnames ;;
|
||||
--term|-t)
|
||||
command -v toe > /dev/null || return 1
|
||||
COMPREPLY=( $(compgen -W "$(toe -a | awk '$1 !~ /[+]/ {print $1}')" -- ${cur}) ) ;;
|
||||
--font|-f)
|
||||
command -v fc-list > /dev/null || return 1
|
||||
COMPREPLY=( $(compgen -W "$(fc-list : family | sed 's/,/\n/g' | uniq | tr -d ' ')" -- ${cur}) ) ;;
|
||||
--log-level|-d)
|
||||
COMPREPLY=( $(compgen -W "none error warning info" -- ${cur}) ) ;;
|
||||
--log-colorize|-l)
|
||||
COMPREPLY=( $(compgen -W "never always auto" -- ${cur}) ) ;;
|
||||
--app-id|--help|--override|--title|--version|--window-size-chars|--window-size-pixels|--check-config|-[ahoTvWwC])
|
||||
# Don't autocomplete for these flags
|
||||
: ;;
|
||||
*)
|
||||
# Complete commands from $PATH
|
||||
COMPREPLY=( $(compgen -c -- ${cur}) ) ;;
|
||||
esac
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ _footclient()
|
|||
cur=${COMP_WORDS[COMP_CWORD]}
|
||||
prev=${COMP_WORDS[COMP_CWORD-1]}
|
||||
|
||||
# check if positional argument is completed
|
||||
# Check if positional argument is completed
|
||||
previous_words=( "${COMP_WORDS[@]}" )
|
||||
unset previous_words[-1]
|
||||
commands=$(compgen -c | grep -vFx "$(compgen -k)" | grep -vE '^([.:[]|footclient)$' | sort -u)
|
||||
|
|
@ -39,37 +39,42 @@ _footclient()
|
|||
(( i++ ))
|
||||
continue
|
||||
fi
|
||||
# positional argument found
|
||||
# Positional argument found
|
||||
offset=$i
|
||||
fi
|
||||
(( i++ ))
|
||||
done
|
||||
|
||||
if [[ ! -z "$offset" ]] ; then
|
||||
# depends on bash_completion being available
|
||||
# Depends on bash_completion being available
|
||||
declare -F _command_offset >/dev/null || return 1
|
||||
_command_offset $offset
|
||||
return 0
|
||||
elif [[ ${cur} == --* ]] ; then
|
||||
COMPREPLY=( $(compgen -W "${flags}" -- ${cur}) )
|
||||
elif [[ ${prev} == '--server-socket' ]] ; then
|
||||
compopt -o default
|
||||
elif [[ ${prev} == '--working-directory' ]] ; then
|
||||
compopt -o dirnames
|
||||
elif [[ ${prev} == '--term' ]] ; then
|
||||
# check if toe is available
|
||||
which toe > /dev/null || return 1
|
||||
COMPREPLY=( $(compgen -W "$(toe -a | awk '$1 ~ /[+]/ {next}; {print $1}')" -- ${cur}) )
|
||||
elif [[ ${prev} == '--log-level' ]] ; then
|
||||
COMPREPLY=( $(compgen -W "none error warning info" -- ${cur}) )
|
||||
elif [[ ${prev} == '--log-colorize' ]] ; then
|
||||
COMPREPLY=( $(compgen -W "never always auto" -- ${cur}) )
|
||||
elif [[ ${prev} =~ ^(--app-id|--help|--override|--title|--version|--window-size-chars|--window-size-pixels|)$ ]] ; then
|
||||
: # don't autocomplete for these flags
|
||||
else
|
||||
# complete commands from $PATH
|
||||
COMPREPLY=( $(compgen -c -- ${cur}) )
|
||||
return 0
|
||||
fi
|
||||
|
||||
case "$prev" in
|
||||
--server-socket|-s)
|
||||
compopt -o default ;;
|
||||
--working-directory|-D)
|
||||
compopt -o dirnames ;;
|
||||
--term|-t)
|
||||
command -v toe > /dev/null || return 1
|
||||
COMPREPLY=( $(compgen -W "$(toe -a | awk '$1 ~ /[+]/ {next}; {print $1}')" -- ${cur}) ) ;;
|
||||
--log-level|-d)
|
||||
COMPREPLY=( $(compgen -W "none error warning info" -- ${cur}) ) ;;
|
||||
--log-colorize|-l)
|
||||
COMPREPLY=( $(compgen -W "never always auto" -- ${cur}) ) ;;
|
||||
--app-id|--help|--override|--title|--version|--window-size-chars|--window-size-pixels|-[ahoTvWw])
|
||||
# Don't autocomplete for these flags
|
||||
: ;;
|
||||
*)
|
||||
# Complete commands from $PATH
|
||||
COMPREPLY=( $(compgen -c -- ${cur}) ) ;;
|
||||
esac
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ complete -c foot -x -s W -l window-size-chars
|
|||
complete -c foot -F -s s -l server -d "run as server; open terminals by running footclient"
|
||||
complete -c foot -s H -l hold -d "remain open after child process exits"
|
||||
complete -c foot -r -s p -l print-pid -d "print PID to this file or FD when up and running (server mode only)"
|
||||
complete -c foot -x -s d -l log-level -a "info warning error none" -d "log-level (info)"
|
||||
complete -c foot -x -s d -l log-level -a "info warning error none" -d "log-level (warning)"
|
||||
complete -c foot -x -s l -l log-colorize -a "always never auto" -d "enable or disable colorization of log output on stderr"
|
||||
complete -c foot -s S -l log-no-syslog -d "disable syslog logging (server mode only)"
|
||||
complete -c foot -s v -l version -d "show the version number and quit"
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ _arguments \
|
|||
'(-s --server)'{-s,--server}'[run as server; open terminals by running footclient]:server:_files' \
|
||||
'(-H --hold)'{-H,--hold}'[remain open after child process exits]' \
|
||||
'(-p --print-pid)'{-p,--print-pid}'[print PID to this file or FD when up and running (server mode only)]:pidfile:_files' \
|
||||
'(-d --log-level)'{-d,--log-level}'[log level (info)]:loglevel:(info warning error none)' \
|
||||
'(-d --log-level)'{-d,--log-level}'[log level (warning)]:loglevel:(info warning error none)' \
|
||||
'(-l --log-colorize)'{-l,--log-colorize}'[enable or disable colorization of log output on stderr]:logcolor:(never always auto)' \
|
||||
'(-S --log-no-syslog)'{-s,--log-no-syslog}'[disable syslog logging (server mode only)]' \
|
||||
'(-v --version)'{-v,--version}'[show the version number and quit]' \
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ _arguments \
|
|||
'(-N --no-wait)'{-N,--no-wait}'[detach the client process from the running terminal, exiting immediately]' \
|
||||
'(-o --override)'{-o,--override}'[configuration option to override, in form SECTION.KEY=VALUE]:()' \
|
||||
'(-E --client-environment)'{-E,--client-environment}"[child process inherits footclient's environment, instead of the server's]" \
|
||||
'(-d --log-level)'{-d,--log-level}'[log level (info)]:loglevel:(info warning error none)' \
|
||||
'(-d --log-level)'{-d,--log-level}'[log level (warning)]:loglevel:(info warning error none)' \
|
||||
'(-l --log-colorize)'{-l,--log-colorize}'[enable or disable colorization of log output on stderr]:logcolor:(never always auto)' \
|
||||
'(-v --version)'{-v,--version}'[show the version number and quit]' \
|
||||
'(-h --help)'{-h,--help}'[show help message and quit]' \
|
||||
|
|
|
|||
138
config.c
138
config.c
|
|
@ -503,8 +503,48 @@ value_to_double(struct context *ctx, float *res)
|
|||
static bool NOINLINE
|
||||
value_to_str(struct context *ctx, char **res)
|
||||
{
|
||||
char *copy = xstrdup(ctx->value);
|
||||
char *end = copy + strlen(copy) - 1;
|
||||
|
||||
/* Un-quote
|
||||
*
|
||||
* Note: this is very simple; we only support the *entire* value
|
||||
* being quoted. That is, no mid-value quotes. Both double and
|
||||
* single quotes are supported.
|
||||
*
|
||||
* - key="value" OK
|
||||
* - key=abc "quote" def NOT OK
|
||||
* - key=’value’ OK
|
||||
*
|
||||
* Finally, we support escaping the quote character, and the
|
||||
* escape character itself:
|
||||
*
|
||||
* - key="value \"quotes\""
|
||||
* - key="backslash: \\"
|
||||
*
|
||||
* ONLY the "current" quote character can be escaped:
|
||||
*
|
||||
* key="value \'" NOt OK (both backslash and single quote is kept)
|
||||
*/
|
||||
|
||||
if ((copy[0] == '"' && *end == '"') ||
|
||||
(copy[0] == '\'' && *end == '\''))
|
||||
{
|
||||
const char quote = copy[0];
|
||||
*end = '\0';
|
||||
|
||||
memmove(copy, copy + 1, end - copy);
|
||||
|
||||
/* Un-escape */
|
||||
for (char *p = copy; *p != '\0'; p++) {
|
||||
if (p[0] == '\\' && (p[1] == '\\' || p[1] == quote)) {
|
||||
memmove(p, p + 1, end - p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free(*res);
|
||||
*res = xstrdup(ctx->value);
|
||||
*res = copy;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -612,7 +652,7 @@ value_to_pt_or_px(struct context *ctx, struct pt_or_px *res)
|
|||
char *end = NULL;
|
||||
|
||||
long value = strtol(s, &end, 10);
|
||||
if (!(errno == 0 && end == s + len - 2)) {
|
||||
if (!(len > 2 && errno == 0 && end == s + len - 2)) {
|
||||
LOG_CONTEXTUAL_ERR("invalid px value (must be in the form 12px)");
|
||||
return false;
|
||||
}
|
||||
|
|
@ -886,6 +926,31 @@ parse_section_main(struct context *ctx)
|
|||
return true;
|
||||
}
|
||||
|
||||
else if (strcmp(key, "font-size-adjustment") == 0) {
|
||||
const size_t len = strlen(ctx->value);
|
||||
if (len >= 1 && ctx->value[len - 1] == '%') {
|
||||
errno = 0;
|
||||
char *end = NULL;
|
||||
|
||||
float percent = strtof(ctx->value, &end);
|
||||
if (!(len > 1 && errno == 0 && end == ctx->value + len - 1)) {
|
||||
LOG_CONTEXTUAL_ERR(
|
||||
"invalid percent value (must be in the form 10.5%%)");
|
||||
return false;
|
||||
}
|
||||
|
||||
conf->font_size_adjustment.percent = percent / 100.;
|
||||
conf->font_size_adjustment.pt_or_px.pt = 0;
|
||||
conf->font_size_adjustment.pt_or_px.px = 0;
|
||||
return true;
|
||||
} else {
|
||||
bool ret = value_to_pt_or_px(ctx, &conf->font_size_adjustment.pt_or_px);
|
||||
if (ret)
|
||||
conf->font_size_adjustment.percent = 0.;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
else if (strcmp(key, "line-height") == 0)
|
||||
return value_to_pt_or_px(ctx, &conf->line_height);
|
||||
|
||||
|
|
@ -1413,6 +1478,9 @@ parse_section_csd(struct context *ctx)
|
|||
static void
|
||||
free_binding_aux(struct binding_aux *aux)
|
||||
{
|
||||
if (!aux->master_copy)
|
||||
return;
|
||||
|
||||
switch (aux->type) {
|
||||
case BINDING_AUX_NONE: break;
|
||||
case BINDING_AUX_PIPE: free_argv(&aux->pipe); break;
|
||||
|
|
@ -2256,21 +2324,22 @@ parse_section_environment(struct context *ctx)
|
|||
{
|
||||
struct config *conf = ctx->conf;
|
||||
const char *key = ctx->key;
|
||||
const char *value = ctx->value;
|
||||
|
||||
/* Check for pre-existing env variable */
|
||||
tll_foreach(conf->env_vars, it) {
|
||||
if (strcmp(it->item.name, key) == 0) {
|
||||
free(it->item.value);
|
||||
it->item.value = xstrdup(value);
|
||||
return true;
|
||||
}
|
||||
if (strcmp(it->item.name, key) == 0)
|
||||
return value_to_str(ctx, &it->item.value);
|
||||
}
|
||||
|
||||
struct env_var var = {
|
||||
.name = xstrdup(key),
|
||||
.value = xstrdup(value),
|
||||
};
|
||||
tll_push_back(conf->env_vars, var);
|
||||
/*
|
||||
* No pre-existing variable - allocate a new one
|
||||
*/
|
||||
|
||||
char *value = NULL;
|
||||
if (!value_to_str(ctx, &value))
|
||||
return false;
|
||||
|
||||
tll_push_back(conf->env_vars, ((struct env_var){xstrdup(key), value}));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -2847,6 +2916,7 @@ config_load(struct config *conf, const char *conf_path,
|
|||
},
|
||||
.startup_mode = STARTUP_WINDOWED,
|
||||
.fonts = {{0}},
|
||||
.font_size_adjustment = {.percent = 0., .pt_or_px = {.pt = 0.5, .px = 0}},
|
||||
.line_height = {.pt = 0, .px = -1},
|
||||
.letter_spacing = {.pt = 0, .px = 0},
|
||||
.horizontal_letter_offset = {.pt = 0, .px = 0},
|
||||
|
|
@ -2938,7 +3008,7 @@ config_load(struct config *conf, const char *conf_path,
|
|||
#if defined(FOOT_GRAPHEME_CLUSTERING) && FOOT_GRAPHEME_CLUSTERING
|
||||
.grapheme_shaping = fcft_caps & FCFT_CAPABILITY_GRAPHEME_SHAPING,
|
||||
#endif
|
||||
.grapheme_width_method = GRAPHEME_WIDTH_WCSWIDTH,
|
||||
.grapheme_width_method = GRAPHEME_WIDTH_DOUBLE,
|
||||
.delayed_render_lower_ns = 500000, /* 0.5ms */
|
||||
.delayed_render_upper_ns = 16666666 / 2, /* half a frame period (60Hz) */
|
||||
.max_shm_pool_size = 512 * 1024 * 1024,
|
||||
|
|
@ -3322,20 +3392,48 @@ config_font_parse(const char *pattern, struct config_font *font)
|
|||
if (pat == NULL)
|
||||
return false;
|
||||
|
||||
/*
|
||||
* First look for user specified {pixel}size option
|
||||
* e.g. “font-name:size=12”
|
||||
*/
|
||||
|
||||
double pt_size = -1.0;
|
||||
FcPatternGetDouble(pat, FC_SIZE, 0, &pt_size);
|
||||
FcPatternRemove(pat, FC_SIZE, 0);
|
||||
FcResult have_pt_size = FcPatternGetDouble(pat, FC_SIZE, 0, &pt_size);
|
||||
|
||||
int px_size = -1;
|
||||
FcPatternGetInteger(pat, FC_PIXEL_SIZE, 0, &px_size);
|
||||
FcPatternRemove(pat, FC_PIXEL_SIZE, 0);
|
||||
FcResult have_px_size = FcPatternGetInteger(pat, FC_PIXEL_SIZE, 0, &px_size);
|
||||
|
||||
if (pt_size == -1. && px_size == -1)
|
||||
pt_size = 8.0;
|
||||
if (have_pt_size != FcResultMatch && have_px_size != FcResultMatch) {
|
||||
/*
|
||||
* Apply fontconfig config. Can’t do that until we’ve first
|
||||
* checked for a user provided size, since we may end up with
|
||||
* both “size” and “pixelsize” being set, and we don’t know
|
||||
* which one takes priority.
|
||||
*/
|
||||
FcPattern *pat_copy = FcPatternDuplicate(pat);
|
||||
if (pat_copy == NULL ||
|
||||
!FcConfigSubstitute(NULL, pat_copy, FcMatchPattern))
|
||||
{
|
||||
LOG_WARN("%s: failed to do config substitution", pattern);
|
||||
} else {
|
||||
have_pt_size = FcPatternGetDouble(pat_copy, FC_SIZE, 0, &pt_size);
|
||||
have_px_size = FcPatternGetInteger(pat_copy, FC_PIXEL_SIZE, 0, &px_size);
|
||||
}
|
||||
|
||||
FcPatternDestroy(pat_copy);
|
||||
|
||||
if (have_pt_size != FcResultMatch && have_px_size != FcResultMatch)
|
||||
pt_size = 8.0;
|
||||
}
|
||||
|
||||
FcPatternRemove(pat, FC_SIZE, 0);
|
||||
FcPatternRemove(pat, FC_PIXEL_SIZE, 0);
|
||||
|
||||
char *stripped_pattern = (char *)FcNameUnparse(pat);
|
||||
FcPatternDestroy(pat);
|
||||
|
||||
LOG_DBG("%s: pt-size=%.2f, px-size=%d", stripped_pattern, pt_size, px_size);
|
||||
|
||||
*font = (struct config_font){
|
||||
.pattern = stripped_pattern,
|
||||
.pt_size = pt_size,
|
||||
|
|
|
|||
11
config.h
11
config.h
|
|
@ -22,6 +22,11 @@ struct pt_or_px {
|
|||
float pt;
|
||||
};
|
||||
|
||||
struct font_size_adjustment {
|
||||
struct pt_or_px pt_or_px;
|
||||
float percent;
|
||||
};
|
||||
|
||||
enum cursor_style { CURSOR_BLOCK, CURSOR_UNDERLINE, CURSOR_BEAM };
|
||||
|
||||
enum conf_size_type {CONF_SIZE_PX, CONF_SIZE_CELLS};
|
||||
|
|
@ -69,11 +74,6 @@ enum key_binding_type {
|
|||
MOUSE_BINDING,
|
||||
};
|
||||
|
||||
struct config_key_binding_text {
|
||||
char *text;
|
||||
bool master_copy;
|
||||
};
|
||||
|
||||
struct config_key_binding {
|
||||
int action; /* One of the varios bind_action_* enums from wayland.h */
|
||||
struct config_key_modifiers modifiers;
|
||||
|
|
@ -139,6 +139,7 @@ struct config {
|
|||
|
||||
enum {DPI_AWARE_AUTO, DPI_AWARE_YES, DPI_AWARE_NO} dpi_aware;
|
||||
struct config_font_list fonts[4];
|
||||
struct font_size_adjustment font_size_adjustment;
|
||||
|
||||
/* Custom font metrics (-1 = use real font metrics) */
|
||||
struct pt_or_px line_height;
|
||||
|
|
|
|||
27
csi.c
27
csi.c
|
|
@ -276,21 +276,6 @@ decset_decrst(struct terminal *term, unsigned param, bool enable)
|
|||
enable ? CURSOR_KEYS_APPLICATION : CURSOR_KEYS_NORMAL;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
/* DECCOLM */
|
||||
if (enable)
|
||||
LOG_WARN("unimplemented: 132 column mode (DECCOLM)");
|
||||
|
||||
term_erase(term, 0, 0, term->rows - 1, term->cols - 1);
|
||||
term_cursor_home(term);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
/* DECSCLM - Smooth scroll */
|
||||
if (enable)
|
||||
LOG_WARN("unimplemented: Smooth (Slow) Scroll (DECSCLM)");
|
||||
break;
|
||||
|
||||
case 5:
|
||||
/* DECSCNM */
|
||||
term->reverse = enable;
|
||||
|
|
@ -558,8 +543,6 @@ decrqm(const struct terminal *term, unsigned param)
|
|||
{
|
||||
switch (param) {
|
||||
case 1: return decrpm(term->cursor_keys_mode == CURSOR_KEYS_APPLICATION);
|
||||
case 3: return DECRPM_PERMANENTLY_RESET;
|
||||
case 4: return DECRPM_PERMANENTLY_RESET;
|
||||
case 5: return decrpm(term->reverse);
|
||||
case 6: return decrpm(term->origin);
|
||||
case 7: return decrpm(term->auto_margin);
|
||||
|
|
@ -601,8 +584,6 @@ xtsave(struct terminal *term, unsigned param)
|
|||
{
|
||||
switch (param) {
|
||||
case 1: term->xtsave.application_cursor_keys = term->cursor_keys_mode == CURSOR_KEYS_APPLICATION; break;
|
||||
case 3: break;
|
||||
case 4: break;
|
||||
case 5: term->xtsave.reverse = term->reverse; break;
|
||||
case 6: term->xtsave.origin = term->origin; break;
|
||||
case 7: term->xtsave.auto_margin = term->auto_margin; break;
|
||||
|
|
@ -644,8 +625,6 @@ xtrestore(struct terminal *term, unsigned param)
|
|||
bool enable;
|
||||
switch (param) {
|
||||
case 1: enable = term->xtsave.application_cursor_keys; break;
|
||||
case 3: return;
|
||||
case 4: return;
|
||||
case 5: enable = term->xtsave.reverse; break;
|
||||
case 6: enable = term->xtsave.origin; break;
|
||||
case 7: enable = term->xtsave.auto_margin; break;
|
||||
|
|
@ -933,7 +912,7 @@ csi_dispatch(struct terminal *term, uint8_t final)
|
|||
break;
|
||||
}
|
||||
|
||||
case 'L': {
|
||||
case 'L': { /* IL */
|
||||
if (term->grid->cursor.point.row < term->scroll_region.start ||
|
||||
term->grid->cursor.point.row >= term->scroll_region.end)
|
||||
break;
|
||||
|
|
@ -953,7 +932,7 @@ csi_dispatch(struct terminal *term, uint8_t final)
|
|||
break;
|
||||
}
|
||||
|
||||
case 'M': {
|
||||
case 'M': { /* DL */
|
||||
if (term->grid->cursor.point.row < term->scroll_region.start ||
|
||||
term->grid->cursor.point.row >= term->scroll_region.end)
|
||||
break;
|
||||
|
|
@ -1518,7 +1497,7 @@ csi_dispatch(struct terminal *term, uint8_t final)
|
|||
break; /* final == 'm' */
|
||||
|
||||
case 'n': {
|
||||
int resource = vt_param_get(term, 0, 2); /* Default is modifyFuncionKeys */
|
||||
int resource = vt_param_get(term, 0, 2); /* Default is modifyFunctionKeys */
|
||||
switch (resource) {
|
||||
case 0: /* modifyKeyboard */
|
||||
case 1: /* modifyCursorKeys */
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ This document describes all the control sequences supported by foot.
|
|||
|
||||
[[ *Sequence*
|
||||
:[ *Name*
|
||||
:[ *Description*
|
||||
:< *Description*
|
||||
| \\a
|
||||
: BEL
|
||||
: Depends on what *bell* in *foot.ini*(5) is set to.
|
||||
|
|
@ -60,7 +60,7 @@ equivalent to 8-bit C1 controls.
|
|||
[[ *Sequence*
|
||||
:[ *Name*
|
||||
:[ *Origin*
|
||||
:[ *Description*
|
||||
:< *Description*
|
||||
| \\E 7
|
||||
: DECSC
|
||||
: VT100
|
||||
|
|
@ -140,7 +140,7 @@ single CSI sequence by separating them with semicolons: *\\E[ 1;2;3
|
|||
m*.
|
||||
|
||||
[[ *Parameter*
|
||||
:[ *Description*
|
||||
:< *Description*
|
||||
| 0
|
||||
: Reset all attributes
|
||||
| 1
|
||||
|
|
@ -223,7 +223,7 @@ following 4 escape sequences:
|
|||
|
||||
[[ *Sequence*
|
||||
:[ *Name*
|
||||
:[ *Description*
|
||||
:< *Description*
|
||||
| \\E[ ? _Pm_ h
|
||||
: DECSET
|
||||
: Enable private mode
|
||||
|
|
@ -243,7 +243,7 @@ that corresponds to one of the following modes:
|
|||
|
||||
[[ *Parameter*
|
||||
:[ *Origin*
|
||||
:[ *Description*
|
||||
:< *Description*
|
||||
| 1
|
||||
: VT100
|
||||
: Cursor keys mode (DECCKM)
|
||||
|
|
@ -344,7 +344,7 @@ manipulation sequences. The generic format is:
|
|||
|
||||
[[ *Parameter 1*
|
||||
:[ *Parameter 2*
|
||||
:[ *Description*
|
||||
:< *Description*
|
||||
| 11
|
||||
: -
|
||||
: Report if window is iconified. Foot always reports *1* - not iconified.
|
||||
|
|
@ -394,7 +394,7 @@ manipulation sequences. The generic format is:
|
|||
[[ *Parameter*
|
||||
:[ *Name*
|
||||
:[ *Origin*
|
||||
:[ *Description*
|
||||
:< *Description*
|
||||
| \\E[ _Ps_ c
|
||||
: DA
|
||||
: VT100
|
||||
|
|
@ -504,7 +504,7 @@ manipulation sequences. The generic format is:
|
|||
| \\E[ = _Ps_ c
|
||||
: DA3
|
||||
: VT510
|
||||
: send tertiary device attributes. Foot responds with "FOOT", in
|
||||
: Send tertiary device attributes. Foot responds with "FOOT", in
|
||||
hexadecimal.
|
||||
| \\E[ _Pm_ d
|
||||
: VPA
|
||||
|
|
@ -595,7 +595,7 @@ All _OSC_ sequences begin with *\\E]*, sometimes abbreviated _OSC_.
|
|||
|
||||
[[ *Sequence*
|
||||
:[ *Origin*
|
||||
:[ *Description*
|
||||
:< *Description*
|
||||
| \\E] 0 ; _Pt_ \\E\\
|
||||
: xterm
|
||||
: Set window icon and title to _Pt_ (foot does not support setting the
|
||||
|
|
@ -693,7 +693,7 @@ All _DCS_ sequences begin with *\\EP* (sometimes abbreviated _DCS_),
|
|||
and are terminated by *\\E\\* (ST).
|
||||
|
||||
[[ *Sequence*
|
||||
:[ *Description*
|
||||
:< *Description*
|
||||
| \\EP q <sixel data> \\E\\
|
||||
: Emit a sixel image at the current cursor position
|
||||
| \\P $ q <query> \\E\\
|
||||
|
|
@ -703,7 +703,7 @@ and are terminated by *\\E\\* (ST).
|
|||
: Begin (_C_=*1*) or end (_C_=*2*) application synchronized updates.
|
||||
This sequence is supported for compatibility reasons, but it's
|
||||
recommended to use private mode 2026 (see above) instead.
|
||||
| \\EP + q <hex encoded capability name> \\E\\
|
||||
| \\EP + q <hex encoded capability name> \\E\\
|
||||
: Query builtin terminfo database (XTGETTCAP)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -142,7 +142,7 @@ the foot command line
|
|||
|
||||
*-d*,*--log-level*={*info*,*warning*,*error*,*none*}
|
||||
Log level, used both for log output on stderr as well as
|
||||
syslog. Default: _info_.
|
||||
syslog. Default: _warning_.
|
||||
|
||||
*-l*,*--log-colorize*=[{*never*,*always*,*auto*}]
|
||||
Enables or disables colorization of log output on stderr. Default:
|
||||
|
|
@ -543,10 +543,24 @@ In all other cases, the exit code is that of the client application
|
|||
set according to either the *--term* command-line option or the
|
||||
*term* config option in *foot.ini*(5).
|
||||
|
||||
*PWD*
|
||||
Current working directory (at the time of launching foot)
|
||||
|
||||
*COLORTERM*
|
||||
This variable is set to *truecolor*, to indicate to client
|
||||
applications that 24-bit RGB colors are supported.
|
||||
|
||||
*TERM_PROGRAM*
|
||||
Always set to *foot*. This can be used by client applications to
|
||||
check which terminal is in use, but with the caveat that it may
|
||||
have been inherited from a parent process in other terminals that
|
||||
aren't known to set the variable.
|
||||
|
||||
*TERM_PROGRAM_VERSION*
|
||||
Set to the foot version string, in the format _major_*.*_minor_*.*_patch_
|
||||
or _major_*.*_minor_*.*_patch_*-*_revision_*-\g*_commit_ for inter-release
|
||||
builds. The same caveat as for *TERM_PROGRAM* applies.
|
||||
|
||||
In addition to the variables listed above, custom environment
|
||||
variables may be defined in *foot.ini*(5).
|
||||
|
||||
|
|
@ -561,7 +575,7 @@ the same issue.
|
|||
The report should contain the following:
|
||||
|
||||
- Foot version (*foot --version*).
|
||||
- Log output from foot (start foot from another terminal).
|
||||
- Log output from foot (run *foot -d info* from another terminal).
|
||||
- Which Wayland compositor (and version) you are running.
|
||||
- If reporting a crash, please try to provide a *bt full* backtrace
|
||||
with symbols.
|
||||
|
|
|
|||
|
|
@ -22,6 +22,15 @@ in this order:
|
|||
An example configuration file containing all options with their default value
|
||||
commented out will usually be installed to */etc/xdg/foot/foot.ini*.
|
||||
|
||||
Options are set using KEY=VALUE pairs:
|
||||
|
||||
*\[colors\]*++
|
||||
*background=000000*++
|
||||
*foreground=ffffff*
|
||||
|
||||
Empty values (*KEY=*) are not supported. String options do allow the
|
||||
empty string to be set, but it must be quoted: *KEY=""*)
|
||||
|
||||
# SECTION: main
|
||||
|
||||
*shell*
|
||||
|
|
@ -71,6 +80,19 @@ commented out will usually be installed to */etc/xdg/foot/foot.ini*.
|
|||
Default: _monospace:size=8_ (*font*), _not set_ (*font-bold*,
|
||||
*font-italic*, *font-bold-italic*).
|
||||
|
||||
*font-size-adjustment*
|
||||
Amount, in _points_, _pixels_ or _percent_, to increment/decrement
|
||||
the font size when zooming in our out.
|
||||
|
||||
Examples:
|
||||
```
|
||||
font-size-adjustment=0.5 # Adjust by 0.5 points
|
||||
font-size-adjustment=10xp # Adjust by 10 pixels
|
||||
font-size-adjustment=7.5% # Adjust by 7.5 percent
|
||||
```
|
||||
|
||||
Default: _0.5_
|
||||
|
||||
*include*
|
||||
Absolute path to configuration file to import.
|
||||
|
||||
|
|
@ -213,15 +235,19 @@ commented out will usually be installed to */etc/xdg/foot/foot.ini*.
|
|||
Default: _0x0_.
|
||||
|
||||
*resize-delay-ms*
|
||||
Time, in milliseconds, of "idle time" before foot sends the new
|
||||
window dimensions to the client application while doing an
|
||||
interactive resize of a foot window. Idle time in this context is
|
||||
a period of time where the window size is not changing.
|
||||
|
||||
Time, in milliseconds, of "idle time" before foot performs text
|
||||
reflow, and sends the new window dimensions to the client
|
||||
application while doing an interactive resize of a foot
|
||||
window. Idle time in this context is a period of time where the
|
||||
window size is not changing.
|
||||
|
||||
In other words, while you are fiddling with the window size, foot
|
||||
does not send the updated dimensions to the client. Only when you
|
||||
pause the fiddling for *resize-delay-ms* milliseconds is the
|
||||
client updated.
|
||||
does not send the updated dimensions to the client. It also does a
|
||||
fast "truncating" resize of the grid, instead of actually
|
||||
reflowing the contents. Only when you pause the fiddling for
|
||||
*resize-delay-ms* milliseconds is the client updated, and the
|
||||
contents properly reflowed.
|
||||
|
||||
Emphasis is on _while_ here; as soon as the interactive resize
|
||||
ends (i.e. when you let go of the window border), the final
|
||||
|
|
@ -339,7 +365,7 @@ Note: do not set *TERM* here; use the *term* option in the main
|
|||
*urgent*
|
||||
When set to _yes_, foot will signal urgency to the compositor
|
||||
through the XDG activation protocol whenever *BEL* is received,
|
||||
and the window does NOT have keyboard foccus.
|
||||
and the window does NOT have keyboard focus.
|
||||
|
||||
If the compositor does not implement this protocol, the margins
|
||||
will be painted in red instead.
|
||||
|
|
@ -448,14 +474,13 @@ applications can change these at runtime.
|
|||
by applications. Default: _no_.
|
||||
|
||||
*color*
|
||||
Two RRGGBB values (i.e. plain old 6-digit hex values, without
|
||||
prefix) specifying the foreground (text) and background (cursor)
|
||||
colors for the cursor.
|
||||
Two space separated RRGGBB values (i.e. plain old 6-digit hex
|
||||
values, without prefix) specifying the foreground (text) and
|
||||
background (cursor) colors for the cursor.
|
||||
|
||||
Default: _inverse foreground/background colors_.
|
||||
|
||||
Note that this value only applies to the block cursor. The other
|
||||
cursor styles are always rendered with the foreground color.
|
||||
Example: *ff0000 00ff00* (green cursor, red text)
|
||||
|
||||
Default: the regular foreground and background colors, reversed.
|
||||
|
||||
*beam-thickness*
|
||||
Thickness (width) of the beam styled cursor. The value is in
|
||||
|
|
@ -551,7 +576,7 @@ can configure the background transparency with the _alpha_ option.
|
|||
options are unconfigured). 24-bit RGB colors will typically fall
|
||||
into this category.
|
||||
|
||||
Note that applications can change the *regularN* and *brighN*
|
||||
Note that applications can change the *regularN* and *brightN*
|
||||
colors at runtime. However, they have no way of changing the
|
||||
*dimN* colors. If an application has changed the *regularN*
|
||||
colors, foot will still use the corresponding *dimN* color, as
|
||||
|
|
@ -939,7 +964,7 @@ Be careful; do not use single-letter keys that are also used in
|
|||
original text.
|
||||
|
||||
But with e.g. OSC-8 URLs (the terminal version of HTML anchors,
|
||||
i.e. "links"), the text on the screen can be something completey
|
||||
i.e. "links"), the text on the screen can be something completely
|
||||
different than the URL.
|
||||
|
||||
This action toggles between showing and hiding the URL on the jump
|
||||
|
|
@ -1235,7 +1260,7 @@ any of these options.
|
|||
|
||||
*max* uses the width of the largest codepoint in the cluster.
|
||||
|
||||
Default: _wcswidth_
|
||||
Default: _double-width_
|
||||
|
||||
*font-monospace-warn*
|
||||
Boolean. When enabled, foot will use heuristics to try to verify
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ terminal has terminated.
|
|||
|
||||
*-d*,*--log-level*={*info*,*warning*,*error*,*none*}
|
||||
Log level, used both for log output on stderr as well as
|
||||
syslog. Default: _info_.
|
||||
syslog. Default: _warning_.
|
||||
|
||||
*-l*,*--log-colorize*=[{*never*,*always*,*auto*}]
|
||||
Enables or disables colorization of log output on stderr.
|
||||
|
|
@ -89,7 +89,7 @@ terminal has terminated.
|
|||
|
||||
# EXIT STATUS
|
||||
|
||||
Footlient will exit with code 220 if there is a failure in footclient
|
||||
Footclient will exit with code 220 if there is a failure in footclient
|
||||
itself (for example, the server socket does not exist).
|
||||
|
||||
If *-N*,*--no-wait* is used, footclient exits with code 0 as soon as
|
||||
|
|
@ -158,6 +158,17 @@ terminfo entries manually, by copying *foot* and *foot-direct* to
|
|||
This variable is set to *truecolor*, to indicate to client
|
||||
applications that 24-bit RGB colors are supported.
|
||||
|
||||
*TERM_PROGRAM*
|
||||
Always set to *foot*. This can be used by client applications to
|
||||
check which terminal is in use, but with the caveat that it may
|
||||
have been inherited from a parent process in other terminals that
|
||||
aren't known to set the variable.
|
||||
|
||||
*TERM_PROGRAM_VERSION*
|
||||
Set to the foot version string, in the format _major_*.*_minor_*.*_patch_
|
||||
or _major_*.*_minor_*.*_patch_*-*_revision_*-\g*_commit_ for inter-release
|
||||
builds. The same caveat as for *TERM_PROGRAM* applies.
|
||||
|
||||
In addition to the variables listed above, custom environment
|
||||
variables may be defined in *foot.ini*(5).
|
||||
|
||||
|
|
|
|||
19
foot.info
19
foot.info
|
|
@ -12,6 +12,10 @@
|
|||
setaf=\E[%?%p1%{8}%<%t3%p1%d%e38\:2\:\:%p1%{65536}%/%d\:%p1%{256}%/%{255}%&%d\:%p1%{255}%&%d%;m,
|
||||
|
||||
@default_terminfo@+base|foot base fragment,
|
||||
AX,
|
||||
Tc,
|
||||
XF,
|
||||
XT,
|
||||
am,
|
||||
bce,
|
||||
bw,
|
||||
|
|
@ -21,21 +25,24 @@
|
|||
msgr,
|
||||
npc,
|
||||
xenl,
|
||||
AX,
|
||||
XT,
|
||||
Tc,
|
||||
cols#80,
|
||||
it#8,
|
||||
lines#24,
|
||||
pairs#0x10000,
|
||||
BD=\E[?2004l,
|
||||
BE=\E[?2004h,
|
||||
Cr=\E]112\E\\,
|
||||
Cs=\E]12;%p1%s\E\\,
|
||||
E3=\E[3J,
|
||||
Ms=\E]52;%p1%s;%p2%s\E\\,
|
||||
PE=\E[201~,
|
||||
PS=\E[200~,
|
||||
RV=\E[>c,
|
||||
Se=\E[ q,
|
||||
Ss=\E[%p1%d q,
|
||||
Sync=\E[?2026%?%p1%{1}%-%tl%eh,
|
||||
XM=\E[?1006;1000%?%p1%{1}%=%th%el%;,
|
||||
XR=\E[>0q,
|
||||
acsc=``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~,
|
||||
bel=^G,
|
||||
blink=\E[5m,
|
||||
|
|
@ -79,7 +86,7 @@
|
|||
indn=\E[%p1%dS,
|
||||
initc=\E]4;%p1%d;rgb\:%p2%{255}%*%{1000}%/%2.2X/%p3%{255}%*%{1000}%/%2.2X/%p4%{255}%*%{1000}%/%2.2X\E\\,
|
||||
invis=\E[8m,
|
||||
is2=\E[!p\E[?3;4l\E[4l\E>,
|
||||
is2=\E[!p\E[4l\E>,
|
||||
kDC3=\E[3;3~,
|
||||
kDC4=\E[3;4~,
|
||||
kDC5=\E[3;5~,
|
||||
|
|
@ -237,7 +244,8 @@
|
|||
rmul=\E[24m,
|
||||
rmxx=\E[29m,
|
||||
rs1=\Ec,
|
||||
rs2=\E[!p\E[?3;4l\E[4l\E>,
|
||||
rs2=\E[!p\E[4l\E>,
|
||||
rv=\E\\[[0-9]+;[0-9]+;[0-9]+c,
|
||||
sc=\E7,
|
||||
setrgbb=\E[48\:2\:\:%p1%d\:%p2%d\:%p3%dm,
|
||||
setrgbf=\E[38\:2\:\:%p1%d\:%p2%d\:%p3%dm,
|
||||
|
|
@ -260,6 +268,7 @@
|
|||
u9=\E[c,
|
||||
vpa=\E[%i%p1%dd,
|
||||
xm=\E[<%i%p3%d;%p1%d;%p2%d;%?%p4%tM%em%;,
|
||||
xr=\EP>\\|[ -~]+\E\\\\,
|
||||
|
||||
# XT,
|
||||
# AX,
|
||||
|
|
|
|||
3
foot.ini
3
foot.ini
|
|
@ -12,6 +12,7 @@
|
|||
# font-bold=<bold variant of regular font>
|
||||
# font-italic=<italic variant of regular font>
|
||||
# font-bold-italic=<bold+italic variant of regular font>
|
||||
# font-size-adjustment=0.5
|
||||
# line-height=<font metrics>
|
||||
# letter-spacing=0
|
||||
# horizontal-letter-offset=0
|
||||
|
|
@ -48,7 +49,7 @@
|
|||
# lines=1000
|
||||
# multiplier=3.0
|
||||
# indicator-position=relative
|
||||
# indicator-format=
|
||||
# indicator-format=""
|
||||
|
||||
[url]
|
||||
# launch=xdg-open ${url}
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ patch=$(echo "${new_version}" | sed -r 's/([0-9]+)\.([0-9]+)\.([0-9]+).*/\3/')
|
|||
extra=$(echo "${new_version}" | sed -r 's/([0-9]+)\.([0-9]+)\.([0-9]+)(-([0-9]+-g[a-z0-9]+) .*)?.*/\5/')
|
||||
|
||||
new_version="#define FOOT_VERSION \"${new_version}\"
|
||||
#define FOOT_VERSION_SHORT \"${git_version:-${default_version}}\"
|
||||
#define FOOT_MAJOR ${major}
|
||||
#define FOOT_MINOR ${minor}
|
||||
#define FOOT_PATCH ${patch}
|
||||
|
|
|
|||
11
grid.c
11
grid.c
|
|
@ -210,6 +210,8 @@ grid_snapshot(const struct grid *grid)
|
|||
clone->offset = grid->offset;
|
||||
clone->view = grid->view;
|
||||
clone->cursor = grid->cursor;
|
||||
clone->saved_cursor = grid->saved_cursor;
|
||||
clone->kitty_kbd = grid->kitty_kbd;
|
||||
clone->rows = xcalloc(grid->num_rows, sizeof(clone->rows[0]));
|
||||
memset(&clone->scroll_damage, 0, sizeof(clone->scroll_damage));
|
||||
memset(&clone->sixel_images, 0, sizeof(clone->sixel_images));
|
||||
|
|
@ -285,6 +287,9 @@ grid_snapshot(const struct grid *grid)
|
|||
void
|
||||
grid_free(struct grid *grid)
|
||||
{
|
||||
if (grid == NULL)
|
||||
return;
|
||||
|
||||
for (int r = 0; r < grid->num_rows; r++)
|
||||
grid_row_free(grid->rows[r]);
|
||||
|
||||
|
|
@ -483,6 +488,8 @@ grid_resize_without_reflow(
|
|||
grid->saved_cursor.point = saved_cursor;
|
||||
|
||||
grid->cur_row = new_grid[(grid->offset + cursor.row) & (new_rows - 1)];
|
||||
xassert(grid->cur_row != NULL);
|
||||
|
||||
grid->cursor.lcf = false;
|
||||
grid->saved_cursor.lcf = false;
|
||||
|
||||
|
|
@ -786,7 +793,7 @@ grid_resize_and_reflow(
|
|||
|
||||
/*
|
||||
* Set end-coordinate for this chunk, by finding the next
|
||||
* point-of-interrest on this row.
|
||||
* point-of-interest on this row.
|
||||
*
|
||||
* If there are no more tracking points, or URI ranges,
|
||||
* the end-coordinate will be at the end of the row,
|
||||
|
|
@ -1045,6 +1052,8 @@ grid_resize_and_reflow(
|
|||
saved_cursor.col = min(saved_cursor.col, new_cols - 1);
|
||||
|
||||
grid->cur_row = new_grid[(grid->offset + cursor.row) & (new_rows - 1)];
|
||||
xassert(grid->cur_row != NULL);
|
||||
|
||||
grid->cursor.point = cursor;
|
||||
grid->saved_cursor.point = saved_cursor;
|
||||
|
||||
|
|
|
|||
41
input.c
41
input.c
|
|
@ -898,7 +898,7 @@ struct kbd_ctx {
|
|||
const uint8_t *buf;
|
||||
size_t count;
|
||||
} utf8;
|
||||
uint32_t utf32;
|
||||
uint32_t *utf32;
|
||||
|
||||
enum xkb_compose_status compose_status;
|
||||
enum wl_keyboard_key_state key_state;
|
||||
|
|
@ -1121,12 +1121,18 @@ kitty_kbd_protocol(struct seat *seat, struct terminal *term,
|
|||
(seat->kbd.mod_num != XKB_MOD_INVALID ? 1 << seat->kbd.mod_num : 0);
|
||||
|
||||
const xkb_keysym_t sym = ctx->sym;
|
||||
const uint32_t utf32 = ctx->utf32;
|
||||
const uint32_t *utf32 = ctx->utf32;
|
||||
const uint8_t *const utf8 = ctx->utf8.buf;
|
||||
|
||||
const bool is_text = iswprint(utf32) && (effective & ~caps_num) == 0;
|
||||
const size_t count = ctx->utf8.count;
|
||||
|
||||
bool is_text = count > 0 && utf32 != NULL && (effective & ~caps_num) == 0;
|
||||
for (size_t i = 0; utf32[i] != U'\0'; i++) {
|
||||
if (!iswprint(utf32[i])) {
|
||||
is_text = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const bool report_associated_text =
|
||||
(flags & KITTY_KBD_REPORT_ASSOCIATED) && is_text && !released;
|
||||
|
||||
|
|
@ -1245,7 +1251,7 @@ emit_escapes:
|
|||
: sym;
|
||||
|
||||
if (composed)
|
||||
key = utf32;
|
||||
key = utf32[0]; /* TODO: what if there are multiple codepoints? */
|
||||
else {
|
||||
key = xkb_keysym_to_utf32(sym_to_use);
|
||||
if (key == 0)
|
||||
|
|
@ -1284,7 +1290,7 @@ emit_escapes:
|
|||
} else
|
||||
event[0] = '\0';
|
||||
|
||||
char buf[64], *p = buf;
|
||||
char buf[128], *p = buf;
|
||||
size_t left = sizeof(buf);
|
||||
size_t bytes;
|
||||
|
||||
|
|
@ -1316,8 +1322,16 @@ emit_escapes:
|
|||
}
|
||||
|
||||
if (report_associated_text) {
|
||||
bytes = snprintf(p, left, "%s;%u", !emit_mods ? ";" : "", utf32);
|
||||
bytes = snprintf(p, left, "%s;%u", !emit_mods ? ";" : "", utf32[0]);
|
||||
p += bytes; left -= bytes;
|
||||
|
||||
/* Additional text codepoints */
|
||||
if (utf32[0] != U'\0') {
|
||||
for (size_t i = 1; utf32[i] != U'\0'; i++) {
|
||||
bytes = snprintf(p, left, ":%u", utf32[i]);
|
||||
p += bytes; left -= bytes;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bytes = snprintf(p, left, "%c", final);
|
||||
|
|
@ -1514,19 +1528,20 @@ key_press_release(struct seat *seat, struct terminal *term, uint32_t serial,
|
|||
* and use a malloc:ed buffer when necessary */
|
||||
uint8_t buf[32];
|
||||
uint8_t *utf8 = count < sizeof(buf) ? buf : xmalloc(count + 1);
|
||||
uint32_t utf32 = (uint32_t)-1;
|
||||
uint32_t *utf32 = NULL;
|
||||
|
||||
if (composed) {
|
||||
xkb_compose_state_get_utf8(
|
||||
seat->kbd.xkb_compose_state, (char *)utf8, count + 1);
|
||||
|
||||
char32_t wc;
|
||||
if (mbrtoc32(&wc, (const char *)utf8, count, &(mbstate_t){0}) == count)
|
||||
utf32 = wc;
|
||||
if (count > 0)
|
||||
utf32 = ambstoc32((const char *)utf8);
|
||||
} else {
|
||||
xkb_state_key_get_utf8(
|
||||
seat->kbd.xkb_state, key, (char *)utf8, count + 1);
|
||||
utf32 = xkb_state_key_get_utf32(seat->kbd.xkb_state, key);
|
||||
|
||||
utf32 = xcalloc(2, sizeof(utf32[0]));
|
||||
utf32[0] = xkb_state_key_get_utf32(seat->kbd.xkb_state, key);
|
||||
}
|
||||
|
||||
struct kbd_ctx ctx = {
|
||||
|
|
@ -1563,6 +1578,8 @@ key_press_release(struct seat *seat, struct terminal *term, uint32_t serial,
|
|||
selection_cancel(term);
|
||||
}
|
||||
|
||||
free(utf32);
|
||||
|
||||
maybe_repeat:
|
||||
clock_gettime(
|
||||
term->wl->presentation_clock_id, &term->render.input_time);
|
||||
|
|
|
|||
|
|
@ -350,6 +350,60 @@ maybe_repair_key_combo(const struct seat *seat,
|
|||
return sym;
|
||||
}
|
||||
|
||||
static int
|
||||
key_cmp(struct key_binding a, struct key_binding b)
|
||||
{
|
||||
xassert(a.type == b.type);
|
||||
|
||||
/*
|
||||
* Sort bindings such that bindings with the same symbol are
|
||||
* sorted with the binding having the most modifiers comes first.
|
||||
*
|
||||
* This fixes an issue where the “wrong” key binding are triggered
|
||||
* when used with “consumed” modifiers.
|
||||
*
|
||||
* For example: if Control+BackSpace is bound before
|
||||
* Control+Shift+BackSpace, then the latter binding is never
|
||||
* triggered.
|
||||
*
|
||||
* Why? Because Shift is a consumed modifier. This means
|
||||
* Control+BackSpace is “the same” as Control+Shift+BackSpace.
|
||||
*
|
||||
* By sorting bindings with more modifiers first, we work around
|
||||
* the problem. But note that it is *just* a workaround, and I’m
|
||||
* not confident there aren’t cases where it doesn’t work.
|
||||
*
|
||||
* See https://codeberg.org/dnkl/foot/issues/1280
|
||||
*/
|
||||
|
||||
const int a_mod_count = __builtin_popcount(a.mods);
|
||||
const int b_mod_count = __builtin_popcount(b.mods);
|
||||
|
||||
switch (a.type) {
|
||||
case KEY_BINDING:
|
||||
if (a.k.sym != b.k.sym)
|
||||
return b.k.sym - a.k.sym;
|
||||
return b_mod_count - a_mod_count;
|
||||
|
||||
case MOUSE_BINDING: {
|
||||
if (a.m.button != b.m.button)
|
||||
return b.m.button - a.m.button;
|
||||
if (a_mod_count != b_mod_count)
|
||||
return b_mod_count - a_mod_count;
|
||||
return b.m.count - a.m.count;
|
||||
}
|
||||
}
|
||||
|
||||
BUG("invalid key binding type");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void NOINLINE
|
||||
sort_binding_list(key_binding_list_t *list)
|
||||
{
|
||||
tll_sort(*list, key_cmp);
|
||||
}
|
||||
|
||||
static void NOINLINE
|
||||
convert_key_binding(struct key_set *set,
|
||||
const struct config_key_binding *conf_binding,
|
||||
|
|
@ -371,6 +425,7 @@ convert_key_binding(struct key_set *set,
|
|||
},
|
||||
};
|
||||
tll_push_back(*bindings, binding);
|
||||
sort_binding_list(bindings);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -421,6 +476,7 @@ convert_mouse_binding(struct key_set *set,
|
|||
},
|
||||
};
|
||||
tll_push_back(set->public.mouse, binding);
|
||||
sort_binding_list(&set->public.mouse);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
|||
9
log.c
9
log.c
|
|
@ -15,7 +15,7 @@
|
|||
#include "xsnprintf.h"
|
||||
|
||||
static bool colorize = false;
|
||||
static bool do_syslog = true;
|
||||
static bool do_syslog = false;
|
||||
static enum log_class log_level = LOG_CLASS_NONE;
|
||||
|
||||
static const struct {
|
||||
|
|
@ -45,8 +45,13 @@ log_init(enum log_colorize _colorize, bool _do_syslog,
|
|||
log_level = _log_level;
|
||||
|
||||
int slvl = log_level_map[_log_level].syslog_equivalent;
|
||||
if (do_syslog && slvl != -1) {
|
||||
if (slvl < 0)
|
||||
do_syslog = false;
|
||||
|
||||
if (do_syslog) {
|
||||
openlog(NULL, /*LOG_PID*/0, facility_map[syslog_facility]);
|
||||
|
||||
xassert(slvl >= 0);
|
||||
setlogmask(LOG_UPTO(slvl));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
13
main.c
13
main.c
|
|
@ -83,7 +83,7 @@ print_usage(const char *prog_name)
|
|||
" Without PATH, $XDG_RUNTIME_DIR/foot-$WAYLAND_DISPLAY.sock will be used.\n"
|
||||
" -H,--hold remain open after child process exits\n"
|
||||
" -p,--print-pid=FILE|FD print PID to file or FD (only applicable in server mode)\n"
|
||||
" -d,--log-level={info|warning|error|none} log level (info)\n"
|
||||
" -d,--log-level={info|warning|error|none} log level (warning)\n"
|
||||
" -l,--log-colorize=[{never|always|auto}] enable/disable colorization of log output on stderr\n"
|
||||
" -s,--log-no-syslog disable syslog logging (only applicable in server mode)\n"
|
||||
" -v,--version show the version number and quit\n"
|
||||
|
|
@ -236,7 +236,7 @@ main(int argc, char *const *argv)
|
|||
bool fullscreen = false;
|
||||
bool unlink_pid_file = false;
|
||||
const char *pid_file = NULL;
|
||||
enum log_class log_level = LOG_CLASS_INFO;
|
||||
enum log_class log_level = LOG_CLASS_WARNING;
|
||||
enum log_colorize log_colorize = LOG_COLORIZE_AUTO;
|
||||
bool log_syslog = true;
|
||||
user_notifications_t user_notifications = tll_init();
|
||||
|
|
@ -433,8 +433,13 @@ main(int argc, char *const *argv)
|
|||
|
||||
const char *locale = setlocale(LC_CTYPE, "");
|
||||
if (locale == NULL) {
|
||||
LOG_ERR("setlocale() failed");
|
||||
return ret;
|
||||
/*
|
||||
* If the user has configured an invalid locale, or a name of a locale
|
||||
* that does not exist on this system, then the above call may return
|
||||
* NULL. We should just continue with the fallback method below.
|
||||
*/
|
||||
LOG_WARN("setlocale() failed");
|
||||
locale = "C";
|
||||
}
|
||||
|
||||
LOG_INFO("locale: %s", locale);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
project('foot', 'c',
|
||||
version: '1.13.1',
|
||||
version: '1.14.0',
|
||||
license: 'MIT',
|
||||
meson_version: '>=0.58.0',
|
||||
default_options: [
|
||||
|
|
@ -110,7 +110,7 @@ if utf8proc.found()
|
|||
add_project_arguments('-DFOOT_GRAPHEME_CLUSTERING=1', language: 'c')
|
||||
endif
|
||||
|
||||
tllist = dependency('tllist', version: '>=1.0.4', fallback: 'tllist')
|
||||
tllist = dependency('tllist', version: '>=1.1.0', fallback: 'tllist')
|
||||
fcft = dependency('fcft', version: ['>=3.0.1', '<4.0.0'], fallback: 'fcft')
|
||||
|
||||
wayland_protocols_datadir = wayland_protocols.get_variable('pkgdatadir')
|
||||
|
|
@ -331,6 +331,7 @@ endif
|
|||
|
||||
subdir('completions')
|
||||
subdir('icons')
|
||||
subdir('utils')
|
||||
|
||||
if (get_option('tests'))
|
||||
subdir('tests')
|
||||
|
|
|
|||
|
|
@ -9,3 +9,4 @@ Keywords=shell;prompt;command;commandline;
|
|||
Name=Foot Server
|
||||
GenericName=Terminal
|
||||
Comment=A wayland native terminal emulator (server)
|
||||
StartupWMClass=foot
|
||||
|
|
|
|||
|
|
@ -9,3 +9,4 @@ Keywords=shell;prompt;command;commandline;
|
|||
Name=Foot
|
||||
GenericName=Terminal
|
||||
Comment=A wayland native terminal emulator
|
||||
StartupWMClass=foot
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<component type="desktop-application">
|
||||
<id>org.codeberg.dnkl.foot</id>
|
||||
<metadata_license>CC0-1.0</metadata_license>
|
||||
<metadata_license>MIT</metadata_license>
|
||||
<project_license>MIT</project_license>
|
||||
<developer_name>dnkl</developer_name>
|
||||
<name>foot</name>
|
||||
|
|
|
|||
|
|
@ -9,3 +9,4 @@ Keywords=shell;prompt;command;commandline;
|
|||
Name=Foot Client
|
||||
GenericName=Terminal
|
||||
Comment=A wayland native terminal emulator (client)
|
||||
StartupWMClass=foot
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ rm -f "${blddir}"/pgo-ok
|
|||
# To ensure profiling data is generated in the build directory
|
||||
cd "${blddir}"
|
||||
|
||||
"${blddir}"/utils/xtgettcap
|
||||
"${blddir}"/footclient --version
|
||||
"${blddir}"/foot \
|
||||
--config=/dev/null \
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ rm -f "${blddir}"/pgo-ok
|
|||
# To ensure profiling data is generated in the build directory
|
||||
cd "${blddir}"
|
||||
|
||||
"${blddir}"/utils/xtgettcap
|
||||
"${blddir}"/footclient --version
|
||||
"${blddir}"/foot --version
|
||||
"${blddir}"/pgo "${pgo_data}"
|
||||
|
|
|
|||
30
pgo/pgo.c
30
pgo/pgo.c
|
|
@ -228,10 +228,14 @@ main(int argc, const char *const *argv)
|
|||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
struct row **rows = calloc(grid_row_count, sizeof(rows[0]));
|
||||
struct row **normal_rows = calloc(grid_row_count, sizeof(normal_rows[0]));
|
||||
struct row **alt_rows = calloc(grid_row_count, sizeof(alt_rows[0]));
|
||||
|
||||
for (int i = 0; i < grid_row_count; i++) {
|
||||
rows[i] = calloc(1, sizeof(*rows[i]));
|
||||
rows[i]->cells = calloc(col_count, sizeof(rows[i]->cells[0]));
|
||||
normal_rows[i] = calloc(1, sizeof(*normal_rows[i]));
|
||||
normal_rows[i]->cells = calloc(col_count, sizeof(normal_rows[i]->cells[0]));
|
||||
alt_rows[i] = calloc(1, sizeof(*alt_rows[i]));
|
||||
alt_rows[i]->cells = calloc(col_count, sizeof(alt_rows[i]->cells[0]));
|
||||
}
|
||||
|
||||
struct config conf = {
|
||||
|
|
@ -254,14 +258,14 @@ main(int argc, const char *const *argv)
|
|||
.normal = {
|
||||
.num_rows = grid_row_count,
|
||||
.num_cols = col_count,
|
||||
.rows = rows,
|
||||
.cur_row = rows[0],
|
||||
.rows = normal_rows,
|
||||
.cur_row = normal_rows[0],
|
||||
},
|
||||
.alt = {
|
||||
.num_rows = grid_row_count,
|
||||
.num_cols = col_count,
|
||||
.rows = rows,
|
||||
.cur_row = rows[0],
|
||||
.rows = alt_rows,
|
||||
.cur_row = alt_rows[0],
|
||||
},
|
||||
.scale = 1,
|
||||
.width = col_count * 8,
|
||||
|
|
@ -371,11 +375,17 @@ out:
|
|||
tll_free(wayl.terms);
|
||||
|
||||
for (int i = 0; i < grid_row_count; i++) {
|
||||
free(rows[i]->cells);
|
||||
free(rows[i]);
|
||||
if (normal_rows[i] != NULL)
|
||||
free(normal_rows[i]->cells);
|
||||
free(normal_rows[i]);
|
||||
|
||||
if (alt_rows[i] != NULL)
|
||||
free(alt_rows[i]->cells);
|
||||
free(alt_rows[i]);
|
||||
}
|
||||
|
||||
free(rows);
|
||||
free(normal_rows);
|
||||
free(alt_rows);
|
||||
close(lower_fd);
|
||||
close(upper_fd);
|
||||
return ret;
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ do_pgo=no
|
|||
CFLAGS="${CFLAGS-} -O3"
|
||||
|
||||
case $(${CC-cc} --version) in
|
||||
*GCC*)
|
||||
*Free\ Software\ Foundation*)
|
||||
compiler=gcc
|
||||
do_pgo=yes
|
||||
;;
|
||||
|
|
|
|||
269
render.c
269
render.c
|
|
@ -420,6 +420,12 @@ cursor_colors_for_cell(const struct terminal *term, const struct cell *cell,
|
|||
} else {
|
||||
*cursor_color = *fg;
|
||||
*text_color = *bg;
|
||||
|
||||
if (unlikely(text_color->alpha != 0xffff)) {
|
||||
/* The *only* color that can have transparency is the
|
||||
* default background color */
|
||||
*text_color = color_hex_to_pixman(term->colors.bg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -639,17 +645,21 @@ render_cell(struct terminal *term, pixman_image_t *pix,
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
if (single == NULL && grapheme == NULL) {
|
||||
xassert(base != 0);
|
||||
single = fcft_rasterize_char_utf32(font, base, term->font_subpixel);
|
||||
if (single == NULL) {
|
||||
if (unlikely(base >= CELL_SPACER)) {
|
||||
glyph_count = 0;
|
||||
cell_cols = 1;
|
||||
} else {
|
||||
glyph_count = 1;
|
||||
glyphs = &single;
|
||||
cell_cols = single->cols;
|
||||
xassert(base != 0);
|
||||
single = fcft_rasterize_char_utf32(font, base, term->font_subpixel);
|
||||
if (single == NULL) {
|
||||
glyph_count = 0;
|
||||
cell_cols = 1;
|
||||
} else {
|
||||
glyph_count = 1;
|
||||
glyphs = &single;
|
||||
cell_cols = single->cols;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -919,14 +929,19 @@ static void
|
|||
grid_render_scroll(struct terminal *term, struct buffer *buf,
|
||||
const struct damage *dmg)
|
||||
{
|
||||
int height = (dmg->region.end - dmg->region.start - dmg->lines) * term->cell_height;
|
||||
|
||||
LOG_DBG(
|
||||
"damage: SCROLL: %d-%d by %d lines",
|
||||
dmg->region.start, dmg->region.end, dmg->lines);
|
||||
|
||||
if (height <= 0)
|
||||
const int region_size = dmg->region.end - dmg->region.start;
|
||||
|
||||
if (dmg->lines >= region_size) {
|
||||
/* The entire scroll region will be scrolled out (i.e. replaced) */
|
||||
return;
|
||||
}
|
||||
|
||||
const int height = (region_size - dmg->lines) * term->cell_height;
|
||||
xassert(height > 0);
|
||||
|
||||
#if TIME_SCROLL_DAMAGE
|
||||
struct timespec start_time;
|
||||
|
|
@ -1027,14 +1042,19 @@ static void
|
|||
grid_render_scroll_reverse(struct terminal *term, struct buffer *buf,
|
||||
const struct damage *dmg)
|
||||
{
|
||||
int height = (dmg->region.end - dmg->region.start - dmg->lines) * term->cell_height;
|
||||
|
||||
LOG_DBG(
|
||||
"damage: SCROLL REVERSE: %d-%d by %d lines",
|
||||
dmg->region.start, dmg->region.end, dmg->lines);
|
||||
|
||||
if (height <= 0)
|
||||
const int region_size = dmg->region.end - dmg->region.start;
|
||||
|
||||
if (dmg->lines >= region_size) {
|
||||
/* The entire scroll region will be scrolled out (i.e. replaced) */
|
||||
return;
|
||||
}
|
||||
|
||||
const int height = (region_size - dmg->lines) * term->cell_height;
|
||||
xassert(height > 0);
|
||||
|
||||
#if TIME_SCROLL_DAMAGE
|
||||
struct timespec start_time;
|
||||
|
|
@ -3663,13 +3683,67 @@ tiocswinsz(struct terminal *term)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
delayed_reflow_of_normal_grid(struct terminal *term)
|
||||
{
|
||||
if (term->interactive_resizing.grid == NULL)
|
||||
return;
|
||||
|
||||
xassert(term->interactive_resizing.new_rows > 0);
|
||||
|
||||
struct coord *const tracking_points[] = {
|
||||
&term->selection.coords.start,
|
||||
&term->selection.coords.end,
|
||||
};
|
||||
|
||||
/* Reflow the original (since before the resize was started) grid,
|
||||
* to the *current* dimensions */
|
||||
grid_resize_and_reflow(
|
||||
term->interactive_resizing.grid,
|
||||
term->interactive_resizing.new_rows, term->normal.num_cols,
|
||||
term->interactive_resizing.old_screen_rows, term->rows,
|
||||
term->selection.coords.end.row >= 0 ? ALEN(tracking_points) : 0,
|
||||
tracking_points);
|
||||
|
||||
/* Replace the current, truncated, “normal” grid with the
|
||||
* correctly reflowed one */
|
||||
grid_free(&term->normal);
|
||||
term->normal = *term->interactive_resizing.grid;
|
||||
free(term->interactive_resizing.grid);
|
||||
|
||||
term->hide_cursor = term->interactive_resizing.old_hide_cursor;
|
||||
|
||||
/* Reset */
|
||||
term->interactive_resizing.grid = NULL;
|
||||
term->interactive_resizing.old_screen_rows = 0;
|
||||
term->interactive_resizing.new_rows = 0;
|
||||
term->interactive_resizing.old_hide_cursor = false;
|
||||
|
||||
/* Invalidate render pointers */
|
||||
shm_unref(term->render.last_buf);
|
||||
term->render.last_buf = NULL;
|
||||
term->render.last_cursor.row = NULL;
|
||||
|
||||
tll_free(term->normal.scroll_damage);
|
||||
sixel_reflow_grid(term, &term->normal);
|
||||
|
||||
if (term->grid == &term->normal) {
|
||||
term_damage_view(term);
|
||||
render_refresh(term);
|
||||
}
|
||||
|
||||
term_ptmx_resume(term);
|
||||
}
|
||||
|
||||
static bool
|
||||
fdm_tiocswinsz(struct fdm *fdm, int fd, int events, void *data)
|
||||
{
|
||||
struct terminal *term = data;
|
||||
|
||||
if (events & EPOLLIN)
|
||||
if (events & EPOLLIN) {
|
||||
tiocswinsz(term);
|
||||
delayed_reflow_of_normal_grid(term);
|
||||
}
|
||||
|
||||
if (term->window->resize_timeout_fd >= 0) {
|
||||
fdm_del(fdm, term->window->resize_timeout_fd);
|
||||
|
|
@ -3686,6 +3760,7 @@ send_dimensions_to_client(struct terminal *term)
|
|||
if (!win->is_resizing || term->conf->resize_delay_ms == 0) {
|
||||
/* Send new dimensions to client immediately */
|
||||
tiocswinsz(term);
|
||||
delayed_reflow_of_normal_grid(term);
|
||||
|
||||
/* And make sure to reset and deallocate a lingering timer */
|
||||
if (win->resize_timeout_fd >= 0) {
|
||||
|
|
@ -3716,7 +3791,10 @@ send_dimensions_to_client(struct terminal *term)
|
|||
if (fd >= 0) {
|
||||
/* Reset timeout */
|
||||
const struct itimerspec timeout = {
|
||||
.it_value = {.tv_sec = 0, .tv_nsec = delay_ms * 1000000},
|
||||
.it_value = {
|
||||
.tv_sec = delay_ms / 1000,
|
||||
.tv_nsec = (delay_ms % 1000) * 1000000,
|
||||
},
|
||||
};
|
||||
|
||||
if (timerfd_settime(fd, 0, &timeout, NULL) < 0) {
|
||||
|
|
@ -3727,8 +3805,10 @@ send_dimensions_to_client(struct terminal *term)
|
|||
successfully_scheduled = true;
|
||||
}
|
||||
|
||||
if (!successfully_scheduled)
|
||||
if (!successfully_scheduled) {
|
||||
tiocswinsz(term);
|
||||
delayed_reflow_of_normal_grid(term);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -3815,9 +3895,9 @@ maybe_resize(struct terminal *term, int width, int height, bool force)
|
|||
const int min_cols = 2;
|
||||
const int min_rows = 1;
|
||||
|
||||
/* Minimum window size */
|
||||
const int min_width = min_cols * term->cell_width;
|
||||
const int min_height = min_rows * term->cell_height;
|
||||
/* Minimum window size (must be divisible by the scaling factor)*/
|
||||
const int min_width = (min_cols * term->cell_width + scale - 1) / scale * scale;
|
||||
const int min_height = (min_rows * term->cell_height + scale - 1) / scale * scale;
|
||||
|
||||
width = max(width, min_width);
|
||||
height = max(height, min_height);
|
||||
|
|
@ -3844,8 +3924,8 @@ maybe_resize(struct terminal *term, int width, int height, bool force)
|
|||
const uint32_t scrollback_lines = term->render.scrollback_lines;
|
||||
|
||||
/* Screen rows/cols before resize */
|
||||
const int old_cols = term->cols;
|
||||
const int old_rows = term->rows;
|
||||
int old_cols = term->cols;
|
||||
int old_rows = term->rows;
|
||||
|
||||
/* Screen rows/cols after resize */
|
||||
const int new_cols = (term->width - 2 * pad_x) / term->cell_width;
|
||||
|
|
@ -3881,9 +3961,86 @@ maybe_resize(struct terminal *term, int width, int height, bool force)
|
|||
|
||||
if (new_cols == old_cols && new_rows == old_rows) {
|
||||
LOG_DBG("grid layout unaffected; skipping reflow");
|
||||
term->interactive_resizing.new_rows = new_normal_grid_rows;
|
||||
goto damage_view;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Since text reflow is slow, don’t do it *while* resizing. Only
|
||||
* do it when done, or after “pausing” the resize for sufficiently
|
||||
* long. We re-use the TIOCSWINSZ timer to handle this. See
|
||||
* send_dimensions_to_client() and fdm_tiocswinsz().
|
||||
*
|
||||
* To be able to do the final reflow correctly, we need a copy of
|
||||
* the original grid, before the resize started.
|
||||
*/
|
||||
if (term->window->is_resizing && term->conf->resize_delay_ms > 0) {
|
||||
if (term->interactive_resizing.grid == NULL) {
|
||||
term_ptmx_pause(term);
|
||||
|
||||
/* Stash the current ‘normal’ grid, as-is, to be used when
|
||||
* doing the final reflow */
|
||||
term->interactive_resizing.old_screen_rows = term->rows;
|
||||
term->interactive_resizing.old_cols = term->cols;
|
||||
term->interactive_resizing.old_hide_cursor = term->hide_cursor;
|
||||
term->interactive_resizing.grid = xmalloc(sizeof(*term->interactive_resizing.grid));
|
||||
*term->interactive_resizing.grid = term->normal;
|
||||
term->interactive_resizing.selection_coords = term->selection.coords;
|
||||
} else {
|
||||
/* We’ll replace the current temporary grid, with a new
|
||||
* one (again based on the original grid) */
|
||||
grid_free(&term->normal);
|
||||
}
|
||||
|
||||
struct grid *orig = term->interactive_resizing.grid;
|
||||
|
||||
/*
|
||||
* Copy the current viewport (of the original grid) to a new
|
||||
* grid that will be used during the resize. For now, throw
|
||||
* away sixels and OSC-8 URLs. They’ll be "restored" when we
|
||||
* do the final reflow.
|
||||
*
|
||||
* Note that OSC-8 URLs are perfectly ok to throw away; they
|
||||
* cannot be interacted with during the resize. And, even if
|
||||
* url.osc8-underline=always, the “underline” attribute is
|
||||
* part of the cell, not the URI struct (and thus our faked
|
||||
* grid will still render OSC-8 links underlined).
|
||||
*
|
||||
* TODO:
|
||||
* - sixels?
|
||||
*/
|
||||
struct grid g = {
|
||||
.num_rows = 1 << (32 - __builtin_clz(term->interactive_resizing.old_screen_rows)),
|
||||
.num_cols = term->interactive_resizing.old_cols,
|
||||
.offset = 0,
|
||||
.view = 0,
|
||||
.cursor = orig->cursor,
|
||||
.saved_cursor = orig->saved_cursor,
|
||||
.rows = xcalloc(g.num_rows, sizeof(g.rows[0])),
|
||||
.cur_row = NULL,
|
||||
.scroll_damage = tll_init(),
|
||||
.sixel_images = tll_init(),
|
||||
.kitty_kbd = orig->kitty_kbd,
|
||||
};
|
||||
|
||||
term->selection.coords.start.row -= orig->view;
|
||||
term->selection.coords.end.row -= orig->view;
|
||||
|
||||
for (size_t i = 0, j = orig->view;
|
||||
i < term->interactive_resizing.old_screen_rows;
|
||||
i++, j = (j + 1) & (orig->num_rows - 1))
|
||||
{
|
||||
g.rows[i] = grid_row_alloc(g.num_cols, false);
|
||||
memcpy(g.rows[i]->cells,
|
||||
orig->rows[j]->cells,
|
||||
g.num_cols * sizeof(g.rows[i]->cells[0]));
|
||||
}
|
||||
|
||||
term->normal = g;
|
||||
term->hide_cursor = true;
|
||||
}
|
||||
|
||||
if (term->grid == &term->alt)
|
||||
selection_cancel(term);
|
||||
else {
|
||||
|
|
@ -3903,16 +4060,51 @@ maybe_resize(struct terminal *term, int width, int height, bool force)
|
|||
* selection’s pivot point coordinates *must* be added to the
|
||||
* tracking points list.
|
||||
*/
|
||||
struct coord *const tracking_points[] = {
|
||||
&term->selection.coords.start,
|
||||
&term->selection.coords.end,
|
||||
};
|
||||
|
||||
/* Resize grids */
|
||||
grid_resize_and_reflow(
|
||||
&term->normal, new_normal_grid_rows, new_cols, old_rows, new_rows,
|
||||
term->selection.coords.end.row >= 0 ? ALEN(tracking_points) : 0,
|
||||
tracking_points);
|
||||
if (term->window->is_resizing && term->conf->resize_delay_ms > 0) {
|
||||
/* Simple truncating resize, *while* an interactive resize is
|
||||
* ongoing. */
|
||||
xassert(term->interactive_resizing.grid != NULL);
|
||||
xassert(new_normal_grid_rows > 0);
|
||||
term->interactive_resizing.new_rows = new_normal_grid_rows;
|
||||
|
||||
grid_resize_without_reflow(
|
||||
&term->normal, new_alt_grid_rows, new_cols,
|
||||
term->interactive_resizing.old_screen_rows, new_rows);
|
||||
} else {
|
||||
/* Full text reflow */
|
||||
|
||||
if (term->interactive_resizing.grid != NULL) {
|
||||
/* Throw away the current, truncated, “normal” grid, and
|
||||
* use the original grid instead (from before the resize
|
||||
* started) */
|
||||
grid_free(&term->normal);
|
||||
term->normal = *term->interactive_resizing.grid;
|
||||
free(term->interactive_resizing.grid);
|
||||
|
||||
term->hide_cursor = term->interactive_resizing.old_hide_cursor;
|
||||
term->selection.coords = term->interactive_resizing.selection_coords;
|
||||
|
||||
old_rows = term->interactive_resizing.old_screen_rows;
|
||||
|
||||
term->interactive_resizing.grid = NULL;
|
||||
term->interactive_resizing.old_screen_rows = 0;
|
||||
term->interactive_resizing.new_rows = 0;
|
||||
term->interactive_resizing.old_hide_cursor = false;
|
||||
term->interactive_resizing.selection_coords = (struct range){{-1, -1}, {-1, -1}};
|
||||
term_ptmx_resume(term);
|
||||
}
|
||||
|
||||
struct coord *const tracking_points[] = {
|
||||
&term->selection.coords.start,
|
||||
&term->selection.coords.end,
|
||||
};
|
||||
|
||||
grid_resize_and_reflow(
|
||||
&term->normal, new_normal_grid_rows, new_cols, old_rows, new_rows,
|
||||
term->selection.coords.end.row >= 0 ? ALEN(tracking_points) : 0,
|
||||
tracking_points);
|
||||
}
|
||||
|
||||
grid_resize_without_reflow(
|
||||
&term->alt, new_alt_grid_rows, new_cols, old_rows, new_rows);
|
||||
|
|
@ -3936,9 +4128,11 @@ maybe_resize(struct terminal *term, int width, int height, bool force)
|
|||
|
||||
if (term->scroll_region.start >= term->rows)
|
||||
term->scroll_region.start = 0;
|
||||
|
||||
if (term->scroll_region.end >= old_rows)
|
||||
if (term->scroll_region.end > term->rows ||
|
||||
term->scroll_region.end >= old_rows)
|
||||
{
|
||||
term->scroll_region.end = term->rows;
|
||||
}
|
||||
|
||||
term->render.last_cursor.row = NULL;
|
||||
|
||||
|
|
@ -3956,12 +4150,6 @@ damage_view:
|
|||
term->stashed_height = term->height;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* TODO: doesn't include CSD title bar */
|
||||
xdg_toplevel_set_min_size(
|
||||
term->window->xdg_toplevel, min_width / scale, min_height / scale);
|
||||
#endif
|
||||
|
||||
{
|
||||
const bool title_shown = wayl_win_csd_titlebar_visible(term->window);
|
||||
const bool border_shown = wayl_win_csd_borders_visible(term->window);
|
||||
|
|
@ -3971,6 +4159,11 @@ damage_view:
|
|||
const int border_width =
|
||||
border_shown ? term->conf->csd.border_width_visible : 0;
|
||||
|
||||
xdg_toplevel_set_min_size(
|
||||
term->window->xdg_toplevel,
|
||||
min_width / scale + 2 * border_width,
|
||||
min_height / scale + title_height + 2 * border_width);
|
||||
|
||||
xdg_surface_set_window_geometry(
|
||||
term->window->xdg_surface,
|
||||
-border_width,
|
||||
|
|
|
|||
|
|
@ -52,14 +52,25 @@ class StringCapability(Capability):
|
|||
def __init__(self, name: str, value: str):
|
||||
# Expand \E to literal ESC in non-parameterized capabilities
|
||||
if '%' not in value:
|
||||
# Ensure e.g. \E7 doesn’t get translated to “\0337”, which
|
||||
# would be interpreted as octal 337 by the C compiler
|
||||
value = re.sub(r'\\E([0-7])', r'\\033" "\1', value)
|
||||
value = re.sub(r'\\E', r'\\033', value)
|
||||
else:
|
||||
# Need to double-escape \E in C string literals
|
||||
value = value.replace('\\E', '\\\\E')
|
||||
|
||||
# Don’t escape ‘:’
|
||||
value = value.replace('\\:', ':')
|
||||
# Replace \E with an actual escape
|
||||
value = re.sub(r'\\E', r'\\033', value)
|
||||
|
||||
# Don’t escape ‘:’
|
||||
value = value.replace('\\:', ':')
|
||||
|
||||
else:
|
||||
value = value.replace("\\", "\\\\")
|
||||
# # Need to double-escape backslashes. These only occur in
|
||||
# # ‘\E\’ combos. Note that \E itself is updated below
|
||||
# value = value.replace('\\E\\\\', '\\E\\\\\\\\')
|
||||
|
||||
# # Need to double-escape \E in C string literals
|
||||
# value = value.replace('\\E', '\\\\E')
|
||||
|
||||
|
||||
super().__init__(name, value)
|
||||
|
||||
|
|
|
|||
13
selection.c
13
selection.c
|
|
@ -86,7 +86,7 @@ selection_on_rows(const struct terminal *term, int row_start, int row_end)
|
|||
const int rel_row_start =
|
||||
grid_row_abs_to_sb_precalc_sb_start(grid, sb_start, row_start);
|
||||
const int rel_row_end =
|
||||
grid_row_abs_to_sb_precalc_sb_start(grid, sb_start, row_start);
|
||||
grid_row_abs_to_sb_precalc_sb_start(grid, sb_start, row_end);
|
||||
int rel_sel_start =
|
||||
grid_row_abs_to_sb_precalc_sb_start(grid, sb_start, start->row);
|
||||
int rel_sel_end =
|
||||
|
|
@ -133,13 +133,18 @@ selection_scroll_down(struct terminal *term, int rows)
|
|||
{
|
||||
xassert(term->selection.coords.end.row >= 0);
|
||||
|
||||
const struct grid *grid = term->grid;
|
||||
const struct range *sel = &term->selection.coords;
|
||||
|
||||
const int screen_end =
|
||||
grid_row_abs_to_sb(grid, term->rows, grid->offset + term->rows - 1);
|
||||
const int rel_row_start =
|
||||
grid_row_abs_to_sb(term->grid, term->rows, term->selection.coords.start.row);
|
||||
grid_row_abs_to_sb(term->grid, term->rows, sel->start.row);
|
||||
const int rel_row_end =
|
||||
grid_row_abs_to_sb(term->grid, term->rows, term->selection.coords.end.row);
|
||||
grid_row_abs_to_sb(term->grid, term->rows, sel->end.row);
|
||||
const int actual_end = max(rel_row_start, rel_row_end);
|
||||
|
||||
if (actual_end + rows <= term->grid->num_rows) {
|
||||
if (actual_end > screen_end - rows) {
|
||||
/* Part of the selection will be scrolled out, cancel it */
|
||||
selection_cancel(term);
|
||||
}
|
||||
|
|
|
|||
150
sixel.c
150
sixel.c
|
|
@ -154,7 +154,7 @@ verify_list_order(const struct terminal *term)
|
|||
int prev_col_count = 0;
|
||||
|
||||
/* To aid debugging */
|
||||
size_t idx = 0;
|
||||
size_t UNUSED idx = 0;
|
||||
|
||||
tll_foreach(term->grid->sixel_images, it) {
|
||||
int row = grid_row_abs_to_sb(
|
||||
|
|
@ -838,85 +838,89 @@ sixel_cell_size_changed(struct terminal *term)
|
|||
}
|
||||
|
||||
void
|
||||
sixel_reflow(struct terminal *term)
|
||||
sixel_reflow_grid(struct terminal *term, struct grid *grid)
|
||||
{
|
||||
struct grid *g = term->grid;
|
||||
/* Meh - the sixel functions we call use term->grid... */
|
||||
struct grid *active_grid = term->grid;
|
||||
term->grid = grid;
|
||||
|
||||
for (size_t i = 0; i < 2; i++) {
|
||||
struct grid *grid = i == 0 ? &term->normal : &term->alt;
|
||||
/* Need the “real” list to be empty from the beginning */
|
||||
tll(struct sixel) copy = tll_init();
|
||||
tll_foreach(grid->sixel_images, it)
|
||||
tll_push_back(copy, it->item);
|
||||
tll_free(grid->sixel_images);
|
||||
|
||||
term->grid = grid;
|
||||
tll_rforeach(copy, it) {
|
||||
struct sixel *six = &it->item;
|
||||
int start = six->pos.row;
|
||||
int end = (start + six->rows - 1) & (grid->num_rows - 1);
|
||||
|
||||
/* Need the “real” list to be empty from the beginning */
|
||||
tll(struct sixel) copy = tll_init();
|
||||
tll_foreach(grid->sixel_images, it)
|
||||
tll_push_back(copy, it->item);
|
||||
tll_free(grid->sixel_images);
|
||||
|
||||
tll_rforeach(copy, it) {
|
||||
struct sixel *six = &it->item;
|
||||
int start = six->pos.row;
|
||||
int end = (start + six->rows - 1) & (grid->num_rows - 1);
|
||||
|
||||
if (end < start) {
|
||||
/* Crosses scrollback wrap-around */
|
||||
/* TODO: split image */
|
||||
sixel_destroy(six);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (six->rows > grid->num_rows) {
|
||||
/* Image too large */
|
||||
/* TODO: keep bottom part? */
|
||||
sixel_destroy(six);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Drop sixels that now cross the current scrollback end
|
||||
* border. This is similar to a sixel that have been
|
||||
* scrolled out */
|
||||
/* TODO: should be possible to optimize this */
|
||||
bool sixel_destroyed = false;
|
||||
int last_row = -1;
|
||||
|
||||
for (int j = 0; j < six->rows; j++) {
|
||||
int row_no = grid_row_abs_to_sb(
|
||||
term->grid, term->rows, six->pos.row + j);
|
||||
if (last_row != -1 && last_row >= row_no) {
|
||||
sixel_destroy(six);
|
||||
sixel_destroyed = true;
|
||||
break;
|
||||
}
|
||||
|
||||
last_row = row_no;
|
||||
}
|
||||
|
||||
if (sixel_destroyed) {
|
||||
LOG_WARN("destroyed sixel that now crossed history");
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Sixels that didn’t overlap may now do so, which isn’t
|
||||
* allowed of course */
|
||||
_sixel_overwrite_by_rectangle(
|
||||
term, six->pos.row, six->pos.col, six->rows, six->cols,
|
||||
&it->item.pix, &it->item.opaque);
|
||||
|
||||
if (it->item.data != pixman_image_get_data(it->item.pix)) {
|
||||
it->item.data = pixman_image_get_data(it->item.pix);
|
||||
it->item.width = pixman_image_get_width(it->item.pix);
|
||||
it->item.height = pixman_image_get_height(it->item.pix);
|
||||
it->item.cols = (it->item.width + term->cell_width - 1) / term->cell_width;
|
||||
it->item.rows = (it->item.height + term->cell_height - 1) / term->cell_height;
|
||||
}
|
||||
|
||||
sixel_insert(term, it->item);
|
||||
if (end < start) {
|
||||
/* Crosses scrollback wrap-around */
|
||||
/* TODO: split image */
|
||||
sixel_destroy(six);
|
||||
continue;
|
||||
}
|
||||
|
||||
tll_free(copy);
|
||||
if (six->rows > grid->num_rows) {
|
||||
/* Image too large */
|
||||
/* TODO: keep bottom part? */
|
||||
sixel_destroy(six);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Drop sixels that now cross the current scrollback end
|
||||
* border. This is similar to a sixel that have been
|
||||
* scrolled out */
|
||||
/* TODO: should be possible to optimize this */
|
||||
bool sixel_destroyed = false;
|
||||
int last_row = -1;
|
||||
|
||||
for (int j = 0; j < six->rows; j++) {
|
||||
int row_no = grid_row_abs_to_sb(
|
||||
term->grid, term->rows, six->pos.row + j);
|
||||
if (last_row != -1 && last_row >= row_no) {
|
||||
sixel_destroy(six);
|
||||
sixel_destroyed = true;
|
||||
break;
|
||||
}
|
||||
|
||||
last_row = row_no;
|
||||
}
|
||||
|
||||
if (sixel_destroyed) {
|
||||
LOG_WARN("destroyed sixel that now crossed history");
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Sixels that didn’t overlap may now do so, which isn’t
|
||||
* allowed of course */
|
||||
_sixel_overwrite_by_rectangle(
|
||||
term, six->pos.row, six->pos.col, six->rows, six->cols,
|
||||
&it->item.pix, &it->item.opaque);
|
||||
|
||||
if (it->item.data != pixman_image_get_data(it->item.pix)) {
|
||||
it->item.data = pixman_image_get_data(it->item.pix);
|
||||
it->item.width = pixman_image_get_width(it->item.pix);
|
||||
it->item.height = pixman_image_get_height(it->item.pix);
|
||||
it->item.cols = (it->item.width + term->cell_width - 1) / term->cell_width;
|
||||
it->item.rows = (it->item.height + term->cell_height - 1) / term->cell_height;
|
||||
}
|
||||
|
||||
sixel_insert(term, it->item);
|
||||
}
|
||||
|
||||
term->grid = g;
|
||||
tll_free(copy);
|
||||
term->grid = active_grid;
|
||||
}
|
||||
|
||||
void
|
||||
sixel_reflow(struct terminal *term)
|
||||
{
|
||||
for (size_t i = 0; i < 2; i++) {
|
||||
struct grid *grid = i == 0 ? &term->normal : &term->alt;
|
||||
sixel_reflow_grid(term, grid);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -1291,7 +1295,7 @@ sixel_add_many(struct terminal *term, uint8_t c, unsigned count)
|
|||
if (unlikely(col + count - 1 >= width)) {
|
||||
resize_horizontally(term, col + count);
|
||||
width = term->sixel.image.width;
|
||||
count = min(count, width - col);
|
||||
count = min(count, max(width - col, 0));
|
||||
}
|
||||
|
||||
uint32_t color = term->sixel.color;
|
||||
|
|
|
|||
4
sixel.h
4
sixel.h
|
|
@ -19,6 +19,10 @@ void sixel_scroll_up(struct terminal *term, int rows);
|
|||
void sixel_scroll_down(struct terminal *term, int rows);
|
||||
|
||||
void sixel_cell_size_changed(struct terminal *term);
|
||||
|
||||
void sixel_reflow_grid(struct terminal *term, struct grid *grid);
|
||||
|
||||
/* Shortcut for sixel_reflow_grid(normal) + sixel_reflow_grid(alt) */
|
||||
void sixel_reflow(struct terminal *term);
|
||||
|
||||
/*
|
||||
|
|
|
|||
14
slave.c
14
slave.c
|
|
@ -21,6 +21,7 @@
|
|||
#include "macros.h"
|
||||
#include "terminal.h"
|
||||
#include "tokenize.h"
|
||||
#include "version.h"
|
||||
#include "xmalloc.h"
|
||||
|
||||
extern char **environ;
|
||||
|
|
@ -351,6 +352,8 @@ slave_spawn(int ptmx, int argc, const char *cwd, char *const *argv,
|
|||
}
|
||||
|
||||
setenv("TERM", term_env, 1);
|
||||
setenv("TERM_PROGRAM", "foot", 1);
|
||||
setenv("TERM_PROGRAM_VERSION", FOOT_VERSION_SHORT, 1);
|
||||
setenv("COLORTERM", "truecolor", 1);
|
||||
setenv("PWD", cwd, 1);
|
||||
|
||||
|
|
@ -359,8 +362,15 @@ slave_spawn(int ptmx, int argc, const char *cwd, char *const *argv,
|
|||
#endif
|
||||
|
||||
if (extra_env_vars != NULL) {
|
||||
tll_foreach(*extra_env_vars, it)
|
||||
setenv(it->item.name, it->item.value, 1);
|
||||
tll_foreach(*extra_env_vars, it) {
|
||||
const char *name = it->item.name;
|
||||
const char *value = it->item.value;
|
||||
|
||||
if (strlen(value) == 0)
|
||||
unsetenv(name);
|
||||
else
|
||||
setenv(name, value, 1);
|
||||
}
|
||||
}
|
||||
|
||||
char **_shell_argv = NULL;
|
||||
|
|
|
|||
192
terminal.c
192
terminal.c
|
|
@ -7,6 +7,7 @@
|
|||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <sys/wait.h>
|
||||
|
|
@ -255,8 +256,18 @@ fdm_ptmx(struct fdm *fdm, int fd, int events, void *data)
|
|||
cursor_blink_rearm_timer(term);
|
||||
}
|
||||
|
||||
if (unlikely(term->interactive_resizing.grid != NULL)) {
|
||||
/*
|
||||
* Don’t consume PTMX while we’re doing an interactive resize,
|
||||
* since the ‘normal’ grid we’re currently using is a
|
||||
* temporary one - all changes done to it will be lost when
|
||||
* the interactive resize ends.
|
||||
*/
|
||||
return true;
|
||||
}
|
||||
|
||||
uint8_t buf[24 * 1024];
|
||||
const size_t max_iterations = !hup ? 10 : (size_t)-1ll;
|
||||
const size_t max_iterations = !hup ? 10 : SIZE_MAX;
|
||||
|
||||
for (size_t i = 0; i < max_iterations && pollin; i++) {
|
||||
xassert(pollin);
|
||||
|
|
@ -278,6 +289,7 @@ fdm_ptmx(struct fdm *fdm, int fd, int events, void *data)
|
|||
break;
|
||||
}
|
||||
|
||||
xassert(term->interactive_resizing.grid == NULL);
|
||||
vt_from_slave(term, buf, count);
|
||||
}
|
||||
|
||||
|
|
@ -358,6 +370,18 @@ fdm_ptmx(struct fdm *fdm, int fd, int events, void *data)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
term_ptmx_pause(struct terminal *term)
|
||||
{
|
||||
return fdm_event_del(term->fdm, term->ptmx, EPOLLIN);
|
||||
}
|
||||
|
||||
bool
|
||||
term_ptmx_resume(struct terminal *term)
|
||||
{
|
||||
return fdm_event_add(term->fdm, term->ptmx, EPOLLIN);
|
||||
}
|
||||
|
||||
static bool
|
||||
fdm_flash(struct fdm *fdm, int fd, int events, void *data)
|
||||
{
|
||||
|
|
@ -680,6 +704,37 @@ free_custom_glyphs(struct fcft_glyph ***glyphs, size_t count)
|
|||
*glyphs = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
term_line_height_update(struct terminal *term)
|
||||
{
|
||||
const struct config *conf = term->conf;
|
||||
|
||||
if (term->conf->line_height.px < 0) {
|
||||
term->font_line_height.pt = 0;
|
||||
term->font_line_height.px = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
const float dpi = term->font_is_sized_by_dpi ? term->font_dpi : 96.;
|
||||
|
||||
const float font_original_pt_size =
|
||||
conf->fonts[0].arr[0].px_size > 0
|
||||
? conf->fonts[0].arr[0].px_size * 72. / dpi
|
||||
: conf->fonts[0].arr[0].pt_size;
|
||||
const float font_current_pt_size =
|
||||
term->font_sizes[0][0].px_size > 0
|
||||
? term->font_sizes[0][0].px_size * 72. / dpi
|
||||
: term->font_sizes[0][0].pt_size;
|
||||
|
||||
const float change = font_current_pt_size / font_original_pt_size;
|
||||
const float line_original_pt_size = conf->line_height.px > 0
|
||||
? conf->line_height.px * 72. / dpi
|
||||
: conf->line_height.pt;
|
||||
|
||||
term->font_line_height.px = 0;
|
||||
term->font_line_height.pt = fmaxf(line_original_pt_size * change, 0.);
|
||||
}
|
||||
|
||||
static bool
|
||||
term_set_fonts(struct terminal *term, struct fcft_font *fonts[static 4])
|
||||
{
|
||||
|
|
@ -706,6 +761,8 @@ term_set_fonts(struct terminal *term, struct fcft_font *fonts[static 4])
|
|||
fonts[0], U'M', term->font_subpixel);
|
||||
int advance = M != NULL ? M->advance.x : term->fonts[0]->max_advance.x;
|
||||
|
||||
term_line_height_update(term);
|
||||
|
||||
term->cell_width = advance +
|
||||
term_pt_or_px_as_pixels(term, &conf->letter_spacing);
|
||||
|
||||
|
|
@ -889,7 +946,7 @@ term_pt_or_px_as_pixels(const struct terminal *term,
|
|||
|
||||
return pt_or_px->px == 0
|
||||
? round(pt_or_px->pt * scale * dpi / 72)
|
||||
: pt_or_px->px;
|
||||
: pt_or_px->px * scale;
|
||||
}
|
||||
|
||||
struct font_load_data {
|
||||
|
|
@ -1054,7 +1111,6 @@ load_fonts_from_conf(struct terminal *term)
|
|||
}
|
||||
}
|
||||
|
||||
term->font_line_height = term->conf->line_height;
|
||||
return reload_fonts(term);
|
||||
}
|
||||
|
||||
|
|
@ -1274,7 +1330,6 @@ term_init(const struct config *conf, struct fdm *fdm, struct reaper *reaper,
|
|||
.pt_size = font->pt_size, .px_size = font->px_size};
|
||||
}
|
||||
}
|
||||
term->font_line_height = conf->line_height;
|
||||
|
||||
add_utmp_record(conf, reaper, ptmx);
|
||||
|
||||
|
|
@ -1728,6 +1783,8 @@ term_destroy(struct terminal *term)
|
|||
|
||||
grid_free(&term->normal);
|
||||
grid_free(&term->alt);
|
||||
grid_free(term->interactive_resizing.grid);
|
||||
free(term->interactive_resizing.grid);
|
||||
|
||||
free(term->foot_exe);
|
||||
free(term->cwd);
|
||||
|
|
@ -1978,39 +2035,71 @@ term_reset(struct terminal *term, bool hard)
|
|||
}
|
||||
|
||||
static bool
|
||||
term_font_size_adjust(struct terminal *term, double amount)
|
||||
term_font_size_adjust_by_points(struct terminal *term, float amount)
|
||||
{
|
||||
const struct config *conf = term->conf;
|
||||
|
||||
const float dpi = term->font_is_sized_by_dpi ? term->font_dpi : 96.;
|
||||
|
||||
for (size_t i = 0; i < 4; i++) {
|
||||
const struct config_font_list *font_list = &conf->fonts[i];
|
||||
|
||||
for (size_t j = 0; j < font_list->count; j++) {
|
||||
float old_pt_size = term->font_sizes[i][j].pt_size;
|
||||
struct config_font *font = &term->font_sizes[i][j];
|
||||
float old_pt_size = font->pt_size;
|
||||
|
||||
/*
|
||||
* To ensure primary and user-configured fallback fonts are
|
||||
* resizes by the same amount, convert pixel sizes to point
|
||||
* sizes, and to the adjustment on point sizes only.
|
||||
*/
|
||||
if (font->px_size > 0)
|
||||
old_pt_size = font->px_size * 72. / dpi;
|
||||
|
||||
if (term->font_sizes[i][j].px_size > 0)
|
||||
old_pt_size = term->font_sizes[i][j].px_size * 72. / dpi;
|
||||
|
||||
term->font_sizes[i][j].pt_size = fmaxf(old_pt_size + amount, 0.);
|
||||
term->font_sizes[i][j].px_size = -1;
|
||||
font->pt_size = fmaxf(old_pt_size + amount, 0.);
|
||||
font->px_size = -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (term->font_line_height.px >= 0) {
|
||||
float old_pt_size = term->font_line_height.px > 0
|
||||
? term->font_line_height.px * 72. / dpi
|
||||
: term->font_line_height.pt;
|
||||
return reload_fonts(term);
|
||||
}
|
||||
|
||||
term->font_line_height.px = 0;
|
||||
term->font_line_height.pt = fmaxf(old_pt_size + amount, 0.);
|
||||
static bool
|
||||
term_font_size_adjust_by_pixels(struct terminal *term, int amount)
|
||||
{
|
||||
const struct config *conf = term->conf;
|
||||
const float dpi = term->font_is_sized_by_dpi ? term->font_dpi : 96.;
|
||||
|
||||
for (size_t i = 0; i < 4; i++) {
|
||||
const struct config_font_list *font_list = &conf->fonts[i];
|
||||
|
||||
for (size_t j = 0; j < font_list->count; j++) {
|
||||
struct config_font *font = &term->font_sizes[i][j];
|
||||
int old_px_size = font->px_size;
|
||||
|
||||
if (font->px_size <= 0)
|
||||
old_px_size = font->pt_size * dpi / 72.;
|
||||
|
||||
font->px_size = max(old_px_size + amount, 1);
|
||||
}
|
||||
}
|
||||
|
||||
return reload_fonts(term);
|
||||
}
|
||||
|
||||
static bool
|
||||
term_font_size_adjust_by_percent(struct terminal *term, bool increment, float percent)
|
||||
{
|
||||
const struct config *conf = term->conf;
|
||||
const float multiplier = increment
|
||||
? 1. + percent
|
||||
: 1. / (1. + percent);
|
||||
|
||||
for (size_t i = 0; i < 4; i++) {
|
||||
const struct config_font_list *font_list = &conf->fonts[i];
|
||||
|
||||
for (size_t j = 0; j < font_list->count; j++) {
|
||||
struct config_font *font = &term->font_sizes[i][j];
|
||||
|
||||
if (font->px_size > 0)
|
||||
font->px_size = max(font->px_size * multiplier, 1);
|
||||
else
|
||||
font->pt_size = fmax(font->pt_size * multiplier, 0);
|
||||
}
|
||||
}
|
||||
|
||||
return reload_fonts(term);
|
||||
|
|
@ -2019,19 +2108,29 @@ term_font_size_adjust(struct terminal *term, double amount)
|
|||
bool
|
||||
term_font_size_increase(struct terminal *term)
|
||||
{
|
||||
if (!term_font_size_adjust(term, 0.5))
|
||||
return false;
|
||||
const struct config *conf = term->conf;
|
||||
const struct font_size_adjustment *inc_dec = &conf->font_size_adjustment;
|
||||
|
||||
return true;
|
||||
if (inc_dec->percent > 0.)
|
||||
return term_font_size_adjust_by_percent(term, true, inc_dec->percent);
|
||||
else if (inc_dec->pt_or_px.px > 0)
|
||||
return term_font_size_adjust_by_pixels(term, inc_dec->pt_or_px.px);
|
||||
else
|
||||
return term_font_size_adjust_by_points(term, inc_dec->pt_or_px.pt);
|
||||
}
|
||||
|
||||
bool
|
||||
term_font_size_decrease(struct terminal *term)
|
||||
{
|
||||
if (!term_font_size_adjust(term, -0.5))
|
||||
return false;
|
||||
const struct config *conf = term->conf;
|
||||
const struct font_size_adjustment *inc_dec = &conf->font_size_adjustment;
|
||||
|
||||
return true;
|
||||
if (inc_dec->percent > 0.)
|
||||
return term_font_size_adjust_by_percent(term, false, inc_dec->percent);
|
||||
else if (inc_dec->pt_or_px.px > 0)
|
||||
return term_font_size_adjust_by_pixels(term, -inc_dec->pt_or_px.px);
|
||||
else
|
||||
return term_font_size_adjust_by_points(term, -inc_dec->pt_or_px.pt);
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
@ -2153,15 +2252,20 @@ void
|
|||
term_damage_scroll(struct terminal *term, enum damage_type damage_type,
|
||||
struct scroll_region region, int lines)
|
||||
{
|
||||
if (tll_length(term->grid->scroll_damage) > 0) {
|
||||
if (likely(tll_length(term->grid->scroll_damage) > 0)) {
|
||||
struct damage *dmg = &tll_back(term->grid->scroll_damage);
|
||||
|
||||
if (dmg->type == damage_type &&
|
||||
dmg->region.start == region.start &&
|
||||
dmg->region.end == region.end)
|
||||
if (likely(
|
||||
dmg->type == damage_type &&
|
||||
dmg->region.start == region.start &&
|
||||
dmg->region.end == region.end))
|
||||
{
|
||||
dmg->lines += lines;
|
||||
return;
|
||||
/* Make sure we don’t overflow... */
|
||||
int new_line_count = (int)dmg->lines + lines;
|
||||
if (likely(new_line_count <= UINT16_MAX)) {
|
||||
dmg->lines = new_line_count;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
struct damage dmg = {
|
||||
|
|
@ -2612,13 +2716,13 @@ term_scroll_partial(struct terminal *term, struct scroll_region region, int rows
|
|||
erase_line(term, row);
|
||||
}
|
||||
|
||||
term_damage_scroll(term, DAMAGE_SCROLL, region, rows);
|
||||
term->grid->cur_row = grid_row(term->grid, term->grid->cursor.point.row);
|
||||
|
||||
#if defined(_DEBUG)
|
||||
for (int r = 0; r < term->rows; r++)
|
||||
xassert(grid_row(term->grid, r) != NULL);
|
||||
#endif
|
||||
|
||||
term_damage_scroll(term, DAMAGE_SCROLL, region, rows);
|
||||
term->grid->cur_row = grid_row(term->grid, term->grid->cursor.point.row);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -2652,6 +2756,18 @@ term_scroll_reverse_partial(struct terminal *term,
|
|||
selection_scroll_down(term, rows);
|
||||
}
|
||||
|
||||
/* Unallocate scrolled out lines */
|
||||
for (int r = region.end - rows; r < region.end; r++) {
|
||||
const int abs_r = grid_row_absolute(term->grid, r);
|
||||
struct row *row = term->grid->rows[abs_r];
|
||||
|
||||
grid_row_free(row);
|
||||
term->grid->rows[abs_r] = NULL;
|
||||
|
||||
if (term->render.last_cursor.row == row)
|
||||
term->render.last_cursor.row = NULL;
|
||||
}
|
||||
|
||||
sixel_scroll_down(term, rows);
|
||||
|
||||
bool view_follows = term->grid->view == term->grid->offset;
|
||||
|
|
|
|||
14
terminal.h
14
terminal.h
|
|
@ -96,7 +96,7 @@ enum damage_type {DAMAGE_SCROLL, DAMAGE_SCROLL_REVERSE,
|
|||
struct damage {
|
||||
enum damage_type type;
|
||||
struct scroll_region region;
|
||||
int lines;
|
||||
uint16_t lines;
|
||||
};
|
||||
|
||||
struct row_uri_range {
|
||||
|
|
@ -598,6 +598,15 @@ struct terminal {
|
|||
struct timespec input_time;
|
||||
} render;
|
||||
|
||||
struct {
|
||||
struct grid *grid; /* Original ‘normal’ grid, before resize started */
|
||||
int old_screen_rows; /* term->rows before resize started */
|
||||
int old_cols; /* term->cols before resize started */
|
||||
int old_hide_cursor; /* term->hide_cursor before resize started */
|
||||
int new_rows; /* New number of scrollback rows */
|
||||
struct range selection_coords;
|
||||
} interactive_resizing;
|
||||
|
||||
struct {
|
||||
enum {
|
||||
SIXEL_DECSIXEL, /* DECSIXEL body part ", $, -, ? ... ~ */
|
||||
|
|
@ -805,6 +814,9 @@ void term_collect_urls(struct terminal *term);
|
|||
void term_osc8_open(struct terminal *term, uint64_t id, const char *uri);
|
||||
void term_osc8_close(struct terminal *term);
|
||||
|
||||
bool term_ptmx_pause(struct terminal *term);
|
||||
bool term_ptmx_resume(struct terminal *term);
|
||||
|
||||
static inline void term_reset_grapheme_state(struct terminal *term)
|
||||
{
|
||||
#if defined(FOOT_GRAPHEME_CLUSTERING)
|
||||
|
|
|
|||
|
|
@ -467,6 +467,7 @@ test_section_main(void)
|
|||
test_boolean(&ctx, &parse_section_main, "locked-title", &conf.locked_title);
|
||||
test_boolean(&ctx, &parse_section_main, "notify-focus-inhibit", &conf.notify_focus_inhibit);
|
||||
|
||||
test_pt_or_px(&ctx, &parse_section_main, "font-size-adjustment", &conf.font_size_adjustment.pt_or_px); /* TODO: test ‘N%’ values too */
|
||||
test_pt_or_px(&ctx, &parse_section_main, "line-height", &conf.line_height);
|
||||
test_pt_or_px(&ctx, &parse_section_main, "letter-spacing", &conf.letter_spacing);
|
||||
test_pt_or_px(&ctx, &parse_section_main, "horizontal-letter-offset", &conf.horizontal_letter_offset);
|
||||
|
|
@ -894,7 +895,7 @@ enum collision_test_mode {
|
|||
FAIL_DIFFERENT_ACTION,
|
||||
FAIL_DIFFERENT_ARGV,
|
||||
FAIL_MOUSE_OVERRIDE,
|
||||
SUCCED_SAME_ACTION_AND_ARGV,
|
||||
SUCCEED_SAME_ACTION_AND_ARGV,
|
||||
};
|
||||
|
||||
static void
|
||||
|
|
@ -948,7 +949,7 @@ _test_binding_collisions(struct context *ctx,
|
|||
break;
|
||||
|
||||
case FAIL_DIFFERENT_ARGV:
|
||||
case SUCCED_SAME_ACTION_AND_ARGV:
|
||||
case SUCCEED_SAME_ACTION_AND_ARGV:
|
||||
bindings.arr[0].aux.type = BINDING_AUX_PIPE;
|
||||
bindings.arr[0].aux.master_copy = true;
|
||||
bindings.arr[0].aux.pipe.args = xcalloc(
|
||||
|
|
@ -964,13 +965,13 @@ _test_binding_collisions(struct context *ctx,
|
|||
bindings.arr[1].aux.pipe.args[0] = xstrdup("/usr/bin/foobar");
|
||||
bindings.arr[1].aux.pipe.args[1] = xstrdup("hello");
|
||||
|
||||
if (test_mode == SUCCED_SAME_ACTION_AND_ARGV)
|
||||
if (test_mode == SUCCEED_SAME_ACTION_AND_ARGV)
|
||||
bindings.arr[1].aux.pipe.args[2] = xstrdup("world");
|
||||
break;
|
||||
}
|
||||
|
||||
bool expected_result =
|
||||
test_mode == SUCCED_SAME_ACTION_AND_ARGV ? true : false;
|
||||
test_mode == SUCCEED_SAME_ACTION_AND_ARGV ? true : false;
|
||||
|
||||
if (resolve_key_binding_collisions(
|
||||
ctx->conf, ctx->section, map, &bindings, type) != expected_result)
|
||||
|
|
@ -1003,7 +1004,7 @@ test_binding_collisions(struct context *ctx,
|
|||
{
|
||||
_test_binding_collisions(ctx, max_action, map, type, FAIL_DIFFERENT_ACTION);
|
||||
_test_binding_collisions(ctx, max_action, map, type, FAIL_DIFFERENT_ARGV);
|
||||
_test_binding_collisions(ctx, max_action, map, type, SUCCED_SAME_ACTION_AND_ARGV);
|
||||
_test_binding_collisions(ctx, max_action, map, type, SUCCEED_SAME_ACTION_AND_ARGV);
|
||||
|
||||
if (type == MOUSE_BINDING) {
|
||||
_test_binding_collisions(
|
||||
|
|
@ -1303,6 +1304,7 @@ test_section_tweak(void)
|
|||
int
|
||||
main(int argc, const char *const *argv)
|
||||
{
|
||||
FcInit();
|
||||
log_init(LOG_COLORIZE_AUTO, false, 0, LOG_CLASS_ERROR);
|
||||
test_section_main();
|
||||
test_section_bell();
|
||||
|
|
@ -1324,5 +1326,6 @@ main(int argc, const char *const *argv)
|
|||
test_section_environment();
|
||||
test_section_tweak();
|
||||
log_deinit();
|
||||
FcFini();
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
# -*- conf -*-
|
||||
# https://github.com/romainl/Apprentice
|
||||
|
||||
[cursor]
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
# -*- conf -*-
|
||||
# Catppuccin
|
||||
|
||||
[cursor]
|
||||
color=1A1826 D9E0EE
|
||||
|
||||
[colors]
|
||||
alpha=1.0
|
||||
foreground=D9E0EE
|
||||
background=1E1D2F
|
||||
regular0=6E6C7E # black
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
# -*- conf -*-
|
||||
# Derp
|
||||
|
||||
[cursor]
|
||||
|
|
|
|||
31
themes/deus
Normal file
31
themes/deus
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
# -*- conf -*-
|
||||
# Deus
|
||||
# Color palette based on: https://github.com/ajmwagar/vim-deus
|
||||
|
||||
[cursor]
|
||||
color=2c323b eaeaea
|
||||
|
||||
[colors]
|
||||
background=2c323b
|
||||
foreground=eaeaea
|
||||
regular0=242a32
|
||||
regular1=d54e53
|
||||
regular2=98c379
|
||||
regular3=e5c07b
|
||||
regular4=83a598
|
||||
regular5=c678dd
|
||||
regular6=70c0ba
|
||||
regular7=eaeaea
|
||||
bright0=666666
|
||||
bright1=ec3e45
|
||||
bright2=90c966
|
||||
bright3=edbf69
|
||||
bright4=73ba9f
|
||||
bright5=c858e9
|
||||
bright6=2bcec2
|
||||
bright7=ffffff
|
||||
|
||||
# Enable if prefer Deus colors instead of inverterd fg/bg for
|
||||
# highlighting (mouse selection)
|
||||
# selection-foreground=2c323b
|
||||
# selection-background=eaeaea
|
||||
|
|
@ -1,10 +1,10 @@
|
|||
# -*- conf -*-
|
||||
# Dracula
|
||||
|
||||
[cursor]
|
||||
color=282a36 f8f8f2
|
||||
|
||||
[colors]
|
||||
alpha=1.0
|
||||
foreground=f8f8f2
|
||||
background=282a36
|
||||
regular0=000000 # black
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
# -*- conf -*-
|
||||
# Gruvbox
|
||||
|
||||
[colors]
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
# -*- conf -*-
|
||||
# Gruvbox - Light
|
||||
|
||||
[colors]
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
# -*- conf -*-
|
||||
[cursor]
|
||||
color=141414 c9c9c9
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
# -*- conf -*-
|
||||
# JetBrains Darcula
|
||||
# Palette based on the same theme from https://github.com/dexpota/kitty-themes
|
||||
|
||||
|
|
@ -5,7 +6,6 @@
|
|||
color=202020 ffffff
|
||||
|
||||
[colors]
|
||||
#alpha=0.80
|
||||
background=202020
|
||||
foreground=adadad
|
||||
regular0=000000 # black
|
||||
|
|
@ -24,5 +24,5 @@ bright4=6d9df1 # bright blue
|
|||
bright5=fb82ff # bright magenta
|
||||
bright6=60d3d1 # bright cyan
|
||||
bright7=eeeeee # bright white
|
||||
selection-foreground=202020
|
||||
selection-background=1a3272
|
||||
# selection-foreground=202020
|
||||
# selection-background=1a3272
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
# -*- conf -*-
|
||||
|
||||
[cursor]
|
||||
color=111111 cccccc
|
||||
|
||||
|
|
|
|||
40
themes/material-amber
Normal file
40
themes/material-amber
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
# -*- conf -*-
|
||||
# Material Amber
|
||||
# Based on material.io guidelines with Amber 50 background
|
||||
|
||||
# [cursor]
|
||||
# color=fff8e1 21201d
|
||||
|
||||
[colors]
|
||||
foreground = 21201d
|
||||
background = fff8e1
|
||||
|
||||
regular0 = 21201d # black
|
||||
regular1 = cd4340 # red
|
||||
regular2 = 498d49 # green
|
||||
regular3 = fab32d # yellow
|
||||
regular4 = 3378c4 # blue
|
||||
regular5 = b83269 # magenta
|
||||
regular6 = 21929a # cyan
|
||||
regular7 = ffd7d7 # white
|
||||
|
||||
bright0 = 66635a # bright black
|
||||
bright1 = dd7b72 # bright red
|
||||
bright2 = 82ae78 # bright green
|
||||
bright3 = fbc870 # bright yellow
|
||||
bright4 = 73a0cd # bright blue
|
||||
bright5 = ce6f8e # bright magenta
|
||||
bright6 = 548c94 # bright cyan
|
||||
bright7 = ffe1da # bright white
|
||||
|
||||
dim0 = 9e9a8c # dim black
|
||||
dim1 = e9a99b # dim red
|
||||
dim2 = b0c99f # dim green
|
||||
dim3 = fdda9a # dim yellow
|
||||
dim4 = a6c0d4 # dim blue
|
||||
dim5 = e0a1ad # dim magenta
|
||||
dim6 = 3c6064 # dim cyan
|
||||
dim7 = ffe9dd # dim white
|
||||
|
||||
# selection-foreground=fff8e1
|
||||
# selection-background=21201d
|
||||
|
|
@ -1,11 +1,10 @@
|
|||
# -*- conf -*-
|
||||
# Material
|
||||
# From https://github.com/MartinSeeler/iterm2-material-design
|
||||
|
||||
[colors]
|
||||
foreground=ECEFF1
|
||||
background=263238
|
||||
selection-foreground=ECEFF1
|
||||
selection-background=607D8B
|
||||
regular0=546E7A # black
|
||||
regular1=FF5252 # red
|
||||
regular2=5CF19E # green
|
||||
|
|
@ -22,3 +21,5 @@ bright4=80D8FF # bright blue
|
|||
bright5=FF80AB # bright magenta
|
||||
bright6=A7FDEB # bright cyan
|
||||
bright7=FFFFFF # bright white
|
||||
# selection-foreground=ECEFF1
|
||||
# selection-background=607D8B
|
||||
|
|
|
|||
24
themes/modus-operandi
Normal file
24
themes/modus-operandi
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
# -*- conf -*-
|
||||
#
|
||||
# modus-operandi
|
||||
# See: https://protesilaos.com/emacs/modus-themes
|
||||
#
|
||||
[colors]
|
||||
background=ffffff
|
||||
foreground=000000
|
||||
regular0=000000
|
||||
regular1=a60000
|
||||
regular2=005e00
|
||||
regular3=813e00
|
||||
regular4=0031a9
|
||||
regular5=721045
|
||||
regular6=00538b
|
||||
regular7=bfbfbf
|
||||
bright0=595959
|
||||
bright1=972500
|
||||
bright2=315b00
|
||||
bright3=70480f
|
||||
bright4=2544bb
|
||||
bright5=5317ac
|
||||
bright6=005a5f
|
||||
bright7=ffffff
|
||||
25
themes/modus-vivendi
Normal file
25
themes/modus-vivendi
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
# -*- conf -*-
|
||||
#
|
||||
# modus-vivendi
|
||||
# See: https://protesilaos.com/emacs/modus-themes
|
||||
#
|
||||
|
||||
[colors]
|
||||
background=000000
|
||||
foreground=ffffff
|
||||
regular0=000000
|
||||
regular1=ff8059
|
||||
regular2=44bc44
|
||||
regular3=d0bc00
|
||||
regular4=2fafff
|
||||
regular5=feacd0
|
||||
regular6=00d3d0
|
||||
regular7=bfbfbf
|
||||
bright0=595959
|
||||
bright1=ef8b50
|
||||
bright2=70b900
|
||||
bright3=c0c530
|
||||
bright4=79a8ff
|
||||
bright5=b6a0ff
|
||||
bright6=6ae4b9
|
||||
bright7=ffffff
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
# -*- conf -*-
|
||||
# Monokai Pro
|
||||
|
||||
[colors]
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
# -*- conf -*-
|
||||
# moonfly
|
||||
# Based on https://github.com/bluz71/vim-moonfly-colors
|
||||
|
||||
|
|
@ -7,8 +8,9 @@ color = 080808 9e9e9e
|
|||
[colors]
|
||||
foreground = b2b2b2
|
||||
background = 080808
|
||||
selection-foreground = 080808
|
||||
selection-background = b2ceee
|
||||
|
||||
# selection-foreground = 080808
|
||||
# selection-background = b2ceee
|
||||
|
||||
regular0 = 323437
|
||||
regular1 = ff5454
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
# -*- conf -*-
|
||||
# nightfly
|
||||
# Based on https://github.com/bluz71/vim-nightfly-guicolors
|
||||
|
||||
|
|
@ -7,8 +8,9 @@ color = 080808 9ca1aa
|
|||
[colors]
|
||||
foreground = acb4c2
|
||||
background = 011627
|
||||
selection-foreground = 080808
|
||||
selection-background = b2ceee
|
||||
|
||||
# selection-foreground = 080808
|
||||
# selection-background = b2ceee
|
||||
|
||||
regular0 = 1d3b53
|
||||
regular1 = fc514e
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
# -*- conf -*-
|
||||
# theme: Nord
|
||||
# author: Arctic Ice Studio <development@arcticicestudio.com>, Sven Greb <code@svengreb.de>
|
||||
# description: „Nord“ — An arctic, north-bluish color palette
|
||||
|
|
@ -11,8 +12,9 @@ color = 2e3440 d8dee9
|
|||
[colors]
|
||||
foreground = d8dee9
|
||||
background = 2e3440
|
||||
#selection-foreground = d8dee9
|
||||
#selection-background = 4c566a
|
||||
|
||||
# selection-foreground = d8dee9
|
||||
# selection-background = 4c566a
|
||||
|
||||
regular0 = 3b4252
|
||||
regular1 = bf616a
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
# -*- conf -*-
|
||||
# Nordiq
|
||||
|
||||
[cursor]
|
||||
|
|
|
|||
27
themes/onedark
Normal file
27
themes/onedark
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
# OneDark
|
||||
# Palette based on the same theme from https://github.com/dexpota/kitty-themes
|
||||
|
||||
[cursor]
|
||||
color=111111 cccccc
|
||||
|
||||
[colors]
|
||||
foreground=979eab
|
||||
background=282c34
|
||||
regular0=282c34 # black
|
||||
regular1=e06c75 # red
|
||||
regular2=98c379 # green
|
||||
regular3=e5c07b # yellow
|
||||
regular4=61afef # blue
|
||||
regular5=be5046 # magenta
|
||||
regular6=56b6c2 # cyan
|
||||
regular7=979eab # white
|
||||
bright0=393e48 # bright black
|
||||
bright1=d19a66 # bright red
|
||||
bright2=56b6c2 # bright green
|
||||
bright3=e5c07b # bright yellow
|
||||
bright4=61afef # bright blue
|
||||
bright5=be5046 # bright magenta
|
||||
bright6=56b6c2 # bright cyan
|
||||
bright7=abb2bf # bright white
|
||||
# selection-foreground=282c34
|
||||
# selection-background=979eab
|
||||
|
|
@ -1,28 +1,28 @@
|
|||
# -*- conf -*-
|
||||
# PaperColorDark
|
||||
# Palette based on https://github.com/NLKNguyen/papercolor-theme
|
||||
|
||||
[cursor]
|
||||
color=1c1c1c eeeeee
|
||||
color=1c1c1c eeeeee
|
||||
|
||||
[colors]
|
||||
alpha=0.80
|
||||
background=1c1c1c
|
||||
foreground=eeeeee
|
||||
regular0=1c1c1c # black
|
||||
regular1=af005f # red
|
||||
regular2=5faf00 # green
|
||||
regular3=d7af5f # yellow
|
||||
regular4=5fafd7 # blue
|
||||
regular5=808080 # magenta
|
||||
regular6=d7875f # cyan
|
||||
regular7=d0d0d0 # white
|
||||
bright0=bcbcbc # bright black
|
||||
bright1=5faf5f # bright red
|
||||
bright2=afd700 # bright green
|
||||
bright3=af87d7 # bright yellow
|
||||
bright4=ffaf00 # bright blue
|
||||
bright5=ff5faf # bright magenta
|
||||
bright6=00afaf # bright cyan
|
||||
bright7=5f8787 # bright white
|
||||
#selection-foreground=1c1c1c
|
||||
#selection-background=af87d7
|
||||
background=1c1c1c
|
||||
foreground=eeeeee
|
||||
regular0=1c1c1c # black
|
||||
regular1=af005f # red
|
||||
regular2=5faf00 # green
|
||||
regular3=d7af5f # yellow
|
||||
regular4=5fafd7 # blue
|
||||
regular5=808080 # magenta
|
||||
regular6=d7875f # cyan
|
||||
regular7=d0d0d0 # white
|
||||
bright0=bcbcbc # bright black
|
||||
bright1=5faf5f # bright red
|
||||
bright2=afd700 # bright green
|
||||
bright3=af87d7 # bright yellow
|
||||
bright4=ffaf00 # bright blue
|
||||
bright5=ff5faf # bright magenta
|
||||
bright6=00afaf # bright cyan
|
||||
bright7=5f8787 # bright white
|
||||
# selection-foreground=1c1c1c
|
||||
# selection-background=af87d7
|
||||
|
|
|
|||
|
|
@ -1,28 +1,28 @@
|
|||
# -*- conf -*-
|
||||
# PaperColor Light
|
||||
# Palette based on https://github.com/NLKNguyen/papercolor-theme
|
||||
|
||||
[cursor]
|
||||
color=eeeeee 444444
|
||||
color=eeeeee 444444
|
||||
|
||||
[colors]
|
||||
alpha=1.0
|
||||
background=eeeeee
|
||||
foreground=444444
|
||||
regular0=eeeeee # black
|
||||
regular1=af0000 # red
|
||||
regular2=008700 # green
|
||||
regular3=5f8700 # yellow
|
||||
regular4=0087af # blue
|
||||
regular5=878787 # magenta
|
||||
regular6=005f87 # cyan
|
||||
regular7=764e37 # white
|
||||
bright0=bcbcbc # bright black
|
||||
bright1=d70000 # bright red
|
||||
bright2=d70087 # bright green
|
||||
bright3=8700af # bright yellow
|
||||
bright4=d75f00 # bright blue
|
||||
bright5=d75f00 # bright magenta
|
||||
bright6=4c7a5d # bright cyan
|
||||
bright7=005faf # bright white
|
||||
#selection-foreground=eeeeee
|
||||
#selection-background=0087af
|
||||
background=eeeeee
|
||||
foreground=444444
|
||||
regular0=eeeeee # black
|
||||
regular1=af0000 # red
|
||||
regular2=008700 # green
|
||||
regular3=5f8700 # yellow
|
||||
regular4=0087af # blue
|
||||
regular5=878787 # magenta
|
||||
regular6=005f87 # cyan
|
||||
regular7=764e37 # white
|
||||
bright0=bcbcbc # bright black
|
||||
bright1=d70000 # bright red
|
||||
bright2=d70087 # bright green
|
||||
bright3=8700af # bright yellow
|
||||
bright4=d75f00 # bright blue
|
||||
bright5=d75f00 # bright magenta
|
||||
bright6=4c7a5d # bright cyan
|
||||
bright7=005faf # bright white
|
||||
# selection-foreground=eeeeee
|
||||
# selection-background=0087af
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
# -*- conf -*-
|
||||
# theme: rezza
|
||||
# author: Doug Whiteley (rezza)
|
||||
# original URL: http://metawire.org/~rezza/index.php
|
||||
|
|
|
|||
26
themes/rose-pine
Normal file
26
themes/rose-pine
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
# -*- conf -*-
|
||||
# Rose-Piné
|
||||
|
||||
[cursor]
|
||||
color=191724 e0def4
|
||||
|
||||
[colors]
|
||||
background=191724
|
||||
foreground=e0def4
|
||||
regular0=26233a # black
|
||||
regular1=eb6f92 # red
|
||||
regular2=31748f # green
|
||||
regular3=f6c177 # yellow
|
||||
regular4=9ccfd8 # blue
|
||||
regular5=c4a7e7 # magenta
|
||||
regular6=ebbcba # cyan
|
||||
regular7=e0def4 # white
|
||||
|
||||
bright0=6e6a86 # bright black
|
||||
bright1=eb6f92 # bright red
|
||||
bright2=31748f # bright green
|
||||
bright3=f6c177 # bright yellow
|
||||
bright4=9ccfd8 # bright blue
|
||||
bright5=c4a7e7 # bright magenta
|
||||
bright6=ebbcba # bright cyan
|
||||
bright7=e0def4 # bright white
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
# -*- conf -*-
|
||||
# Selenized black
|
||||
|
||||
[cursor]
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
# -*- conf -*-
|
||||
# Selenized dark
|
||||
|
||||
[cursor]
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
# -*- conf -*-
|
||||
# Selenized light
|
||||
|
||||
[cursor]
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
# -*- conf -*-
|
||||
# Selenized white
|
||||
|
||||
[cursor]
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
# -*- conf -*-
|
||||
# Solarized dark
|
||||
|
||||
[cursor]
|
||||
|
|
@ -23,7 +24,7 @@ bright5= 6c71c4
|
|||
bright6= 93a1a1
|
||||
bright7= fdf6e3
|
||||
|
||||
## Enable if prefer solarized colors instead of inverterd fg/bg for
|
||||
## highlighting (mouse selection)
|
||||
# Enable if prefer solarized colors instead of inverterd fg/bg for
|
||||
# highlighting (mouse selection)
|
||||
# selection-foreground=93a1a1
|
||||
# selection-background=073642
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
# -*- conf -*-
|
||||
# Solarized dark
|
||||
|
||||
[cursor]
|
||||
|
|
@ -25,7 +26,7 @@ bright5= dc619d
|
|||
bright6= 32c1b6
|
||||
bright7= ffffff
|
||||
|
||||
## Enable if prefer solarized colors instead of inverterd fg/bg for
|
||||
## highlighting (mouse selection)
|
||||
# Enable if prefer solarized colors instead of inverterd fg/bg for
|
||||
# highlighting (mouse selection)
|
||||
# selection-foreground=93a1a1
|
||||
# selection-background=073642
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
# -*- conf -*-
|
||||
# Solarized light
|
||||
|
||||
[cursor]
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
# -*- conf -*-
|
||||
# Tango
|
||||
|
||||
[cursor]
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
# -*- conf -*-
|
||||
# theme: Tempus Autumn
|
||||
# author: Protesilaos Stavrou (https://protesilaos.com)
|
||||
# description: Dark theme with a palette inspired by earthly colours (WCAG AA compliant)
|
||||
|
|
@ -24,5 +25,5 @@ bright4 = 958fdf
|
|||
bright5 = ce7dc4
|
||||
bright6 = 2fa6b7
|
||||
bright7 = a9a2a6
|
||||
#selection-foreground = a8948a
|
||||
#selection-background = 36302a
|
||||
# selection-foreground = a8948a
|
||||
# selection-background = 36302a
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
# -*- conf -*-
|
||||
# theme: Tempus Classic
|
||||
# author: Protesilaos Stavrou (https://protesilaos.com)
|
||||
# description: Dark theme with warm hues (WCAG AA compliant)
|
||||
|
|
@ -24,5 +25,5 @@ bright4 = 8e9cc0
|
|||
bright5 = d58888
|
||||
bright6 = 7aa880
|
||||
bright7 = aeadaf
|
||||
#selection-foreground = 949d9f
|
||||
#selection-background = 312e30
|
||||
# selection-foreground = 949d9f
|
||||
# selection-background = 312e30
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
# -*- conf -*-
|
||||
# theme: Tempus Dawn
|
||||
# author: Protesilaos Stavrou (https://protesilaos.com)
|
||||
# description: Light theme with a soft, slightly desaturated palette (WCAG AA compliant)
|
||||
|
|
@ -24,5 +25,5 @@ bright4 = 5c59b2
|
|||
bright5 = 8e45a8
|
||||
bright6 = 3f649c
|
||||
bright7 = eff0f2
|
||||
#selection-foreground = 676364
|
||||
#selection-background = dee2e0
|
||||
# selection-foreground = 676364
|
||||
# selection-background = dee2e0
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
# -*- conf -*-
|
||||
# theme: Tempus Day
|
||||
# author: Protesilaos Stavrou (https://protesilaos.com)
|
||||
# description: Light theme with warm colours (WCAG AA compliant)
|
||||
|
|
@ -24,5 +25,5 @@ bright4 = 0f64c4
|
|||
bright5 = 8050a7
|
||||
bright6 = 336c87
|
||||
bright7 = f8f2e5
|
||||
#selection-foreground = 68607d
|
||||
#selection-background = e7e3d7
|
||||
# selection-foreground = 68607d
|
||||
# selection-background = e7e3d7
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
# -*- conf -*-
|
||||
# theme: Tempus Dusk
|
||||
# author: Protesilaos Stavrou (https://protesilaos.com)
|
||||
# description: Dark theme with a deep blue-ish, slightly desaturated palette (WCAG AA compliant)
|
||||
|
|
@ -24,5 +25,5 @@ bright4 = 9ca5de
|
|||
bright5 = c69ac6
|
||||
bright6 = 8caeb6
|
||||
bright7 = a2a8ba
|
||||
#selection-foreground = a29899
|
||||
#selection-background = 2c3150
|
||||
# selection-foreground = a29899
|
||||
# selection-background = 2c3150
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
# -*- conf -*-
|
||||
# theme: Tempus Fugit
|
||||
# author: Protesilaos Stavrou (https://protesilaos.com)
|
||||
# description: Light, pleasant theme optimised for long writing/coding sessions (WCAG AA compliant)
|
||||
|
|
@ -24,5 +25,5 @@ bright4 = 485adf
|
|||
bright5 = a234c0
|
||||
bright6 = 00756a
|
||||
bright7 = fff5f3
|
||||
#selection-foreground = 796271
|
||||
#selection-background = efe6e4
|
||||
# selection-foreground = 796271
|
||||
# selection-background = efe6e4
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
# -*- conf -*-
|
||||
# theme: Tempus Future
|
||||
# author: Protesilaos Stavrou (https://protesilaos.com)
|
||||
# description: Dark theme with colours inspired by concept art of outer space (WCAG AAA compliant)
|
||||
|
|
@ -24,5 +25,5 @@ bright4 = 8ba7ea
|
|||
bright5 = e08bd6
|
||||
bright6 = 2cbab6
|
||||
bright7 = b4abac
|
||||
#selection-foreground = a7a2c4
|
||||
#selection-background = 2b1329
|
||||
# selection-foreground = a7a2c4
|
||||
# selection-background = 2b1329
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
# -*- conf -*-
|
||||
# theme: Tempus Night
|
||||
# author: Protesilaos Stavrou (https://protesilaos.com)
|
||||
# description: High contrast dark theme with bright colours (WCAG AAA compliant)
|
||||
|
|
@ -24,5 +25,5 @@ bright4 = 8cb4f0
|
|||
bright5 = de99f0
|
||||
bright6 = 00ca9a
|
||||
bright7 = e0e0e0
|
||||
#selection-foreground = c4bdaf
|
||||
#selection-background = 242536
|
||||
# selection-foreground = c4bdaf
|
||||
# selection-background = 242536
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
# -*- conf -*-
|
||||
# theme: Tempus Past
|
||||
# author: Protesilaos Stavrou (https://protesilaos.com)
|
||||
# description: Light theme inspired by old vaporwave concept art (WCAG AA compliant)
|
||||
|
|
@ -24,5 +25,5 @@ bright4 = 5559bb
|
|||
bright5 = b022a7
|
||||
bright6 = 07707a
|
||||
bright7 = f3f2f4
|
||||
#selection-foreground = 80565d
|
||||
#selection-background = eae2de
|
||||
# selection-foreground = 80565d
|
||||
# selection-background = eae2de
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
# -*- conf -*-
|
||||
# theme: Tempus Rift
|
||||
# author: Protesilaos Stavrou (https://protesilaos.com)
|
||||
# description: Dark theme with a subdued palette on the green side of the spectrum (WCAG AA compliant)
|
||||
|
|
@ -24,5 +25,5 @@ bright4 = 56bdad
|
|||
bright5 = cca0ba
|
||||
bright6 = 10c480
|
||||
bright7 = bbbcbc
|
||||
#selection-foreground = ab9aa9
|
||||
#selection-background = 283431
|
||||
# selection-foreground = ab9aa9
|
||||
# selection-background = 283431
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
# -*- conf -*-
|
||||
# theme: Tempus Spring
|
||||
# author: Protesilaos Stavrou (https://protesilaos.com)
|
||||
# description: Dark theme with a palette inspired by early spring colours (WCAG AA compliant)
|
||||
|
|
@ -24,5 +25,5 @@ bright4 = 70afef
|
|||
bright5 = d095e2
|
||||
bright6 = 3cbfaf
|
||||
bright7 = b5b8b7
|
||||
#selection-foreground = 99afae
|
||||
#selection-background = 2a453d
|
||||
# selection-foreground = 99afae
|
||||
# selection-background = 2a453d
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
# -*- conf -*-
|
||||
# theme: Tempus Summer
|
||||
# author: Protesilaos Stavrou (https://protesilaos.com)
|
||||
# description: Dark theme with colours inspired by summer evenings by the sea (WCAG AA compliant)
|
||||
|
|
@ -24,5 +25,5 @@ bright4 = 8599ef
|
|||
bright5 = cc82d7
|
||||
bright6 = 2aacbf
|
||||
bright7 = a0abae
|
||||
#selection-foreground = 949cbf
|
||||
#selection-background = 39304f
|
||||
# selection-foreground = 949cbf
|
||||
# selection-background = 39304f
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
# -*- conf -*-
|
||||
# theme: Tempus Tempest
|
||||
# author: Protesilaos Stavrou (https://protesilaos.com)
|
||||
# description: A green-scale, subtle theme for late night hackers (WCAG AAA compliant)
|
||||
|
|
@ -24,5 +25,5 @@ bright4 = 74e4cd
|
|||
bright5 = d2d4aa
|
||||
bright6 = 9bdfc4
|
||||
bright7 = b6e0ca
|
||||
#selection-foreground = b0c8ca
|
||||
#selection-background = 323535
|
||||
# selection-foreground = b0c8ca
|
||||
# selection-background = 323535
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
# -*- conf -*-
|
||||
# theme: Tempus Totus
|
||||
# author: Protesilaos Stavrou (https://protesilaos.com)
|
||||
# description: Light theme for prose or for coding in an open space (WCAG AAA compliant)
|
||||
|
|
@ -24,5 +25,5 @@ bright4 = 2d45b0
|
|||
bright5 = 700dc9
|
||||
bright6 = 005289
|
||||
bright7 = ffffff
|
||||
#selection-foreground = 5e4b4f
|
||||
#selection-background = efefef
|
||||
# selection-foreground = 5e4b4f
|
||||
# selection-background = efefef
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
# -*- conf -*-
|
||||
# theme: Tempus Warp
|
||||
# author: Protesilaos Stavrou (https://protesilaos.com)
|
||||
# description: Dark theme with a vibrant palette (WCAG AA compliant)
|
||||
|
|
@ -24,5 +25,5 @@ bright4 = 8887f0
|
|||
bright5 = d85cf2
|
||||
bright6 = 1da1af
|
||||
bright7 = a29fa0
|
||||
#selection-foreground = 968282
|
||||
#selection-background = 261c2c
|
||||
# selection-foreground = 968282
|
||||
# selection-background = 261c2c
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
# -*- conf -*-
|
||||
# theme: Tempus Winter
|
||||
# author: Protesilaos Stavrou (https://protesilaos.com)
|
||||
# description: Dark theme with a palette inspired by winter nights at the city (WCAG AA compliant)
|
||||
|
|
@ -24,5 +25,5 @@ bright4 = 329fcb
|
|||
bright5 = ca77c5
|
||||
bright6 = 1ba6a4
|
||||
bright7 = 8da3b8
|
||||
#selection-foreground = 91959b
|
||||
#selection-background = 2a2e38
|
||||
# selection-foreground = 91959b
|
||||
# selection-background = 2a2e38
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
# -*- conf -*-
|
||||
|
||||
[colors]
|
||||
background=e1e2e7
|
||||
foreground=3760bf
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
# -*- conf -*-
|
||||
|
||||
[colors]
|
||||
background=1a1b26
|
||||
foreground=c0caf5
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
# -*- conf -*-
|
||||
|
||||
[colors]
|
||||
background=24283b
|
||||
foreground=c0caf5
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
# -*- conf -*-
|
||||
# VisiBone
|
||||
|
||||
[cursor]
|
||||
|
|
|
|||
25
themes/zenburn
Normal file
25
themes/zenburn
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
# -*- conf -*-
|
||||
|
||||
[colors]
|
||||
foreground=dcdccc
|
||||
background=111111
|
||||
|
||||
## Normal/regular colors (color palette 0-7)
|
||||
regular0=222222 # black
|
||||
regular1=cc9393 # red
|
||||
regular2=7f9f7f # green
|
||||
regular3=d0bf8f # yellow
|
||||
regular4=6ca0a3 # blue
|
||||
regular5=dc8cc3 # magenta
|
||||
regular6=93e0e3 # cyan
|
||||
regular7=dcdccc # white
|
||||
|
||||
## Bright colors (color palette 8-15)
|
||||
bright0=666666 # bright black
|
||||
bright1=dca3a3 # bright red
|
||||
bright2=bfebbf # bright green
|
||||
bright3=f0dfaf # bright yellow
|
||||
bright4=8cd0d3 # bright blue
|
||||
bright5=fcace3 # bright magenta
|
||||
bright6=b3ffff # bright cyan
|
||||
bright7=ffffff # bright white
|
||||
2
uri.c
2
uri.c
|
|
@ -159,7 +159,7 @@ uri_parse(const char *uri, size_t len,
|
|||
char *p = decoded;
|
||||
|
||||
size_t encoded_len = path_len;
|
||||
size_t decoded_len = 0;
|
||||
size_t UNUSED decoded_len = 0;
|
||||
|
||||
while (true) {
|
||||
/* Find next '%' */
|
||||
|
|
|
|||
32
url-mode.c
32
url-mode.c
|
|
@ -746,15 +746,18 @@ tag_cells_for_url(struct terminal *term, const struct url *url, bool value)
|
|||
if (url->url_mode_dont_change_url_attr)
|
||||
return;
|
||||
|
||||
struct grid *grid = term->url_grid_snapshot;
|
||||
xassert(grid != NULL);
|
||||
|
||||
const struct coord *start = &url->range.start;
|
||||
const struct coord *end = &url->range.end;
|
||||
|
||||
size_t end_r = end->row & (term->grid->num_rows - 1);
|
||||
size_t end_r = end->row & (grid->num_rows - 1);
|
||||
|
||||
size_t r = start->row & (term->grid->num_rows - 1);
|
||||
size_t r = start->row & (grid->num_rows - 1);
|
||||
size_t c = start->col;
|
||||
|
||||
struct row *row = term->grid->rows[r];
|
||||
struct row *row = grid->rows[r];
|
||||
row->dirty = true;
|
||||
|
||||
while (true) {
|
||||
|
|
@ -766,10 +769,10 @@ tag_cells_for_url(struct terminal *term, const struct url *url, bool value)
|
|||
break;
|
||||
|
||||
if (++c >= term->cols) {
|
||||
r = (r + 1) & (term->grid->num_rows - 1);
|
||||
r = (r + 1) & (grid->num_rows - 1);
|
||||
c = 0;
|
||||
|
||||
row = term->grid->rows[r];
|
||||
row = grid->rows[r];
|
||||
if (row == NULL) {
|
||||
/* Un-allocated scrollback. This most likely means a
|
||||
* runaway OSC-8 URL. */
|
||||
|
|
@ -788,15 +791,6 @@ urls_render(struct terminal *term)
|
|||
if (tll_length(win->term->urls) == 0)
|
||||
return;
|
||||
|
||||
xassert(tll_length(win->urls) == 0);
|
||||
tll_foreach(win->term->urls, it) {
|
||||
struct wl_url url = {.url = &it->item};
|
||||
wayl_win_subsurface_new(win, &url.surf, false);
|
||||
|
||||
tll_push_back(win->urls, url);
|
||||
tag_cells_for_url(term, &it->item, true);
|
||||
}
|
||||
|
||||
/* Dirty the last cursor, to ensure it is erased */
|
||||
{
|
||||
struct row *cursor_row = term->render.last_cursor.row;
|
||||
|
|
@ -819,6 +813,15 @@ urls_render(struct terminal *term)
|
|||
/* Snapshot the current grid */
|
||||
term->url_grid_snapshot = grid_snapshot(term->grid);
|
||||
|
||||
xassert(tll_length(win->urls) == 0);
|
||||
tll_foreach(win->term->urls, it) {
|
||||
struct wl_url url = {.url = &it->item};
|
||||
wayl_win_subsurface_new(win, &url.surf, false);
|
||||
|
||||
tll_push_back(win->urls, url);
|
||||
tag_cells_for_url(term, &it->item, true);
|
||||
}
|
||||
|
||||
render_refresh_urls(term);
|
||||
render_refresh(term);
|
||||
}
|
||||
|
|
@ -860,7 +863,6 @@ urls_reset(struct terminal *term)
|
|||
}
|
||||
|
||||
tll_foreach(term->urls, it) {
|
||||
tag_cells_for_url(term, &it->item, false);
|
||||
url_destroy(&it->item);
|
||||
tll_remove(term->urls, it);
|
||||
}
|
||||
|
|
|
|||
1
utils/meson.build
Normal file
1
utils/meson.build
Normal file
|
|
@ -0,0 +1 @@
|
|||
executable('xtgettcap', 'xtgettcap.c')
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue