├── samples
└── c
│ ├── .gitignore
│ ├── src
│ └── main.c
│ ├── .clang-tidy
│ ├── Makefile
│ └── .clang-format
├── home
├── .inputrc
├── .gitconfig
├── .bash_profile
├── .xprofile
├── .bashrc
└── .gdbinit
├── helix
├── languages.toml
└── config.toml
├── dunst
├── icons
│ ├── bell.svg
│ ├── message.svg
│ └── alert-triangle.svg
└── dunstrc
├── st
├── patches
│ ├── st-scrollback-mouse-0.9.2.diff
│ └── st-scrollback-ringbuffer-0.9.2.diff
└── config.def.h
├── .packages
└── dwm
└── config.def.h
/samples/c/.gitignore:
--------------------------------------------------------------------------------
1 | .helix/
2 | .cache/
3 | build/
4 | compile_commands.json
5 |
--------------------------------------------------------------------------------
/home/.inputrc:
--------------------------------------------------------------------------------
1 | set colored-completion-prefix on
2 | set colored-stats on
3 | set completion-ignore-case on
4 | set show-all-if-ambiguous on
5 |
--------------------------------------------------------------------------------
/helix/languages.toml:
--------------------------------------------------------------------------------
1 | [language-server.clangd]
2 | command = "clangd"
3 | args = ["--background-index", "--header-insertion=never", "--clang-tidy"]
4 |
--------------------------------------------------------------------------------
/samples/c/src/main.c:
--------------------------------------------------------------------------------
1 | #include "just.h"
2 |
3 | int
4 | main(int argc, char* argv[]) {
5 | (void)argc;
6 | (void)argv;
7 |
8 | return EXIT_SUCCESS;
9 | }
10 |
--------------------------------------------------------------------------------
/home/.gitconfig:
--------------------------------------------------------------------------------
1 | [user]
2 | email = fartdraft@gmail.com
3 | name = pithecantrope
4 |
5 | [init]
6 | defaultBranch = main
7 |
8 | [core]
9 | pager = delta
10 |
11 | [interactive]
12 | diffFilter = delta --color-only
13 |
14 | [delta]
15 | navigate = true
16 | dark = true
17 | syntax-theme = gruvbox-dark
18 |
19 | [merge]
20 | conflictstyle = zdiff3
21 |
22 | [diff]
23 | colorMoved = default
24 |
25 |
--------------------------------------------------------------------------------
/dunst/icons/bell.svg:
--------------------------------------------------------------------------------
1 |
7 |
21 |
--------------------------------------------------------------------------------
/home/.bash_profile:
--------------------------------------------------------------------------------
1 | #
2 | # ~/.bash_profile
3 | #
4 |
5 | [[ -f ~/.bashrc ]] && . ~/.bashrc
6 |
7 | export EDITOR=helix
8 | export BROWSER=firefox
9 | export HISTSIZE=4096
10 | export HISTFILESIZE=4096
11 | export HISTCONTROL=erasedups
12 | export COLORTERM=truecolor
13 | export GTK_THEME=Adwaita:dark
14 | export QT_STYLE_OVERRIDE=Adwaita-Dark
15 | export LS_COLORS="$(vivid generate gruvbox-dark)"
16 | export BAT_THEME="gruvbox-dark"
17 | export MANPAGER="sh -c 'awk '\''{ gsub(/\x1B\[[0-9;]*m/, \"\", \$0); gsub(/.\x08/, \"\", \$0); print }'\'' | bat -p -lman'"
18 | man 2 select
19 |
--------------------------------------------------------------------------------
/dunst/icons/message.svg:
--------------------------------------------------------------------------------
1 |
7 |
22 |
--------------------------------------------------------------------------------
/home/.xprofile:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | {
4 | while true; do
5 | time=$(date '+%H:%M')
6 | battery=$(cat /sys/class/power_supply/BAT0/capacity 2>/dev/null || echo '?')
7 | if [ "$battery" -lt 25 ] 2>/dev/null; then
8 | notify-send -u critical 'Low Battery'
9 | fi
10 | todo=$(rg -F '[ ]' ~/projects/TODO -m1 | sed 's/^\[ \] //' || echo 'None')
11 | xsetroot -name "TODO: '${todo}' | BAT: ${battery}% | ${time}"
12 | sleep 33s
13 | done
14 | } &
15 | unclutter --start-hidden -b
16 | dunst &
17 |
18 | st &
19 | firefox &
20 |
21 | exec dwm
22 |
--------------------------------------------------------------------------------
/dunst/icons/alert-triangle.svg:
--------------------------------------------------------------------------------
1 |
7 |
22 |
--------------------------------------------------------------------------------
/samples/c/.clang-tidy:
--------------------------------------------------------------------------------
1 | Checks: >
2 | performance-*,
3 | misc-*,
4 | android-cloexec-*,
5 | readability-duplicate-include,
6 | readability-misleading-indentation,
7 | bugprone-assert-side-effect,
8 | bugprone-macro-repeated-side-effects,
9 | bugprone-infinite-loop,
10 | bugprone-macro-parentheses,
11 | bugprone-posix-return,
12 | bugprone-reserved-identifier,
13 | bugprone-signal-handler,
14 | bugprone-signed-char-misuse,
15 | bugprone-sizeof-expression,
16 | bugprone-branch-clone,
17 | -clang-analyzer-security.insecureAPI.*,
18 | -misc-no-recursion,
19 |
20 | WarningsAsErrors: '*'
21 |
22 | ExtraArgs: [-std=c17]
23 |
--------------------------------------------------------------------------------
/dunst/dunstrc:
--------------------------------------------------------------------------------
1 | [global]
2 | # Gruvbox-dark colorscheme
3 | offset = (0, 20) # Just under 'WM_NAME'
4 | frame_color = "#928374"
5 | font = Adwaita Mono 11
6 | enable_recursive_icon_lookup = false
7 | icon_path = ~/projects/dotfiles/dunst/icons
8 |
9 | [urgency_low]
10 | background = "#458588"
11 | foreground = "#d5c4a1"
12 | timeout = 10
13 | default_icon = message
14 |
15 | [urgency_normal]
16 | background = "#689d6a"
17 | foreground = "#ebdbb2"
18 | timeout = 30
19 | default_icon = bell
20 |
21 | [urgency_critical]
22 | background = "#b16286"
23 | foreground = "#fbf1c7"
24 | timeout = 0
25 | default_icon = alert-triangle
26 |
--------------------------------------------------------------------------------
/helix/config.toml:
--------------------------------------------------------------------------------
1 | theme = "sunset"
2 |
3 | [editor]
4 | gutters = ["diagnostics", "spacer", "diff"]
5 | true-color = true
6 | bufferline = "always"
7 | auto-format = false
8 | popup-border = "all"
9 | jump-label-alphabet = "jfkdls;aurieowpqnvmcxz"
10 | trim-final-newlines = true
11 | trim-trailing-whitespace = true
12 |
13 | [keys.normal]
14 | "X" = "extend_line_above"
15 | "C-c" = ["save_selection", "extend_to_line_bounds", "yank_to_primary_clipboard",
16 | "paste_primary_clipboard_before", "jump_backward"]
17 |
18 | [keys.insert]
19 | "C-c" = ["normal_mode", "save_selection", "extend_to_line_bounds", "yank_to_primary_clipboard",
20 | "paste_primary_clipboard_before", "jump_backward", "insert_mode"]
21 |
22 | [keys.select]
23 | "C-c" = ["yank_to_primary_clipboard", "paste_primary_clipboard_before"]
24 |
--------------------------------------------------------------------------------
/st/patches/st-scrollback-mouse-0.9.2.diff:
--------------------------------------------------------------------------------
1 | From 6b7e7e6c5c44dd6347ad49691b80d808c1b0cb77 Mon Sep 17 00:00:00 2001
2 | From: Jernej Jakob
3 | Date: Mon, 1 Jul 2024 14:00:02 +0200
4 | Subject: [PATCH] [st][patch] Update st-scrollback-mouse for 0.9.2
5 |
6 | ---
7 | config.def.h | 2 ++
8 | 1 file changed, 2 insertions(+)
9 |
10 | diff --git a/config.def.h b/config.def.h
11 | index 8b25d40..d259675 100644
12 | --- a/config.def.h
13 | +++ b/config.def.h
14 | @@ -176,6 +176,8 @@ static uint forcemousemod = ShiftMask;
15 | */
16 | static MouseShortcut mshortcuts[] = {
17 | /* mask button function argument release */
18 | + { ShiftMask, Button4, kscrollup, {.i = 1} },
19 | + { ShiftMask, Button5, kscrolldown, {.i = 1} },
20 | { XK_ANY_MOD, Button2, selpaste, {.i = 0}, 1 },
21 | { ShiftMask, Button4, ttysend, {.s = "\033[5;2~"} },
22 | { XK_ANY_MOD, Button4, ttysend, {.s = "\031"} },
23 | --
24 | 2.44.2
25 |
26 |
--------------------------------------------------------------------------------
/home/.bashrc:
--------------------------------------------------------------------------------
1 | #
2 | # ~/.bashrc
3 | #
4 |
5 | # If not running interactively, don't do anything
6 | [[ $- != *i* ]] && return
7 |
8 | PS1='\[\e[3;33m\]\w \[\e[1;32m\]>\[\e[0m\] '
9 | alias e=helix
10 |
11 | alias ls='eza --group-directories-first --icons --git-ignore'
12 | alias lt='eza --group-directories-first --icons --git-ignore --tree --level=3'
13 | alias la='eza --group-directories-first --icons --all'
14 | alias ll='eza --group-directories-first --icons --git-ignore --long --header --color-scale --binary --total-size --git'
15 | # --{modified, changed, accessed, created}
16 |
17 | cd() {
18 | builtin cd "$@" && la
19 | }
20 |
21 | man() {
22 | command man "$@" 2>/dev/null || "$@" --help 2>&1 | bat --plain --language=help
23 | }
24 |
25 | alias c='xclip -selection clipboard'
26 | alias pb='curl -F "file=@-" 0x0.st'
27 |
28 | alias fp='fzf --preview "bat --color=always --style=numbers --line-range=:500 {}"'
29 | eval "$(fzf --bash)" # Ctrl-T, Ctrl-R, Alt-C and helix **
30 |
31 | alias pomowork='sleep 1m && notify-send -u low "Pomodoro" "You have earned a rest"'
32 | alias pomobreak='sleep 1m && notify-send -u normal "Pomodoro" "Get back to work"'
33 |
--------------------------------------------------------------------------------
/home/.gdbinit:
--------------------------------------------------------------------------------
1 | # set disassembly-flavor intel
2 | # set width unlimited
3 | # set height unlimited
4 | # set pagination off
5 | # set verbose off
6 |
7 | set debuginfod enabled off
8 | set confirm off
9 | set disassembly-flavor intel
10 | set history save on
11 | set history filename ~/.gdb_history
12 | # set history size 100000
13 | # set history remove-duplicates 10
14 | set host-charset UTF-8
15 | set target-charset UTF-8
16 | set target-wide-charset UTF-8
17 |
18 | set print pretty on
19 | set print object on
20 | set print static-members on
21 | set print vtbl on
22 |
23 | set print demangle on
24 | set demangle-style gnu-v3
25 | set print sevenbit-strings off
26 |
27 |
28 | # Essential .gdbinit configuration
29 | set confirm off
30 | set pagination off
31 | set history save on
32 | set history filename ~/.gdb_history
33 |
34 | # Better display
35 | set print pretty on
36 | set print object on
37 | set print static-members on
38 | set print vtbl on
39 | set print array on
40 | set print array-indexes on
41 |
42 | # Stop at first instruction
43 | set startup-with-shell off
44 |
45 | # Common shortcuts
46 | define x
47 | examine/8x $arg0
48 | end
49 |
50 | define xx
51 | examine/16x $arg0
52 | end
53 |
54 | define d
55 | examine/8dw $arg0
56 | end
57 |
58 | define dd
59 | examine/16dw $arg0
60 | end
61 |
62 | # Enhanced backtrace
63 | define bt
64 | backtrace
65 | frame
66 | end
67 |
68 | # Common hook
69 | define hook-quit
70 | set confirm on
71 | end
72 |
73 | # TUI mode improvements
74 | tui enable
75 | set tui border-kind ascii
76 | set tui tab-width 4
77 |
78 | # Source code context
79 | set listsize 20
80 | set disassembly-flavor intel
81 |
82 |
83 |
84 | break abort # Catch abort() calls
85 | break __assert_fail # Catch failed assertions
86 | break exit # Catch normal exits
87 | break _exit # Catch immediate exits
88 |
--------------------------------------------------------------------------------
/.packages:
--------------------------------------------------------------------------------
1 | # To install packages, run:
2 | # sed 's/ *#.*//; /^$/d' .packages | sudo pacman -S --needed -
3 | # Software with a leading '#' must be installed manually.
4 | # A)
5 | # B)
6 | bat # Modern `cat`
7 | brightnessctl # Brightness control
8 | btop # Resources monitor
9 | # C)
10 | #chatterino2-bin # Chat client 'yay -S chatterino2-bin'
11 | # D)
12 | dmenu # Dynamic menu
13 | dunst # Notification daemon
14 | #dwm # Window manager `git clone https://git.suckless.org/dwm`
15 | # E)
16 | easyeffects # Audio enhancer
17 | eza # Modern `ls`
18 | # F)
19 | fastfetch # System information
20 | fd # Modern `find`
21 | firefox # Web browser
22 | firefox-tridactyl # Vim-like interface
23 | fzf # Fuzzy finder
24 | # G)
25 | git # Version control
26 | git-delta # `git` pager
27 | glow # CLI markdown
28 | gnome-themes-extra # Dark mode
29 | # H)
30 | helix # Text editor
31 | # I)
32 | # J)
33 | # K)
34 | keyd # Key remapper
35 | # L)
36 | libreoffice-still-ru # Office suite
37 | ly # Display manager
38 | # M)
39 | maim # Screenshot maker
40 | mpv # Media player
41 | # N)
42 | # O)
43 | obs-studio # Live streaming
44 | openssh # Remote connection
45 | ouch # Compression decompression
46 | # P)
47 | pacman-contrib # Cache cleaner
48 | #pinta # Paint program 'yay -S pinta'
49 | python-qrcode # QR code
50 | # Q)
51 | # R)
52 | reflector # Mirror manager
53 | ripgrep # Modern `grep`
54 | # S)
55 | #st # Suckless terminal `git clone https://git.suckless.org/st`
56 | # T)
57 | tlp # Battery life
58 | tokei # Code counter
59 | ttf-cascadia-mono-nerd # Terminal font
60 | # U)
61 | unclutter # Cursor hider
62 | # V)
63 | vivid # `LS_COLORS` generator
64 | # W)
65 | wireless-regdb # Regulatory database
66 | # X)
67 | xclip # X11 Clipboard
68 | xorg # Window system
69 | # Y)
70 | #yay # AUR helper `sudo pacman -S --needed git base-devel && git clone https://aur.archlinux.org/yay.git && cd yay && makepkg -si`
71 | yt-dlp # Video downloader
72 | # Z)
73 |
--------------------------------------------------------------------------------
/samples/c/Makefile:
--------------------------------------------------------------------------------
1 | MAKEFLAGS += -j$(nproc)
2 | PROJECT_NAME := bin
3 | LDFLAGS :=
4 | ARGS ?=
5 |
6 | BUILD_DIR := build
7 | SRC_DIR := src
8 | CONFIG ?= DEV
9 | CC := gcc
10 | CPPFLAGS := -MMD -MP
11 |
12 | TARGET_DIR := $(BUILD_DIR)/$(CONFIG)
13 | TARGET := $(TARGET_DIR)/$(PROJECT_NAME)-$(CONFIG)
14 |
15 | CFLAGS_RELEASE := -O3 -flto=auto -DNDEBUG
16 | CFLAGS_DEBUG := -O0 -ggdb3
17 | CFLAGS_PROFILE := -O2 -fno-inline -fno-omit-frame-pointer -g3
18 | CFLAGS_DEV := -std=c17 -O0 -g3 -Werror -Wall -Wextra -Wpedantic -fsanitize=address,undefined \
19 | -Wcast-qual -Wconversion -Wdouble-promotion -Wfloat-equal -Winline -Wlogical-op \
20 | -Wold-style-definition -Wshadow -Wswitch-default -Wswitch-enum -Wundef
21 | CFLAGS := $(CFLAGS_$(CONFIG))
22 |
23 | SRCS := $(wildcard $(SRC_DIR)/*.c)
24 | OBJS := $(SRCS:$(SRC_DIR)/%.c=$(TARGET_DIR)/%.o)
25 | DEPS := $(OBJS:.o=.d)
26 |
27 | .SILENT:
28 | .PHONY: all release _release debug _debug perf _perf leak _leak cache _cache call _call mem _mem run spell clean db
29 |
30 | all: $(TARGET)
31 |
32 | $(TARGET_DIR):
33 | mkdir -p $@
34 |
35 | $(TARGET): $(OBJS)
36 | $(CC) $(CFLAGS) $^ -o $@ $(LDFLAGS)
37 |
38 | $(TARGET_DIR)/%.o: $(SRC_DIR)/%.c | $(TARGET_DIR)
39 | $(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@
40 |
41 | release:
42 | $(MAKE) -s CONFIG=RELEASE
43 | $(MAKE) -s CONFIG=RELEASE _release
44 |
45 | _release:
46 | $(TARGET) $(ARGS)
47 |
48 | debug:
49 | $(MAKE) -s CONFIG=DEBUG
50 | $(MAKE) -s CONFIG=DEBUG _debug
51 |
52 | _debug:
53 | gdb -q -ex 'break main' --tui --args $(TARGET) $(ARGS)
54 |
55 | perf:
56 | $(MAKE) -s CONFIG=PROFILE
57 | $(MAKE) -s CONFIG=PROFILE _perf
58 |
59 | _perf:
60 | perf record -g --freq=max -o $(TARGET_DIR)/perf.data $(TARGET) $(ARGS)
61 | perf script -i $(TARGET_DIR)/perf.data | stackcollapse-perf.pl | flamegraph.pl > $(TARGET_DIR)/flamegraph.svg
62 | $(BROWSER) $(TARGET_DIR)/flamegraph.svg
63 |
64 | leak:
65 | $(MAKE) -s CONFIG=DEBUG
66 | $(MAKE) -s CONFIG=DEBUG _leak
67 |
68 | _leak:
69 | valgrind --tool=memcheck --leak-check=full --show-leak-kinds=all --track-origins=yes --log-file=$(TARGET_DIR)/leak.txt $(TARGET) $(ARGS)
70 | $(EDITOR) $(TARGET_DIR)/leak.txt
71 |
72 | cache:
73 | $(MAKE) -s CONFIG=PROFILE
74 | $(MAKE) -s CONFIG=PROFILE _cache
75 |
76 | _cache:
77 | valgrind -q --tool=cachegrind --cachegrind-out-file=$(TARGET_DIR)/cache.out $(TARGET) $(ARGS)
78 | cg_annotate $(TARGET_DIR)/cache.out > $(TARGET_DIR)/cache.txt
79 | $(EDITOR) $(TARGET_DIR)/cache.txt
80 |
81 | call:
82 | $(MAKE) -s CONFIG=PROFILE
83 | $(MAKE) -s CONFIG=PROFILE _call
84 |
85 | _call:
86 | valgrind -q --tool=callgrind --callgrind-out-file=$(TARGET_DIR)/call.out $(TARGET) $(ARGS)
87 | callgrind_annotate $(TARGET_DIR)/call.out > $(TARGET_DIR)/call.txt
88 | $(EDITOR) $(TARGET_DIR)/call.txt
89 |
90 | mem:
91 | $(MAKE) -s CONFIG=PROFILE
92 | $(MAKE) -s CONFIG=PROFILE _mem
93 |
94 | _mem:
95 | valgrind -q --tool=massif --massif-out-file=$(TARGET_DIR)/mem.out $(TARGET) $(ARGS)
96 | ms_print $(TARGET_DIR)/mem.out > $(TARGET_DIR)/mem.txt
97 | $(EDITOR) $(TARGET_DIR)/mem.txt
98 |
99 | run: $(TARGET)
100 | $^ $(ARGS)
101 |
102 | spell:
103 | codespell $(SRC_DIR)
104 |
105 | clean:
106 | rm -rf $(BUILD_DIR)
107 |
108 | db: clean
109 | bear -- make
110 |
111 | -include $(DEPS)
112 |
--------------------------------------------------------------------------------
/samples/c/.clang-format:
--------------------------------------------------------------------------------
1 | ---
2 | AccessModifierOffset: -2
3 | AlignAfterOpenBracket: Align
4 | AlignArrayOfStructures: None
5 | AlignConsecutiveMacros:
6 | Enabled: true
7 | AcrossEmptyLines: true
8 | AcrossComments: true
9 | AlignConsecutiveAssignments: None
10 | AlignConsecutiveBitFields:
11 | Enabled: true
12 | AcrossEmptyLines: true
13 | AcrossComments: true
14 | AlignConsecutiveDeclarations: None
15 | AlignEscapedNewlines: Right
16 | AlignOperands: Align
17 | SortIncludes: true
18 | InsertBraces: true # Control statements must have curly brackets
19 | AlignTrailingComments: true
20 | AllowAllArgumentsOnNextLine: true
21 | AllowAllParametersOfDeclarationOnNextLine: true
22 | AllowShortEnumsOnASingleLine: true
23 | AllowShortBlocksOnASingleLine: Empty
24 | AllowShortCaseLabelsOnASingleLine: true
25 | AllowShortFunctionsOnASingleLine: All
26 | AllowShortLambdasOnASingleLine: All
27 | AllowShortIfStatementsOnASingleLine: Never
28 | AllowShortLoopsOnASingleLine: false
29 | AlwaysBreakAfterDefinitionReturnType: None
30 | AlwaysBreakAfterReturnType: AllDefinitions
31 | AlwaysBreakBeforeMultilineStrings: false
32 | AlwaysBreakTemplateDeclarations: Yes
33 | AttributeMacros:
34 | - __capability
35 | BinPackArguments: true
36 | BinPackParameters: true
37 | BraceWrapping:
38 | AfterCaseLabel: false
39 | AfterClass: false
40 | AfterControlStatement: Never
41 | AfterEnum: false
42 | AfterFunction: false
43 | AfterNamespace: false
44 | AfterObjCDeclaration: false
45 | AfterStruct: false
46 | AfterUnion: false
47 | AfterExternBlock: false
48 | BeforeCatch: false
49 | BeforeElse: false
50 | BeforeLambdaBody: false
51 | BeforeWhile: false
52 | IndentBraces: false
53 | SplitEmptyFunction: true
54 | SplitEmptyRecord: true
55 | SplitEmptyNamespace: true
56 | BreakBeforeBinaryOperators: NonAssignment
57 | BreakBeforeConceptDeclarations: true
58 | BreakBeforeBraces: Attach
59 | BreakBeforeInheritanceComma: false
60 | BreakInheritanceList: BeforeColon
61 | BreakBeforeTernaryOperators: true
62 | BreakConstructorInitializersBeforeComma: false
63 | BreakConstructorInitializers: BeforeColon
64 | BreakAfterJavaFieldAnnotations: false
65 | BreakStringLiterals: true
66 | ColumnLimit: 100
67 | CommentPragmas: "^ IWYU pragma:"
68 | QualifierAlignment: Leave
69 | CompactNamespaces: false
70 | ConstructorInitializerIndentWidth: 8
71 | ContinuationIndentWidth: 8
72 | Cpp11BracedListStyle: true
73 | DeriveLineEnding: true
74 | DerivePointerAlignment: false
75 | DisableFormat: false
76 | EmptyLineAfterAccessModifier: Never
77 | EmptyLineBeforeAccessModifier: LogicalBlock
78 | ExperimentalAutoDetectBinPacking: false
79 | PackConstructorInitializers: BinPack
80 | BasedOnStyle: ""
81 | ConstructorInitializerAllOnOneLineOrOnePerLine: false
82 | AllowAllConstructorInitializersOnNextLine: true
83 | FixNamespaceComments: true
84 | ForEachMacros:
85 | - foreach
86 | - Q_FOREACH
87 | - BOOST_FOREACH
88 | IfMacros:
89 | - KJ_IF_MAYBE
90 | IncludeBlocks: Preserve
91 | IncludeCategories:
92 | - Regex: "^<(.*)>"
93 | Priority: 0
94 | - Regex: '^"(.*)"'
95 | Priority: 1
96 | - Regex: "(.*)"
97 | Priority: 2
98 | IncludeIsMainRegex: "(Test)?$"
99 | IncludeIsMainSourceRegex: ""
100 | IndentAccessModifiers: false
101 | IndentCaseLabels: true
102 | IndentCaseBlocks: false
103 | IndentGotoLabels: true
104 | IndentPPDirectives: None
105 | IndentExternBlock: AfterExternBlock
106 | IndentRequires: true
107 | IndentWidth: 8
108 | IndentWrappedFunctionNames: false
109 | InsertTrailingCommas: None
110 | JavaScriptQuotes: Leave
111 | JavaScriptWrapImports: true
112 | KeepEmptyLinesAtTheStartOfBlocks: true
113 | LambdaBodyIndentation: Signature
114 | MacroBlockBegin: ""
115 | MacroBlockEnd: ""
116 | MaxEmptyLinesToKeep: 1
117 | NamespaceIndentation: None
118 | ObjCBinPackProtocolList: Auto
119 | ObjCBlockIndentWidth: 2
120 | ObjCBreakBeforeNestedBlockParam: true
121 | ObjCSpaceAfterProperty: false
122 | ObjCSpaceBeforeProtocolList: true
123 | PenaltyBreakAssignment: 2
124 | PenaltyBreakBeforeFirstCallParameter: 19
125 | PenaltyBreakComment: 300
126 | PenaltyBreakFirstLessLess: 100
127 | PenaltyBreakOpenParenthesis: 0
128 | PenaltyBreakString: 1000
129 | PenaltyBreakTemplateDeclaration: 10
130 | PenaltyExcessCharacter: 1000000
131 | PenaltyReturnTypeOnItsOwnLine: 60
132 | PenaltyIndentedWhitespace: 0
133 | PointerAlignment: Left
134 | PPIndentWidth: -1
135 | ReferenceAlignment: Pointer
136 | ReflowComments: false
137 | RemoveBracesLLVM: false
138 | SeparateDefinitionBlocks: Always
139 | ShortNamespaceLines: 1
140 | SortJavaStaticImport: Before
141 | SortUsingDeclarations: true
142 | SpaceAfterCStyleCast: false
143 | SpaceAfterLogicalNot: false
144 | SpaceAfterTemplateKeyword: true
145 | SpaceBeforeAssignmentOperators: true
146 | SpaceBeforeCaseColon: false
147 | SpaceBeforeParens: ControlStatements
148 | SpaceBeforeParensOptions:
149 | AfterControlStatements: true
150 | AfterForeachMacros: true
151 | AfterFunctionDefinitionName: false
152 | AfterFunctionDeclarationName: false
153 | AfterIfMacros: true
154 | AfterOverloadedOperator: false
155 | BeforeNonEmptyParentheses: false
156 | SpaceAroundPointerQualifiers: Default
157 | SpaceBeforeRangeBasedForLoopColon: true
158 | SpaceInEmptyBlock: false
159 | SpaceInEmptyParentheses: false
160 | SpacesBeforeTrailingComments: 1
161 | SpacesInAngles: Never
162 | SpacesInConditionalStatement: false
163 | SpacesInContainerLiterals: true
164 | SpacesInCStyleCastParentheses: false
165 | SpacesInLineCommentPrefix:
166 | Minimum: 1
167 | Maximum: -1
168 | SpacesInParentheses: false
169 | SpacesInSquareBrackets: false
170 | SpaceBeforeSquareBrackets: false
171 | BitFieldColonSpacing: Both
172 | Standard: Latest
173 | StatementAttributeLikeMacros:
174 | - Q_EMIT
175 | StatementMacros:
176 | - Q_UNUSED
177 | - QT_REQUIRE_VERSION
178 | TabWidth: 8
179 | UseCRLF: false
180 | UseTab: Never
181 | WhitespaceSensitiveMacros:
182 | - STRINGIZE
183 | - PP_STRINGIZE
184 | - BOOST_PP_STRINGIZE
185 | - NS_SWIFT_NAME
186 | - CF_SWIFT_NAME
187 | SpaceBeforeCpp11BracedList: false
188 | SpaceBeforeCtorInitializerColon: true
189 | SpaceBeforeInheritanceColon: true
190 | ---
191 |
--------------------------------------------------------------------------------
/dwm/config.def.h:
--------------------------------------------------------------------------------
1 | /* See LICENSE file for copyright and license details. */
2 |
3 | /* appearance */
4 | static const unsigned int borderpx = 2; /* border pixel of windows */
5 | static const unsigned int snap = 32; /* snap pixel */
6 | static const int showbar = 1; /* 0 means no bar */
7 | static const int topbar = 1; /* 0 means bottom bar */
8 | static const char *fonts[] = { "monospace:size=11" };
9 | static const char dmenufont[] = "monospace:size=11";
10 | static const char col_gray1[] = "#222222";
11 | static const char col_gray2[] = "#444444";
12 | static const char col_gray3[] = "#bbbbbb";
13 | static const char col_gray4[] = "#eeeeee";
14 | static const char col_cyan[] = "#005577";
15 | static const char *colors[][3] = {
16 | /* fg bg border */
17 | [SchemeNorm] = { col_gray3, col_gray1, col_gray2 },
18 | [SchemeSel] = { col_gray4, col_cyan, col_cyan },
19 | };
20 |
21 | /* tagging */
22 | static const char *tags[] = { "1", "2", "3", "4" };
23 |
24 | static const Rule rules[] = {
25 | /* xprop(1):
26 | * WM_CLASS(STRING) = instance, class
27 | * WM_NAME(STRING) = title
28 | */
29 | /* class instance title tags mask isfloating monitor */
30 | { "libreoffice", NULL, NULL, 1 << 1, 0, -1 },
31 | { "pinta" , NULL, NULL, 1 << 1, 0, -1 },
32 | { "firefox", NULL, NULL, 1 << 2, 0, -1 },
33 | { "obs", NULL, NULL, 1 << 3, 0, -1 },
34 | };
35 |
36 | /* layout(s) */
37 | static const float mfact = 0.55; /* factor of master area size [0.05..0.95] */
38 | static const int nmaster = 1; /* number of clients in master area */
39 | static const int resizehints = 1; /* 1 means respect size hints in tiled resizals */
40 | static const int lockfullscreen = 1; /* 1 will force focus on the fullscreen window */
41 | static const int refreshrate = 120; /* refresh rate (per second) for client move/resize */
42 |
43 | static const Layout layouts[] = {
44 | /* symbol arrange function */
45 | { "[]=", tile }, /* first entry is default */
46 | { "><>", NULL }, /* no layout function means floating behavior */
47 | { "[M]", monocle },
48 | };
49 |
50 | /* key definitions */
51 | #define MODKEY Mod4Mask
52 | #define TAGKEYS(KEY,TAG) \
53 | { MODKEY, KEY, view, {.ui = 1 << TAG} }, \
54 | { MODKEY|ControlMask, KEY, toggleview, {.ui = 1 << TAG} }, \
55 | { MODKEY|ShiftMask, KEY, tag, {.ui = 1 << TAG} }, \
56 | { MODKEY|ControlMask|ShiftMask, KEY, toggletag, {.ui = 1 << TAG} },
57 |
58 | /* helper for spawning shell commands in the pre dwm-5.0 fashion */
59 | #define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } }
60 |
61 | /* commands */
62 | static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() */
63 | static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", dmenufont, "-nb", col_gray1, "-nf", col_gray3, "-sb", col_cyan, "-sf", col_gray4, NULL };
64 | static const char *termcmd[] = { "st", NULL };
65 |
66 | static const char *screen_dec[] = { "brightnessctl", "-q", "set", "10%-", NULL };
67 | static const char *screen_inc[] = { "brightnessctl", "-q", "set", "10%+", NULL };
68 | static const char *keyboard_dec[] = { "brightnessctl", "-d", "*::kbd_backlight", "set", "1-", NULL };
69 | static const char *keyboard_inc[] = { "brightnessctl", "-d", "*::kbd_backlight", "set", "1+", NULL };
70 | static const char *volume_dec[] = { "wpctl", "set-volume", "@DEFAULT_SINK@", "10%-", NULL };
71 | static const char *volume_inc[] = { "wpctl", "set-volume", "@DEFAULT_SINK@", "10%+", NULL };
72 | static const char *volume_mute[] = { "wpctl", "set-mute", "@DEFAULT_SINK@", "toggle", NULL };
73 | static const char *screenshot_active[] = { "sh", "-c", "maim -u $HOME/Downloads/$(date +%s).png", NULL };
74 | static const char *screenshot_region[] = { "sh", "-c", "maim -u -s $HOME/Downloads/$(date +%s).png", NULL };
75 |
76 | static const Key keys[] = {
77 | /* modifier key function argument */
78 | { MODKEY, XK_a, spawn, {.v = dmenucmd } },
79 | { MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } },
80 | { MODKEY, XK_Left, spawn, {.v = screen_dec} },
81 | { MODKEY, XK_Right, spawn, {.v = screen_inc} },
82 | { MODKEY|ShiftMask, XK_Left, spawn, {.v = keyboard_dec} },
83 | { MODKEY|ShiftMask, XK_Right, spawn, {.v = keyboard_inc} },
84 | { MODKEY, XK_Down, spawn, {.v = volume_dec} },
85 | { MODKEY, XK_Up, spawn, {.v = volume_inc} },
86 | { MODKEY, XK_v, spawn, {.v = volume_mute} },
87 | { MODKEY, XK_s, spawn, {.v = screenshot_active} },
88 | { MODKEY|ShiftMask, XK_s, spawn, {.v = screenshot_region} },
89 | { MODKEY, XK_b, togglebar, {0} },
90 | { MODKEY, XK_j, focusstack, {.i = +1 } },
91 | { MODKEY, XK_k, focusstack, {.i = -1 } },
92 | { MODKEY, XK_e, incnmaster, {.i = +1 } },
93 | { MODKEY, XK_d, incnmaster, {.i = -1 } },
94 | { MODKEY, XK_h, setmfact, {.f = -0.05} },
95 | { MODKEY, XK_l, setmfact, {.f = +0.05} },
96 | { MODKEY, XK_Return, zoom, {0} },
97 | { MODKEY, XK_Tab, view, {0} },
98 | { MODKEY|ShiftMask, XK_c, killclient, {0} },
99 | { MODKEY, XK_t, setlayout, {.v = &layouts[0]} },
100 | { MODKEY, XK_f, setlayout, {.v = &layouts[1]} },
101 | { MODKEY, XK_m, setlayout, {.v = &layouts[2]} },
102 | { MODKEY, XK_space, setlayout, {0} },
103 | { MODKEY|ShiftMask, XK_space, togglefloating, {0} },
104 | { MODKEY, XK_0, view, {.ui = ~0 } },
105 | { MODKEY|ShiftMask, XK_0, tag, {.ui = ~0 } },
106 | { MODKEY, XK_comma, focusmon, {.i = -1 } },
107 | { MODKEY, XK_period, focusmon, {.i = +1 } },
108 | { MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } },
109 | { MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } },
110 | TAGKEYS( XK_u, 0)
111 | TAGKEYS( XK_i, 1)
112 | TAGKEYS( XK_o, 2)
113 | TAGKEYS( XK_p, 3)
114 | { MODKEY|ShiftMask, XK_q, quit, {0} },
115 | };
116 |
117 | /* button definitions */
118 | /* click can be ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */
119 | static const Button buttons[] = {
120 | /* click event mask button function argument */
121 | { ClkLtSymbol, 0, Button1, setlayout, {0} },
122 | { ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} },
123 | { ClkWinTitle, 0, Button2, zoom, {0} },
124 | { ClkStatusText, 0, Button2, spawn, {.v = termcmd } },
125 | { ClkClientWin, MODKEY, Button1, movemouse, {0} },
126 | { ClkClientWin, MODKEY, Button2, togglefloating, {0} },
127 | { ClkClientWin, MODKEY, Button3, resizemouse, {0} },
128 | { ClkTagBar, 0, Button1, view, {0} },
129 | { ClkTagBar, 0, Button3, toggleview, {0} },
130 | { ClkTagBar, MODKEY, Button1, tag, {0} },
131 | { ClkTagBar, MODKEY, Button3, toggletag, {0} },
132 | };
133 |
134 |
--------------------------------------------------------------------------------
/st/patches/st-scrollback-ringbuffer-0.9.2.diff:
--------------------------------------------------------------------------------
1 | commit 0663bdf11a409961da5b1120741a69814da8ce65
2 | Author: Timo Röhling
3 | Date: Tue Nov 23 19:45:33 2021 +0100
4 |
5 | Terminal scrollback with ring buffer
6 |
7 | This patch adds a ring buffer for scrollback to the terminal. The
8 | advantage of using a ring buffer is that the common case, scrolling with
9 | no static screen content, can be achieved very efficiently by
10 | incrementing and decrementing the starting line (modulo buffer size).
11 |
12 | The scrollback buffer is limited to HISTSIZE lines in order to bound
13 | memory usage. As the lines are allocated on demand, it is possible to
14 | implement unlimited scrollback with few changes. If the terminal is
15 | reset, the scroll back buffer is reset, too.
16 |
17 | diff --git a/config.def.h b/config.def.h
18 | index 2cd740a..8b25d40 100644
19 | --- a/config.def.h
20 | +++ b/config.def.h
21 | @@ -201,6 +201,8 @@ static Shortcut shortcuts[] = {
22 | { TERMMOD, XK_Y, selpaste, {.i = 0} },
23 | { ShiftMask, XK_Insert, selpaste, {.i = 0} },
24 | { TERMMOD, XK_Num_Lock, numlock, {.i = 0} },
25 | + { ShiftMask, XK_Page_Up, kscrollup, {.i = -1} },
26 | + { ShiftMask, XK_Page_Down, kscrolldown, {.i = -1} },
27 | };
28 |
29 | /*
30 | diff --git a/st.c b/st.c
31 | index b9f66e7..d9b163e 100644
32 | --- a/st.c
33 | +++ b/st.c
34 | @@ -43,6 +43,10 @@
35 | #define ISCONTROL(c) (ISCONTROLC0(c) || ISCONTROLC1(c))
36 | #define ISDELIM(u) (u && wcschr(worddelimiters, u))
37 |
38 | +#define TSCREEN term.screen[IS_SET(MODE_ALTSCREEN)]
39 | +#define TLINEOFFSET(y) (((y) + TSCREEN.cur - TSCREEN.off + TSCREEN.size) % TSCREEN.size)
40 | +#define TLINE(y) (TSCREEN.buffer[TLINEOFFSET(y)])
41 | +
42 | enum term_mode {
43 | MODE_WRAP = 1 << 0,
44 | MODE_INSERT = 1 << 1,
45 | @@ -109,12 +113,21 @@ typedef struct {
46 | int alt;
47 | } Selection;
48 |
49 | +/* Screen lines */
50 | +typedef struct {
51 | + Line* buffer; /* ring buffer */
52 | + int size; /* size of buffer */
53 | + int cur; /* start of active screen */
54 | + int off; /* scrollback line offset */
55 | + TCursor sc; /* saved cursor */
56 | +} LineBuffer;
57 | +
58 | /* Internal representation of the screen */
59 | typedef struct {
60 | int row; /* nb row */
61 | int col; /* nb col */
62 | - Line *line; /* screen */
63 | - Line *alt; /* alternate screen */
64 | + LineBuffer screen[2]; /* screen and alternate screen */
65 | + int linelen; /* allocated line length */
66 | int *dirty; /* dirtyness of lines */
67 | TCursor c; /* cursor */
68 | int ocx; /* old cursor col */
69 | @@ -203,6 +216,8 @@ static void tdeftran(char);
70 | static void tstrsequence(uchar);
71 |
72 | static void drawregion(int, int, int, int);
73 | +static void clearline(Line, Glyph, int, int);
74 | +static Line ensureline(Line);
75 |
76 | static void selnormalize(void);
77 | static void selscroll(int, int);
78 | @@ -408,11 +423,12 @@ int
79 | tlinelen(int y)
80 | {
81 | int i = term.col;
82 | + Line line = TLINE(y);
83 |
84 | - if (term.line[y][i - 1].mode & ATTR_WRAP)
85 | + if (line[i - 1].mode & ATTR_WRAP)
86 | return i;
87 |
88 | - while (i > 0 && term.line[y][i - 1].u == ' ')
89 | + while (i > 0 && line[i - 1].u == ' ')
90 | --i;
91 |
92 | return i;
93 | @@ -521,7 +537,7 @@ selsnap(int *x, int *y, int direction)
94 | * Snap around if the word wraps around at the end or
95 | * beginning of a line.
96 | */
97 | - prevgp = &term.line[*y][*x];
98 | + prevgp = &TLINE(*y)[*x];
99 | prevdelim = ISDELIM(prevgp->u);
100 | for (;;) {
101 | newx = *x + direction;
102 | @@ -536,14 +552,14 @@ selsnap(int *x, int *y, int direction)
103 | yt = *y, xt = *x;
104 | else
105 | yt = newy, xt = newx;
106 | - if (!(term.line[yt][xt].mode & ATTR_WRAP))
107 | + if (!(TLINE(yt)[xt].mode & ATTR_WRAP))
108 | break;
109 | }
110 |
111 | if (newx >= tlinelen(newy))
112 | break;
113 |
114 | - gp = &term.line[newy][newx];
115 | + gp = &TLINE(newy)[newx];
116 | delim = ISDELIM(gp->u);
117 | if (!(gp->mode & ATTR_WDUMMY) && (delim != prevdelim
118 | || (delim && gp->u != prevgp->u)))
119 | @@ -564,14 +580,14 @@ selsnap(int *x, int *y, int direction)
120 | *x = (direction < 0) ? 0 : term.col - 1;
121 | if (direction < 0) {
122 | for (; *y > 0; *y += direction) {
123 | - if (!(term.line[*y-1][term.col-1].mode
124 | + if (!(TLINE(*y-1)[term.col-1].mode
125 | & ATTR_WRAP)) {
126 | break;
127 | }
128 | }
129 | } else if (direction > 0) {
130 | for (; *y < term.row-1; *y += direction) {
131 | - if (!(term.line[*y][term.col-1].mode
132 | + if (!(TLINE(*y)[term.col-1].mode
133 | & ATTR_WRAP)) {
134 | break;
135 | }
136 | @@ -602,13 +618,13 @@ getsel(void)
137 | }
138 |
139 | if (sel.type == SEL_RECTANGULAR) {
140 | - gp = &term.line[y][sel.nb.x];
141 | + gp = &TLINE(y)[sel.nb.x];
142 | lastx = sel.ne.x;
143 | } else {
144 | - gp = &term.line[y][sel.nb.y == y ? sel.nb.x : 0];
145 | + gp = &TLINE(y)[sel.nb.y == y ? sel.nb.x : 0];
146 | lastx = (sel.ne.y == y) ? sel.ne.x : term.col-1;
147 | }
148 | - last = &term.line[y][MIN(lastx, linelen-1)];
149 | + last = &TLINE(y)[MIN(lastx, linelen-1)];
150 | while (last >= gp && last->u == ' ')
151 | --last;
152 |
153 | @@ -949,12 +965,15 @@ int
154 | tattrset(int attr)
155 | {
156 | int i, j;
157 | + int y = TLINEOFFSET(0);
158 |
159 | for (i = 0; i < term.row-1; i++) {
160 | + Line line = TSCREEN.buffer[y];
161 | for (j = 0; j < term.col-1; j++) {
162 | - if (term.line[i][j].mode & attr)
163 | + if (line[j].mode & attr)
164 | return 1;
165 | }
166 | + y = (y+1) % TSCREEN.size;
167 | }
168 |
169 | return 0;
170 | @@ -976,14 +995,17 @@ void
171 | tsetdirtattr(int attr)
172 | {
173 | int i, j;
174 | + int y = TLINEOFFSET(0);
175 |
176 | for (i = 0; i < term.row-1; i++) {
177 | + Line line = TSCREEN.buffer[y];
178 | for (j = 0; j < term.col-1; j++) {
179 | - if (term.line[i][j].mode & attr) {
180 | + if (line[j].mode & attr) {
181 | tsetdirt(i, i);
182 | break;
183 | }
184 | }
185 | + y = (y+1) % TSCREEN.size;
186 | }
187 | }
188 |
189 | @@ -996,27 +1018,19 @@ tfulldirt(void)
190 | void
191 | tcursor(int mode)
192 | {
193 | - static TCursor c[2];
194 | - int alt = IS_SET(MODE_ALTSCREEN);
195 | -
196 | if (mode == CURSOR_SAVE) {
197 | - c[alt] = term.c;
198 | + TSCREEN.sc = term.c;
199 | } else if (mode == CURSOR_LOAD) {
200 | - term.c = c[alt];
201 | - tmoveto(c[alt].x, c[alt].y);
202 | + term.c = TSCREEN.sc;
203 | + tmoveto(term.c.x, term.c.y);
204 | }
205 | }
206 |
207 | void
208 | treset(void)
209 | {
210 | - uint i;
211 | -
212 | - term.c = (TCursor){{
213 | - .mode = ATTR_NULL,
214 | - .fg = defaultfg,
215 | - .bg = defaultbg
216 | - }, .x = 0, .y = 0, .state = CURSOR_DEFAULT};
217 | + int i, j;
218 | + Glyph g = (Glyph){ .fg = defaultfg, .bg = defaultbg};
219 |
220 | memset(term.tabs, 0, term.col * sizeof(*term.tabs));
221 | for (i = tabspaces; i < term.col; i += tabspaces)
222 | @@ -1028,17 +1042,37 @@ treset(void)
223 | term.charset = 0;
224 |
225 | for (i = 0; i < 2; i++) {
226 | - tmoveto(0, 0);
227 | - tcursor(CURSOR_SAVE);
228 | - tclearregion(0, 0, term.col-1, term.row-1);
229 | - tswapscreen();
230 | + term.screen[i].sc = (TCursor){{
231 | + .fg = defaultfg,
232 | + .bg = defaultbg
233 | + }};
234 | + term.screen[i].cur = 0;
235 | + term.screen[i].off = 0;
236 | + for (j = 0; j < term.row; ++j) {
237 | + if (term.col != term.linelen)
238 | + term.screen[i].buffer[j] = xrealloc(term.screen[i].buffer[j], term.col * sizeof(Glyph));
239 | + clearline(term.screen[i].buffer[j], g, 0, term.col);
240 | + }
241 | + for (j = term.row; j < term.screen[i].size; ++j) {
242 | + free(term.screen[i].buffer[j]);
243 | + term.screen[i].buffer[j] = NULL;
244 | + }
245 | }
246 | + tcursor(CURSOR_LOAD);
247 | + term.linelen = term.col;
248 | + tfulldirt();
249 | }
250 |
251 | void
252 | tnew(int col, int row)
253 | {
254 | - term = (Term){ .c = { .attr = { .fg = defaultfg, .bg = defaultbg } } };
255 | + int i;
256 | + term = (Term){};
257 | + term.screen[0].buffer = xmalloc(HISTSIZE * sizeof(Line));
258 | + term.screen[0].size = HISTSIZE;
259 | + term.screen[1].buffer = NULL;
260 | + for (i = 0; i < HISTSIZE; ++i) term.screen[0].buffer[i] = NULL;
261 | +
262 | tresize(col, row);
263 | treset();
264 | }
265 | @@ -1046,14 +1080,42 @@ tnew(int col, int row)
266 | void
267 | tswapscreen(void)
268 | {
269 | - Line *tmp = term.line;
270 | -
271 | - term.line = term.alt;
272 | - term.alt = tmp;
273 | term.mode ^= MODE_ALTSCREEN;
274 | tfulldirt();
275 | }
276 |
277 | +void
278 | +kscrollup(const Arg *a)
279 | +{
280 | + int n = a->i;
281 | +
282 | + if (IS_SET(MODE_ALTSCREEN))
283 | + return;
284 | +
285 | + if (n < 0) n = (-n) * term.row;
286 | + if (n > TSCREEN.size - term.row - TSCREEN.off) n = TSCREEN.size - term.row - TSCREEN.off;
287 | + while (!TLINE(-n)) --n;
288 | + TSCREEN.off += n;
289 | + selscroll(0, n);
290 | + tfulldirt();
291 | +}
292 | +
293 | +void
294 | +kscrolldown(const Arg *a)
295 | +{
296 | +
297 | + int n = a->i;
298 | +
299 | + if (IS_SET(MODE_ALTSCREEN))
300 | + return;
301 | +
302 | + if (n < 0) n = (-n) * term.row;
303 | + if (n > TSCREEN.off) n = TSCREEN.off;
304 | + TSCREEN.off -= n;
305 | + selscroll(0, -n);
306 | + tfulldirt();
307 | +}
308 | +
309 | void
310 | tscrolldown(int orig, int n)
311 | {
312 | @@ -1062,15 +1124,29 @@ tscrolldown(int orig, int n)
313 |
314 | LIMIT(n, 0, term.bot-orig+1);
315 |
316 | - tsetdirt(orig, term.bot-n);
317 | - tclearregion(0, term.bot-n+1, term.col-1, term.bot);
318 | + /* Ensure that lines are allocated */
319 | + for (i = -n; i < 0; i++) {
320 | + TLINE(i) = ensureline(TLINE(i));
321 | + }
322 |
323 | - for (i = term.bot; i >= orig+n; i--) {
324 | - temp = term.line[i];
325 | - term.line[i] = term.line[i-n];
326 | - term.line[i-n] = temp;
327 | + /* Shift non-scrolling areas in ring buffer */
328 | + for (i = term.bot+1; i < term.row; i++) {
329 | + temp = TLINE(i);
330 | + TLINE(i) = TLINE(i-n);
331 | + TLINE(i-n) = temp;
332 | + }
333 | + for (i = 0; i < orig; i++) {
334 | + temp = TLINE(i);
335 | + TLINE(i) = TLINE(i-n);
336 | + TLINE(i-n) = temp;
337 | }
338 |
339 | + /* Scroll buffer */
340 | + TSCREEN.cur = (TSCREEN.cur + TSCREEN.size - n) % TSCREEN.size;
341 | + /* Clear lines that have entered the view */
342 | + tclearregion(0, orig, term.linelen-1, orig+n-1);
343 | + /* Redraw portion of the screen that has scrolled */
344 | + tsetdirt(orig+n-1, term.bot);
345 | selscroll(orig, n);
346 | }
347 |
348 | @@ -1082,15 +1158,29 @@ tscrollup(int orig, int n)
349 |
350 | LIMIT(n, 0, term.bot-orig+1);
351 |
352 | - tclearregion(0, orig, term.col-1, orig+n-1);
353 | - tsetdirt(orig+n, term.bot);
354 | + /* Ensure that lines are allocated */
355 | + for (i = term.row; i < term.row + n; i++) {
356 | + TLINE(i) = ensureline(TLINE(i));
357 | + }
358 |
359 | - for (i = orig; i <= term.bot-n; i++) {
360 | - temp = term.line[i];
361 | - term.line[i] = term.line[i+n];
362 | - term.line[i+n] = temp;
363 | + /* Shift non-scrolling areas in ring buffer */
364 | + for (i = orig-1; i >= 0; i--) {
365 | + temp = TLINE(i);
366 | + TLINE(i) = TLINE(i+n);
367 | + TLINE(i+n) = temp;
368 | + }
369 | + for (i = term.row-1; i >term.bot; i--) {
370 | + temp = TLINE(i);
371 | + TLINE(i) = TLINE(i+n);
372 | + TLINE(i+n) = temp;
373 | }
374 |
375 | + /* Scroll buffer */
376 | + TSCREEN.cur = (TSCREEN.cur + n) % TSCREEN.size;
377 | + /* Clear lines that have entered the view */
378 | + tclearregion(0, term.bot-n+1, term.linelen-1, term.bot);
379 | + /* Redraw portion of the screen that has scrolled */
380 | + tsetdirt(orig, term.bot-n+1);
381 | selscroll(orig, -n);
382 | }
383 |
384 | @@ -1194,6 +1284,7 @@ tsetchar(Rune u, const Glyph *attr, int x, int y)
385 | "⎻", "─", "⎼", "⎽", "├", "┤", "┴", "┬", /* p - w */
386 | "│", "≤", "≥", "π", "≠", "£", "·", /* x - ~ */
387 | };
388 | + Line line = TLINE(y);
389 |
390 | /*
391 | * The table is proudly stolen from rxvt.
392 | @@ -1202,25 +1293,25 @@ tsetchar(Rune u, const Glyph *attr, int x, int y)
393 | BETWEEN(u, 0x41, 0x7e) && vt100_0[u - 0x41])
394 | utf8decode(vt100_0[u - 0x41], &u, UTF_SIZ);
395 |
396 | - if (term.line[y][x].mode & ATTR_WIDE) {
397 | + if (line[x].mode & ATTR_WIDE) {
398 | if (x+1 < term.col) {
399 | - term.line[y][x+1].u = ' ';
400 | - term.line[y][x+1].mode &= ~ATTR_WDUMMY;
401 | + line[x+1].u = ' ';
402 | + line[x+1].mode &= ~ATTR_WDUMMY;
403 | }
404 | - } else if (term.line[y][x].mode & ATTR_WDUMMY) {
405 | - term.line[y][x-1].u = ' ';
406 | - term.line[y][x-1].mode &= ~ATTR_WIDE;
407 | + } else if (line[x].mode & ATTR_WDUMMY) {
408 | + line[x-1].u = ' ';
409 | + line[x-1].mode &= ~ATTR_WIDE;
410 | }
411 |
412 | term.dirty[y] = 1;
413 | - term.line[y][x] = *attr;
414 | - term.line[y][x].u = u;
415 | + line[x] = *attr;
416 | + line[x].u = u;
417 | }
418 |
419 | void
420 | tclearregion(int x1, int y1, int x2, int y2)
421 | {
422 | - int x, y, temp;
423 | + int x, y, L, S, temp;
424 | Glyph *gp;
425 |
426 | if (x1 > x2)
427 | @@ -1228,15 +1319,16 @@ tclearregion(int x1, int y1, int x2, int y2)
428 | if (y1 > y2)
429 | temp = y1, y1 = y2, y2 = temp;
430 |
431 | - LIMIT(x1, 0, term.col-1);
432 | - LIMIT(x2, 0, term.col-1);
433 | + LIMIT(x1, 0, term.linelen-1);
434 | + LIMIT(x2, 0, term.linelen-1);
435 | LIMIT(y1, 0, term.row-1);
436 | LIMIT(y2, 0, term.row-1);
437 |
438 | + L = TLINEOFFSET(y1);
439 | for (y = y1; y <= y2; y++) {
440 | term.dirty[y] = 1;
441 | for (x = x1; x <= x2; x++) {
442 | - gp = &term.line[y][x];
443 | + gp = &TSCREEN.buffer[L][x];
444 | if (selected(x, y))
445 | selclear();
446 | gp->fg = term.c.attr.fg;
447 | @@ -1244,6 +1336,7 @@ tclearregion(int x1, int y1, int x2, int y2)
448 | gp->mode = 0;
449 | gp->u = ' ';
450 | }
451 | + L = (L + 1) % TSCREEN.size;
452 | }
453 | }
454 |
455 | @@ -1258,7 +1351,7 @@ tdeletechar(int n)
456 | dst = term.c.x;
457 | src = term.c.x + n;
458 | size = term.col - src;
459 | - line = term.line[term.c.y];
460 | + line = TLINE(term.c.y);
461 |
462 | memmove(&line[dst], &line[src], size * sizeof(Glyph));
463 | tclearregion(term.col-n, term.c.y, term.col-1, term.c.y);
464 | @@ -1275,7 +1368,7 @@ tinsertblank(int n)
465 | dst = term.c.x + n;
466 | src = term.c.x;
467 | size = term.col - dst;
468 | - line = term.line[term.c.y];
469 | + line = TLINE(term.c.y);
470 |
471 | memmove(&line[dst], &line[src], size * sizeof(Glyph));
472 | tclearregion(src, term.c.y, dst - 1, term.c.y);
473 | @@ -2079,7 +2172,7 @@ tdumpline(int n)
474 | char buf[UTF_SIZ];
475 | const Glyph *bp, *end;
476 |
477 | - bp = &term.line[n][0];
478 | + bp = &TLINE(n)[0];
479 | end = &bp[MIN(tlinelen(n), term.col) - 1];
480 | if (bp != end || bp->u != ' ') {
481 | for ( ; bp <= end; ++bp)
482 | @@ -2466,11 +2559,11 @@ check_control_code:
483 | if (selected(term.c.x, term.c.y))
484 | selclear();
485 |
486 | - gp = &term.line[term.c.y][term.c.x];
487 | + gp = &TLINE(term.c.y)[term.c.x];
488 | if (IS_SET(MODE_WRAP) && (term.c.state & CURSOR_WRAPNEXT)) {
489 | gp->mode |= ATTR_WRAP;
490 | tnewline(1);
491 | - gp = &term.line[term.c.y][term.c.x];
492 | + gp = &TLINE(term.c.y)[term.c.x];
493 | }
494 |
495 | if (IS_SET(MODE_INSERT) && term.c.x+width < term.col) {
496 | @@ -2483,7 +2576,7 @@ check_control_code:
497 | tnewline(1);
498 | else
499 | tmoveto(term.col - width, term.c.y);
500 | - gp = &term.line[term.c.y][term.c.x];
501 | + gp = &TLINE(term.c.y)[term.c.x];
502 | }
503 |
504 | tsetchar(u, &term.c.attr, term.c.x, term.c.y);
505 | @@ -2514,6 +2607,11 @@ twrite(const char *buf, int buflen, int show_ctrl)
506 | Rune u;
507 | int n;
508 |
509 | + if (TSCREEN.off) {
510 | + TSCREEN.off = 0;
511 | + tfulldirt();
512 | + }
513 | +
514 | for (n = 0; n < buflen; n += charsize) {
515 | if (IS_SET(MODE_UTF8)) {
516 | /* process a complete utf8 char */
517 | @@ -2540,56 +2638,85 @@ twrite(const char *buf, int buflen, int show_ctrl)
518 | }
519 |
520 | void
521 | -tresize(int col, int row)
522 | +clearline(Line line, Glyph g, int x, int xend)
523 | {
524 | int i;
525 | + g.mode = 0;
526 | + g.u = ' ';
527 | + for (i = x; i < xend; ++i) {
528 | + line[i] = g;
529 | + }
530 | +}
531 | +
532 | +Line
533 | +ensureline(Line line)
534 | +{
535 | + if (!line) {
536 | + line = xmalloc(term.linelen * sizeof(Glyph));
537 | + }
538 | + return line;
539 | +}
540 | +
541 | +void
542 | +tresize(int col, int row)
543 | +{
544 | + int i, j;
545 | int minrow = MIN(row, term.row);
546 | int mincol = MIN(col, term.col);
547 | + int linelen = MAX(col, term.linelen);
548 | int *bp;
549 | - TCursor c;
550 |
551 | - if (col < 1 || row < 1) {
552 | + if (col < 1 || row < 1 || row > HISTSIZE) {
553 | fprintf(stderr,
554 | "tresize: error resizing to %dx%d\n", col, row);
555 | return;
556 | }
557 |
558 | - /*
559 | - * slide screen to keep cursor where we expect it -
560 | - * tscrollup would work here, but we can optimize to
561 | - * memmove because we're freeing the earlier lines
562 | - */
563 | - for (i = 0; i <= term.c.y - row; i++) {
564 | - free(term.line[i]);
565 | - free(term.alt[i]);
566 | + /* Shift buffer to keep the cursor where we expect it */
567 | + if (row <= term.c.y) {
568 | + term.screen[0].cur = (term.screen[0].cur - row + term.c.y + 1) % term.screen[0].size;
569 | + }
570 | +
571 | + /* Resize and clear line buffers as needed */
572 | + if (linelen > term.linelen) {
573 | + for (i = 0; i < term.screen[0].size; ++i) {
574 | + if (term.screen[0].buffer[i]) {
575 | + term.screen[0].buffer[i] = xrealloc(term.screen[0].buffer[i], linelen * sizeof(Glyph));
576 | + clearline(term.screen[0].buffer[i], term.c.attr, term.linelen, linelen);
577 | + }
578 | + }
579 | + for (i = 0; i < minrow; ++i) {
580 | + term.screen[1].buffer[i] = xrealloc(term.screen[1].buffer[i], linelen * sizeof(Glyph));
581 | + clearline(term.screen[1].buffer[i], term.c.attr, term.linelen, linelen);
582 | + }
583 | }
584 | - /* ensure that both src and dst are not NULL */
585 | - if (i > 0) {
586 | - memmove(term.line, term.line + i, row * sizeof(Line));
587 | - memmove(term.alt, term.alt + i, row * sizeof(Line));
588 | + /* Allocate all visible lines for regular line buffer */
589 | + for (j = term.screen[0].cur, i = 0; i < row; ++i, j = (j + 1) % term.screen[0].size)
590 | + {
591 | + if (!term.screen[0].buffer[j]) {
592 | + term.screen[0].buffer[j] = xmalloc(linelen * sizeof(Glyph));
593 | + }
594 | + if (i >= term.row) {
595 | + clearline(term.screen[0].buffer[j], term.c.attr, 0, linelen);
596 | + }
597 | }
598 | - for (i += row; i < term.row; i++) {
599 | - free(term.line[i]);
600 | - free(term.alt[i]);
601 | + /* Resize alt screen */
602 | + term.screen[1].cur = 0;
603 | + term.screen[1].size = row;
604 | + for (i = row; i < term.row; ++i) {
605 | + free(term.screen[1].buffer[i]);
606 | + }
607 | + term.screen[1].buffer = xrealloc(term.screen[1].buffer, row * sizeof(Line));
608 | + for (i = term.row; i < row; ++i) {
609 | + term.screen[1].buffer[i] = xmalloc(linelen * sizeof(Glyph));
610 | + clearline(term.screen[1].buffer[i], term.c.attr, 0, linelen);
611 | }
612 |
613 | /* resize to new height */
614 | - term.line = xrealloc(term.line, row * sizeof(Line));
615 | - term.alt = xrealloc(term.alt, row * sizeof(Line));
616 | term.dirty = xrealloc(term.dirty, row * sizeof(*term.dirty));
617 | term.tabs = xrealloc(term.tabs, col * sizeof(*term.tabs));
618 |
619 | - /* resize each row to new width, zero-pad if needed */
620 | - for (i = 0; i < minrow; i++) {
621 | - term.line[i] = xrealloc(term.line[i], col * sizeof(Glyph));
622 | - term.alt[i] = xrealloc(term.alt[i], col * sizeof(Glyph));
623 | - }
624 | -
625 | - /* allocate any new rows */
626 | - for (/* i = minrow */; i < row; i++) {
627 | - term.line[i] = xmalloc(col * sizeof(Glyph));
628 | - term.alt[i] = xmalloc(col * sizeof(Glyph));
629 | - }
630 | + /* fix tabstops */
631 | if (col > term.col) {
632 | bp = term.tabs + term.col;
633 |
634 | @@ -2599,26 +2726,16 @@ tresize(int col, int row)
635 | for (bp += tabspaces; bp < term.tabs + col; bp += tabspaces)
636 | *bp = 1;
637 | }
638 | +
639 | /* update terminal size */
640 | term.col = col;
641 | term.row = row;
642 | + term.linelen = linelen;
643 | /* reset scrolling region */
644 | tsetscroll(0, row-1);
645 | /* make use of the LIMIT in tmoveto */
646 | tmoveto(term.c.x, term.c.y);
647 | - /* Clearing both screens (it makes dirty all lines) */
648 | - c = term.c;
649 | - for (i = 0; i < 2; i++) {
650 | - if (mincol < col && 0 < minrow) {
651 | - tclearregion(mincol, 0, col - 1, minrow - 1);
652 | - }
653 | - if (0 < col && minrow < row) {
654 | - tclearregion(0, minrow, col - 1, row - 1);
655 | - }
656 | - tswapscreen();
657 | - tcursor(CURSOR_LOAD);
658 | - }
659 | - term.c = c;
660 | + tfulldirt();
661 | }
662 |
663 | void
664 | @@ -2630,14 +2747,15 @@ resettitle(void)
665 | void
666 | drawregion(int x1, int y1, int x2, int y2)
667 | {
668 | - int y;
669 | + int y, L;
670 |
671 | + L = TLINEOFFSET(y1);
672 | for (y = y1; y < y2; y++) {
673 | - if (!term.dirty[y])
674 | - continue;
675 | -
676 | - term.dirty[y] = 0;
677 | - xdrawline(term.line[y], x1, y, x2);
678 | + if (term.dirty[y]) {
679 | + term.dirty[y] = 0;
680 | + xdrawline(TSCREEN.buffer[L], x1, y, x2);
681 | + }
682 | + L = (L + 1) % TSCREEN.size;
683 | }
684 | }
685 |
686 | @@ -2652,14 +2770,15 @@ draw(void)
687 | /* adjust cursor position */
688 | LIMIT(term.ocx, 0, term.col-1);
689 | LIMIT(term.ocy, 0, term.row-1);
690 | - if (term.line[term.ocy][term.ocx].mode & ATTR_WDUMMY)
691 | + if (TLINE(term.ocy)[term.ocx].mode & ATTR_WDUMMY)
692 | term.ocx--;
693 | - if (term.line[term.c.y][cx].mode & ATTR_WDUMMY)
694 | + if (TLINE(term.c.y)[cx].mode & ATTR_WDUMMY)
695 | cx--;
696 |
697 | drawregion(0, 0, term.col, term.row);
698 | - xdrawcursor(cx, term.c.y, term.line[term.c.y][cx],
699 | - term.ocx, term.ocy, term.line[term.ocy][term.ocx]);
700 | + if (TSCREEN.off == 0)
701 | + xdrawcursor(cx, term.c.y, TLINE(term.c.y)[cx],
702 | + term.ocx, term.ocy, TLINE(term.ocy)[term.ocx]);
703 | term.ocx = cx;
704 | term.ocy = term.c.y;
705 | xfinishdraw();
706 | diff --git a/st.h b/st.h
707 | index fd3b0d8..3cea73b 100644
708 | --- a/st.h
709 | +++ b/st.h
710 | @@ -19,6 +19,7 @@
711 |
712 | #define TRUECOLOR(r,g,b) (1 << 24 | (r) << 16 | (g) << 8 | (b))
713 | #define IS_TRUECOL(x) (1 << 24 & (x))
714 | +#define HISTSIZE 2000
715 |
716 | enum glyph_attribute {
717 | ATTR_NULL = 0,
718 | diff --git a/x.c b/x.c
719 | index bd23686..25785a6 100644
720 | --- a/x.c
721 | +++ b/x.c
722 | @@ -59,6 +59,8 @@ static void zoom(const Arg *);
723 | static void zoomabs(const Arg *);
724 | static void zoomreset(const Arg *);
725 | static void ttysend(const Arg *);
726 | +void kscrollup(const Arg *);
727 | +void kscrolldown(const Arg *);
728 |
729 | /* config.h for applying patches and the configuration. */
730 | #include "config.h"
731 |
--------------------------------------------------------------------------------
/st/config.def.h:
--------------------------------------------------------------------------------
1 | /* See LICENSE file for copyright and license details. */
2 |
3 | /*
4 | * appearance
5 | *
6 | * font: see http://freedesktop.org/software/fontconfig/fontconfig-user.html
7 | */
8 | static char *font = "Cascadia Mono NF:size=19:antialias=true:autohint=true";
9 | static int borderpx = 2;
10 |
11 | /*
12 | * What program is execed by st depends of these precedence rules:
13 | * 1: program passed with -e
14 | * 2: scroll and/or utmp
15 | * 3: SHELL environment variable
16 | * 4: value of shell in /etc/passwd
17 | * 5: value of shell in config.h
18 | */
19 | static char *shell = "/bin/sh";
20 | char *utmp = NULL;
21 | /* scroll program: to enable use a string like "scroll" */
22 | char *scroll = NULL;
23 | char *stty_args = "stty raw pass8 nl -echo -iexten -cstopb 38400";
24 |
25 | /* identification sequence returned in DA and DECID */
26 | char *vtiden = "\033[?6c";
27 |
28 | /* Kerning / character bounding-box multipliers */
29 | static float cwscale = 1.0;
30 | static float chscale = 1.0;
31 |
32 | /*
33 | * word delimiter string
34 | *
35 | * More advanced example: L" `'\"()[]{}"
36 | */
37 | wchar_t *worddelimiters = L" ";
38 |
39 | /* selection timeouts (in milliseconds) */
40 | static unsigned int doubleclicktimeout = 300;
41 | static unsigned int tripleclicktimeout = 600;
42 |
43 | /* alt screens */
44 | int allowaltscreen = 1;
45 |
46 | /* allow certain non-interactive (insecure) window operations such as:
47 | setting the clipboard text */
48 | int allowwindowops = 0;
49 |
50 | /*
51 | * draw latency range in ms - from new content/keypress/etc until drawing.
52 | * within this range, st draws when content stops arriving (idle). mostly it's
53 | * near minlatency, but it waits longer for slow updates to avoid partial draw.
54 | * low minlatency will tear/flicker more, as it can "detect" idle too early.
55 | */
56 | static double minlatency = 2;
57 | static double maxlatency = 33;
58 |
59 | /*
60 | * blinking timeout (set to 0 to disable blinking) for the terminal blinking
61 | * attribute.
62 | */
63 | static unsigned int blinktimeout = 0;
64 |
65 | /*
66 | * thickness of underline and bar cursors
67 | */
68 | static unsigned int cursorthickness = 2;
69 |
70 | /*
71 | * bell volume. It must be a value between -100 and 100. Use 0 for disabling
72 | * it
73 | */
74 | static int bellvolume = 0;
75 |
76 | /* default TERM value */
77 | char *termname = "st-256color";
78 |
79 | /*
80 | * spaces per tab
81 | *
82 | * When you are changing this value, don't forget to adapt the »it« value in
83 | * the st.info and appropriately install the st.info in the environment where
84 | * you use this st version.
85 | *
86 | * it#$tabspaces,
87 | *
88 | * Secondly make sure your kernel is not expanding tabs. When running `stty
89 | * -a` »tab0« should appear. You can tell the terminal to not expand tabs by
90 | * running following command:
91 | *
92 | * stty tabs
93 | */
94 | unsigned int tabspaces = 8;
95 |
96 | /* Terminal colors (16 first used in escape sequence) */
97 | static const char *colorname[] = {
98 | /* 8 normal colors */
99 | "black",
100 | "red3",
101 | "green3",
102 | "yellow3",
103 | "blue2",
104 | "magenta3",
105 | "cyan3",
106 | "gray90",
107 |
108 | /* 8 bright colors */
109 | "gray50",
110 | "red",
111 | "green",
112 | "yellow",
113 | "#5c5cff",
114 | "magenta",
115 | "cyan",
116 | "white",
117 |
118 | [255] = 0,
119 |
120 | /* more colors can be added after 255 to use with DefaultXX */
121 | "#cccccc",
122 | "#555555",
123 | "gray90", /* default foreground colour */
124 | "black", /* default background colour */
125 | };
126 |
127 |
128 | /*
129 | * Default colors (colorname index)
130 | * foreground, background, cursor, reverse cursor
131 | */
132 | unsigned int defaultfg = 258;
133 | unsigned int defaultbg = 259;
134 | unsigned int defaultcs = 256;
135 | static unsigned int defaultrcs = 257;
136 |
137 | /*
138 | * Default shape of cursor
139 | * 2: Block ("█")
140 | * 4: Underline ("_")
141 | * 6: Bar ("|")
142 | * 7: Snowman ("☃")
143 | */
144 | static unsigned int cursorshape = 2;
145 |
146 | /*
147 | * Default columns and rows numbers
148 | */
149 |
150 | static unsigned int cols = 80;
151 | static unsigned int rows = 24;
152 |
153 | /*
154 | * Default colour and shape of the mouse cursor
155 | */
156 | static unsigned int mouseshape = XC_xterm;
157 | static unsigned int mousefg = 7;
158 | static unsigned int mousebg = 0;
159 |
160 | /*
161 | * Color used to display font attributes when fontconfig selected a font which
162 | * doesn't match the ones requested.
163 | */
164 | static unsigned int defaultattr = 11;
165 |
166 | /*
167 | * Force mouse select/shortcuts while mask is active (when MODE_MOUSE is set).
168 | * Note that if you want to use ShiftMask with selmasks, set this to an other
169 | * modifier, set to 0 to not use it.
170 | */
171 | static uint forcemousemod = ShiftMask;
172 |
173 | /*
174 | * Internal mouse shortcuts.
175 | * Beware that overloading Button1 will disable the selection.
176 | */
177 | static MouseShortcut mshortcuts[] = {
178 | /* mask button function argument release */
179 | { ShiftMask, Button4, kscrollup, {.i = 1} },
180 | { ShiftMask, Button5, kscrolldown, {.i = 1} },
181 | { XK_ANY_MOD, Button2, selpaste, {.i = 0}, 1 },
182 | { ShiftMask, Button4, ttysend, {.s = "\033[5;2~"} },
183 | { XK_ANY_MOD, Button4, ttysend, {.s = "\031"} },
184 | { ShiftMask, Button5, ttysend, {.s = "\033[6;2~"} },
185 | { XK_ANY_MOD, Button5, ttysend, {.s = "\005"} },
186 | };
187 |
188 | /* Internal keyboard shortcuts. */
189 | #define MODKEY Mod1Mask
190 | #define TERMMOD (ControlMask|ShiftMask)
191 |
192 | static Shortcut shortcuts[] = {
193 | /* mask keysym function argument */
194 | { XK_ANY_MOD, XK_Break, sendbreak, {.i = 0} },
195 | { ControlMask, XK_Print, toggleprinter, {.i = 0} },
196 | { ShiftMask, XK_Print, printscreen, {.i = 0} },
197 | { XK_ANY_MOD, XK_Print, printsel, {.i = 0} },
198 | { TERMMOD, XK_I, zoom, {.f = +1} },
199 | { TERMMOD, XK_O, zoom, {.f = -1} },
200 | { TERMMOD, XK_Z, zoomreset, {.f = 0} },
201 | { TERMMOD, XK_C, clipcopy, {.i = 0} },
202 | { TERMMOD, XK_V, clippaste, {.i = 0} },
203 | { TERMMOD, XK_Y, selpaste, {.i = 0} },
204 | { ShiftMask, XK_Insert, selpaste, {.i = 0} },
205 | { TERMMOD, XK_Num_Lock, numlock, {.i = 0} },
206 | { TERMMOD, XK_U, kscrollup, {.i = -1} },
207 | { TERMMOD, XK_D, kscrolldown, {.i = -1} },
208 | };
209 |
210 | /*
211 | * Special keys (change & recompile st.info accordingly)
212 | *
213 | * Mask value:
214 | * * Use XK_ANY_MOD to match the key no matter modifiers state
215 | * * Use XK_NO_MOD to match the key alone (no modifiers)
216 | * appkey value:
217 | * * 0: no value
218 | * * > 0: keypad application mode enabled
219 | * * = 2: term.numlock = 1
220 | * * < 0: keypad application mode disabled
221 | * appcursor value:
222 | * * 0: no value
223 | * * > 0: cursor application mode enabled
224 | * * < 0: cursor application mode disabled
225 | *
226 | * Be careful with the order of the definitions because st searches in
227 | * this table sequentially, so any XK_ANY_MOD must be in the last
228 | * position for a key.
229 | */
230 |
231 | /*
232 | * If you want keys other than the X11 function keys (0xFD00 - 0xFFFF)
233 | * to be mapped below, add them to this array.
234 | */
235 | static KeySym mappedkeys[] = { -1 };
236 |
237 | /*
238 | * State bits to ignore when matching key or button events. By default,
239 | * numlock (Mod2Mask) and keyboard layout (XK_SWITCH_MOD) are ignored.
240 | */
241 | static uint ignoremod = Mod2Mask|XK_SWITCH_MOD;
242 |
243 | /*
244 | * This is the huge key array which defines all compatibility to the Linux
245 | * world. Please decide about changes wisely.
246 | */
247 | static Key key[] = {
248 | /* keysym mask string appkey appcursor */
249 | { XK_KP_Home, ShiftMask, "\033[2J", 0, -1},
250 | { XK_KP_Home, ShiftMask, "\033[1;2H", 0, +1},
251 | { XK_KP_Home, XK_ANY_MOD, "\033[H", 0, -1},
252 | { XK_KP_Home, XK_ANY_MOD, "\033[1~", 0, +1},
253 | { XK_KP_Up, XK_ANY_MOD, "\033Ox", +1, 0},
254 | { XK_KP_Up, XK_ANY_MOD, "\033[A", 0, -1},
255 | { XK_KP_Up, XK_ANY_MOD, "\033OA", 0, +1},
256 | { XK_KP_Down, XK_ANY_MOD, "\033Or", +1, 0},
257 | { XK_KP_Down, XK_ANY_MOD, "\033[B", 0, -1},
258 | { XK_KP_Down, XK_ANY_MOD, "\033OB", 0, +1},
259 | { XK_KP_Left, XK_ANY_MOD, "\033Ot", +1, 0},
260 | { XK_KP_Left, XK_ANY_MOD, "\033[D", 0, -1},
261 | { XK_KP_Left, XK_ANY_MOD, "\033OD", 0, +1},
262 | { XK_KP_Right, XK_ANY_MOD, "\033Ov", +1, 0},
263 | { XK_KP_Right, XK_ANY_MOD, "\033[C", 0, -1},
264 | { XK_KP_Right, XK_ANY_MOD, "\033OC", 0, +1},
265 | { XK_KP_Prior, ShiftMask, "\033[5;2~", 0, 0},
266 | { XK_KP_Prior, XK_ANY_MOD, "\033[5~", 0, 0},
267 | { XK_KP_Begin, XK_ANY_MOD, "\033[E", 0, 0},
268 | { XK_KP_End, ControlMask, "\033[J", -1, 0},
269 | { XK_KP_End, ControlMask, "\033[1;5F", +1, 0},
270 | { XK_KP_End, ShiftMask, "\033[K", -1, 0},
271 | { XK_KP_End, ShiftMask, "\033[1;2F", +1, 0},
272 | { XK_KP_End, XK_ANY_MOD, "\033[4~", 0, 0},
273 | { XK_KP_Next, ShiftMask, "\033[6;2~", 0, 0},
274 | { XK_KP_Next, XK_ANY_MOD, "\033[6~", 0, 0},
275 | { XK_KP_Insert, ShiftMask, "\033[2;2~", +1, 0},
276 | { XK_KP_Insert, ShiftMask, "\033[4l", -1, 0},
277 | { XK_KP_Insert, ControlMask, "\033[L", -1, 0},
278 | { XK_KP_Insert, ControlMask, "\033[2;5~", +1, 0},
279 | { XK_KP_Insert, XK_ANY_MOD, "\033[4h", -1, 0},
280 | { XK_KP_Insert, XK_ANY_MOD, "\033[2~", +1, 0},
281 | { XK_KP_Delete, ControlMask, "\033[M", -1, 0},
282 | { XK_KP_Delete, ControlMask, "\033[3;5~", +1, 0},
283 | { XK_KP_Delete, ShiftMask, "\033[2K", -1, 0},
284 | { XK_KP_Delete, ShiftMask, "\033[3;2~", +1, 0},
285 | { XK_KP_Delete, XK_ANY_MOD, "\033[P", -1, 0},
286 | { XK_KP_Delete, XK_ANY_MOD, "\033[3~", +1, 0},
287 | { XK_KP_Multiply, XK_ANY_MOD, "\033Oj", +2, 0},
288 | { XK_KP_Add, XK_ANY_MOD, "\033Ok", +2, 0},
289 | { XK_KP_Enter, XK_ANY_MOD, "\033OM", +2, 0},
290 | { XK_KP_Enter, XK_ANY_MOD, "\r", -1, 0},
291 | { XK_KP_Subtract, XK_ANY_MOD, "\033Om", +2, 0},
292 | { XK_KP_Decimal, XK_ANY_MOD, "\033On", +2, 0},
293 | { XK_KP_Divide, XK_ANY_MOD, "\033Oo", +2, 0},
294 | { XK_KP_0, XK_ANY_MOD, "\033Op", +2, 0},
295 | { XK_KP_1, XK_ANY_MOD, "\033Oq", +2, 0},
296 | { XK_KP_2, XK_ANY_MOD, "\033Or", +2, 0},
297 | { XK_KP_3, XK_ANY_MOD, "\033Os", +2, 0},
298 | { XK_KP_4, XK_ANY_MOD, "\033Ot", +2, 0},
299 | { XK_KP_5, XK_ANY_MOD, "\033Ou", +2, 0},
300 | { XK_KP_6, XK_ANY_MOD, "\033Ov", +2, 0},
301 | { XK_KP_7, XK_ANY_MOD, "\033Ow", +2, 0},
302 | { XK_KP_8, XK_ANY_MOD, "\033Ox", +2, 0},
303 | { XK_KP_9, XK_ANY_MOD, "\033Oy", +2, 0},
304 | { XK_Up, ShiftMask, "\033[1;2A", 0, 0},
305 | { XK_Up, Mod1Mask, "\033[1;3A", 0, 0},
306 | { XK_Up, ShiftMask|Mod1Mask,"\033[1;4A", 0, 0},
307 | { XK_Up, ControlMask, "\033[1;5A", 0, 0},
308 | { XK_Up, ShiftMask|ControlMask,"\033[1;6A", 0, 0},
309 | { XK_Up, ControlMask|Mod1Mask,"\033[1;7A", 0, 0},
310 | { XK_Up,ShiftMask|ControlMask|Mod1Mask,"\033[1;8A", 0, 0},
311 | { XK_Up, XK_ANY_MOD, "\033[A", 0, -1},
312 | { XK_Up, XK_ANY_MOD, "\033OA", 0, +1},
313 | { XK_Down, ShiftMask, "\033[1;2B", 0, 0},
314 | { XK_Down, Mod1Mask, "\033[1;3B", 0, 0},
315 | { XK_Down, ShiftMask|Mod1Mask,"\033[1;4B", 0, 0},
316 | { XK_Down, ControlMask, "\033[1;5B", 0, 0},
317 | { XK_Down, ShiftMask|ControlMask,"\033[1;6B", 0, 0},
318 | { XK_Down, ControlMask|Mod1Mask,"\033[1;7B", 0, 0},
319 | { XK_Down,ShiftMask|ControlMask|Mod1Mask,"\033[1;8B",0, 0},
320 | { XK_Down, XK_ANY_MOD, "\033[B", 0, -1},
321 | { XK_Down, XK_ANY_MOD, "\033OB", 0, +1},
322 | { XK_Left, ShiftMask, "\033[1;2D", 0, 0},
323 | { XK_Left, Mod1Mask, "\033[1;3D", 0, 0},
324 | { XK_Left, ShiftMask|Mod1Mask,"\033[1;4D", 0, 0},
325 | { XK_Left, ControlMask, "\033[1;5D", 0, 0},
326 | { XK_Left, ShiftMask|ControlMask,"\033[1;6D", 0, 0},
327 | { XK_Left, ControlMask|Mod1Mask,"\033[1;7D", 0, 0},
328 | { XK_Left,ShiftMask|ControlMask|Mod1Mask,"\033[1;8D",0, 0},
329 | { XK_Left, XK_ANY_MOD, "\033[D", 0, -1},
330 | { XK_Left, XK_ANY_MOD, "\033OD", 0, +1},
331 | { XK_Right, ShiftMask, "\033[1;2C", 0, 0},
332 | { XK_Right, Mod1Mask, "\033[1;3C", 0, 0},
333 | { XK_Right, ShiftMask|Mod1Mask,"\033[1;4C", 0, 0},
334 | { XK_Right, ControlMask, "\033[1;5C", 0, 0},
335 | { XK_Right, ShiftMask|ControlMask,"\033[1;6C", 0, 0},
336 | { XK_Right, ControlMask|Mod1Mask,"\033[1;7C", 0, 0},
337 | { XK_Right,ShiftMask|ControlMask|Mod1Mask,"\033[1;8C",0, 0},
338 | { XK_Right, XK_ANY_MOD, "\033[C", 0, -1},
339 | { XK_Right, XK_ANY_MOD, "\033OC", 0, +1},
340 | { XK_ISO_Left_Tab, ShiftMask, "\033[Z", 0, 0},
341 | { XK_Return, Mod1Mask, "\033\r", 0, 0},
342 | { XK_Return, XK_ANY_MOD, "\r", 0, 0},
343 | { XK_Insert, ShiftMask, "\033[4l", -1, 0},
344 | { XK_Insert, ShiftMask, "\033[2;2~", +1, 0},
345 | { XK_Insert, ControlMask, "\033[L", -1, 0},
346 | { XK_Insert, ControlMask, "\033[2;5~", +1, 0},
347 | { XK_Insert, XK_ANY_MOD, "\033[4h", -1, 0},
348 | { XK_Insert, XK_ANY_MOD, "\033[2~", +1, 0},
349 | { XK_Delete, ControlMask, "\033[M", -1, 0},
350 | { XK_Delete, ControlMask, "\033[3;5~", +1, 0},
351 | { XK_Delete, ShiftMask, "\033[2K", -1, 0},
352 | { XK_Delete, ShiftMask, "\033[3;2~", +1, 0},
353 | { XK_Delete, XK_ANY_MOD, "\033[P", -1, 0},
354 | { XK_Delete, XK_ANY_MOD, "\033[3~", +1, 0},
355 | { XK_BackSpace, XK_NO_MOD, "\177", 0, 0},
356 | { XK_BackSpace, Mod1Mask, "\033\177", 0, 0},
357 | { XK_Home, ShiftMask, "\033[2J", 0, -1},
358 | { XK_Home, ShiftMask, "\033[1;2H", 0, +1},
359 | { XK_Home, XK_ANY_MOD, "\033[H", 0, -1},
360 | { XK_Home, XK_ANY_MOD, "\033[1~", 0, +1},
361 | { XK_End, ControlMask, "\033[J", -1, 0},
362 | { XK_End, ControlMask, "\033[1;5F", +1, 0},
363 | { XK_End, ShiftMask, "\033[K", -1, 0},
364 | { XK_End, ShiftMask, "\033[1;2F", +1, 0},
365 | { XK_End, XK_ANY_MOD, "\033[4~", 0, 0},
366 | { XK_Prior, ControlMask, "\033[5;5~", 0, 0},
367 | { XK_Prior, ShiftMask, "\033[5;2~", 0, 0},
368 | { XK_Prior, XK_ANY_MOD, "\033[5~", 0, 0},
369 | { XK_Next, ControlMask, "\033[6;5~", 0, 0},
370 | { XK_Next, ShiftMask, "\033[6;2~", 0, 0},
371 | { XK_Next, XK_ANY_MOD, "\033[6~", 0, 0},
372 | { XK_F1, XK_NO_MOD, "\033OP" , 0, 0},
373 | { XK_F1, /* F13 */ ShiftMask, "\033[1;2P", 0, 0},
374 | { XK_F1, /* F25 */ ControlMask, "\033[1;5P", 0, 0},
375 | { XK_F1, /* F37 */ Mod4Mask, "\033[1;6P", 0, 0},
376 | { XK_F1, /* F49 */ Mod1Mask, "\033[1;3P", 0, 0},
377 | { XK_F1, /* F61 */ Mod3Mask, "\033[1;4P", 0, 0},
378 | { XK_F2, XK_NO_MOD, "\033OQ" , 0, 0},
379 | { XK_F2, /* F14 */ ShiftMask, "\033[1;2Q", 0, 0},
380 | { XK_F2, /* F26 */ ControlMask, "\033[1;5Q", 0, 0},
381 | { XK_F2, /* F38 */ Mod4Mask, "\033[1;6Q", 0, 0},
382 | { XK_F2, /* F50 */ Mod1Mask, "\033[1;3Q", 0, 0},
383 | { XK_F2, /* F62 */ Mod3Mask, "\033[1;4Q", 0, 0},
384 | { XK_F3, XK_NO_MOD, "\033OR" , 0, 0},
385 | { XK_F3, /* F15 */ ShiftMask, "\033[1;2R", 0, 0},
386 | { XK_F3, /* F27 */ ControlMask, "\033[1;5R", 0, 0},
387 | { XK_F3, /* F39 */ Mod4Mask, "\033[1;6R", 0, 0},
388 | { XK_F3, /* F51 */ Mod1Mask, "\033[1;3R", 0, 0},
389 | { XK_F3, /* F63 */ Mod3Mask, "\033[1;4R", 0, 0},
390 | { XK_F4, XK_NO_MOD, "\033OS" , 0, 0},
391 | { XK_F4, /* F16 */ ShiftMask, "\033[1;2S", 0, 0},
392 | { XK_F4, /* F28 */ ControlMask, "\033[1;5S", 0, 0},
393 | { XK_F4, /* F40 */ Mod4Mask, "\033[1;6S", 0, 0},
394 | { XK_F4, /* F52 */ Mod1Mask, "\033[1;3S", 0, 0},
395 | { XK_F5, XK_NO_MOD, "\033[15~", 0, 0},
396 | { XK_F5, /* F17 */ ShiftMask, "\033[15;2~", 0, 0},
397 | { XK_F5, /* F29 */ ControlMask, "\033[15;5~", 0, 0},
398 | { XK_F5, /* F41 */ Mod4Mask, "\033[15;6~", 0, 0},
399 | { XK_F5, /* F53 */ Mod1Mask, "\033[15;3~", 0, 0},
400 | { XK_F6, XK_NO_MOD, "\033[17~", 0, 0},
401 | { XK_F6, /* F18 */ ShiftMask, "\033[17;2~", 0, 0},
402 | { XK_F6, /* F30 */ ControlMask, "\033[17;5~", 0, 0},
403 | { XK_F6, /* F42 */ Mod4Mask, "\033[17;6~", 0, 0},
404 | { XK_F6, /* F54 */ Mod1Mask, "\033[17;3~", 0, 0},
405 | { XK_F7, XK_NO_MOD, "\033[18~", 0, 0},
406 | { XK_F7, /* F19 */ ShiftMask, "\033[18;2~", 0, 0},
407 | { XK_F7, /* F31 */ ControlMask, "\033[18;5~", 0, 0},
408 | { XK_F7, /* F43 */ Mod4Mask, "\033[18;6~", 0, 0},
409 | { XK_F7, /* F55 */ Mod1Mask, "\033[18;3~", 0, 0},
410 | { XK_F8, XK_NO_MOD, "\033[19~", 0, 0},
411 | { XK_F8, /* F20 */ ShiftMask, "\033[19;2~", 0, 0},
412 | { XK_F8, /* F32 */ ControlMask, "\033[19;5~", 0, 0},
413 | { XK_F8, /* F44 */ Mod4Mask, "\033[19;6~", 0, 0},
414 | { XK_F8, /* F56 */ Mod1Mask, "\033[19;3~", 0, 0},
415 | { XK_F9, XK_NO_MOD, "\033[20~", 0, 0},
416 | { XK_F9, /* F21 */ ShiftMask, "\033[20;2~", 0, 0},
417 | { XK_F9, /* F33 */ ControlMask, "\033[20;5~", 0, 0},
418 | { XK_F9, /* F45 */ Mod4Mask, "\033[20;6~", 0, 0},
419 | { XK_F9, /* F57 */ Mod1Mask, "\033[20;3~", 0, 0},
420 | { XK_F10, XK_NO_MOD, "\033[21~", 0, 0},
421 | { XK_F10, /* F22 */ ShiftMask, "\033[21;2~", 0, 0},
422 | { XK_F10, /* F34 */ ControlMask, "\033[21;5~", 0, 0},
423 | { XK_F10, /* F46 */ Mod4Mask, "\033[21;6~", 0, 0},
424 | { XK_F10, /* F58 */ Mod1Mask, "\033[21;3~", 0, 0},
425 | { XK_F11, XK_NO_MOD, "\033[23~", 0, 0},
426 | { XK_F11, /* F23 */ ShiftMask, "\033[23;2~", 0, 0},
427 | { XK_F11, /* F35 */ ControlMask, "\033[23;5~", 0, 0},
428 | { XK_F11, /* F47 */ Mod4Mask, "\033[23;6~", 0, 0},
429 | { XK_F11, /* F59 */ Mod1Mask, "\033[23;3~", 0, 0},
430 | { XK_F12, XK_NO_MOD, "\033[24~", 0, 0},
431 | { XK_F12, /* F24 */ ShiftMask, "\033[24;2~", 0, 0},
432 | { XK_F12, /* F36 */ ControlMask, "\033[24;5~", 0, 0},
433 | { XK_F12, /* F48 */ Mod4Mask, "\033[24;6~", 0, 0},
434 | { XK_F12, /* F60 */ Mod1Mask, "\033[24;3~", 0, 0},
435 | { XK_F13, XK_NO_MOD, "\033[1;2P", 0, 0},
436 | { XK_F14, XK_NO_MOD, "\033[1;2Q", 0, 0},
437 | { XK_F15, XK_NO_MOD, "\033[1;2R", 0, 0},
438 | { XK_F16, XK_NO_MOD, "\033[1;2S", 0, 0},
439 | { XK_F17, XK_NO_MOD, "\033[15;2~", 0, 0},
440 | { XK_F18, XK_NO_MOD, "\033[17;2~", 0, 0},
441 | { XK_F19, XK_NO_MOD, "\033[18;2~", 0, 0},
442 | { XK_F20, XK_NO_MOD, "\033[19;2~", 0, 0},
443 | { XK_F21, XK_NO_MOD, "\033[20;2~", 0, 0},
444 | { XK_F22, XK_NO_MOD, "\033[21;2~", 0, 0},
445 | { XK_F23, XK_NO_MOD, "\033[23;2~", 0, 0},
446 | { XK_F24, XK_NO_MOD, "\033[24;2~", 0, 0},
447 | { XK_F25, XK_NO_MOD, "\033[1;5P", 0, 0},
448 | { XK_F26, XK_NO_MOD, "\033[1;5Q", 0, 0},
449 | { XK_F27, XK_NO_MOD, "\033[1;5R", 0, 0},
450 | { XK_F28, XK_NO_MOD, "\033[1;5S", 0, 0},
451 | { XK_F29, XK_NO_MOD, "\033[15;5~", 0, 0},
452 | { XK_F30, XK_NO_MOD, "\033[17;5~", 0, 0},
453 | { XK_F31, XK_NO_MOD, "\033[18;5~", 0, 0},
454 | { XK_F32, XK_NO_MOD, "\033[19;5~", 0, 0},
455 | { XK_F33, XK_NO_MOD, "\033[20;5~", 0, 0},
456 | { XK_F34, XK_NO_MOD, "\033[21;5~", 0, 0},
457 | { XK_F35, XK_NO_MOD, "\033[23;5~", 0, 0},
458 | };
459 |
460 | /*
461 | * Selection types' masks.
462 | * Use the same masks as usual.
463 | * Button1Mask is always unset, to make masks match between ButtonPress.
464 | * ButtonRelease and MotionNotify.
465 | * If no match is found, regular selection is used.
466 | */
467 | static uint selmasks[] = {
468 | [SEL_RECTANGULAR] = Mod1Mask,
469 | };
470 |
471 | /*
472 | * Printable characters in ASCII, used to estimate the advance width
473 | * of single wide characters.
474 | */
475 | static char ascii_printable[] =
476 | " !\"#$%&'()*+,-./0123456789:;<=>?"
477 | "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_"
478 | "`abcdefghijklmnopqrstuvwxyz{|}~";
479 |
--------------------------------------------------------------------------------