my dotfiles
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

add everything

radsteve 7bf44f2e ae303123

+8729 -1389
-209
.config/i3/config
··· 1 - # This file has been auto-generated by i3-config-wizard(1). 2 - # It will not be overwritten, so edit it as you like. 3 - # 4 - # Should you change your keyboard layout some time, delete 5 - # this file and re-run i3-config-wizard(1). 6 - # 7 - 8 - # i3 config file (v4) 9 - # 10 - # Please see https://i3wm.org/docs/userguide.html for a complete reference! 11 - 12 - set $mod Mod4 13 - 14 - # Font for window titles. Will also be used by the bar unless a different font 15 - # is used in the bar {} block below. 16 - font pango:"JetBrains Mono" 8 17 - 18 - # This font is widely installed, provides lots of unicode glyphs, right-to-left 19 - # text rendering and scalability on retina/hidpi displays (thanks to pango). 20 - #font pango:DejaVu Sans Mono 8 21 - 22 - # Start XDG autostart .desktop files using dex. See also 23 - # https://wiki.archlinux.org/index.php/XDG_Autostart 24 - exec --no-startup-id dex --autostart --environment i3 25 - 26 - # The combination of xss-lock, nm-applet and pactl is a popular choice, so 27 - # they are included here as an example. Modify as you see fit. 28 - 29 - # xss-lock grabs a logind suspend inhibit lock and will use i3lock to lock the 30 - # screen before suspend. Use loginctl lock-session to lock your screen. 31 - exec --no-startup-id xss-lock --transfer-sleep-lock -- i3lock --nofork 32 - 33 - # NetworkManager is the most popular way to manage wireless networks on Linux, 34 - # and nm-applet is a desktop environment-independent system tray GUI for it. 35 - exec --no-startup-id nm-applet 36 - 37 - # Use pactl to adjust volume in PulseAudio. 38 - set $refresh_i3status killall -SIGUSR1 i3status 39 - bindsym XF86AudioRaiseVolume exec --no-startup-id pactl set-sink-volume @DEFAULT_SINK@ +10% && $refresh_i3status 40 - bindsym XF86AudioLowerVolume exec --no-startup-id pactl set-sink-volume @DEFAULT_SINK@ -10% && $refresh_i3status 41 - bindsym XF86AudioMute exec --no-startup-id pactl set-sink-mute @DEFAULT_SINK@ toggle && $refresh_i3status 42 - bindsym XF86AudioMicMute exec --no-startup-id pactl set-source-mute @DEFAULT_SOURCE@ toggle && $refresh_i3status 43 - 44 - # screenshotting 45 - bindsym --release Print exec screenshot 46 - 47 - # disable window titles 48 - for_window [class=".*"] border pixel 2 49 - 50 - # window borders 51 - # class border backgr. text indicator child_border 52 - client.focused #ddb6f2 #285577 #ffffff #2e9ef4 #ddb6f2 53 - client.focused_inactive #333333 #5f676a #ffffff #484e50 #5f676a 54 - client.unfocused #333333 #222222 #888888 #292d2e #575368 55 - client.urgent #2f343a #f28fad #ffffff #f28fad #f28fad 56 - client.placeholder #000000 #0c0c0c #ffffff #000000 #0c0c0c 57 - 58 - # Use Mouse+$mod to drag floating windows to their wanted position 59 - floating_modifier $mod 60 - 61 - # programs 62 - bindsym $mod+Return exec kitty 63 - bindsym $mod+Shift+d exec discord 64 - bindsym $mod+Shift+w exec firefox 65 - bindsym $mod+Shift+s exec spotify 66 - 67 - # kill focused window 68 - bindsym $mod+Shift+q kill 69 - 70 - # program launcher 71 - bindsym $mod+d exec --no-startup-id rofi -show drun 72 - 73 - # change focus 74 - bindsym $mod+j focus left 75 - bindsym $mod+k focus down 76 - bindsym $mod+l focus up 77 - bindsym $mod+odiaeresis focus right 78 - 79 - # alternatively, you can use the cursor keys: 80 - bindsym $mod+Left focus left 81 - bindsym $mod+Down focus down 82 - bindsym $mod+Up focus up 83 - bindsym $mod+Right focus right 84 - 85 - # move focused window 86 - bindsym $mod+Shift+j move left 87 - bindsym $mod+Shift+k move down 88 - bindsym $mod+Shift+l move up 89 - bindsym $mod+Shift+odiaeresis move right 90 - 91 - # alternatively, you can use the cursor keys: 92 - bindsym $mod+Shift+Left move left 93 - bindsym $mod+Shift+Down move down 94 - bindsym $mod+Shift+Up move up 95 - bindsym $mod+Shift+Right move right 96 - 97 - # split in horizontal orientation 98 - bindsym $mod+h split h 99 - 100 - # split in vertical orientation 101 - bindsym $mod+v split v 102 - 103 - # enter fullscreen mode for the focused container 104 - bindsym $mod+f fullscreen toggle 105 - 106 - # change container layout (stacked, tabbed, toggle split) 107 - bindsym $mod+s layout stacking 108 - bindsym $mod+w layout tabbed 109 - bindsym $mod+e layout toggle split 110 - 111 - # toggle tiling / floating 112 - bindsym $mod+Shift+space floating toggle 113 - 114 - # change focus between tiling / floating windows 115 - bindsym $mod+space focus mode_toggle 116 - 117 - # focus the parent container 118 - bindsym $mod+a focus parent 119 - 120 - # specific apps to specific workspaces 121 - assign [class="firefox"] 1 122 - assign [class="discord"] 2 123 - assign [class="kitty"] 3 124 - assign [class="Spotify"] 4 125 - assign [class="thunar"] 5 126 - for_window [class="firefox"] move to workspace $ws1 127 - for_window [class="discord"] move to workspace $ws2 128 - for_window [class="kitty"] move to workspace $ws3 129 - for_window [class="Spotify"] move to workspace $ws4 130 - for_window [class="thunar"] move to workspace $ws5 131 - 132 - 133 - # focus the child container 134 - #bindsym $mod+d focus child 135 - 136 - # Define names for default workspaces for which we configure key bindings later on. 137 - # We use variables to avoid repeating the names in multiple places. 138 - set $ws1 "1" 139 - set $ws2 "2" 140 - set $ws3 "3" 141 - set $ws4 "4" 142 - set $ws5 "5" 143 - set $ws6 "6" 144 - set $ws7 "7" 145 - set $ws8 "8" 146 - set $ws9 "9" 147 - set $ws10 "10" 148 - 149 - # switch to workspace 150 - bindsym $mod+1 workspace number $ws1 151 - bindsym $mod+2 workspace number $ws2 152 - bindsym $mod+3 workspace number $ws3 153 - bindsym $mod+4 workspace number $ws4 154 - bindsym $mod+5 workspace number $ws5 155 - bindsym $mod+6 workspace number $ws6 156 - bindsym $mod+7 workspace number $ws7 157 - bindsym $mod+8 workspace number $ws8 158 - bindsym $mod+9 workspace number $ws9 159 - bindsym $mod+0 workspace number $ws10 160 - 161 - # move focused container to workspace 162 - bindsym $mod+Shift+1 move container to workspace number $ws1 163 - bindsym $mod+Shift+2 move container to workspace number $ws2 164 - bindsym $mod+Shift+3 move container to workspace number $ws3 165 - bindsym $mod+Shift+4 move container to workspace number $ws4 166 - bindsym $mod+Shift+5 move container to workspace number $ws5 167 - bindsym $mod+Shift+6 move container to workspace number $ws6 168 - bindsym $mod+Shift+7 move container to workspace number $ws7 169 - bindsym $mod+Shift+8 move container to workspace number $ws8 170 - bindsym $mod+Shift+9 move container to workspace number $ws9 171 - bindsym $mod+Shift+0 move container to workspace number $ws10 172 - 173 - # reload the configuration file 174 - bindsym $mod+Shift+c reload 175 - # restart i3 inplace (preserves your layout/session, can be used to upgrade i3) 176 - bindsym $mod+Shift+r restart 177 - # exit i3 (logs you out of your X session) 178 - bindsym $mod+Shift+e exec "i3-nagbar -t warning -m 'You pressed the exit shortcut. Do you really want to exit i3? This will end your X session.' -B 'Yes, exit i3' 'i3-msg exit'" 179 - 180 - # resize window (you can also use the mouse for that) 181 - mode "resize" { 182 - # These bindings trigger as soon as you enter the resize mode 183 - 184 - # Pressing left will shrink the window’s width. 185 - # Pressing right will grow the window’s width. 186 - # Pressing up will shrink the window’s height. 187 - # Pressing down will grow the window’s height. 188 - bindsym j resize shrink width 10 px or 10 ppt 189 - bindsym k resize grow height 10 px or 10 ppt 190 - bindsym l resize shrink height 10 px or 10 ppt 191 - bindsym odiaeresis resize grow width 10 px or 10 ppt 192 - 193 - # same bindings, but for the arrow keys 194 - bindsym Left resize shrink width 10 px or 10 ppt 195 - bindsym Down resize grow height 10 px or 10 ppt 196 - bindsym Up resize shrink height 10 px or 10 ppt 197 - bindsym Right resize grow width 10 px or 10 ppt 198 - 199 - # back to normal: Enter or Escape or $mod+r 200 - bindsym Return mode "default" 201 - bindsym Escape mode "default" 202 - bindsym $mod+r mode "default" 203 - } 204 - 205 - bindsym $mod+r mode "resize" 206 - 207 - # autostart 208 - exec bash $HOME/.config/i3/scripts/autostart &> $HOME/.autostart.log 209 -
-7
.config/i3/scripts/autostart
··· 1 - #!/bin/bash 2 - feh --bg-scale $HOME/Pictures/wallpaper.jpg 3 - polybar & 4 - nmcli con up WIFI_SSID --ask <<< 'WIFI_PASSWD' 5 - $HOME/deckmaster/deckmaster --deck $HOME/deckmaster/main.deck & 6 - firefox & 7 - discord &
-84
.config/kitty/kitty.conf
··· 1 - # vim:ft=kitty 2 - 3 - ## name: Catppuccin 4 - ## author: Pocco81 (https://github.com/Pocco81) 5 - ## license: MIT 6 - ## upstream: https://github.com/catppuccin/kitty/blob/main/catppuccin.conf 7 - ## blurb: Soothing pastel theme for the high-spirited! 8 - 9 - font_family JetBrains Mono 10 - bold_font JetBrains Mono Medium 11 - italic_font JetBrains Mono Italic 12 - bold_italic_font JetBrains Mono Medium Italic 13 - 14 - # The basic colors 15 - foreground #D9E0EE 16 - background #1E1E2E 17 - selection_foreground #D9E0EE 18 - selection_background #575268 19 - 20 - # Cursor colors 21 - cursor #F5E0DC 22 - cursor_text_color #1E1E2E 23 - 24 - # URL underline color when hovering with mouse 25 - url_color #F5E0DC 26 - 27 - # kitty window border colors 28 - active_border_color #C9CBFF 29 - inactive_border_color #575268 30 - bell_border_color #FAE3B0 31 - 32 - # OS Window titlebar colors 33 - wayland_titlebar_color system 34 - macos_titlebar_color system 35 - 36 - #: Tab bar colors 37 - active_tab_foreground #F5C2E7 38 - active_tab_background #575268 39 - inactive_tab_foreground #D9E0EE 40 - inactive_tab_background #1E1E2E 41 - tab_bar_background #161320 42 - 43 - # Colors for marks (marked text in the terminal) 44 - 45 - mark1_foreground #1E1E2E 46 - mark1_background #96CDFB 47 - mark2_foreground #1E1E2E 48 - mark2_background #F5C2E7 49 - mark3_foreground #1E1E2E 50 - mark3_background #B5E8E0 51 - 52 - #: The 16 terminal colors 53 - 54 - #: black 55 - color0 #6E6C7E 56 - color8 #988BA2 57 - 58 - #: red 59 - color1 #F28FAD 60 - color9 #F28FAD 61 - 62 - #: green 63 - color2 #ABE9B3 64 - color10 #ABE9B3 65 - 66 - #: yellow 67 - color3 #FAE3B0 68 - color11 #FAE3B0 69 - 70 - #: blue 71 - color4 #96CDFB 72 - color12 #96CDFB 73 - 74 - #: magenta 75 - color5 #F5C2E7 76 - color13 #F5C2E7 77 - 78 - #: cyan 79 - color6 #89DCEB 80 - color14 #89DCEB 81 - 82 - #: white 83 - color7 #D9E0EE 84 - color15 #D9E0EE
+2 -31
.config/neofetch/config.conf cfg/neofetch/config.conf.bak
··· 1 1 print_info() { 2 + info "distro" distro 2 3 info "cpu" cpu 3 4 info "gpu" gpu 4 5 info "mem" memory 5 - info "res" resolution 6 - info "distro" distro 7 6 info "kernel" kernel 8 7 info "de" de 9 8 info "wm" wm 10 - info "sh" shell 11 9 info "term" term 12 - info "font" font 13 10 info "pkgs" packages 14 11 } 15 12 16 13 kernel_shorthand="on" 17 14 distro_shorthand="off" 18 - os_arch="on" 15 + os_arch="off" 19 16 uptime_shorthand="on" 20 17 memory_percent="on" 21 18 package_managers="on" ··· 34 31 gtk2="on" 35 32 gtk3="on" 36 33 disk_show=('/') 37 - colors=(distro) 38 34 bold="on" 39 35 underline_enabled="on" 40 36 underline_char="-" ··· 42 38 color_blocks="off" 43 39 block_range=(0 15) # Colorblocks 44 40 45 - # Colors for custom colorblocks 46 - magenta="\033[1;35m" 47 - green="\033[1;32m" 48 - white="\033[1;37m" 49 - blue="\033[1;34m" 50 - red="\033[1;31m" 51 - black="\033[1;40;30m" 52 - yellow="\033[1;33m" 53 - cyan="\033[1;36m" 54 - reset="\033[0m" 55 - bgyellow="\033[1;43;33m" 56 - bgwhite="\033[1;47;37m" 57 - cl0="${reset}" 58 - cl1="${magenta}" 59 - cl2="${green}" 60 - cl3="${white}" 61 - cl4="${blue}" 62 - cl5="${red}" 63 - cl6="${yellow}" 64 - cl7="${cyan}" 65 - cl8="${black}" 66 - cl9="${bgyellow}" 67 - cl10="${bgwhite}" 68 - 69 41 block_width=4 70 42 block_height=1 71 43 ··· 90 62 yoffset=0 91 63 xoffset=0 92 64 93 - #stdout="off"
-9
.config/pipes-rs/config.toml
··· 1 - bold = true 2 - color_mode = "rgb" # ansi, rgb or none 3 - palette = "pastel" # default, darker, pastel or matrix 4 - delay_ms = 25 5 - inherit_style = false 6 - kinds = ["curved"] # heavy, light, curved, knobby, emoji, outline, dots, blocks 7 - num_pipes = 5 8 - reset_threshold = 0.8 # 0.0–1.0 9 - turn_chance = 0.10 # 0.0–1.0
-211
.config/polybar/config
··· 1 - ;========================================================== 2 - ; 3 - ; 4 - ; ██████╗ ██████╗ ██╗ ██╗ ██╗██████╗ █████╗ ██████╗ 5 - ; ██╔══██╗██╔═══██╗██║ ╚██╗ ██╔╝██╔══██╗██╔══██╗██╔══██╗ 6 - ; ██████╔╝██║ ██║██║ ╚████╔╝ ██████╔╝███████║██████╔╝ 7 - ; ██╔═══╝ ██║ ██║██║ ╚██╔╝ ██╔══██╗██╔══██║██╔══██╗ 8 - ; ██║ ╚██████╔╝███████╗██║ ██████╔╝██║ ██║██║ ██║ 9 - ; ╚═╝ ╚═════╝ ╚══════╝╚═╝ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝ 10 - ; 11 - ; 12 - ; To learn more about how to configure Polybar 13 - ; go to https://github.com/polybar/polybar 14 - ; 15 - ; The README contains a lot of information 16 - ; 17 - ;========================================================== 18 - 19 - 20 - [colors] 21 - background = #302d41 22 - foreground = #ddb6f2 23 - primary = #96cdfb 24 - secondary = #fae3b0 25 - alert = #f28fad 26 - disabled = #d9e0ee 27 - black = #1e1d2f 28 - red = #f28fad 29 - green = #abe9b3 30 - yellow = #fae3b0 31 - blue = #96cdfb 32 - mauve = #ddb6f2 33 - sky = #89dceb 34 - white = #d9e0ee 35 - teal = #b5e8e0 36 - grey = #575268 37 - 38 - 39 - [bar/example] 40 - width = 100% 41 - height = 24pt 42 - radius = 6 43 - 44 - ; dpi = 96 45 - 46 - background = ${colors.background} 47 - foreground = ${colors.foreground} 48 - 49 - line-size = 3pt 50 - 51 - border-size = 4pt 52 - border-color = #00000000 53 - 54 - padding-left = 0 55 - padding-right = 1 56 - 57 - module-margin = 1 58 - 59 - separator = | 60 - separator-foreground = ${colors.green} 61 - 62 - font-0 = "JetBrains Mono Nerd Font" 63 - 64 - modules-left = menu i3 xwindow 65 - modules-right = filesystem pulseaudio xkeyboard memory cpu date 66 - 67 - cursor-click = pointer 68 - cursor-scroll = ns-resize 69 - 70 - bottom = true 71 - 72 - enable-ipc = true 73 - 74 - ; tray-position = right 75 - 76 - ; wm-restack = generic 77 - ; wm-restack = bspwm 78 - ; wm-restack = i3 79 - 80 - ; override-redirect = true 81 - 82 - [module/menu] 83 - type = custom/script 84 - label = " 異" 85 - interval = 10 86 - exec = echo 'rofi' 87 - click-left = rofi -show drun 88 - 89 - [module/i3] 90 - type = internal/i3 91 - 92 - pin-workspaces = true 93 - 94 - format = <label-state> <label-mode> 95 - 96 - label-mode = %mode% 97 - label-mode-padding = 1 98 - label-mode-background = ${colors.red} 99 - 100 - label-focused = %icon% 101 - label-focused-foreground = ${colors.primary} 102 - label-focused-background = ${colors.background} 103 - label-focused-underline = ${colors.primary} 104 - label-focused-padding = 1 105 - 106 - label-unfocused = %icon% 107 - label-unfocused-padding = 1 108 - 109 - label-visible = %icon% 110 - label-visible-padding = 1 111 - 112 - label-urgent = %icon% 113 - label-urgent-foreground = ${colors.alert} 114 - label-urgent-background = ${colors.background} 115 - label-urgent-padding = 1 116 - 117 - ;   ﭮ     118 - 119 - ws-icon-0 = 1; 120 - ws-icon-1 = 2;ﭮ 121 - ws-icon-2 = 3; 122 - ws-icon-3 = 4; 123 - ws-icon-4 = 5; 124 - ws-icon-5 = 6; 125 - ws-icon-6 = 7; 7 126 - ws-icon-7 = 8; 8 127 - ws-icon-8 = 9; 9 128 - ws-icon-9 = 10; 10 129 - 130 - [module/xwindow] 131 - type = internal/xwindow 132 - label = %title:0:60:...% 133 - 134 - [module/filesystem] 135 - type = internal/fs 136 - interval = 25 137 - 138 - mount-0 = / 139 - 140 - label-mounted = %{F#96cdfb}%{F-} %percentage_used%% 141 - label-mounted-foreground = ${colors.primary} 142 - 143 - [module/pulseaudio] 144 - type = internal/pulseaudio 145 - 146 - format-volume-prefix = "蓼 " 147 - format-volume-prefix-foreground = ${colors.primary} 148 - format-volume = <label-volume> 149 - 150 - label-volume = %percentage%% 151 - 152 - label-muted = "%{F#96cdfb}蓼 %{F#ddb6f2}muted" 153 - 154 - [module/xkeyboard] 155 - type = internal/xkeyboard 156 - blacklist-0 = num lock 157 - 158 - label-layout =  %layout% 159 - label-layout-foreground = ${colors.primary} 160 - 161 - label-indicator-padding = 2 162 - label-indicator-margin = 1 163 - label-indicator-foreground = ${colors.background} 164 - label-indicator-background = ${colors.secondary} 165 - 166 - [module/memory] 167 - type = internal/memory 168 - interval = 2 169 - format-prefix = " " 170 - format-prefix-foreground = ${colors.primary} 171 - label = %percentage_used:2%% 172 - 173 - [module/cpu] 174 - type = internal/cpu 175 - interval = 2 176 - format-prefix = " " 177 - format-prefix-foreground = ${colors.primary} 178 - label = %percentage:2%% 179 - 180 - [network-base] 181 - type = internal/network 182 - interval = 5 183 - format-connected = <label-connected> 184 - format-disconnected = <label-disconnected> 185 - label-disconnected = %{F#F0C674}%ifname%%{F#707880} disconnected 186 - 187 - ;[module/wlan] 188 - ;inherit = network-base 189 - ;interface-type = wireless 190 - ;label-connected = %{F#F0C674}%ifname%%{F-} %essid% %local_ip% 191 - 192 - ;[module/eth] 193 - ;inherit = network-base 194 - ;interface-type = wired 195 - ;label-connected = %{F#F0C674}%ifname%%{F-} %local_ip% 196 - 197 - [module/date] 198 - type = internal/date 199 - interval = 1 200 - 201 - date = %H:%M 202 - date-alt = %H:%M:%S - %d.%m.%Y 203 - 204 - label =  %date% 205 - label-foreground = ${colors.primary} 206 - 207 - [settings] 208 - screenchange-reload = true 209 - pseudo-transparency = true 210 - 211 - ; vim:ft=dosini
+1 -1
.config/rofi/config.rasi cfg/rofi/config.rasi
··· 3 3 lines: 5; 4 4 font: "JetBrainsMono Nerd Font 14"; 5 5 show-icons: true; 6 - icon-theme: "Oranchelo"; 6 + icon-theme: "Papirus-Dark"; 7 7 terminal: "kitty"; 8 8 drun-display-format: "{icon} {name}"; 9 9 location: 0;
-157
.config/starship.toml
··· 1 - right_format = """$battery$time""" 2 - # Prompt: param 2 └─ 3 - 4 - [character] 5 - success_symbol = " [ ](#a9a1e1)" 6 - error_symbol = " [ ](#ff6c6b)" 7 - vicmd_symbol = "[  ](#98be65)" 8 - 9 - # Username 10 - [username] 11 - style_user = "dimmed blue" 12 - 13 - [hostname] 14 - ssh_only = false 15 - format = "<[$hostname]($style)>" 16 - trim_at = "-" 17 - style = "dimmed white" 18 - disabled = true 19 - 20 - [battery] 21 - full_symbol = "" 22 - charging_symbol = "" 23 - discharging_symbol = "" 24 - unknown_symbol = "" 25 - disabled = false 26 - format = "[ ](fg:#ff6c6b bg:none)[$symbol ](fg:#282c34 bg:#ff6c6b)[ ](fg:#ff6c6b bg:#ff7b7a)[$percentage]($style)[ ](fg:#ff7b7a bg:none)" 27 - [[battery.display]] 28 - style = "fg:#282c34 bg:#ff7b7a" 29 - threshold=100 30 - 31 - # Last param in the first line/row 32 - [cmd_duration] 33 - min_time = 1 34 - format = "[ ](fg:#9088c8 bg:none)[ ](fg:#282c34 bg:#9088c8)[](fg:#9088c8 bg:#a9a1e1)[$duration]($style)[](fg:#a9a1e1 bg:none)" 35 - disabled = false 36 - style = "fg:#282c34 bg:#a9a1e1" 37 - 38 - # Third param 39 - [directory] 40 - format = "[](fg:#da8548 bg:none)[ ](fg:#282c34 bg:#da8548)[](fg:#da8548 bg:#ECBE7B)[ $path]($style)[](fg:#ECBE7B bg:none) " 41 - style = "fg:#282c34 bg:#ECBE7B" 42 - truncation_length = 3 43 - truncate_to_repo=false 44 - 45 - [git_branch] 46 - format = "[](fg:#7fa54c bg:none)[](fg:#282c34 bg:#7fa54c)[](fg:#7fa54c bg:#98be65)[ $branch]($style)[](fg:#98be65 bg:none) " 47 - style = "fg:#282c34 bg:#98be65" 48 - 49 - [git_commit] 50 - format = "[\\($hash\\)]($style) [\\($tag\\)]($style)" 51 - style = "green" 52 - 53 - [git_status] 54 - format="[](fg:#3896d6 bg:none)[ ](fg:#282c34 bg:#3896d6)[ ](fg:#3896d6 bg:#51afef)[$modified](fg:#282c34 bg:#51afef)[$untracked](fg:#282c34 bg:#51afef)[$staged](fg:#282c34 bg:#51afef)[$renamed](fg:#282c34 bg:#51afef)[](fg:#51afef bg:none)" 55 - conflicted = "=" 56 - ahead = "⇡${count} " 57 - behind = "⇣${count} " 58 - diverged = "⇕⇡${ahead_count}⇣${behind_count}" 59 - untracked = "?${count} " 60 - modified = "!${count} " 61 - staged = "+${count} " 62 - renamed = "»${count} " 63 - deleted = "✘${count} " 64 - style = "red" 65 - disabled = false 66 - 67 - [git_state] 68 - rebase = "REBASING" 69 - merge = "MERGING" 70 - revert = "REVERTING" 71 - cherry_pick = "CHERRY-PICKING" 72 - bisect = "BISECTING" 73 - am = "AM" 74 - am_or_rebase = "AM/REBASE" 75 - style = "yellow" 76 - format = '\([$state( $progress_current/$progress_total)]($style)\) ' 77 - disabled = false 78 - 79 - [hg_branch] 80 - symbol = "" 81 - style = "purple" 82 - format = "on [$symbol$branch]($style) " 83 - 84 - [time] 85 - style="fg:#282c34 bg:#51afef" 86 - format="[](fg:#3896d6 bg:none)[ ](fg:#282c34 bg:#3896d6)[](fg:#3896d6 bg:#51afef)[ $time]($style)[](fg:#51afef bg:none)" 87 - time_format = "%R" 88 - disabled = false 89 - 90 - [docker_context] 91 - disabled=true 92 - symbol = " " 93 - 94 - [c] 95 - disabled=true 96 - 97 - [conda] 98 - disabled=true 99 - symbol = " " 100 - 101 - [dart] 102 - disabled=true 103 - symbol = " " 104 - 105 - [package] 106 - disabled=true 107 - symbol = " " 108 - 109 - [perl] 110 - disabled=true 111 - symbol = " " 112 - 113 - [php] 114 - disabled=true 115 - symbol = " " 116 - 117 - 118 - [ruby] 119 - disabled=true 120 - symbol = " " 121 - 122 - [java] 123 - disabled=true 124 - symbol = " " 125 - 126 - [lua] 127 - disabled=true 128 - symbol = " " 129 - style = "bold blue" 130 - 131 - [nodejs] 132 - disabled=true 133 - 134 - [swift] 135 - disabled=true 136 - symbol = "ﯣ " 137 - 138 - [julia] 139 - disabled=true 140 - format = "[$symbol$version]($style) " 141 - symbol = "ஃ " 142 - style = "bold green" 143 - 144 - [python] 145 - disabled=true 146 - format = 'via [${symbol}${pyenv_prefix}${version}( $virtualenv)]($style) ' 147 - symbol = " " 148 - style = "italic Blue" 149 - 150 - [rust] 151 - disabled=true 152 - format = "[$symbol$version]($style) " 153 - # style = "bold green" 154 - symbol = " " 155 - 156 - # Prompt: optional param 1 157 -
-674
LICENSE
··· 1 - GNU GENERAL PUBLIC LICENSE 2 - Version 3, 29 June 2007 3 - 4 - Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/> 5 - Everyone is permitted to copy and distribute verbatim copies 6 - of this license document, but changing it is not allowed. 7 - 8 - Preamble 9 - 10 - The GNU General Public License is a free, copyleft license for 11 - software and other kinds of works. 12 - 13 - The licenses for most software and other practical works are designed 14 - to take away your freedom to share and change the works. By contrast, 15 - the GNU General Public License is intended to guarantee your freedom to 16 - share and change all versions of a program--to make sure it remains free 17 - software for all its users. We, the Free Software Foundation, use the 18 - GNU General Public License for most of our software; it applies also to 19 - any other work released this way by its authors. You can apply it to 20 - your programs, too. 21 - 22 - When we speak of free software, we are referring to freedom, not 23 - price. Our General Public Licenses are designed to make sure that you 24 - have the freedom to distribute copies of free software (and charge for 25 - them if you wish), that you receive source code or can get it if you 26 - want it, that you can change the software or use pieces of it in new 27 - free programs, and that you know you can do these things. 28 - 29 - To protect your rights, we need to prevent others from denying you 30 - these rights or asking you to surrender the rights. Therefore, you have 31 - certain responsibilities if you distribute copies of the software, or if 32 - you modify it: responsibilities to respect the freedom of others. 33 - 34 - For example, if you distribute copies of such a program, whether 35 - gratis or for a fee, you must pass on to the recipients the same 36 - freedoms that you received. You must make sure that they, too, receive 37 - or can get the source code. And you must show them these terms so they 38 - know their rights. 39 - 40 - Developers that use the GNU GPL protect your rights with two steps: 41 - (1) assert copyright on the software, and (2) offer you this License 42 - giving you legal permission to copy, distribute and/or modify it. 43 - 44 - For the developers' and authors' protection, the GPL clearly explains 45 - that there is no warranty for this free software. For both users' and 46 - authors' sake, the GPL requires that modified versions be marked as 47 - changed, so that their problems will not be attributed erroneously to 48 - authors of previous versions. 49 - 50 - Some devices are designed to deny users access to install or run 51 - modified versions of the software inside them, although the manufacturer 52 - can do so. This is fundamentally incompatible with the aim of 53 - protecting users' freedom to change the software. The systematic 54 - pattern of such abuse occurs in the area of products for individuals to 55 - use, which is precisely where it is most unacceptable. Therefore, we 56 - have designed this version of the GPL to prohibit the practice for those 57 - products. If such problems arise substantially in other domains, we 58 - stand ready to extend this provision to those domains in future versions 59 - of the GPL, as needed to protect the freedom of users. 60 - 61 - Finally, every program is threatened constantly by software patents. 62 - States should not allow patents to restrict development and use of 63 - software on general-purpose computers, but in those that do, we wish to 64 - avoid the special danger that patents applied to a free program could 65 - make it effectively proprietary. To prevent this, the GPL assures that 66 - patents cannot be used to render the program non-free. 67 - 68 - The precise terms and conditions for copying, distribution and 69 - modification follow. 70 - 71 - TERMS AND CONDITIONS 72 - 73 - 0. Definitions. 74 - 75 - "This License" refers to version 3 of the GNU General Public License. 76 - 77 - "Copyright" also means copyright-like laws that apply to other kinds of 78 - works, such as semiconductor masks. 79 - 80 - "The Program" refers to any copyrightable work licensed under this 81 - License. Each licensee is addressed as "you". "Licensees" and 82 - "recipients" may be individuals or organizations. 83 - 84 - To "modify" a work means to copy from or adapt all or part of the work 85 - in a fashion requiring copyright permission, other than the making of an 86 - exact copy. The resulting work is called a "modified version" of the 87 - earlier work or a work "based on" the earlier work. 88 - 89 - A "covered work" means either the unmodified Program or a work based 90 - on the Program. 91 - 92 - To "propagate" a work means to do anything with it that, without 93 - permission, would make you directly or secondarily liable for 94 - infringement under applicable copyright law, except executing it on a 95 - computer or modifying a private copy. Propagation includes copying, 96 - distribution (with or without modification), making available to the 97 - public, and in some countries other activities as well. 98 - 99 - To "convey" a work means any kind of propagation that enables other 100 - parties to make or receive copies. Mere interaction with a user through 101 - a computer network, with no transfer of a copy, is not conveying. 102 - 103 - An interactive user interface displays "Appropriate Legal Notices" 104 - to the extent that it includes a convenient and prominently visible 105 - feature that (1) displays an appropriate copyright notice, and (2) 106 - tells the user that there is no warranty for the work (except to the 107 - extent that warranties are provided), that licensees may convey the 108 - work under this License, and how to view a copy of this License. If 109 - the interface presents a list of user commands or options, such as a 110 - menu, a prominent item in the list meets this criterion. 111 - 112 - 1. Source Code. 113 - 114 - The "source code" for a work means the preferred form of the work 115 - for making modifications to it. "Object code" means any non-source 116 - form of a work. 117 - 118 - A "Standard Interface" means an interface that either is an official 119 - standard defined by a recognized standards body, or, in the case of 120 - interfaces specified for a particular programming language, one that 121 - is widely used among developers working in that language. 122 - 123 - The "System Libraries" of an executable work include anything, other 124 - than the work as a whole, that (a) is included in the normal form of 125 - packaging a Major Component, but which is not part of that Major 126 - Component, and (b) serves only to enable use of the work with that 127 - Major Component, or to implement a Standard Interface for which an 128 - implementation is available to the public in source code form. A 129 - "Major Component", in this context, means a major essential component 130 - (kernel, window system, and so on) of the specific operating system 131 - (if any) on which the executable work runs, or a compiler used to 132 - produce the work, or an object code interpreter used to run it. 133 - 134 - The "Corresponding Source" for a work in object code form means all 135 - the source code needed to generate, install, and (for an executable 136 - work) run the object code and to modify the work, including scripts to 137 - control those activities. However, it does not include the work's 138 - System Libraries, or general-purpose tools or generally available free 139 - programs which are used unmodified in performing those activities but 140 - which are not part of the work. For example, Corresponding Source 141 - includes interface definition files associated with source files for 142 - the work, and the source code for shared libraries and dynamically 143 - linked subprograms that the work is specifically designed to require, 144 - such as by intimate data communication or control flow between those 145 - subprograms and other parts of the work. 146 - 147 - The Corresponding Source need not include anything that users 148 - can regenerate automatically from other parts of the Corresponding 149 - Source. 150 - 151 - The Corresponding Source for a work in source code form is that 152 - same work. 153 - 154 - 2. Basic Permissions. 155 - 156 - All rights granted under this License are granted for the term of 157 - copyright on the Program, and are irrevocable provided the stated 158 - conditions are met. This License explicitly affirms your unlimited 159 - permission to run the unmodified Program. The output from running a 160 - covered work is covered by this License only if the output, given its 161 - content, constitutes a covered work. This License acknowledges your 162 - rights of fair use or other equivalent, as provided by copyright law. 163 - 164 - You may make, run and propagate covered works that you do not 165 - convey, without conditions so long as your license otherwise remains 166 - in force. You may convey covered works to others for the sole purpose 167 - of having them make modifications exclusively for you, or provide you 168 - with facilities for running those works, provided that you comply with 169 - the terms of this License in conveying all material for which you do 170 - not control copyright. Those thus making or running the covered works 171 - for you must do so exclusively on your behalf, under your direction 172 - and control, on terms that prohibit them from making any copies of 173 - your copyrighted material outside their relationship with you. 174 - 175 - Conveying under any other circumstances is permitted solely under 176 - the conditions stated below. Sublicensing is not allowed; section 10 177 - makes it unnecessary. 178 - 179 - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 180 - 181 - No covered work shall be deemed part of an effective technological 182 - measure under any applicable law fulfilling obligations under article 183 - 11 of the WIPO copyright treaty adopted on 20 December 1996, or 184 - similar laws prohibiting or restricting circumvention of such 185 - measures. 186 - 187 - When you convey a covered work, you waive any legal power to forbid 188 - circumvention of technological measures to the extent such circumvention 189 - is effected by exercising rights under this License with respect to 190 - the covered work, and you disclaim any intention to limit operation or 191 - modification of the work as a means of enforcing, against the work's 192 - users, your or third parties' legal rights to forbid circumvention of 193 - technological measures. 194 - 195 - 4. Conveying Verbatim Copies. 196 - 197 - You may convey verbatim copies of the Program's source code as you 198 - receive it, in any medium, provided that you conspicuously and 199 - appropriately publish on each copy an appropriate copyright notice; 200 - keep intact all notices stating that this License and any 201 - non-permissive terms added in accord with section 7 apply to the code; 202 - keep intact all notices of the absence of any warranty; and give all 203 - recipients a copy of this License along with the Program. 204 - 205 - You may charge any price or no price for each copy that you convey, 206 - and you may offer support or warranty protection for a fee. 207 - 208 - 5. Conveying Modified Source Versions. 209 - 210 - You may convey a work based on the Program, or the modifications to 211 - produce it from the Program, in the form of source code under the 212 - terms of section 4, provided that you also meet all of these conditions: 213 - 214 - a) The work must carry prominent notices stating that you modified 215 - it, and giving a relevant date. 216 - 217 - b) The work must carry prominent notices stating that it is 218 - released under this License and any conditions added under section 219 - 7. This requirement modifies the requirement in section 4 to 220 - "keep intact all notices". 221 - 222 - c) You must license the entire work, as a whole, under this 223 - License to anyone who comes into possession of a copy. This 224 - License will therefore apply, along with any applicable section 7 225 - additional terms, to the whole of the work, and all its parts, 226 - regardless of how they are packaged. This License gives no 227 - permission to license the work in any other way, but it does not 228 - invalidate such permission if you have separately received it. 229 - 230 - d) If the work has interactive user interfaces, each must display 231 - Appropriate Legal Notices; however, if the Program has interactive 232 - interfaces that do not display Appropriate Legal Notices, your 233 - work need not make them do so. 234 - 235 - A compilation of a covered work with other separate and independent 236 - works, which are not by their nature extensions of the covered work, 237 - and which are not combined with it such as to form a larger program, 238 - in or on a volume of a storage or distribution medium, is called an 239 - "aggregate" if the compilation and its resulting copyright are not 240 - used to limit the access or legal rights of the compilation's users 241 - beyond what the individual works permit. Inclusion of a covered work 242 - in an aggregate does not cause this License to apply to the other 243 - parts of the aggregate. 244 - 245 - 6. Conveying Non-Source Forms. 246 - 247 - You may convey a covered work in object code form under the terms 248 - of sections 4 and 5, provided that you also convey the 249 - machine-readable Corresponding Source under the terms of this License, 250 - in one of these ways: 251 - 252 - a) Convey the object code in, or embodied in, a physical product 253 - (including a physical distribution medium), accompanied by the 254 - Corresponding Source fixed on a durable physical medium 255 - customarily used for software interchange. 256 - 257 - b) Convey the object code in, or embodied in, a physical product 258 - (including a physical distribution medium), accompanied by a 259 - written offer, valid for at least three years and valid for as 260 - long as you offer spare parts or customer support for that product 261 - model, to give anyone who possesses the object code either (1) a 262 - copy of the Corresponding Source for all the software in the 263 - product that is covered by this License, on a durable physical 264 - medium customarily used for software interchange, for a price no 265 - more than your reasonable cost of physically performing this 266 - conveying of source, or (2) access to copy the 267 - Corresponding Source from a network server at no charge. 268 - 269 - c) Convey individual copies of the object code with a copy of the 270 - written offer to provide the Corresponding Source. This 271 - alternative is allowed only occasionally and noncommercially, and 272 - only if you received the object code with such an offer, in accord 273 - with subsection 6b. 274 - 275 - d) Convey the object code by offering access from a designated 276 - place (gratis or for a charge), and offer equivalent access to the 277 - Corresponding Source in the same way through the same place at no 278 - further charge. You need not require recipients to copy the 279 - Corresponding Source along with the object code. If the place to 280 - copy the object code is a network server, the Corresponding Source 281 - may be on a different server (operated by you or a third party) 282 - that supports equivalent copying facilities, provided you maintain 283 - clear directions next to the object code saying where to find the 284 - Corresponding Source. Regardless of what server hosts the 285 - Corresponding Source, you remain obligated to ensure that it is 286 - available for as long as needed to satisfy these requirements. 287 - 288 - e) Convey the object code using peer-to-peer transmission, provided 289 - you inform other peers where the object code and Corresponding 290 - Source of the work are being offered to the general public at no 291 - charge under subsection 6d. 292 - 293 - A separable portion of the object code, whose source code is excluded 294 - from the Corresponding Source as a System Library, need not be 295 - included in conveying the object code work. 296 - 297 - A "User Product" is either (1) a "consumer product", which means any 298 - tangible personal property which is normally used for personal, family, 299 - or household purposes, or (2) anything designed or sold for incorporation 300 - into a dwelling. In determining whether a product is a consumer product, 301 - doubtful cases shall be resolved in favor of coverage. For a particular 302 - product received by a particular user, "normally used" refers to a 303 - typical or common use of that class of product, regardless of the status 304 - of the particular user or of the way in which the particular user 305 - actually uses, or expects or is expected to use, the product. A product 306 - is a consumer product regardless of whether the product has substantial 307 - commercial, industrial or non-consumer uses, unless such uses represent 308 - the only significant mode of use of the product. 309 - 310 - "Installation Information" for a User Product means any methods, 311 - procedures, authorization keys, or other information required to install 312 - and execute modified versions of a covered work in that User Product from 313 - a modified version of its Corresponding Source. The information must 314 - suffice to ensure that the continued functioning of the modified object 315 - code is in no case prevented or interfered with solely because 316 - modification has been made. 317 - 318 - If you convey an object code work under this section in, or with, or 319 - specifically for use in, a User Product, and the conveying occurs as 320 - part of a transaction in which the right of possession and use of the 321 - User Product is transferred to the recipient in perpetuity or for a 322 - fixed term (regardless of how the transaction is characterized), the 323 - Corresponding Source conveyed under this section must be accompanied 324 - by the Installation Information. But this requirement does not apply 325 - if neither you nor any third party retains the ability to install 326 - modified object code on the User Product (for example, the work has 327 - been installed in ROM). 328 - 329 - The requirement to provide Installation Information does not include a 330 - requirement to continue to provide support service, warranty, or updates 331 - for a work that has been modified or installed by the recipient, or for 332 - the User Product in which it has been modified or installed. Access to a 333 - network may be denied when the modification itself materially and 334 - adversely affects the operation of the network or violates the rules and 335 - protocols for communication across the network. 336 - 337 - Corresponding Source conveyed, and Installation Information provided, 338 - in accord with this section must be in a format that is publicly 339 - documented (and with an implementation available to the public in 340 - source code form), and must require no special password or key for 341 - unpacking, reading or copying. 342 - 343 - 7. Additional Terms. 344 - 345 - "Additional permissions" are terms that supplement the terms of this 346 - License by making exceptions from one or more of its conditions. 347 - Additional permissions that are applicable to the entire Program shall 348 - be treated as though they were included in this License, to the extent 349 - that they are valid under applicable law. If additional permissions 350 - apply only to part of the Program, that part may be used separately 351 - under those permissions, but the entire Program remains governed by 352 - this License without regard to the additional permissions. 353 - 354 - When you convey a copy of a covered work, you may at your option 355 - remove any additional permissions from that copy, or from any part of 356 - it. (Additional permissions may be written to require their own 357 - removal in certain cases when you modify the work.) You may place 358 - additional permissions on material, added by you to a covered work, 359 - for which you have or can give appropriate copyright permission. 360 - 361 - Notwithstanding any other provision of this License, for material you 362 - add to a covered work, you may (if authorized by the copyright holders of 363 - that material) supplement the terms of this License with terms: 364 - 365 - a) Disclaiming warranty or limiting liability differently from the 366 - terms of sections 15 and 16 of this License; or 367 - 368 - b) Requiring preservation of specified reasonable legal notices or 369 - author attributions in that material or in the Appropriate Legal 370 - Notices displayed by works containing it; or 371 - 372 - c) Prohibiting misrepresentation of the origin of that material, or 373 - requiring that modified versions of such material be marked in 374 - reasonable ways as different from the original version; or 375 - 376 - d) Limiting the use for publicity purposes of names of licensors or 377 - authors of the material; or 378 - 379 - e) Declining to grant rights under trademark law for use of some 380 - trade names, trademarks, or service marks; or 381 - 382 - f) Requiring indemnification of licensors and authors of that 383 - material by anyone who conveys the material (or modified versions of 384 - it) with contractual assumptions of liability to the recipient, for 385 - any liability that these contractual assumptions directly impose on 386 - those licensors and authors. 387 - 388 - All other non-permissive additional terms are considered "further 389 - restrictions" within the meaning of section 10. If the Program as you 390 - received it, or any part of it, contains a notice stating that it is 391 - governed by this License along with a term that is a further 392 - restriction, you may remove that term. If a license document contains 393 - a further restriction but permits relicensing or conveying under this 394 - License, you may add to a covered work material governed by the terms 395 - of that license document, provided that the further restriction does 396 - not survive such relicensing or conveying. 397 - 398 - If you add terms to a covered work in accord with this section, you 399 - must place, in the relevant source files, a statement of the 400 - additional terms that apply to those files, or a notice indicating 401 - where to find the applicable terms. 402 - 403 - Additional terms, permissive or non-permissive, may be stated in the 404 - form of a separately written license, or stated as exceptions; 405 - the above requirements apply either way. 406 - 407 - 8. Termination. 408 - 409 - You may not propagate or modify a covered work except as expressly 410 - provided under this License. Any attempt otherwise to propagate or 411 - modify it is void, and will automatically terminate your rights under 412 - this License (including any patent licenses granted under the third 413 - paragraph of section 11). 414 - 415 - However, if you cease all violation of this License, then your 416 - license from a particular copyright holder is reinstated (a) 417 - provisionally, unless and until the copyright holder explicitly and 418 - finally terminates your license, and (b) permanently, if the copyright 419 - holder fails to notify you of the violation by some reasonable means 420 - prior to 60 days after the cessation. 421 - 422 - Moreover, your license from a particular copyright holder is 423 - reinstated permanently if the copyright holder notifies you of the 424 - violation by some reasonable means, this is the first time you have 425 - received notice of violation of this License (for any work) from that 426 - copyright holder, and you cure the violation prior to 30 days after 427 - your receipt of the notice. 428 - 429 - Termination of your rights under this section does not terminate the 430 - licenses of parties who have received copies or rights from you under 431 - this License. If your rights have been terminated and not permanently 432 - reinstated, you do not qualify to receive new licenses for the same 433 - material under section 10. 434 - 435 - 9. Acceptance Not Required for Having Copies. 436 - 437 - You are not required to accept this License in order to receive or 438 - run a copy of the Program. Ancillary propagation of a covered work 439 - occurring solely as a consequence of using peer-to-peer transmission 440 - to receive a copy likewise does not require acceptance. However, 441 - nothing other than this License grants you permission to propagate or 442 - modify any covered work. These actions infringe copyright if you do 443 - not accept this License. Therefore, by modifying or propagating a 444 - covered work, you indicate your acceptance of this License to do so. 445 - 446 - 10. Automatic Licensing of Downstream Recipients. 447 - 448 - Each time you convey a covered work, the recipient automatically 449 - receives a license from the original licensors, to run, modify and 450 - propagate that work, subject to this License. You are not responsible 451 - for enforcing compliance by third parties with this License. 452 - 453 - An "entity transaction" is a transaction transferring control of an 454 - organization, or substantially all assets of one, or subdividing an 455 - organization, or merging organizations. If propagation of a covered 456 - work results from an entity transaction, each party to that 457 - transaction who receives a copy of the work also receives whatever 458 - licenses to the work the party's predecessor in interest had or could 459 - give under the previous paragraph, plus a right to possession of the 460 - Corresponding Source of the work from the predecessor in interest, if 461 - the predecessor has it or can get it with reasonable efforts. 462 - 463 - You may not impose any further restrictions on the exercise of the 464 - rights granted or affirmed under this License. For example, you may 465 - not impose a license fee, royalty, or other charge for exercise of 466 - rights granted under this License, and you may not initiate litigation 467 - (including a cross-claim or counterclaim in a lawsuit) alleging that 468 - any patent claim is infringed by making, using, selling, offering for 469 - sale, or importing the Program or any portion of it. 470 - 471 - 11. Patents. 472 - 473 - A "contributor" is a copyright holder who authorizes use under this 474 - License of the Program or a work on which the Program is based. The 475 - work thus licensed is called the contributor's "contributor version". 476 - 477 - A contributor's "essential patent claims" are all patent claims 478 - owned or controlled by the contributor, whether already acquired or 479 - hereafter acquired, that would be infringed by some manner, permitted 480 - by this License, of making, using, or selling its contributor version, 481 - but do not include claims that would be infringed only as a 482 - consequence of further modification of the contributor version. For 483 - purposes of this definition, "control" includes the right to grant 484 - patent sublicenses in a manner consistent with the requirements of 485 - this License. 486 - 487 - Each contributor grants you a non-exclusive, worldwide, royalty-free 488 - patent license under the contributor's essential patent claims, to 489 - make, use, sell, offer for sale, import and otherwise run, modify and 490 - propagate the contents of its contributor version. 491 - 492 - In the following three paragraphs, a "patent license" is any express 493 - agreement or commitment, however denominated, not to enforce a patent 494 - (such as an express permission to practice a patent or covenant not to 495 - sue for patent infringement). To "grant" such a patent license to a 496 - party means to make such an agreement or commitment not to enforce a 497 - patent against the party. 498 - 499 - If you convey a covered work, knowingly relying on a patent license, 500 - and the Corresponding Source of the work is not available for anyone 501 - to copy, free of charge and under the terms of this License, through a 502 - publicly available network server or other readily accessible means, 503 - then you must either (1) cause the Corresponding Source to be so 504 - available, or (2) arrange to deprive yourself of the benefit of the 505 - patent license for this particular work, or (3) arrange, in a manner 506 - consistent with the requirements of this License, to extend the patent 507 - license to downstream recipients. "Knowingly relying" means you have 508 - actual knowledge that, but for the patent license, your conveying the 509 - covered work in a country, or your recipient's use of the covered work 510 - in a country, would infringe one or more identifiable patents in that 511 - country that you have reason to believe are valid. 512 - 513 - If, pursuant to or in connection with a single transaction or 514 - arrangement, you convey, or propagate by procuring conveyance of, a 515 - covered work, and grant a patent license to some of the parties 516 - receiving the covered work authorizing them to use, propagate, modify 517 - or convey a specific copy of the covered work, then the patent license 518 - you grant is automatically extended to all recipients of the covered 519 - work and works based on it. 520 - 521 - A patent license is "discriminatory" if it does not include within 522 - the scope of its coverage, prohibits the exercise of, or is 523 - conditioned on the non-exercise of one or more of the rights that are 524 - specifically granted under this License. You may not convey a covered 525 - work if you are a party to an arrangement with a third party that is 526 - in the business of distributing software, under which you make payment 527 - to the third party based on the extent of your activity of conveying 528 - the work, and under which the third party grants, to any of the 529 - parties who would receive the covered work from you, a discriminatory 530 - patent license (a) in connection with copies of the covered work 531 - conveyed by you (or copies made from those copies), or (b) primarily 532 - for and in connection with specific products or compilations that 533 - contain the covered work, unless you entered into that arrangement, 534 - or that patent license was granted, prior to 28 March 2007. 535 - 536 - Nothing in this License shall be construed as excluding or limiting 537 - any implied license or other defenses to infringement that may 538 - otherwise be available to you under applicable patent law. 539 - 540 - 12. No Surrender of Others' Freedom. 541 - 542 - If conditions are imposed on you (whether by court order, agreement or 543 - otherwise) that contradict the conditions of this License, they do not 544 - excuse you from the conditions of this License. If you cannot convey a 545 - covered work so as to satisfy simultaneously your obligations under this 546 - License and any other pertinent obligations, then as a consequence you may 547 - not convey it at all. For example, if you agree to terms that obligate you 548 - to collect a royalty for further conveying from those to whom you convey 549 - the Program, the only way you could satisfy both those terms and this 550 - License would be to refrain entirely from conveying the Program. 551 - 552 - 13. Use with the GNU Affero General Public License. 553 - 554 - Notwithstanding any other provision of this License, you have 555 - permission to link or combine any covered work with a work licensed 556 - under version 3 of the GNU Affero General Public License into a single 557 - combined work, and to convey the resulting work. The terms of this 558 - License will continue to apply to the part which is the covered work, 559 - but the special requirements of the GNU Affero General Public License, 560 - section 13, concerning interaction through a network will apply to the 561 - combination as such. 562 - 563 - 14. Revised Versions of this License. 564 - 565 - The Free Software Foundation may publish revised and/or new versions of 566 - the GNU General Public License from time to time. Such new versions will 567 - be similar in spirit to the present version, but may differ in detail to 568 - address new problems or concerns. 569 - 570 - Each version is given a distinguishing version number. If the 571 - Program specifies that a certain numbered version of the GNU General 572 - Public License "or any later version" applies to it, you have the 573 - option of following the terms and conditions either of that numbered 574 - version or of any later version published by the Free Software 575 - Foundation. If the Program does not specify a version number of the 576 - GNU General Public License, you may choose any version ever published 577 - by the Free Software Foundation. 578 - 579 - If the Program specifies that a proxy can decide which future 580 - versions of the GNU General Public License can be used, that proxy's 581 - public statement of acceptance of a version permanently authorizes you 582 - to choose that version for the Program. 583 - 584 - Later license versions may give you additional or different 585 - permissions. However, no additional obligations are imposed on any 586 - author or copyright holder as a result of your choosing to follow a 587 - later version. 588 - 589 - 15. Disclaimer of Warranty. 590 - 591 - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 592 - APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 593 - HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 594 - OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 595 - THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 596 - PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 597 - IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 598 - ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 599 - 600 - 16. Limitation of Liability. 601 - 602 - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 603 - WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 604 - THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 605 - GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 606 - USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 607 - DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 608 - PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 609 - EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 610 - SUCH DAMAGES. 611 - 612 - 17. Interpretation of Sections 15 and 16. 613 - 614 - If the disclaimer of warranty and limitation of liability provided 615 - above cannot be given local legal effect according to their terms, 616 - reviewing courts shall apply local law that most closely approximates 617 - an absolute waiver of all civil liability in connection with the 618 - Program, unless a warranty or assumption of liability accompanies a 619 - copy of the Program in return for a fee. 620 - 621 - END OF TERMS AND CONDITIONS 622 - 623 - How to Apply These Terms to Your New Programs 624 - 625 - If you develop a new program, and you want it to be of the greatest 626 - possible use to the public, the best way to achieve this is to make it 627 - free software which everyone can redistribute and change under these terms. 628 - 629 - To do so, attach the following notices to the program. It is safest 630 - to attach them to the start of each source file to most effectively 631 - state the exclusion of warranty; and each file should have at least 632 - the "copyright" line and a pointer to where the full notice is found. 633 - 634 - <one line to give the program's name and a brief idea of what it does.> 635 - Copyright (C) <year> <name of author> 636 - 637 - This program is free software: you can redistribute it and/or modify 638 - it under the terms of the GNU General Public License as published by 639 - the Free Software Foundation, either version 3 of the License, or 640 - (at your option) any later version. 641 - 642 - This program is distributed in the hope that it will be useful, 643 - but WITHOUT ANY WARRANTY; without even the implied warranty of 644 - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 645 - GNU General Public License for more details. 646 - 647 - You should have received a copy of the GNU General Public License 648 - along with this program. If not, see <https://www.gnu.org/licenses/>. 649 - 650 - Also add information on how to contact you by electronic and paper mail. 651 - 652 - If the program does terminal interaction, make it output a short 653 - notice like this when it starts in an interactive mode: 654 - 655 - <program> Copyright (C) <year> <name of author> 656 - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 657 - This is free software, and you are welcome to redistribute it 658 - under certain conditions; type `show c' for details. 659 - 660 - The hypothetical commands `show w' and `show c' should show the appropriate 661 - parts of the General Public License. Of course, your program's commands 662 - might be different; for a GUI interface, you would use an "about box". 663 - 664 - You should also get your employer (if you work as a programmer) or school, 665 - if any, to sign a "copyright disclaimer" for the program, if necessary. 666 - For more information on this, and how to apply and follow the GNU GPL, see 667 - <https://www.gnu.org/licenses/>. 668 - 669 - The GNU General Public License does not permit incorporating your program 670 - into proprietary programs. If your program is a subroutine library, you 671 - may consider it more useful to permit linking proprietary applications with 672 - the library. If this is what you want to do, use the GNU Lesser General 673 - Public License instead of this License. But first, please read 674 - <https://www.gnu.org/licenses/why-not-lgpl.html>.
+58 -6
README.md
··· 1 - # my dotfiles 1 + ## hello! these are my dots 2 2 3 - my i3wm dotfiles 3 + (this readme is straight stolen from alphatechnolog lol) 4 4 5 - showcase 5 + also if you like this shit, gimme a star please 6 + 6 7 ![showcase](/showcase.png) 8 + ![showcase](/showcase.mp4) 7 9 8 - installation: 10 + ## some info 11 + - os: endeavouros/arch (endeavouros installed as arch lol) 12 + - wm: bspwm 13 + - terminal: suckless st 14 + - shell: zsh 15 + - nvim config: nvchad 16 + - compositor: picom 17 + - app launcher: rofi 18 + - bar: polybar 19 + 20 + ## setup 21 + # clone the repo 9 22 ```bash 10 - git clone https://github.com/radstevee/i3-dotfiles ~/.dotfiles 11 - cp -r ~/.dotfiles/.config ~/.config 23 + git clone https://github.com/radstevee/dotfiles.git -b bspwm 24 + cd dotfiles 12 25 ``` 26 + 27 + or using the github cli 28 + 29 + ```bash 30 + gh repo clone radstevee/dotfiles -b bspwm 31 + cd dotfiles 32 + ``` 33 + 34 + # stuff you need (aka requirements) 35 + - jetbrains mono font 36 + - jetbrains mono nerd font 37 + - arian8j2's picom fork 38 + - bspwm 39 + - sxhkd 40 + - nitrogen (you can also use feh tho) 41 + - rofi 42 + - polybar 43 + - bat 44 + - exa 45 + - dunst 46 + - starship 47 + - zsh 48 + - btop (optional) 49 + - cava (optional) 50 + 51 + install them via your package manager/aur, or compile them yourself 52 + 53 + # copy the configs 54 + ```bash 55 + cp -r cfg/* ~/.config/ 56 + cp -r bin/* ~/.local/bin/ 57 + cp -r home/* ~/ 58 + ``` 59 + 60 + # compile st 61 + ```bash 62 + cd ~/.config/st 63 + sudo make clean install 64 + ```
+65
bin/fetch
··· 1 + #!/bin/bash 2 + # Author: https://github.com/AlphaTechnolog 3 + 4 + #clear 5 + 6 + user="${USER}" 7 + shell="$(basename ${SHELL})" 8 + distro=$(. /etc/os-release ; echo "$ID") 9 + #distro='void' 10 + wm="$(xprop -id $(xprop -root -notype | awk '$1=="_NET_SUPPORTING_WM_CHECK:"{print $5}') -notype -f _NET_WM_NAME 8t | grep "WM_NAME" | cut -f2 -d \")" 11 + kernel="$(uname -r | cut -d '-' -f1)" 12 + ram="$(free -t | awk 'NR == 2 {printf("%.2f%"), $3/$2*100}')" 13 + 14 + white='\033[37m' 15 + cyan='\033[36m' 16 + blue='\033[34m' 17 + blue='\033[36m' 18 + yellow='\033[33m' 19 + green='\033[32m' 20 + magenta='\033[35m' 21 + purple='\033[35m' 22 + red='\033[31m' 23 + bold='\033[1m' 24 + end='\033[0m' 25 + 26 + len () { 27 + echo $@ | wc -c 28 + } 29 + 30 + repeat_by_len () { 31 + local str=$1 32 + local char=$2 33 + local len=$(len $str) 34 + local i=1 35 + 36 + while [[ $i -lt $len ]]; do 37 + printf "$char" 38 + i=$(expr $i + 1) 39 + done 40 + } 41 + 42 + if [[ $distro == 'void' || $distro == 'Void' ]]; then 43 + printf '%b' " 44 + ${bold}${green} ▄▄▄▄▄▄ ${end}${bold}${blue}${user}${cyan}@${magenta}$(cat /etc/hostname)${end} 45 + ${bold}${green}${cyan} ▄${green} ▀███████▄ ${end}${green}$(repeat_by_len "${user}@$(cat /etc/hostname)" "─") 46 + ${bold}${green}${cyan}███${white} ▄▄▄${green} ▀███ ${end} 47 + ${bold}${green}${cyan}███${white} █████${green} ███ ${end}${bold}${green}os ${green}  ${magenta}${green}${distro}${end} 48 + ${bold}${green}${cyan}███${white} ▀███▀${green} ███ ${end}${bold}${yellow}sh ${green}  ${magenta}${blue}${shell}${end} 49 + ${bold}${green}${cyan}████▄▄▄▄▄${green} ▀██ ${end}${bold}${magenta}wm ${green}  ${magenta}${yellow}${wm}${end} 50 + ${bold}${green}${cyan} ▀███████▀ ${end}${bold}${blue}ram ${green} ${magenta}${green}${ram}${end} 51 + 52 + " 53 + else 54 + printf '%b' " 55 + ${bold}${blue} ██ ${end}${bold}${blue}${user}${cyan}@${purple}$(cat /etc/hostname)${end} 56 + ${bold}${blue} ████ ${end}${green}$(repeat_by_len "${user}@$(cat /etc/hostname)" "─") 57 + ${bold}${blue} ▀████ ${end} 58 + ${bold}${blue} ██▄ ████ ${end}${bold}${purple}  ${blue}os ${green}  ${magenta}${cyan}${distro}${end} 59 + ${bold}${blue} ██████████ ${end}${bold}${purple}  ${blue}sh ${green}  ${magenta}${cyan}${shell}${end} 60 + ${bold}${blue} ████▀ ▀████ ${end}${bold}${purple}  ${blue}wm ${green}  ${magenta}${cyan}${wm}${end} 61 + ${bold}${blue} ████▀ ▀████ ${end}${bold}${purple}  ${blue}kr ${green}  ${magenta}${cyan}${kernel}${end} 62 + ${bold}${blue}▀▀▀ ▀▀▀ ${end}${bold}${purple}  ${blue}ram ${green} ${magenta}${cyan}${ram}${end} 63 + 64 + " 65 + fi
+8
cfg/autostart
··· 1 + #!/bin/bash 2 + nm-applet & 3 + /home/radsteve/.config/polybar/launch.sh 4 + picom & 5 + dunst & 6 + nitrogen --restore 7 + #feh --bg-scale ~/.config/wallpaper.png 8 + discord &
+48
cfg/bspwm/bspwmrc
··· 1 + #!/bin/sh 2 + 3 + pgrep -x sxhkd > /dev/null || sxhkd & 4 + 5 + bspc monitor -d 1 2 3 4 5 6 7 6 + 7 + xsetroot -cursor_name left_ptr 8 + 9 + bspc config border_width 0 10 + bspc config window_gap 5 11 + 12 + bspc config left_padding 7 13 + bspc config right_padding 7 14 + bspc config bottom_padding 52 15 + 16 + #top padding 17 + while true 18 + do 19 + bspc config top_padding 7 20 + bspc config top_monocle_padding 7 21 + done & 22 + 23 + bspc config split_ratio 0.52 24 + bspc config borderless_monocle true 25 + bspc config gapless_monocle true 26 + 27 + bspc config active_border_color '#ddb6f2' 28 + bspc config focused_border_color '#ddb6f2' 29 + bspc config normal_border_color '#ffc47a' 30 + bspc config presel_border_color '#96cdfb' 31 + bspc config urgent_border_color '#f28fad' 32 + 33 + bspc config active_locked_border_color '#ddb6f2' 34 + bspc config focused_locked_border_color '#ffc47a' 35 + bspc config normal_locked_border_color '#96cdfb' 36 + 37 + bspc config pointer_modifier Mod4 38 + bspc config pointer_action1 move 39 + bspc config pointer_action2 resize_side 40 + bspc config pointer_action2 resize_corner 41 + 42 + bspc rule -a firefox desktop='^1' 43 + bspc rule -a discord desktop='^2' 44 + bspc rule -a spotify desktop='^4' 45 + bspc rule -a code desktop='^5' 46 + bspc rule -a supertuxkart state='tiling' desktop='^6' 47 + 48 + bash ~/.config/autostart
+20
cfg/bspwm/scripts/screenshot.sh
··· 1 + #!/bin/bash 2 + 3 + # options to be displayed 4 + option0="screen" 5 + option1="area" 6 + option2="window" 7 + 8 + # options to be displyed 9 + options="$option0\n$option1\n$option2" 10 + 11 + selected="$(echo -e "$options" | rofi -lines 3 -dmenu -p "scrot")" 12 + case $selected in 13 + $option0) 14 + cd ~/Pictures/ && sleep 1 && scrot;; 15 + $option1) 16 + cd ~/Pictures/ && scrot -s;; 17 + $option2) 18 + cd ~/Pictures/ && sleep 1 && scrot -u;; 19 + esac 20 +
+203
cfg/btop/btop.conf
··· 1 + #? Config file for btop v. 1.2.7 2 + 3 + #* Name of a btop++/bpytop/bashtop formatted ".theme" file, "Default" and "TTY" for builtin themes. 4 + #* Themes should be placed in "../share/btop/themes" relative to binary or "$HOME/.config/btop/themes" 5 + color_theme = "catppuccin" 6 + 7 + #* If the theme set background should be shown, set to False if you want terminal background transparency. 8 + theme_background = True 9 + 10 + #* Sets if 24-bit truecolor should be used, will convert 24-bit colors to 256 color (6x6x6 color cube) if false. 11 + truecolor = True 12 + 13 + #* Set to true to force tty mode regardless if a real tty has been detected or not. 14 + #* Will force 16-color mode and TTY theme, set all graph symbols to "tty" and swap out other non tty friendly symbols. 15 + force_tty = False 16 + 17 + #* Define presets for the layout of the boxes. Preset 0 is always all boxes shown with default settings. Max 9 presets. 18 + #* Format: "box_name:P:G,box_name:P:G" P=(0 or 1) for alternate positions, G=graph symbol to use for box. 19 + #* Use withespace " " as separator between different presets. 20 + #* Example: "cpu:0:default,mem:0:tty,proc:1:default cpu:0:braille,proc:0:tty" 21 + presets = "cpu:1:default,proc:0:default cpu:0:default,mem:0:default,net:0:default cpu:0:block,net:0:tty" 22 + 23 + #* Set to True to enable "h,j,k,l,g,G" keys for directional control in lists. 24 + #* Conflicting keys for h:"help" and k:"kill" is accessible while holding shift. 25 + vim_keys = False 26 + 27 + #* Rounded corners on boxes, is ignored if TTY mode is ON. 28 + rounded_corners = True 29 + 30 + #* Default symbols to use for graph creation, "braille", "block" or "tty". 31 + #* "braille" offers the highest resolution but might not be included in all fonts. 32 + #* "block" has half the resolution of braille but uses more common characters. 33 + #* "tty" uses only 3 different symbols but will work with most fonts and should work in a real TTY. 34 + #* Note that "tty" only has half the horizontal resolution of the other two, so will show a shorter historical view. 35 + graph_symbol = "braille" 36 + 37 + # Graph symbol to use for graphs in cpu box, "default", "braille", "block" or "tty". 38 + graph_symbol_cpu = "default" 39 + 40 + # Graph symbol to use for graphs in cpu box, "default", "braille", "block" or "tty". 41 + graph_symbol_mem = "default" 42 + 43 + # Graph symbol to use for graphs in cpu box, "default", "braille", "block" or "tty". 44 + graph_symbol_net = "default" 45 + 46 + # Graph symbol to use for graphs in cpu box, "default", "braille", "block" or "tty". 47 + graph_symbol_proc = "default" 48 + 49 + #* Manually set which boxes to show. Available values are "cpu mem net proc", separate values with whitespace. 50 + shown_boxes = "cpu mem net proc" 51 + 52 + #* Update time in milliseconds, recommended 2000 ms or above for better sample times for graphs. 53 + update_ms = 2000 54 + 55 + #* Processes sorting, "pid" "program" "arguments" "threads" "user" "memory" "cpu lazy" "cpu direct", 56 + #* "cpu lazy" sorts top process over time (easier to follow), "cpu direct" updates top process directly. 57 + proc_sorting = "cpu direct" 58 + 59 + #* Reverse sorting order, True or False. 60 + proc_reversed = False 61 + 62 + #* Show processes as a tree. 63 + proc_tree = False 64 + 65 + #* Use the cpu graph colors in the process list. 66 + proc_colors = True 67 + 68 + #* Use a darkening gradient in the process list. 69 + proc_gradient = True 70 + 71 + #* If process cpu usage should be of the core it's running on or usage of the total available cpu power. 72 + proc_per_core = False 73 + 74 + #* Show process memory as bytes instead of percent. 75 + proc_mem_bytes = True 76 + 77 + #* Use /proc/[pid]/smaps for memory information in the process info box (very slow but more accurate) 78 + proc_info_smaps = False 79 + 80 + #* Show proc box on left side of screen instead of right. 81 + proc_left = False 82 + 83 + #* Sets the CPU stat shown in upper half of the CPU graph, "total" is always available. 84 + #* Select from a list of detected attributes from the options menu. 85 + cpu_graph_upper = "total" 86 + 87 + #* Sets the CPU stat shown in lower half of the CPU graph, "total" is always available. 88 + #* Select from a list of detected attributes from the options menu. 89 + cpu_graph_lower = "total" 90 + 91 + #* Toggles if the lower CPU graph should be inverted. 92 + cpu_invert_lower = True 93 + 94 + #* Set to True to completely disable the lower CPU graph. 95 + cpu_single_graph = False 96 + 97 + #* Show cpu box at bottom of screen instead of top. 98 + cpu_bottom = False 99 + 100 + #* Shows the system uptime in the CPU box. 101 + show_uptime = True 102 + 103 + #* Show cpu temperature. 104 + check_temp = True 105 + 106 + #* Which sensor to use for cpu temperature, use options menu to select from list of available sensors. 107 + cpu_sensor = "Auto" 108 + 109 + #* Show temperatures for cpu cores also if check_temp is True and sensors has been found. 110 + show_coretemp = True 111 + 112 + #* Set a custom mapping between core and coretemp, can be needed on certain cpus to get correct temperature for correct core. 113 + #* Use lm-sensors or similar to see which cores are reporting temperatures on your machine. 114 + #* Format "x:y" x=core with wrong temp, y=core with correct temp, use space as separator between multiple entries. 115 + #* Example: "4:0 5:1 6:3" 116 + cpu_core_map = "" 117 + 118 + #* Which temperature scale to use, available values: "celsius", "fahrenheit", "kelvin" and "rankine". 119 + temp_scale = "celsius" 120 + 121 + #* Use base 10 for bits/bytes sizes, KB = 1000 instead of KiB = 1024. 122 + base_10_sizes = False 123 + 124 + #* Show CPU frequency. 125 + show_cpu_freq = True 126 + 127 + #* Draw a clock at top of screen, formatting according to strftime, empty string to disable. 128 + #* Special formatting: /host = hostname | /user = username | /uptime = system uptime 129 + clock_format = "%X" 130 + 131 + #* Update main ui in background when menus are showing, set this to false if the menus is flickering too much for comfort. 132 + background_update = True 133 + 134 + #* Custom cpu model name, empty string to disable. 135 + custom_cpu_name = "" 136 + 137 + #* Optional filter for shown disks, should be full path of a mountpoint, separate multiple values with whitespace " ". 138 + #* Begin line with "exclude=" to change to exclude filter, otherwise defaults to "most include" filter. Example: disks_filter="exclude=/boot /home/user". 139 + disks_filter = "" 140 + 141 + #* Show graphs instead of meters for memory values. 142 + mem_graphs = True 143 + 144 + #* Show mem box below net box instead of above. 145 + mem_below_net = False 146 + 147 + #* Count ZFS ARC in cached and available memory. 148 + zfs_arc_cached = True 149 + 150 + #* If swap memory should be shown in memory box. 151 + show_swap = True 152 + 153 + #* Show swap as a disk, ignores show_swap value above, inserts itself after first disk. 154 + swap_disk = True 155 + 156 + #* If mem box should be split to also show disks info. 157 + show_disks = True 158 + 159 + #* Filter out non physical disks. Set this to False to include network disks, RAM disks and similar. 160 + only_physical = True 161 + 162 + #* Read disks list from /etc/fstab. This also disables only_physical. 163 + use_fstab = True 164 + 165 + #* Set to true to show available disk space for privileged users. 166 + disk_free_priv = False 167 + 168 + #* Toggles if io activity % (disk busy time) should be shown in regular disk usage view. 169 + show_io_stat = True 170 + 171 + #* Toggles io mode for disks, showing big graphs for disk read/write speeds. 172 + io_mode = False 173 + 174 + #* Set to True to show combined read/write io graphs in io mode. 175 + io_graph_combined = False 176 + 177 + #* Set the top speed for the io graphs in MiB/s (100 by default), use format "mountpoint:speed" separate disks with whitespace " ". 178 + #* Example: "/mnt/media:100 /:20 /boot:1". 179 + io_graph_speeds = "" 180 + 181 + #* Set fixed values for network graphs in Mebibits. Is only used if net_auto is also set to False. 182 + net_download = 100 183 + 184 + net_upload = 100 185 + 186 + #* Use network graphs auto rescaling mode, ignores any values set above and rescales down to 10 Kibibytes at the lowest. 187 + net_auto = True 188 + 189 + #* Sync the auto scaling for download and upload to whichever currently has the highest scale. 190 + net_sync = True 191 + 192 + #* Starts with the Network Interface specified here. 193 + net_iface = "" 194 + 195 + #* Show battery stats in top right if battery is present. 196 + show_battery = True 197 + 198 + #* Which battery to use if multiple are present. "Auto" for auto detection. 199 + selected_battery = "Auto" 200 + 201 + #* Set loglevel for "~/.config/btop/btop.log" levels are: "ERROR" "WARNING" "INFO" "DEBUG". 202 + #* The level set includes all lower levels, i.e. "DEBUG" will show all logging info. 203 + log_level = "WARNING"
+82
cfg/btop/themes/catppuccin.theme
··· 1 + #vim:ft=conf 2 + # Theme: tokyo-night 3 + # By: Pascal Jaeger 4 + 5 + # Main bg 6 + theme[main_bg]="#1e1e2e" 7 + 8 + # Main text color 9 + theme[main_fg]="#cdd6f4" 10 + 11 + # Title color for boxes 12 + theme[title]="#cba6f7" 13 + 14 + # Higlight color for keyboard shortcuts 15 + theme[hi_fg]="#89b4fa" 16 + 17 + # Background color of selected item in processes box 18 + theme[selected_bg]="#45475a" 19 + 20 + # Foreground color of selected item in processes box 21 + theme[selected_fg]="#fab387" 22 + 23 + # Color of inactive/disabled text 24 + theme[inactive_fg]="#b4befe" 25 + 26 + # Misc colors for processes box including mini cpu graphs, details memory graph and details status text 27 + theme[proc_misc]="#74c7ec" 28 + 29 + # Cpu box outline color 30 + theme[cpu_box]="#a6e3a1" 31 + 32 + # Memory/disks box outline color 33 + theme[mem_box]="#a6e3a1" 34 + 35 + # Net up/down box outline color 36 + theme[net_box]="#a6e3a1" 37 + 38 + # Processes box outline color 39 + theme[proc_box]="#a6e3a1" 40 + 41 + # Box divider line and small boxes line color 42 + theme[div_line]="#a6e3a1" 43 + 44 + # Temperature graph colors 45 + theme[temp_start]="#a6e3a1" 46 + theme[temp_mid]="#fab387" 47 + theme[temp_end]="#f38ba8" 48 + 49 + # CPU graph colors 50 + theme[cpu_start]="#a6e3a1" 51 + theme[cpu_mid]="#fab387" 52 + theme[cpu_end]="#f38ba8" 53 + 54 + # Mem/Disk free meter 55 + theme[free_start]="#a6e3a1" 56 + theme[free_mid]="#fab387" 57 + theme[free_end]="#f38ba8" 58 + 59 + # Mem/Disk cached meter 60 + theme[cached_start]="#a6e3a1" 61 + theme[cached_mid]="#fab387" 62 + theme[cached_end]="#f38ba8" 63 + 64 + # Mem/Disk available meter 65 + theme[available_start]="#a6e3a1" 66 + theme[available_mid]="#fab387" 67 + theme[available_end]="#f38ba8" 68 + 69 + # Mem/Disk used meter 70 + theme[used_start]="#a6e3a1" 71 + theme[used_mid]="#fab387" 72 + theme[used_end]="#f38ba8" 73 + 74 + # Download graph colors 75 + theme[download_start]="#a6e3a1" 76 + theme[download_mid]="#fab387" 77 + theme[download_end]="#f38ba8" 78 + 79 + # Upload graph colors 80 + theme[upload_start]="#a6e3a1" 81 + theme[upload_mid]="#fab387" 82 + theme[upload_end]="#f38ba8"
+12
cfg/cava/config
··· 1 + [color] 2 + 3 + gradient = 1 4 + 5 + gradient_color_1 = '#B5E8E0' 6 + gradient_color_2 = '#89DCEB' 7 + gradient_color_3 = '#96CDFB' 8 + gradient_color_4 = '#DDB6F2' 9 + gradient_color_5 = '#F5C2E7' 10 + gradient_color_6 = '#E8A2AF' 11 + gradient_color_7 = '#F2CDCD' 12 + gradient_color_8 = '#F5E0DC'
+95
cfg/dunst/dunstrc
··· 1 + [global] 2 + monitor = 0 3 + follow = keyboard 4 + 5 + width = (240,480) 6 + height = 480 7 + 8 + progress_bar = true 9 + progress_bar_height = 25 10 + progress_bar_frame_width = 3 11 + progress_bar_min_width = 240 12 + progress_bar_max_width = 480 13 + 14 + dmenu = /usr/bin/rofi -show run 15 + browser = /usr/bin/librewolf 16 + 17 + indicate_hidden = true 18 + shrink = true 19 + transparency = 10 20 + separator_height = 3 21 + padding = 8 22 + horizontal_padding = 8 23 + frame_width = 3 24 + separator_color = frame 25 + frame_color = "#96CDFB" 26 + sort = true 27 + idle_threshold = 0 28 + font = JetBrainsMono Nerd Font 14 29 + line_height = 2 30 + markup = full 31 + highlight = "#96CDFB" 32 + 33 + origin = "top-right" 34 + offset = "11x58" 35 + 36 + format = "<b>%s</b>\n%b" 37 + alignment = left 38 + show_age_threshold = 60 39 + word_wrap = true 40 + ignore_newline = false 41 + stack_duplicates = false 42 + hide_duplicate_count = true 43 + show_indicators = true 44 + 45 + icon_position = left 46 + max_icon_size = 100 47 + min_icon_size = 60 48 + 49 + sticky_history = true 50 + history_length = 25 51 + always_run_script = true 52 + title = Dunst 53 + class = Dunst 54 + corner_radius = 6 55 + notification_limit = 5 56 + icon_theme = Papirus-Dark 57 + enable_recursive_icon_lookup = true 58 + 59 + mouse_left_click = close_current 60 + mouse_right_click = do_action 61 + 62 + ignore_dbusclose = true 63 + 64 + [urgency_low] 65 + background = "#1E1E2E" 66 + foreground = "#D9E0EE" 67 + timeout = 4 68 + 69 + [urgency_normal] 70 + background = "#1E1E2E" 71 + foreground = "#D9E0EE" 72 + timeout = 8 73 + 74 + [urgency_critical] 75 + background = "#1E1E2E" 76 + foreground = "#D9E0EE" 77 + frame_color = "#F8BD96" 78 + timeout = 10 79 + 80 + [screenshot] 81 + appname = "screenshot" 82 + max_icon_size = 250 83 + summary = "*" 84 + set_stack_tag = "screenshot" 85 + format = "<b>%s</b>\n%b" 86 + 87 + [spotify] 88 + appname = Spotify 89 + summary = "*" 90 + set_stack_tag = "spotify" 91 + format = "<b>Now Playing </b>%s\n%b" 92 + 93 + [volume] 94 + summary = "Volume *" 95 + format = "<b>Volume</b>\n%n%%"
+18
cfg/dunst/dunstrc.bak
··· 1 + [global] 2 + frame_color = "#96CDFB" 3 + separator_color = frame 4 + font = JetBrains Mono 11 5 + icon = /usr/share/icons/Papirus-Dark/32x32/status/messagebox_info.svg 6 + 7 + [urgency_low] 8 + background = "#1E1E2E" 9 + foreground = "#D9E0EE" 10 + 11 + [urgency_normal] 12 + background = "#1E1E2E" 13 + foreground = "#D9E0EE" 14 + 15 + [urgency_critical] 16 + background = "#1E1E2E" 17 + foreground = "#D9E0EE" 18 + frame_color = "#F8BD96"
+2
cfg/gtkrc
··· 1 + # created by KDE Plasma, Fr. Juni 10 20:00:34 2022 2 + #
+5
cfg/gtkrc-2.0
··· 1 + # created by KDE Plasma, Fr. Juni 10 20:00:34 2022 2 + # 3 + 4 + gtk-alternative-button-order = 1 5 +
+137
cfg/neofetch/config.conf
··· 1 + # Source: https://github.com/chick2d/neofetch-themes 2 + # Configuration made by Chick 3 + 4 + # See this wiki page for more info: 5 + # https://github.com/dylanaraps/neofetch/wiki/Customizing-Info 6 + 7 + # I used custom seperators as the older one looked not very properly proportioned 8 + 9 + print_info() { 10 + prin "┌─────────\n Hardware Information \n─────────┐" 11 + info " ​ ​  " model 12 + info " ​ ​  " cpu 13 + info " ​ ​ ﬙ " gpu 14 + # info " ​ ​  " disk 15 + info " ​ ​ 塞" memory 16 + info " ​ ​  " resolution 17 + # info " ​ ​ 󱈑 " battery 18 + prin "├─────────\n Software Information \n─────────┤" 19 + # info " ​ ​  " users 20 + info " ​ ​  " distro 21 + # Just get your distro's logo off nerdfonts.com 22 + info " ​ ​  " kernel 23 + # info " ​ ​  " de 24 + info " ​ ​  " wm 25 + info " ​ ​  " shell 26 + info " ​ ​  " term 27 + info " ​ ​  " term_font 28 + # info " ​ ​ │  " font 29 + # info " ​ ​  " theme 30 + # info " ​ ​  " icons 31 + info " ​ ​  " packages 32 + # info " ​ ​ 󰅐 " uptime 33 + # info " ​ ​  " gpu_driver # Linux/macOS only 34 + # info " ​ ​  " cpu_usage 35 + # info " ​ ​ ﱘ " song 36 + # [[ "$player" ]] && prin "Music Player" "$player" 37 + # info " ​ ​  " local_ip 38 + # info " ​ ​  " public_ip 39 + # info " ​ ​  " locale # This only works on glibc systems. 40 + prin "└───────────────────────────────────────┘" 41 + info cols 42 + prin "\n \n \n \n \n ${cl3} \n \n ${cl5} \n \n ${cl2} \n \n ${cl6} \n \n ${cl4} \n \n ${cl1} \n \n ${cl7} \n \n ${cl0}" 43 + } 44 + 45 + kernel_shorthand="on" 46 + distro_shorthand="off" 47 + os_arch="off" 48 + uptime_shorthand="on" 49 + memory_percent="on" 50 + package_managers="on" 51 + shell_path="off" 52 + shell_version="on" 53 + speed_type="bios_limit" 54 + speed_shorthand="on" 55 + cpu_brand="off" 56 + cpu_speed="off" 57 + cpu_cores="logical" 58 + cpu_temp="off" 59 + gpu_brand="off" 60 + gpu_type="all" 61 + refresh_rate="on" 62 + gtk_shorthand="on" 63 + gtk2="on" 64 + gtk3="on" 65 + public_ip_host="http://ident.me" 66 + public_ip_timeout=2 67 + disk_show=('/') 68 + music_player="vlc" 69 + song_format="%artist% - %title%" 70 + song_shorthand="off" 71 + colors=(distro) 72 + bold="on" 73 + underline_enabled="on" 74 + underline_char="-" 75 + separator="  " 76 + color_blocks="off" 77 + block_range=(0 15) # Colorblocks 78 + 79 + # Colors for custom colorblocks 80 + magenta="\033[1;35m" 81 + green="\033[1;32m" 82 + white="\033[1;37m" 83 + blue="\033[1;34m" 84 + red="\033[1;31m" 85 + black="\033[1;40;30m" 86 + yellow="\033[1;33m" 87 + cyan="\033[1;36m" 88 + reset="\033[0m" 89 + bgyellow="\033[1;43;33m" 90 + bgwhite="\033[1;47;37m" 91 + cl0="${reset}" 92 + cl1="${magenta}" 93 + cl2="${green}" 94 + cl3="${white}" 95 + cl4="${blue}" 96 + cl5="${red}" 97 + cl6="${yellow}" 98 + cl7="${cyan}" 99 + cl8="${black}" 100 + cl9="${bgyellow}" 101 + cl10="${bgwhite}" 102 + 103 + block_width=4 104 + block_height=1 105 + 106 + bar_char_elapsed="-" 107 + bar_char_total="=" 108 + bar_border="on" 109 + bar_length=15 110 + bar_color_elapsed="distro" 111 + bar_color_total="distro" 112 + 113 + cpu_display="on" 114 + memory_display="on" 115 + battery_display="on" 116 + disk_display="on" 117 + 118 + image_backend="ascii" 119 + #image_source="$HOME/" 120 + image_size="auto" 121 + image_loop="off" 122 + 123 + aascii_distro="auto" 124 + ascii_colors=(distro) 125 + ascii_bold="on" 126 + 127 + thumbnail_dir="${XDG_CACHE_HOME:-${HOME}/.cache}/thumbnails/neofetch" 128 + crop_mode="normal" 129 + crop_offset="center" 130 + 131 + gap=2 132 + 133 + yoffset=0 134 + xoffset=0 135 + 136 + stdout="off" 137 +
+90
cfg/picom.conf
··· 1 + transition = true; 2 + 3 + transition-offset = 25; 4 + transition-direction = "smart-x"; 5 + 6 + # see https://easings.net for list of all functions 7 + #transition-timing-function = "ease-in-out-bounce" 8 + transition-timing-function = "ease-out-cubic" 9 + 10 + # Time between frames in transition. 11 + transition-step = 0.028; 12 + 13 + # Specify a list of transition rules, in the format `DIRECTION:PATTERN` 14 + transition-rule = []; 15 + 16 + shadow = true; 17 + 18 + shadow-radius = 10; 19 + shadow-offset-x = -12; 20 + shadow-offset-y = -12; 21 + shadow-opacity = 0.45; 22 + shadow-red = 0.0; 23 + shadow-green = 0.0; 24 + shadow-blue = 0.0; 25 + 26 + shadow-exclude = [ 27 + "name = 'stalonetray'", 28 + "name = 'plank'", 29 + "name = 'Notification'", 30 + "name = 'fluxbox'", 31 + "class_g = 'bspwm'", 32 + "class_i = 'presel_feedback'", 33 + "class_g = 'fluxbox'", 34 + "class_g ?= 'Notify-osd'", 35 + "class_g = 'xfce4-panel'", 36 + "class_i = 'POWERPNT.EXE'", 37 + "class_i = 'WINWORD.EXE'", 38 + "class_i = 'Meteo'" 39 + ]; 40 + 41 + inactive-opacity = 1.0; 42 + active-opacity = 1.0; 43 + frame-opacity = 1.0; 44 + inactive-opacity-override = false; 45 + opacity-rule = ["100:class_g = 'bspwm'", "20:class_g = 'presel_feedback'"]; 46 + 47 + wintypes: 48 + { 49 + popup_menu = 50 + { 51 + opacity = 1.0; 52 + }; 53 + dropdown_menu = 54 + { 55 + opacity = 1.0 56 + }; 57 + dnd = 58 + { 59 + shadow = false; 60 + }; 61 + dock = 62 + { 63 + shadow = true; 64 + }; 65 + tooltip = 66 + { 67 + fade = true; 68 + shadow = true; 69 + opacity = 1.0; 70 + focus = true; 71 + }; 72 + }; 73 + 74 + 75 + fading = true; 76 + fade-delta = 2.5; 77 + fade-in-step = 0.010; 78 + fade-out-step = 0.008; 79 + fade-exclude = ["class_i = 'rofi'"] 80 + 81 + corner-radius = 9; 82 + rounded-corners-exclude = []; 83 + detect-client-opacity = true; 84 + 85 + inactive-opacity = 0.97; 86 + frame-opacity = 0.8; 87 + inactive-opacity-override = false; 88 + active-opacity = 0.98 89 + focus-exclude = [ "class_g = 'Cairo-clock'" ]; 90 + opacity-rule = ["99:class_g = 'discord'", "100:class_i = 'osu'", "100:class_i = 'lutris'", "100:class_g = 'osu'", "100:class_g = 'lutris'"];
+28
cfg/polybar/colors.ini
··· 1 + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 2 + ; ______ __ 3 + ; / ________ / ____ __________ 4 + ; / / / __ \/ / __ \/ ___/ ___/ 5 + ; / /___/ /_/ / / /_/ / / (__ ) 6 + ; \____/\____/_/\____/_/ /____/ 7 + ; 8 + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 9 + 10 + ;Catppuccin 11 + 12 + [colors] 13 + ; bg = #302D41 14 + bg = #1E1E2E 15 + tp = #1E1E2E 16 + fg = #D9E0EE 17 + white = #D9E0EE 18 + fg-alt = #6E6C7E 19 + blue-s = #B5E8E0 20 + ; blue = #2C6B95 21 + blue = #96CDFB 22 + blue-alt = #62B4F9 23 + red = #F28FAD 24 + green = #ABE9B3 25 + yellow = #FAE3B0 26 + cyan = #89DCEB 27 + magenta = #F5C2E7 28 + mauve = #DDB6F2
+46
cfg/polybar/config.ini
··· 1 + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 2 + ; ____ __ __ 3 + ; / __ \____ / __ __/ /_ ____ ______ 4 + ; / /_/ / __ \/ / / / / __ \/ __ `/ ___/ 5 + ; / ____/ /_/ / / /_/ / /_/ / /_/ / / 6 + ; /_/ \____/_/\__, /_.___/\__,_/_/ 7 + ; /____/ 8 + ; 9 + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 10 + 11 + [global/wm] 12 + ;margin-top = -18 13 + ;margin-bottom = -18 14 + include-file = $HOME/.config/polybar/colors.ini 15 + include-file = $HOME/.config/polybar/modules.ini 16 + 17 + [bar/main] 18 + width = 99% 19 + height = 39 20 + offset-x = 10 21 + offset-y = 7 22 + radius = 10 23 + fixed-center = true 24 + background = ${colors.bg} 25 + foreground = ${colors.fg} 26 + 27 + ;border-size = 4 28 + ;border-color = ${colors.tp} 29 + 30 + padding = 2 31 + module-margin = 1 32 + 33 + font-0 = JetbrainsMono Nerd Font:style=Medium:size=11;2 34 + 35 + modules-left = menu bspwm 36 + modules-center = time 37 + modules-right = pulseaudio memory disk network battery 38 + 39 + wm-restack = bspwm 40 + 41 + cursor-click = pointer 42 + 43 + bottom = true 44 + 45 + [settings] 46 + screenchange-reload = true
+11
cfg/polybar/launch.sh
··· 1 + #!/usr/bin/env bash 2 + 3 + DIR="$HOME/.config/polybar" 4 + # Terminate already running bar instances 5 + killall -q polybar 6 + 7 + # Wait until the processes have been shut down 8 + while pgrep -u $UID -x polybar >/dev/null; do sleep 1; done 9 + 10 + # Launch the bar 11 + polybar -q main -c "$DIR"/config.ini &
+218
cfg/polybar/modules.ini
··· 1 + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 2 + ; 3 + ; __ ___ __ __ 4 + ; / |/ ____ ____/ __ __/ ___ _____ 5 + ; / /|_/ / __ \/ __ / / / / / _ \/ ___/ 6 + ; / / / / /_/ / /_/ / /_/ / / __(__ ) 7 + ; /_/ /_/\____/\__,_/\__,_/_/\___/____/ 8 + ; 9 + ; 10 + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 11 + 12 + [module/menu] 13 + type = custom/text 14 + content = 異 15 + content-foreground = ${colors.cyan} 16 + content-padding = 1 17 + 18 + click-left = rofi -show drun 19 + click-right = rofi -show window 20 + 21 + [module/bspwm] 22 + type = internal/bspwm 23 + 24 + pin-workspaces = true 25 + 26 + ws-icon-0 = 1; 27 + ws-icon-1 = 2;ﭮ 28 + ws-icon-2 = 3; 29 + ws-icon-3 = 4; 30 + ws-icon-4 = 5; 31 + ws-icon-5 = 6; 32 + ws-icon-default =  33 + 34 + format = <label-state> <label-mode> 35 + 36 + label-focused = %icon% 37 + label-focused-foreground = ${colors.white} 38 + label-focused-background = ${colors.blue-alt} 39 + label-focused-padding = 2 40 + 41 + label-occupied = %icon% 42 + label-occupied-foreground = ${colors.fg} 43 + label-occupied-padding = 2 44 + label-urgent = %icon% 45 + 46 + label-urgent-background = ${colors.red} 47 + label-urgent-foreground = ${colors.white} 48 + label-urgent-overline = ${colors.bg} 49 + label-urgent-underline = ${colors.bg} 50 + label-urgent-padding = 2 51 + 52 + label-empty = %icon% 53 + label-empty-foreground = ${colors.fg-alt} 54 + label-empty-padding = 2 55 + 56 + [module/date] 57 + type = internal/date 58 + interval = 5 59 + label-foreground = ${colors.white} 60 + time = %H:%M:%S 61 + time-alt =" %A, %d %B %Y " 62 + label = %time% 63 + 64 + [module/time] 65 + type = internal/date 66 + interval = 5 67 + label-foreground = ${colors.white} 68 + time = %H:%M:%S 69 + time-alt = " %A, %d %B %Y " 70 + label = %time% 71 + 72 + [module/blt] 73 + type = custom/script 74 + exec = ~/.config/polybar/sblt 75 + format-foreground = ${colors.blue} 76 + click-left = opdrofi 77 + interval = 1 78 + 79 + 80 + [module/pulseaudio] 81 + type = internal/pulseaudio 82 + 83 + ; Sink to be used, if it exists (find using `pacmd list-sinks`, name field) 84 + ; If not, uses default sink 85 + ;sink = alsa_output.pci-0000_12_00.3.analog-stereo 86 + 87 + ; Use PA_VOLUME_UI_MAX (~153%) if true, or PA_VOLUME_NORM (100%) if false 88 + ; Default: true 89 + use-ui-max = false 90 + 91 + ; Interval for volume increase/decrease (in percent points) 92 + ; Default: 5 93 + interval = 5 94 + format-volume = <ramp-volume><label-volume> 95 + format-volume-foreground = ${colors.green} 96 + label-volume = %percentage%% 97 + label-volume-padding = 1 98 + 99 + format-muted-foreground = ${colors.red} 100 + format-muted-prefix = ﱝ 101 + format-muted-prefix-padding = 1 102 + label-muted = Muted 103 + label-muted-padding = ${self.label-volume-padding} 104 + 105 + ramp-volume-0 = 奄 106 + ramp-volume-1 = 奄 107 + ramp-volume-2 = 奔 108 + ramp-volume-3 = 奔 109 + ramp-volume-4 = 墳 110 + ramp-volume-5 = 墳 111 + ramp-volume-6 = 墳 112 + ramp-volume-padding = 1 113 + 114 + 115 + [module/filesystem] 116 + type = internal/fs 117 + interval = 25 118 + 119 + mount-0 = / 120 + 121 + ;format-mounted-foreground = ${colors.foreground-alt} 122 + format-mounted-prefix =  123 + format-mounted-prefix-padding = 1 124 + label-mounted = %free% 125 + label-mounted-padding = 1 126 + 127 + format-unmounted-prefix = 128 + label-unmounted = %mountpoint%: not mounted 129 + label-unmounted-padding = ${self.label-mounted-padding} 130 + 131 + 132 + [module/xkeyboard] 133 + type = internal/xkeyboard 134 + 135 + blacklist-0 = num lock 136 + blacklist-1 = scroll lock 137 + 138 + ;format-foreground = ${colors.foreground-alt} 139 + format-prefix =  140 + format-prefix-padding = 1 141 + label-layout = %layout% 142 + label-layout-padding = 1 143 + 144 + label-indicator-foreground = ${colors.alert} 145 + label-indicator-padding = 1 146 + 147 + [module/disk] 148 + type = custom/script 149 + exec = ~/.config/polybar/scripts/diskusage 150 + format-foreground = ${colors.blue} 151 + interval = 5 152 + click-left = $HOME/.config/st/st -e gdu 153 + 154 + [module/memory] 155 + type = custom/script 156 + exec = ~/.config/polybar/scripts/memory 157 + format-foreground = ${colors.magenta} 158 + interval = 1 159 + click-left = $HOME/.config/st/st -e htop 160 + 161 + 162 + [module/network] 163 + type = custom/script 164 + exec = ~/.config/polybar/scripts/network 165 + format-foreground = ${colors.yellow} 166 + click-left = wifirofi 167 + interval = 1 168 + 169 + [module/battery] 170 + type = internal/battery 171 + 172 + full-at = 99 173 + battery = BAT0 174 + adapter = AC 175 + 176 + poll-interval = 2 177 + time-format = %H:%M 178 + 179 + 180 + format-charging = <animation-charging><label-charging> 181 + format-charging-foreground = ${colors.cyan} 182 + label-charging = %percentage%% 183 + label-charging-padding = 1 184 + 185 + animation-charging-0 =  186 + animation-charging-1 =  187 + animation-charging-2 =  188 + animation-charging-3 =  189 + animation-charging-4 =  190 + animation-charging-5 =  191 + animation-charging-6 =  192 + animation-charging-padding = 1 193 + animation-charging-framerate = 750 194 + 195 + 196 + format-discharging = <ramp-capacity><label-discharging> 197 + format-discharging-foreground = ${self.format-charging-foreground} 198 + label-discharging = ${self.label-charging} 199 + label-discharging-padding = ${self.label-charging-padding} 200 + 201 + ramp-capacity-0 =  202 + ramp-capacity-1 =  203 + ramp-capacity-2 =  204 + ramp-capacity-3 =  205 + ramp-capacity-4 =  206 + ramp-capacity-5 =  207 + ramp-capacity-6 =  208 + ramp-capacity-7 =  209 + ramp-capacity-8 =  210 + ramp-capacity-9 =  211 + ramp-capacity-padding = 1 212 + 213 + format-full = <label-full> 214 + format-full-foreground = ${self.format-charging-foreground} 215 + format-full-prefix =  216 + format-full-prefix-padding = 1 217 + label-full = ${self.label-charging} 218 + label-full-padding = ${self.label-charging-padding}
+12
cfg/polybar/scripts/diskusage
··· 1 + #!/bin/sh 2 + 3 + # Status bar module for disk space 4 + # $1 should be drive mountpoint, otherwise assumed /. 5 + 6 + location=/ 7 + 8 + [ -d "$location" ] || exit 9 + 10 + icon=" " 11 + echo "$icon $(df -h "$location" | awk ' /[0-9]/ {print $3}')" 12 +
+4
cfg/polybar/scripts/memory
··· 1 + #!/bin/sh 2 + 3 + free --mebi | sed -n '2{p;q}' | awk '{printf (" %2.2fGB \n", ( $3 / 1024))}' 4 +
+10
cfg/polybar/scripts/network
··· 1 + #!/bin/sh 2 + 3 + 4 + if grep -xq 'up' /sys/class/net/w*/operstate 2>/dev/null ; then 5 + wifiicon="$(awk '/^\s*w/ { print " 說", int($3 * 100 / 70)"%"}' /proc/net/wireless)" 6 + elif grep -xq 'down' /sys/class/net/w*/operstate 2>/dev/null ; then 7 + grep -xq '0x1003' /sys/class/net/w*/flags && wifiicon="" || wifiicon= "ﲁ" 8 + fi 9 + 10 + echo "$wifiicon"
+122
cfg/rofi/powermenu.rasi
··· 1 + /******************************************************* 2 + * ROFI configs i3 powermenu for EndeavourOS 3 + * Maintainer: joekamprad <joekamprad@endeavouros.com> 4 + *******************************************************/ 5 + 6 + configuration { 7 + font: "Sourcecode Pro Regular 10"; 8 + show-icons: false; 9 + icon-theme: "Arc-X-D"; 10 + scroll-method: 0; 11 + disable-history: false; 12 + sidebar-mode: false; 13 + } 14 + 15 + @theme "catppuccin" 16 + 17 + window { 18 + background-color: @background; 19 + border: 0; 20 + padding: 10; 21 + transparency: "real"; 22 + width: 180px; 23 + location: northwest; 24 + y-offset: 30; 25 + /*x-offset: 850;*/ 26 + transparency: "real"; 27 + } 28 + listview { 29 + lines: 6; 30 + columns: 1; 31 + scrollbar: false; 32 + } 33 + element { 34 + border: 0; 35 + padding: 1px ; 36 + } 37 + element-text { 38 + background-color: inherit; 39 + text-color: inherit; 40 + } 41 + element.normal.normal { 42 + background-color: @normal-background; 43 + text-color: @normal-foreground; 44 + } 45 + element.normal.urgent { 46 + background-color: @urgent-background; 47 + text-color: @urgent-foreground; 48 + } 49 + element.normal.active { 50 + background-color: @active-background; 51 + text-color: @active-foreground; 52 + } 53 + element.selected.normal { 54 + background-color: @selected-normal-background; 55 + text-color: @selected-normal-foreground; 56 + } 57 + element.selected.urgent { 58 + background-color: @selected-urgent-background; 59 + text-color: @selected-urgent-foreground; 60 + } 61 + element.selected.active { 62 + background-color: @selected-active-background; 63 + text-color: @selected-active-foreground; 64 + } 65 + element.alternate.normal { 66 + background-color: @alternate-normal-background; 67 + text-color: @alternate-normal-foreground; 68 + } 69 + element.alternate.urgent { 70 + background-color: @alternate-urgent-background; 71 + text-color: @alternate-urgent-foreground; 72 + } 73 + element.alternate.active { 74 + background-color: @alternate-active-background; 75 + text-color: @alternate-active-foreground; 76 + } 77 + scrollbar { 78 + width: 4px ; 79 + border: 0; 80 + handle-color: @normal-foreground; 81 + handle-width: 8px ; 82 + padding: 0; 83 + } 84 + mode-switcher { 85 + border: 2px 0px 0px ; 86 + border-color: @separatorcolor; 87 + } 88 + button { 89 + spacing: 0; 90 + text-color: @normal-foreground; 91 + } 92 + button.selected { 93 + background-color: @selected-normal-background; 94 + text-color: @selected-normal-foreground; 95 + } 96 + inputbar { 97 + spacing: 0; 98 + text-color: @normal-foreground; 99 + padding: 1px ; 100 + } 101 + case-indicator { 102 + spacing: 0; 103 + text-color: @normal-foreground; 104 + } 105 + entry { 106 + spacing: 0; 107 + text-color: @normal-foreground; 108 + } 109 + prompt { 110 + spacing: 0; 111 + text-color: @normal-foreground; 112 + } 113 + inputbar { 114 + children: [ prompt,textbox-prompt-colon,entry,case-indicator ]; 115 + } 116 + textbox-prompt-colon { 117 + expand: false; 118 + str: ":"; 119 + margin: 0px 0.3em 0em 0em ; 120 + text-color: @normal-foreground; 121 + } 122 +
+45
cfg/rofi/powermenu.sh
··· 1 + #!/bin/env bash 2 + 3 + # Options for powermenu 4 + lock="......Lock" 5 + logout=".....Logout" 6 + shutdown="....Shutdown" 7 + reboot="....Reboot" 8 + sleep="....Sleep" 9 + 10 + # Get answer from user via rofi 11 + selected_option=$(echo "$lock 12 + $logout 13 + $sleep 14 + $reboot 15 + $shutdown" | rofi -dmenu\ 16 + -i\ 17 + -p "Power"\ 18 + -config "~/.config/rofi/powermenu.rasi"\ 19 + -font "Symbols Nerd Font 12"\ 20 + -width "15"\ 21 + -lines 5\ 22 + -line-margin 3\ 23 + -line-padding 10\ 24 + -scrollbar-width "0" ) 25 + 26 + # Do something based on selected option 27 + if [ "$selected_option" == "$lock" ] 28 + then 29 + /home/$USER/.config/bspwm/scripts/i3lock-fancy/i3lock-fancy.sh 30 + elif [ "$selected_option" == "$logout" ] 31 + then 32 + bspc quit 33 + elif [ "$selected_option" == "$shutdown" ] 34 + then 35 + systemctl poweroff 36 + elif [ "$selected_option" == "$reboot" ] 37 + then 38 + systemctl reboot 39 + elif [ "$selected_option" == "$sleep" ] 40 + then 41 + amixer set Master mute 42 + systemctl suspend 43 + else 44 + echo "No match" 45 + fi
+19
cfg/rofi/wifi
··· 1 + # Config for rofi-wifi-menu 2 + 3 + # position values: 4 + # 1 2 3 5 + # 8 0 4 6 + # 7 6 5 7 + POSITION=3 8 + 9 + #y-offset 10 + YOFF=17 11 + 12 + #x-offset 13 + XOFF=0 14 + 15 + #fields to be displayed 16 + FIELDS=SSID,SECURITY,BARS 17 + 18 + #font 19 + FONT="DejaVu Sans Mono 8"
+3
cfg/st/.gitignore
··· 1 + config.h 2 + st 3 + *.o
+18
cfg/st/.vscode/c_cpp_properties.json
··· 1 + { 2 + "configurations": [ 3 + { 4 + "name": "linux-gcc-x64", 5 + "includePath": [ 6 + "${workspaceFolder}/**" 7 + ], 8 + "compilerPath": "/usr/bin/gcc", 9 + "cStandard": "${default}", 10 + "cppStandard": "${default}", 11 + "intelliSenseMode": "linux-gcc-x64", 12 + "compilerArgs": [ 13 + "" 14 + ] 15 + } 16 + ], 17 + "version": 4 18 + }
+1
cfg/st/.vscode/configurationCache.log
··· 1 + {"buildTargets":["all","boxdraw.o","clean","config.h","dist","hb.o","install","options","st","st.o","uninstall","x.o"],"launchTargets":[],"customConfigurationProvider":{"workspaceBrowse":{"browsePath":[],"compilerArgs":[]},"fileIndex":[]}}
+14
cfg/st/.vscode/dryrun.log
··· 1 + make --dry-run --always-make --keep-going --print-directory 2 + make: Entering directory '/opt/st' 3 + echo st build options: 4 + echo "CFLAGS = -I/usr/X11R6/include `pkg-config --cflags fontconfig` `pkg-config --cflags freetype2` `pkg-config --cflags harfbuzz` -DVERSION=\"0.8.4\" -D_XOPEN_SOURCE=600 -O1" 5 + echo "LDFLAGS = -L/usr/X11R6/lib -lm -lrt -lX11 -lutil -lXft `pkg-config --libs fontconfig` `pkg-config --libs freetype2` `pkg-config --libs harfbuzz` " 6 + echo "CC = c99" 7 + cp config.def.h config.h 8 + c99 -I/usr/X11R6/include `pkg-config --cflags fontconfig` `pkg-config --cflags freetype2` `pkg-config --cflags harfbuzz` -DVERSION=\"0.8.4\" -D_XOPEN_SOURCE=600 -O1 -c st.c 9 + c99 -I/usr/X11R6/include `pkg-config --cflags fontconfig` `pkg-config --cflags freetype2` `pkg-config --cflags harfbuzz` -DVERSION=\"0.8.4\" -D_XOPEN_SOURCE=600 -O1 -c x.c 10 + c99 -I/usr/X11R6/include `pkg-config --cflags fontconfig` `pkg-config --cflags freetype2` `pkg-config --cflags harfbuzz` -DVERSION=\"0.8.4\" -D_XOPEN_SOURCE=600 -O1 -c boxdraw.c 11 + c99 -I/usr/X11R6/include `pkg-config --cflags fontconfig` `pkg-config --cflags freetype2` `pkg-config --cflags harfbuzz` -DVERSION=\"0.8.4\" -D_XOPEN_SOURCE=600 -O1 -c hb.c 12 + c99 -o st st.o x.o boxdraw.o hb.o -L/usr/X11R6/lib -lm -lrt -lX11 -lutil -lXft `pkg-config --libs fontconfig` `pkg-config --libs freetype2` `pkg-config --libs harfbuzz` 13 + make: Leaving directory '/opt/st' 14 +
+24
cfg/st/.vscode/launch.json
··· 1 + { 2 + "version": "0.2.0", 3 + "configurations": [ 4 + { 5 + "name": "C/C++ Runner: Debug Session", 6 + "type": "cppdbg", 7 + "request": "launch", 8 + "args": [], 9 + "stopAtEntry": false, 10 + "externalConsole": false, 11 + "cwd": "/opt/st", 12 + "program": "/opt/st/build/Debug/outDebug", 13 + "MIMode": "gdb", 14 + "miDebuggerPath": "gdb", 15 + "setupCommands": [ 16 + { 17 + "description": "Enable pretty-printing for gdb", 18 + "text": "-enable-pretty-printing", 19 + "ignoreFailures": true 20 + } 21 + ] 22 + } 23 + ] 24 + }
+32
cfg/st/.vscode/settings.json
··· 1 + { 2 + "C_Cpp_Runner.cCompilerPath": "gcc", 3 + "C_Cpp_Runner.cppCompilerPath": "g++", 4 + "C_Cpp_Runner.debuggerPath": "gdb", 5 + "C_Cpp_Runner.cStandard": "", 6 + "C_Cpp_Runner.cppStandard": "", 7 + "C_Cpp_Runner.msvcBatchPath": "", 8 + "C_Cpp_Runner.useMsvc": false, 9 + "C_Cpp_Runner.warnings": [ 10 + "-Wall", 11 + "-Wextra", 12 + "-Wpedantic" 13 + ], 14 + "C_Cpp_Runner.enableWarnings": true, 15 + "C_Cpp_Runner.warningsAsError": false, 16 + "C_Cpp_Runner.compilerArgs": [], 17 + "C_Cpp_Runner.linkerArgs": [], 18 + "C_Cpp_Runner.includePaths": [], 19 + "C_Cpp_Runner.includeSearch": [ 20 + "*", 21 + "**/*" 22 + ], 23 + "C_Cpp_Runner.excludeSearch": [ 24 + "**/build", 25 + "**/build/**", 26 + "**/.*", 27 + "**/.*/**", 28 + "**/.vscode", 29 + "**/.vscode/**" 30 + ], 31 + "C_Cpp.errorSquiggles": "Disabled" 32 + }
+500
cfg/st/.vscode/targets.log
··· 1 + make all --print-data-base --no-builtin-variables --no-builtin-rules --question 2 + # GNU Make 4.3 3 + # Built for x86_64-pc-linux-gnu 4 + # Copyright (C) 1988-2020 Free Software Foundation, Inc. 5 + # License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> 6 + # This is free software: you are free to change and redistribute it. 7 + # There is NO WARRANTY, to the extent permitted by law. 8 + 9 + # Make data base, printed on Wed May 25 20:53:33 2022 10 + 11 + # Variables 12 + 13 + # makefile (from 'Makefile', line 8) 14 + OBJ = $(SRC:.c=.o) 15 + # environment 16 + GDK_BACKEND = x11 17 + # default 18 + ARFLAGS := -rv 19 + # environment 20 + LC_ALL = C 21 + # environment 22 + NO_AT_BRIDGE = 1 23 + # makefile (from 'Makefile', line 7) 24 + SRC = st.c x.c boxdraw.c hb.c 25 + # environment 26 + STARSHIP_SESSION_KEY = 2127510294310793 27 + # default 28 + FFLAGS := -O1 29 + # environment 30 + VSCODE_IPC_HOOK_EXTHOST = /run/user/1000/vscode-ipc-4e4ad11c-0669-4a68-873e-63f3de9d5915.sock 31 + 32 + # environment 33 + LC_NAME = de_DE.UTF-8 34 + # environment 35 + LC_NUMERIC = de_DE.UTF-8 36 + # environment 37 + VSCODE_CWD = /opt/st 38 + # environment 39 + WINDOWID = 23068678 40 + # makefile (from 'config.mk', line 20) 41 + LIBS = -L$(X11LIB) -lm -lrt -lX11 -lutil -lXft `$(PKG_CONFIG) --libs fontconfig` `$(PKG_CONFIG) --libs freetype2` `$(PKG_CONFIG) --libs harfbuzz` 42 + # environment 43 + UBUNTU_MENUPROXY = 1 44 + # environment 45 + LC_ADDRESS = de_DE.UTF-8 46 + # default 47 + MAKE_COMMAND := make 48 + # environment 49 + GTK3_MODULES = xapp-gtk3-module 50 + # automatic 51 + @D = $(patsubst %/,%,$(dir $@)) 52 + # makefile (from 'config.mk', line 27) 53 + STCFLAGS = $(INCS) $(STCPPFLAGS) $(CPPFLAGS) $(CFLAGS) 54 + # environment 55 + VSCODE_HANDLES_UNCAUGHT_ERRORS = true 56 + # default 57 + .VARIABLES := 58 + # environment 59 + PWD = /opt/st 60 + # automatic 61 + %D = $(patsubst %/,%,$(dir $%)) 62 + # environment 63 + MAIL = /var/spool/mail/radsteve 64 + # makefile (from 'config.mk', line 13) 65 + PKG_CONFIG = pkg-config 66 + # environment 67 + ENABLE_FLUTTER_DESKTOP = true 68 + # environment 69 + OLDPWD = /home/radsteve 70 + # automatic 71 + ^D = $(patsubst %/,%,$(dir $^)) 72 + # environment 73 + VSCODE_LOG_STACK = false 74 + # automatic 75 + %F = $(notdir $%) 76 + # environment 77 + VSCODE_CODE_CACHE_PATH = /home/radsteve/.config/Code/CachedData/c3511e6c69bb39013c4a4b7b9566ec1ca73fc4d5 78 + # environment 79 + XDG_SESSION_PATH = /org/freedesktop/DisplayManager/Session1 80 + # environment 81 + LANG = C 82 + # environment 83 + XAUTHORITY = /home/radsteve/.Xauthority 84 + # default 85 + .LOADED := 86 + # default 87 + .INCLUDE_DIRS = /usr/include /usr/local/include /usr/include 88 + # makefile 89 + MAKEFLAGS = pqrR 90 + # makefile 91 + CURDIR := /opt/st 92 + # environment 93 + VSCODE_PIPE_LOGGING = true 94 + # environment 95 + APPLICATION_INSIGHTS_NO_DIAGNOSTIC_CHANNEL = true 96 + # automatic 97 + *D = $(patsubst %/,%,$(dir $*)) 98 + # makefile (from 'config.mk', line 2) 99 + VERSION = 0.8.4 100 + # environment 101 + MFLAGS = -pqrR 102 + # default 103 + .SHELLFLAGS := -ec 104 + # automatic 105 + +D = $(patsubst %/,%,$(dir $+)) 106 + # environment 107 + XDG_SESSION_DESKTOP = 108 + # makefile (from 'config.mk', line 1) 109 + MAKEFILE_LIST := Makefile config.mk 110 + # automatic 111 + @F = $(notdir $@) 112 + # environment 113 + VSCODE_VERBOSE_LOGGING = true 114 + # environment 115 + VSCODE_PID = 3448 116 + # environment 117 + XDG_SESSION_TYPE = x11 118 + # automatic 119 + ?D = $(patsubst %/,%,$(dir $?)) 120 + # automatic 121 + *F = $(notdir $*) 122 + # environment 123 + QT_QPA_PLATFORMTHEME = qt5ct 124 + # environment 125 + CHROME_DESKTOP = code-url-handler.desktop 126 + # environment 127 + DBUS_SESSION_BUS_ADDRESS = unix:path=/run/user/1000/bus 128 + # automatic 129 + <D = $(patsubst %/,%,$(dir $<)) 130 + # environment 131 + VSCODE_NLS_CONFIG = {"locale":"en-us","availableLanguages":{},"_languagePackSupport":true} 132 + # environment 133 + ANDROID_SDK_ROOT = /opt/android-sdk 134 + # default 135 + MAKE_HOST := x86_64-pc-linux-gnu 136 + # environment 137 + ANDROID_HOME = /opt/android-sdk 138 + # makefile 139 + SHELL = /bin/sh 140 + # default 141 + MAKECMDGOALS := all 142 + # environment 143 + DOTNET_BUNDLE_EXTRACT_BASE_DIR = /home/radsteve/.cache/dotnet_bundle_extract 144 + # environment 145 + SHLVL = 3 146 + # environment 147 + MAKELEVEL := 0 148 + # default 149 + MAKE = $(MAKE_COMMAND) 150 + # default 151 + FC := fort77 152 + # environment 153 + PATH = /opt/st:/opt/spicetify-cli:/opt/shell-color-scripts/colorscripts:/home/radsteve/.local/bin:/home/radsteve/.yarn/bin:/home/radsteve/.flutter/bin:/home/radsteve/.cargo/bin:/usr/local/sbin:/usr/local/bin:/usr/bin:/opt/android-sdk/tools:/opt/android-sdk/tools/bin:/home/radsteve/.dotnet/tools:/usr/lib/jvm/default/bin:/usr/bin/site_perl:/usr/bin/vendor_perl:/usr/bin/core_perl 154 + # default 155 + MAKEFILES := 156 + # environment 157 + LC_MONETARY = de_DE.UTF-8 158 + # environment 159 + MOTD_SHOWN = pam 160 + # automatic 161 + ^F = $(notdir $^) 162 + # environment 163 + LC_TIME = de_DE.UTF-8 164 + # makefile (from 'config.mk', line 7) 165 + PREFIX = /usr/local 166 + # makefile (from 'config.mk', line 16) 167 + INCS = -I$(X11INC) `$(PKG_CONFIG) --cflags fontconfig` `$(PKG_CONFIG) --cflags freetype2` `$(PKG_CONFIG) --cflags harfbuzz` 168 + # environment 169 + VSCODE_LOG_NATIVE = false 170 + # environment 171 + LC_TELEPHONE = de_DE.UTF-8 172 + # automatic 173 + ?F = $(notdir $?) 174 + # environment 175 + XDG_SEAT = seat0 176 + # environment 177 + XDG_CURRENT_DESKTOP = 178 + # automatic 179 + +F = $(notdir $+) 180 + # environment 181 + XDG_SEAT_PATH = /org/freedesktop/DisplayManager/Seat0 182 + # environment 183 + DESKTOP_SESSION = bspwm 184 + # environment 185 + ORIGINAL_XDG_CURRENT_DESKTOP = 186 + # 'override' directive 187 + GNUMAKEFLAGS := 188 + # environment 189 + BROWSER = firefox 190 + # environment 191 + LOGNAME = radsteve 192 + # makefile (from 'config.mk', line 10) 193 + X11INC = /usr/X11R6/include 194 + # environment 195 + XDG_VTNR = 1 196 + # makefile 197 + .DEFAULT_GOAL := all 198 + # environment 199 + EDITOR = nvim 200 + # environment 201 + DISPLAY = :0 202 + # environment 203 + GTK_MODULES = canberra-gtk-module:appmenu-gtk-module 204 + # environment 205 + USER = radsteve 206 + # default 207 + MAKE_VERSION := 4.3 208 + # default 209 + SCCSGETFLAGS := -s 210 + # environment 211 + LC_MEASUREMENT = de_DE.UTF-8 212 + # environment 213 + STARSHIP_SHELL = zsh 214 + # environment 215 + _ = /usr/bin/make 216 + # environment 217 + LC_PAPER = de_DE.UTF-8 218 + # environment 219 + XDG_RUNTIME_DIR = /run/user/1000 220 + # default 221 + CFLAGS := -O1 222 + # makefile (from 'config.mk', line 26) 223 + STCPPFLAGS = -DVERSION=\"$(VERSION)\" -D_XOPEN_SOURCE=600 224 + # environment 225 + XDG_SESSION_CLASS = user 226 + # environment 227 + VSCODE_AMD_ENTRYPOINT = vs/workbench/api/node/extensionHostProcess 228 + # environment 229 + HOME = /home/radsteve 230 + # makefile (from 'config.mk', line 8) 231 + MANPREFIX = $(PREFIX)/share/man 232 + # makefile (from 'config.mk', line 28) 233 + STLDFLAGS = $(LIBS) $(LDFLAGS) 234 + # environment 235 + ELECTRON_RUN_AS_NODE = 1 236 + # environment 237 + VSCODE_IPC_HOOK = /run/user/1000/vscode-5c59308f-1.67.2-main.sock 238 + # environment 239 + TERM = st-256color 240 + # environment 241 + XDG_SESSION_ID = 2 242 + # default 243 + .RECIPEPREFIX := 244 + # automatic 245 + <F = $(notdir $<) 246 + # default 247 + SUFFIXES := 248 + # makefile (from 'config.mk', line 11) 249 + X11LIB = /usr/X11R6/lib 250 + # environment 251 + VSCODE_CLI = 1 252 + # environment 253 + ELECTRON_NO_ATTACH_CONSOLE = 1 254 + # default 255 + .FEATURES := target-specific order-only second-expansion else-if shortest-stem undefine oneshell nocomment grouped-target extra-prereqs archives jobserver output-sync check-symlink guile load 256 + # default 257 + CC := c99 258 + # environment 259 + DOTNET_ROOT = /usr/share/dotnet 260 + # environment 261 + LC_IDENTIFICATION = de_DE.UTF-8 262 + # variable set hash-table stats: 263 + # Load=124/1024=12%, Rehash=0, Collisions=14/182=8% 264 + 265 + # Pattern-specific Variable Values 266 + 267 + # No pattern-specific variable values. 268 + 269 + # Directories 270 + 271 + # . (device 66306, inode 7603967): 36 files, no impossibilities. 272 + 273 + # 36 files, no impossibilities in 1 directories. 274 + 275 + # Implicit Rules 276 + 277 + # No implicit rules. 278 + 279 + # Files 280 + 281 + dist: clean 282 + # Phony target (prerequisite of .PHONY). 283 + # Implicit rule search has not been done. 284 + # File does not exist. 285 + # File has not been updated. 286 + # recipe to execute (from 'Makefile', line 38): 287 + mkdir -p st-$(VERSION) 288 + cp -R FAQ LEGACY TODO LICENSE Makefile README config.mk\ 289 + config.def.h st.info st.1 arg.h st.h win.h $(SRC)\ 290 + st-$(VERSION) 291 + tar -cf - st-$(VERSION) | gzip > st-$(VERSION).tar.gz 292 + rm -rf st-$(VERSION) 293 + 294 + .c.o: 295 + # Implicit rule search has not been done. 296 + # Modification time never checked. 297 + # File has not been updated. 298 + # recipe to execute (from 'Makefile', line 22): 299 + $(CC) $(STCFLAGS) -c $< 300 + 301 + # Not a target: 302 + arg.h: 303 + # Implicit rule search has not been done. 304 + # Modification time never checked. 305 + # File has not been updated. 306 + 307 + hb.o: st.h config.h config.mk 308 + # Implicit rule search has not been done. 309 + # Modification time never checked. 310 + # File has not been updated. 311 + 312 + # Not a target: 313 + st.h: 314 + # Implicit rule search has not been done. 315 + # Modification time never checked. 316 + # File has not been updated. 317 + 318 + # Not a target: 319 + Makefile: 320 + # Implicit rule search has been done. 321 + # Last modified 2022-05-25 15:21:53.330381246 322 + # File has been updated. 323 + # Successfully updated. 324 + 325 + st.o: config.h st.h win.h config.h config.mk 326 + # Implicit rule search has not been done. 327 + # Modification time never checked. 328 + # File has not been updated. 329 + 330 + x.o: arg.h config.h st.h win.h hb.h config.h config.mk 331 + # Implicit rule search has not been done. 332 + # Modification time never checked. 333 + # File has not been updated. 334 + 335 + uninstall: 336 + # Phony target (prerequisite of .PHONY). 337 + # Implicit rule search has not been done. 338 + # File does not exist. 339 + # File has not been updated. 340 + # recipe to execute (from 'Makefile', line 62): 341 + rm -f $(DESTDIR)$(PREFIX)/bin/st 342 + rm -f $(DESTDIR)$(PREFIX)/bin/st-copyout 343 + rm -f $(DESTDIR)$(PREFIX)/bin/st-urlhandler 344 + rm -f $(DESTDIR)$(MANPREFIX)/man1/st.1 345 + rm -f $(DESTDIR)$(PREFIX)/share/applications/st.desktop 346 + 347 + clean: 348 + # Phony target (prerequisite of .PHONY). 349 + # Implicit rule search has not been done. 350 + # File does not exist. 351 + # File has not been updated. 352 + # recipe to execute (from 'Makefile', line 35): 353 + rm -f st $(OBJ) st-$(VERSION).tar.gz *.o *.orig *.rej 354 + 355 + # Not a target: 356 + boxdraw_data.h: 357 + # Implicit rule search has not been done. 358 + # Modification time never checked. 359 + # File has not been updated. 360 + 361 + # Not a target: 362 + hb.h: 363 + # Implicit rule search has not been done. 364 + # Modification time never checked. 365 + # File has not been updated. 366 + 367 + boxdraw.o: config.h st.h boxdraw_data.h config.h config.mk 368 + # Implicit rule search has not been done. 369 + # Modification time never checked. 370 + # File has not been updated. 371 + 372 + # Not a target: 373 + .DEFAULT: 374 + # Implicit rule search has not been done. 375 + # Modification time never checked. 376 + # File has not been updated. 377 + 378 + all: options st 379 + # Phony target (prerequisite of .PHONY). 380 + # Command line target. 381 + # Implicit rule search has not been done. 382 + # File does not exist. 383 + # File has been updated. 384 + # Needs to be updated (-q is set). 385 + # variable set hash-table stats: 386 + # Load=0/32=0%, Rehash=0, Collisions=0/21=0% 387 + 388 + # Not a target: 389 + config.mk: 390 + # Implicit rule search has been done. 391 + # Last modified 2022-05-25 15:21:53.330381246 392 + # File has been updated. 393 + # Successfully updated. 394 + 395 + st: st.o x.o boxdraw.o hb.o 396 + # Implicit rule search has not been done. 397 + # Modification time never checked. 398 + # File has not been updated. 399 + # recipe to execute (from 'Makefile', line 32): 400 + $(CC) -o $@ $(OBJ) $(STLDFLAGS) 401 + 402 + config.h: 403 + # Implicit rule search has not been done. 404 + # Modification time never checked. 405 + # File has not been updated. 406 + # recipe to execute (from 'Makefile', line 19): 407 + cp config.def.h config.h 408 + 409 + .POSIX: 410 + # Implicit rule search has not been done. 411 + # Modification time never checked. 412 + # File has not been updated. 413 + 414 + install: st 415 + 416 + # Phony target (prerequisite of .PHONY). 417 + # Implicit rule search has not been done. 418 + # File does not exist. 419 + # File has not been updated. 420 + # recipe to execute (from 'Makefile', line 46): 421 + mkdir -p $(DESTDIR)$(PREFIX)/bin 422 + cp -f st $(DESTDIR)$(PREFIX)/bin 423 + cp -f st-copyout $(DESTDIR)$(PREFIX)/bin 424 + cp -f st-urlhandler $(DESTDIR)$(PREFIX)/bin 425 + chmod 755 $(DESTDIR)$(PREFIX)/bin/st 426 + chmod 755 $(DESTDIR)$(PREFIX)/bin/st-copyout 427 + chmod 755 $(DESTDIR)$(PREFIX)/bin/st-urlhandler 428 + mkdir -p $(DESTDIR)$(MANPREFIX)/man1 429 + sed "s/VERSION/$(VERSION)/g" < st.1 > $(DESTDIR)$(MANPREFIX)/man1/st.1 430 + chmod 644 $(DESTDIR)$(MANPREFIX)/man1/st.1 431 + tic -sx st.info 432 + @echo Please see the README file regarding the terminfo entry of st. 433 + mkdir -p $(DESTDIR)$(PREFIX)/share/applications 434 + cp -f st.desktop $(DESTDIR)$(PREFIX)/share/applications 435 + 436 + # Not a target: 437 + win.h: 438 + # Implicit rule search has not been done. 439 + # Modification time never checked. 440 + # File has not been updated. 441 + 442 + # Not a target: 443 + .SUFFIXES: 444 + # Implicit rule search has not been done. 445 + # Modification time never checked. 446 + # File has not been updated. 447 + 448 + .PHONY: all options clean dist install uninstall 449 + # Implicit rule search has not been done. 450 + # Modification time never checked. 451 + # File has not been updated. 452 + 453 + options: 454 + # Phony target (prerequisite of .PHONY). 455 + # Implicit rule search has not been done. 456 + # Implicit/static pattern stem: '' 457 + # File does not exist. 458 + # File has been updated. 459 + # Needs to be updated (-q is set). 460 + # automatic 461 + # @ := options 462 + # automatic 463 + # * := 464 + # automatic 465 + # < := 466 + # automatic 467 + # + := 468 + # automatic 469 + # % := 470 + # automatic 471 + # ^ := 472 + # automatic 473 + # ? := 474 + # automatic 475 + # | := 476 + # variable set hash-table stats: 477 + # Load=8/32=25%, Rehash=0, Collisions=14/29=48% 478 + # recipe to execute (from 'Makefile', line 13): 479 + @echo st build options: 480 + @echo "CFLAGS = $(STCFLAGS)" 481 + @echo "LDFLAGS = $(STLDFLAGS)" 482 + @echo "CC = $(CC)" 483 + 484 + # files hash-table stats: 485 + # Load=24/1024=2%, Rehash=0, Collisions=3/71=4% 486 + # VPATH Search Paths 487 + 488 + # No 'vpath' search paths. 489 + 490 + # No general ('VPATH' variable) search path. 491 + 492 + # strcache buffers: 1 (0) / strings = 49 / storage = 411 B / avg = 8 B 493 + # current buf: size = 8162 B / used = 411 B / count = 49 / avg = 8 B 494 + 495 + # strcache performance: lookups = 114 / hit rate = 57% 496 + # hash-table stats: 497 + # Load=49/8192=1%, Rehash=0, Collisions=0/114=0% 498 + # Finished Make data base on Wed May 25 20:53:33 2022 499 + 500 +
+34
cfg/st/LICENSE
··· 1 + MIT/X Consortium License 2 + 3 + © 2014-2018 Hiltjo Posthuma <hiltjo at codemadness dot org> 4 + © 2018 Devin J. Pohly <djpohly at gmail dot com> 5 + © 2014-2017 Quentin Rameau <quinq at fifth dot space> 6 + © 2009-2012 Aurélien APTEL <aurelien dot aptel at gmail dot com> 7 + © 2008-2017 Anselm R Garbe <garbeam at gmail dot com> 8 + © 2012-2017 Roberto E. Vargas Caballero <k0ga at shike2 dot com> 9 + © 2012-2016 Christoph Lohmann <20h at r-36 dot net> 10 + © 2013 Eon S. Jeon <esjeon at hyunmu dot am> 11 + © 2013 Alexander Sedov <alex0player at gmail dot com> 12 + © 2013 Mark Edgar <medgar123 at gmail dot com> 13 + © 2013-2014 Eric Pruitt <eric.pruitt at gmail dot com> 14 + © 2013 Michael Forney <mforney at mforney dot org> 15 + © 2013-2014 Markus Teich <markus dot teich at stusta dot mhn dot de> 16 + © 2014-2015 Laslo Hunhold <dev at frign dot de> 17 + 18 + Permission is hereby granted, free of charge, to any person obtaining a 19 + copy of this software and associated documentation files (the "Software"), 20 + to deal in the Software without restriction, including without limitation 21 + the rights to use, copy, modify, merge, publish, distribute, sublicense, 22 + and/or sell copies of the Software, and to permit persons to whom the 23 + Software is furnished to do so, subject to the following conditions: 24 + 25 + The above copyright notice and this permission notice shall be included in 26 + all copies or substantial portions of the Software. 27 + 28 + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 29 + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 30 + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 31 + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 32 + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 33 + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 34 + DEALINGS IN THE SOFTWARE.
+68
cfg/st/Makefile
··· 1 + # st - simple terminal 2 + # See LICENSE file for copyright and license details. 3 + .POSIX: 4 + 5 + include config.mk 6 + 7 + SRC = st.c x.c boxdraw.c hb.c 8 + OBJ = $(SRC:.c=.o) 9 + 10 + all: options st 11 + 12 + options: 13 + @echo st build options: 14 + @echo "CFLAGS = $(STCFLAGS)" 15 + @echo "LDFLAGS = $(STLDFLAGS)" 16 + @echo "CC = $(CC)" 17 + 18 + config.h: 19 + cp config.def.h config.h 20 + 21 + .c.o: 22 + $(CC) $(STCFLAGS) -c $< 23 + 24 + st.o: config.h st.h win.h 25 + x.o: arg.h config.h st.h win.h hb.h 26 + hb.o: st.h 27 + boxdraw.o: config.h st.h boxdraw_data.h 28 + 29 + $(OBJ): config.h config.mk 30 + 31 + st: $(OBJ) 32 + $(CC) -o $@ $(OBJ) $(STLDFLAGS) 33 + 34 + clean: 35 + rm -f st $(OBJ) st-$(VERSION).tar.gz *.o *.orig *.rej 36 + 37 + dist: clean 38 + mkdir -p st-$(VERSION) 39 + cp -R FAQ LEGACY TODO LICENSE Makefile README config.mk\ 40 + config.def.h st.info st.1 arg.h st.h win.h $(SRC)\ 41 + st-$(VERSION) 42 + tar -cf - st-$(VERSION) | gzip > st-$(VERSION).tar.gz 43 + rm -rf st-$(VERSION) 44 + 45 + install: st 46 + mkdir -p $(DESTDIR)$(PREFIX)/bin 47 + cp -f st $(DESTDIR)$(PREFIX)/bin 48 + cp -f st-copyout $(DESTDIR)$(PREFIX)/bin 49 + cp -f st-urlhandler $(DESTDIR)$(PREFIX)/bin 50 + chmod 755 $(DESTDIR)$(PREFIX)/bin/st 51 + chmod 755 $(DESTDIR)$(PREFIX)/bin/st-copyout 52 + chmod 755 $(DESTDIR)$(PREFIX)/bin/st-urlhandler 53 + mkdir -p $(DESTDIR)$(MANPREFIX)/man1 54 + sed "s/VERSION/$(VERSION)/g" < st.1 > $(DESTDIR)$(MANPREFIX)/man1/st.1 55 + chmod 644 $(DESTDIR)$(MANPREFIX)/man1/st.1 56 + tic -sx st.info 57 + @echo Please see the README file regarding the terminfo entry of st. 58 + mkdir -p $(DESTDIR)$(PREFIX)/share/applications 59 + cp -f st.desktop $(DESTDIR)$(PREFIX)/share/applications 60 + 61 + uninstall: 62 + rm -f $(DESTDIR)$(PREFIX)/bin/st 63 + rm -f $(DESTDIR)$(PREFIX)/bin/st-copyout 64 + rm -f $(DESTDIR)$(PREFIX)/bin/st-urlhandler 65 + rm -f $(DESTDIR)$(MANPREFIX)/man1/st.1 66 + rm -f $(DESTDIR)$(PREFIX)/share/applications/st.desktop 67 + 68 + .PHONY: all options clean dist install uninstall
cfg/st/README.md

This is a binary file and will not be displayed.

cfg/st/arg.h

This is a binary file and will not be displayed.

+194
cfg/st/boxdraw.c
··· 1 + /* 2 + * Copyright 2018 Avi Halachmi (:avih) avihpit@yahoo.com https://github.com/avih 3 + * MIT/X Consortium License 4 + */ 5 + 6 + #include <X11/Xft/Xft.h> 7 + #include "st.h" 8 + #include "boxdraw_data.h" 9 + 10 + /* Rounded non-negative integers division of n / d */ 11 + #define DIV(n, d) (((n) + (d) / 2) / (d)) 12 + 13 + static Display *xdpy; 14 + static Colormap xcmap; 15 + static XftDraw *xd; 16 + static Visual *xvis; 17 + 18 + static void drawbox(int, int, int, int, XftColor *, XftColor *, ushort); 19 + static void drawboxlines(int, int, int, int, XftColor *, ushort); 20 + 21 + /* public API */ 22 + 23 + void 24 + boxdraw_xinit(Display *dpy, Colormap cmap, XftDraw *draw, Visual *vis) 25 + { 26 + xdpy = dpy; xcmap = cmap; xd = draw, xvis = vis; 27 + } 28 + 29 + int 30 + isboxdraw(Rune u) 31 + { 32 + Rune block = u & ~0xff; 33 + return (boxdraw && block == 0x2500 && boxdata[(uint8_t)u]) || 34 + (boxdraw_braille && block == 0x2800); 35 + } 36 + 37 + /* the "index" is actually the entire shape data encoded as ushort */ 38 + ushort 39 + boxdrawindex(const Glyph *g) 40 + { 41 + if (boxdraw_braille && (g->u & ~0xff) == 0x2800) 42 + return BRL | (uint8_t)g->u; 43 + if (boxdraw_bold && (g->mode & ATTR_BOLD)) 44 + return BDB | boxdata[(uint8_t)g->u]; 45 + return boxdata[(uint8_t)g->u]; 46 + } 47 + 48 + void 49 + drawboxes(int x, int y, int cw, int ch, XftColor *fg, XftColor *bg, 50 + const XftGlyphFontSpec *specs, int len) 51 + { 52 + for ( ; len-- > 0; x += cw, specs++) 53 + drawbox(x, y, cw, ch, fg, bg, (ushort)specs->glyph); 54 + } 55 + 56 + /* implementation */ 57 + 58 + void 59 + drawbox(int x, int y, int w, int h, XftColor *fg, XftColor *bg, ushort bd) 60 + { 61 + ushort cat = bd & ~(BDB | 0xff); /* mask out bold and data */ 62 + if (bd & (BDL | BDA)) { 63 + /* lines (light/double/heavy/arcs) */ 64 + drawboxlines(x, y, w, h, fg, bd); 65 + 66 + } else if (cat == BBD) { 67 + /* lower (8-X)/8 block */ 68 + int d = DIV((uint8_t)bd * h, 8); 69 + XftDrawRect(xd, fg, x, y + d, w, h - d); 70 + 71 + } else if (cat == BBU) { 72 + /* upper X/8 block */ 73 + XftDrawRect(xd, fg, x, y, w, DIV((uint8_t)bd * h, 8)); 74 + 75 + } else if (cat == BBL) { 76 + /* left X/8 block */ 77 + XftDrawRect(xd, fg, x, y, DIV((uint8_t)bd * w, 8), h); 78 + 79 + } else if (cat == BBR) { 80 + /* right (8-X)/8 block */ 81 + int d = DIV((uint8_t)bd * w, 8); 82 + XftDrawRect(xd, fg, x + d, y, w - d, h); 83 + 84 + } else if (cat == BBQ) { 85 + /* Quadrants */ 86 + int w2 = DIV(w, 2), h2 = DIV(h, 2); 87 + if (bd & TL) 88 + XftDrawRect(xd, fg, x, y, w2, h2); 89 + if (bd & TR) 90 + XftDrawRect(xd, fg, x + w2, y, w - w2, h2); 91 + if (bd & BL) 92 + XftDrawRect(xd, fg, x, y + h2, w2, h - h2); 93 + if (bd & BR) 94 + XftDrawRect(xd, fg, x + w2, y + h2, w - w2, h - h2); 95 + 96 + } else if (bd & BBS) { 97 + /* Shades - data is 1/2/3 for 25%/50%/75% alpha, respectively */ 98 + int d = (uint8_t)bd; 99 + XftColor xfc; 100 + XRenderColor xrc = { .alpha = 0xffff }; 101 + 102 + xrc.red = DIV(fg->color.red * d + bg->color.red * (4 - d), 4); 103 + xrc.green = DIV(fg->color.green * d + bg->color.green * (4 - d), 4); 104 + xrc.blue = DIV(fg->color.blue * d + bg->color.blue * (4 - d), 4); 105 + 106 + XftColorAllocValue(xdpy, xvis, xcmap, &xrc, &xfc); 107 + XftDrawRect(xd, &xfc, x, y, w, h); 108 + XftColorFree(xdpy, xvis, xcmap, &xfc); 109 + 110 + } else if (cat == BRL) { 111 + /* braille, each data bit corresponds to one dot at 2x4 grid */ 112 + int w1 = DIV(w, 2); 113 + int h1 = DIV(h, 4), h2 = DIV(h, 2), h3 = DIV(3 * h, 4); 114 + 115 + if (bd & 1) XftDrawRect(xd, fg, x, y, w1, h1); 116 + if (bd & 2) XftDrawRect(xd, fg, x, y + h1, w1, h2 - h1); 117 + if (bd & 4) XftDrawRect(xd, fg, x, y + h2, w1, h3 - h2); 118 + if (bd & 8) XftDrawRect(xd, fg, x + w1, y, w - w1, h1); 119 + if (bd & 16) XftDrawRect(xd, fg, x + w1, y + h1, w - w1, h2 - h1); 120 + if (bd & 32) XftDrawRect(xd, fg, x + w1, y + h2, w - w1, h3 - h2); 121 + if (bd & 64) XftDrawRect(xd, fg, x, y + h3, w1, h - h3); 122 + if (bd & 128) XftDrawRect(xd, fg, x + w1, y + h3, w - w1, h - h3); 123 + 124 + } 125 + } 126 + 127 + void 128 + drawboxlines(int x, int y, int w, int h, XftColor *fg, ushort bd) 129 + { 130 + /* s: stem thickness. width/8 roughly matches underscore thickness. */ 131 + /* We draw bold as 1.5 * normal-stem and at least 1px thicker. */ 132 + /* doubles draw at least 3px, even when w or h < 3. bold needs 6px. */ 133 + int mwh = MIN(w, h); 134 + int base_s = MAX(1, DIV(mwh, 8)); 135 + int bold = (bd & BDB) && mwh >= 6; /* possibly ignore boldness */ 136 + int s = bold ? MAX(base_s + 1, DIV(3 * base_s, 2)) : base_s; 137 + int w2 = DIV(w - s, 2), h2 = DIV(h - s, 2); 138 + /* the s-by-s square (x + w2, y + h2, s, s) is the center texel. */ 139 + /* The base length (per direction till edge) includes this square. */ 140 + 141 + int light = bd & (LL | LU | LR | LD); 142 + int double_ = bd & (DL | DU | DR | DD); 143 + 144 + if (light) { 145 + /* d: additional (negative) length to not-draw the center */ 146 + /* texel - at arcs and avoid drawing inside (some) doubles */ 147 + int arc = bd & BDA; 148 + int multi_light = light & (light - 1); 149 + int multi_double = double_ & (double_ - 1); 150 + /* light crosses double only at DH+LV, DV+LH (ref. shapes) */ 151 + int d = arc || (multi_double && !multi_light) ? -s : 0; 152 + 153 + if (bd & LL) 154 + XftDrawRect(xd, fg, x, y + h2, w2 + s + d, s); 155 + if (bd & LU) 156 + XftDrawRect(xd, fg, x + w2, y, s, h2 + s + d); 157 + if (bd & LR) 158 + XftDrawRect(xd, fg, x + w2 - d, y + h2, w - w2 + d, s); 159 + if (bd & LD) 160 + XftDrawRect(xd, fg, x + w2, y + h2 - d, s, h - h2 + d); 161 + } 162 + 163 + /* double lines - also align with light to form heavy when combined */ 164 + if (double_) { 165 + /* 166 + * going clockwise, for each double-ray: p is additional length 167 + * to the single-ray nearer to the previous direction, and n to 168 + * the next. p and n adjust from the base length to lengths 169 + * which consider other doubles - shorter to avoid intersections 170 + * (p, n), or longer to draw the far-corner texel (n). 171 + */ 172 + int dl = bd & DL, du = bd & DU, dr = bd & DR, dd = bd & DD; 173 + if (dl) { 174 + int p = dd ? -s : 0, n = du ? -s : dd ? s : 0; 175 + XftDrawRect(xd, fg, x, y + h2 + s, w2 + s + p, s); 176 + XftDrawRect(xd, fg, x, y + h2 - s, w2 + s + n, s); 177 + } 178 + if (du) { 179 + int p = dl ? -s : 0, n = dr ? -s : dl ? s : 0; 180 + XftDrawRect(xd, fg, x + w2 - s, y, s, h2 + s + p); 181 + XftDrawRect(xd, fg, x + w2 + s, y, s, h2 + s + n); 182 + } 183 + if (dr) { 184 + int p = du ? -s : 0, n = dd ? -s : du ? s : 0; 185 + XftDrawRect(xd, fg, x + w2 - p, y + h2 - s, w - w2 + p, s); 186 + XftDrawRect(xd, fg, x + w2 - n, y + h2 + s, w - w2 + n, s); 187 + } 188 + if (dd) { 189 + int p = dr ? -s : 0, n = dl ? -s : dr ? s : 0; 190 + XftDrawRect(xd, fg, x + w2 + s, y + h2 - p, s, h - h2 + p); 191 + XftDrawRect(xd, fg, x + w2 - s, y + h2 - n, s, h - h2 + n); 192 + } 193 + } 194 + }
+214
cfg/st/boxdraw_data.h
··· 1 + /* 2 + * Copyright 2018 Avi Halachmi (:avih) avihpit@yahoo.com https://github.com/avih 3 + * MIT/X Consortium License 4 + */ 5 + 6 + /* 7 + * U+25XX codepoints data 8 + * 9 + * References: 10 + * http://www.unicode.org/charts/PDF/U2500.pdf 11 + * http://www.unicode.org/charts/PDF/U2580.pdf 12 + * 13 + * Test page: 14 + * https://github.com/GNOME/vte/blob/master/doc/boxes.txt 15 + */ 16 + 17 + /* Each shape is encoded as 16-bits. Higher bits are category, lower are data */ 18 + /* Categories (mutually exclusive except BDB): */ 19 + /* For convenience, BDL/BDA/BBS/BDB are 1 bit each, the rest are enums */ 20 + #define BDL (1<<8) /* Box Draw Lines (light/double/heavy) */ 21 + #define BDA (1<<9) /* Box Draw Arc (light) */ 22 + 23 + #define BBD (1<<10) /* Box Block Down (lower) X/8 */ 24 + #define BBL (2<<10) /* Box Block Left X/8 */ 25 + #define BBU (3<<10) /* Box Block Upper X/8 */ 26 + #define BBR (4<<10) /* Box Block Right X/8 */ 27 + #define BBQ (5<<10) /* Box Block Quadrants */ 28 + #define BRL (6<<10) /* Box Braille (data is lower byte of U28XX) */ 29 + 30 + #define BBS (1<<14) /* Box Block Shades */ 31 + #define BDB (1<<15) /* Box Draw is Bold */ 32 + 33 + /* (BDL/BDA) Light/Double/Heavy x Left/Up/Right/Down/Horizontal/Vertical */ 34 + /* Heavy is light+double (literally drawing light+double align to form heavy) */ 35 + #define LL (1<<0) 36 + #define LU (1<<1) 37 + #define LR (1<<2) 38 + #define LD (1<<3) 39 + #define LH (LL+LR) 40 + #define LV (LU+LD) 41 + 42 + #define DL (1<<4) 43 + #define DU (1<<5) 44 + #define DR (1<<6) 45 + #define DD (1<<7) 46 + #define DH (DL+DR) 47 + #define DV (DU+DD) 48 + 49 + #define HL (LL+DL) 50 + #define HU (LU+DU) 51 + #define HR (LR+DR) 52 + #define HD (LD+DD) 53 + #define HH (HL+HR) 54 + #define HV (HU+HD) 55 + 56 + /* (BBQ) Quadrants Top/Bottom x Left/Right */ 57 + #define TL (1<<0) 58 + #define TR (1<<1) 59 + #define BL (1<<2) 60 + #define BR (1<<3) 61 + 62 + /* Data for U+2500 - U+259F except dashes/diagonals */ 63 + static const unsigned short boxdata[256] = { 64 + /* light lines */ 65 + [0x00] = BDL + LH, /* light horizontal */ 66 + [0x02] = BDL + LV, /* light vertical */ 67 + [0x0c] = BDL + LD + LR, /* light down and right */ 68 + [0x10] = BDL + LD + LL, /* light down and left */ 69 + [0x14] = BDL + LU + LR, /* light up and right */ 70 + [0x18] = BDL + LU + LL, /* light up and left */ 71 + [0x1c] = BDL + LV + LR, /* light vertical and right */ 72 + [0x24] = BDL + LV + LL, /* light vertical and left */ 73 + [0x2c] = BDL + LH + LD, /* light horizontal and down */ 74 + [0x34] = BDL + LH + LU, /* light horizontal and up */ 75 + [0x3c] = BDL + LV + LH, /* light vertical and horizontal */ 76 + [0x74] = BDL + LL, /* light left */ 77 + [0x75] = BDL + LU, /* light up */ 78 + [0x76] = BDL + LR, /* light right */ 79 + [0x77] = BDL + LD, /* light down */ 80 + 81 + /* heavy [+light] lines */ 82 + [0x01] = BDL + HH, 83 + [0x03] = BDL + HV, 84 + [0x0d] = BDL + HR + LD, 85 + [0x0e] = BDL + HD + LR, 86 + [0x0f] = BDL + HD + HR, 87 + [0x11] = BDL + HL + LD, 88 + [0x12] = BDL + HD + LL, 89 + [0x13] = BDL + HD + HL, 90 + [0x15] = BDL + HR + LU, 91 + [0x16] = BDL + HU + LR, 92 + [0x17] = BDL + HU + HR, 93 + [0x19] = BDL + HL + LU, 94 + [0x1a] = BDL + HU + LL, 95 + [0x1b] = BDL + HU + HL, 96 + [0x1d] = BDL + HR + LV, 97 + [0x1e] = BDL + HU + LD + LR, 98 + [0x1f] = BDL + HD + LR + LU, 99 + [0x20] = BDL + HV + LR, 100 + [0x21] = BDL + HU + HR + LD, 101 + [0x22] = BDL + HD + HR + LU, 102 + [0x23] = BDL + HV + HR, 103 + [0x25] = BDL + HL + LV, 104 + [0x26] = BDL + HU + LD + LL, 105 + [0x27] = BDL + HD + LU + LL, 106 + [0x28] = BDL + HV + LL, 107 + [0x29] = BDL + HU + HL + LD, 108 + [0x2a] = BDL + HD + HL + LU, 109 + [0x2b] = BDL + HV + HL, 110 + [0x2d] = BDL + HL + LD + LR, 111 + [0x2e] = BDL + HR + LL + LD, 112 + [0x2f] = BDL + HH + LD, 113 + [0x30] = BDL + HD + LH, 114 + [0x31] = BDL + HD + HL + LR, 115 + [0x32] = BDL + HR + HD + LL, 116 + [0x33] = BDL + HH + HD, 117 + [0x35] = BDL + HL + LU + LR, 118 + [0x36] = BDL + HR + LU + LL, 119 + [0x37] = BDL + HH + LU, 120 + [0x38] = BDL + HU + LH, 121 + [0x39] = BDL + HU + HL + LR, 122 + [0x3a] = BDL + HU + HR + LL, 123 + [0x3b] = BDL + HH + HU, 124 + [0x3d] = BDL + HL + LV + LR, 125 + [0x3e] = BDL + HR + LV + LL, 126 + [0x3f] = BDL + HH + LV, 127 + [0x40] = BDL + HU + LH + LD, 128 + [0x41] = BDL + HD + LH + LU, 129 + [0x42] = BDL + HV + LH, 130 + [0x43] = BDL + HU + HL + LD + LR, 131 + [0x44] = BDL + HU + HR + LD + LL, 132 + [0x45] = BDL + HD + HL + LU + LR, 133 + [0x46] = BDL + HD + HR + LU + LL, 134 + [0x47] = BDL + HH + HU + LD, 135 + [0x48] = BDL + HH + HD + LU, 136 + [0x49] = BDL + HV + HL + LR, 137 + [0x4a] = BDL + HV + HR + LL, 138 + [0x4b] = BDL + HV + HH, 139 + [0x78] = BDL + HL, 140 + [0x79] = BDL + HU, 141 + [0x7a] = BDL + HR, 142 + [0x7b] = BDL + HD, 143 + [0x7c] = BDL + HR + LL, 144 + [0x7d] = BDL + HD + LU, 145 + [0x7e] = BDL + HL + LR, 146 + [0x7f] = BDL + HU + LD, 147 + 148 + /* double [+light] lines */ 149 + [0x50] = BDL + DH, 150 + [0x51] = BDL + DV, 151 + [0x52] = BDL + DR + LD, 152 + [0x53] = BDL + DD + LR, 153 + [0x54] = BDL + DR + DD, 154 + [0x55] = BDL + DL + LD, 155 + [0x56] = BDL + DD + LL, 156 + [0x57] = BDL + DL + DD, 157 + [0x58] = BDL + DR + LU, 158 + [0x59] = BDL + DU + LR, 159 + [0x5a] = BDL + DU + DR, 160 + [0x5b] = BDL + DL + LU, 161 + [0x5c] = BDL + DU + LL, 162 + [0x5d] = BDL + DL + DU, 163 + [0x5e] = BDL + DR + LV, 164 + [0x5f] = BDL + DV + LR, 165 + [0x60] = BDL + DV + DR, 166 + [0x61] = BDL + DL + LV, 167 + [0x62] = BDL + DV + LL, 168 + [0x63] = BDL + DV + DL, 169 + [0x64] = BDL + DH + LD, 170 + [0x65] = BDL + DD + LH, 171 + [0x66] = BDL + DD + DH, 172 + [0x67] = BDL + DH + LU, 173 + [0x68] = BDL + DU + LH, 174 + [0x69] = BDL + DH + DU, 175 + [0x6a] = BDL + DH + LV, 176 + [0x6b] = BDL + DV + LH, 177 + [0x6c] = BDL + DH + DV, 178 + 179 + /* (light) arcs */ 180 + [0x6d] = BDA + LD + LR, 181 + [0x6e] = BDA + LD + LL, 182 + [0x6f] = BDA + LU + LL, 183 + [0x70] = BDA + LU + LR, 184 + 185 + /* Lower (Down) X/8 block (data is 8 - X) */ 186 + [0x81] = BBD + 7, [0x82] = BBD + 6, [0x83] = BBD + 5, [0x84] = BBD + 4, 187 + [0x85] = BBD + 3, [0x86] = BBD + 2, [0x87] = BBD + 1, [0x88] = BBD + 0, 188 + 189 + /* Left X/8 block (data is X) */ 190 + [0x89] = BBL + 7, [0x8a] = BBL + 6, [0x8b] = BBL + 5, [0x8c] = BBL + 4, 191 + [0x8d] = BBL + 3, [0x8e] = BBL + 2, [0x8f] = BBL + 1, 192 + 193 + /* upper 1/2 (4/8), 1/8 block (X), right 1/2, 1/8 block (8-X) */ 194 + [0x80] = BBU + 4, [0x94] = BBU + 1, 195 + [0x90] = BBR + 4, [0x95] = BBR + 7, 196 + 197 + /* Quadrants */ 198 + [0x96] = BBQ + BL, 199 + [0x97] = BBQ + BR, 200 + [0x98] = BBQ + TL, 201 + [0x99] = BBQ + TL + BL + BR, 202 + [0x9a] = BBQ + TL + BR, 203 + [0x9b] = BBQ + TL + TR + BL, 204 + [0x9c] = BBQ + TL + TR + BR, 205 + [0x9d] = BBQ + TR, 206 + [0x9e] = BBQ + BL + TR, 207 + [0x9f] = BBQ + BL + TR + BR, 208 + 209 + /* Shades, data is an alpha value in 25% units (1/4, 1/2, 3/4) */ 210 + [0x91] = BBS + 1, [0x92] = BBS + 2, [0x93] = BBS + 3, 211 + 212 + /* U+2504 - U+250B, U+254C - U+254F: unsupported (dashes) */ 213 + /* U+2571 - U+2573: unsupported (diagonals) */ 214 + };
+49
cfg/st/catppuccin.config.h
··· 1 + /* 2 + * 3 + * Name : Catppuccin 4 + * author : tsjazil (https://github.com/tsjazil) 5 + * 6 + * Soothing pastel theme for the high-spirited! 7 + * 8 + */ 9 + 10 + 11 + /* Terminal colors (16 first used in escape sequence) */ 12 + static const char *colorname[] = { 13 + /* 8 normal colors */ 14 + "#6E6C7E", 15 + "#F28FAD", 16 + "#ABE9B3", 17 + "#FAE3B0", 18 + "#96CDFB", 19 + "#F5C2E7", 20 + "#89DCEB", 21 + "#D9E0EE", 22 + 23 + /* 8 bright colors */ 24 + "#988BA2", 25 + "#F28FAD", 26 + "#ABE9B3", 27 + "#FAE3B0", 28 + "#96CDFB", 29 + "#F5C2E7", 30 + "#89DCEB", 31 + "#D9E0EE", 32 + 33 + 34 + 35 + [256] = "#D9E0EE", /* default foreground colour */ 36 + [257] = "#1E1E2E", /* default background colour */ 37 + [258] = "#C3BAC6", /*575268*/ 38 + 39 + }; 40 + 41 + 42 + /* 43 + * foreground, background, cursor, reverse cursor 44 + */ 45 + unsigned int defaultfg = 256; 46 + unsigned int defaultbg = 257; 47 + unsigned int defaultcs = 258; 48 + static unsigned int defaultrcs = 258; 49 +
cfg/st/config.def.h

This is a binary file and will not be displayed.

cfg/st/config.mk

This is a binary file and will not be displayed.

cfg/st/hb.c

This is a binary file and will not be displayed.

+7
cfg/st/hb.h
··· 1 + #include <X11/Xft/Xft.h> 2 + #include <hb.h> 3 + #include <hb-ft.h> 4 + 5 + void hbunloadfonts(); 6 + void hbtransform(XftGlyphFontSpec *, const Glyph *, size_t, int, int); 7 +
+284
cfg/st/normalMode.c
··· 1 + #include <X11/keysym.h> 2 + #include <X11/XKBlib.h> 3 + 4 + #include "normalMode.h" 5 + #include "utils.h" 6 + 7 + extern Glyph const styleSearch, style[]; 8 + extern char const wDelS[], wDelL[], *nmKeys[]; 9 + extern unsigned int bg[], fg, currentBg, highlightBg, highlightFg, amountNmKeys; 10 + 11 + typedef struct { int p[3]; } Pos; 12 + 13 + typedef enum {visual='v', visualLine='V', yank = 'y'} Op; 14 + typedef enum {infix_none=0, infix_i='i', infix_a='a'} Infix; 15 + typedef enum {fw='/', bw='?'} Search; 16 + struct NormalModeState { 17 + struct OperationState { Op op; Infix infix; } cmd; 18 + struct MotionState { uint32_t c; int active; Pos searchPos; Search search; } m; 19 + } defaultNormalMode, state; 20 + 21 + DynamicArray searchStr=UTF8_ARRAY, cCmd=UTF8_ARRAY, lCmd=UTF8_ARRAY; 22 + Glyph styleCmd; 23 + char posBuffer[10], braces[6][3] = { {"()"}, {"<>"}, {"{}"}, {"[]"}, {"\"\""}, {"''"}}; 24 + int exited=1, overlay=1; 25 + static inline Rune cChar() { return term.line[term.c.y][term.c.x].u; } 26 + static inline int pos(int p, int h) {return IS_SET(MODE_ALTSCREEN)?p:rangeY(p+h*histOff-insertOff);} 27 + static inline int contains(Rune l, char const * values, size_t const memSize) { 28 + for (uint32_t i = 0; i < memSize; ++i) if (l == values[i]) return 1; 29 + return 0; 30 + } 31 + static inline void decodeTo(char const *cs, size_t len, DynamicArray *arr) { 32 + char *var = expand(arr); 33 + if (!var) empty(arr); else utf8decode(cs, (Rune*)(var), len); 34 + } 35 + static inline void applyPos(Pos p) { 36 + term.c.x = p.p[0], term.c.y = p.p[1]; 37 + if (!IS_SET(MODE_ALTSCREEN) && histOp) term.line = &buf[histOff = p.p[2]]; 38 + } 39 + /// Find string in history buffer, and provide string-match-lookup for highlighting matches 40 + static int highlighted(int x, int y) { 41 + int const s=term.row*term.col, i=y*term.col+x, sz=size(&searchStr); 42 + return sz && i<s && mark[i]!=sz && i+mark[i]<s && !mark[i+mark[i]]; 43 + } 44 + static void markSearchMatches(int all) { 45 + int sz = size(&searchStr), ox = 0, oy = 0, oi=0; 46 + for (int y=0; sz && all && y<term.row; ++y) 47 + for (int x=0; x<term.col; ++x) term.dirty[y] |= highlighted(x, y); 48 + for (int y = 0, wi=0, owi=0, i=0; sz && y < term.row; ++y) 49 + for (int x=0; x<term.col; ++x, wi%=sz, ++i, owi=wi) 50 + if (all || term.dirty[y]) { 51 + mark[i]=sz-(wi=(getU32(&searchStr,wi,1)==term.line[y][x].u?wi+1:0)); 52 + if (wi==1) ox=x, oy=y, oi=i; else if (!wi && owi) x=ox, y=oy, i=oi; 53 + } 54 + for (int y=0; sz &&all &&y<term.row; ++y) 55 + for (int x=0; x<term.col; ++x) term.dirty[y] |= highlighted(x, y); 56 + } 57 + static int findString(int s, int all) { 58 + Pos p = (Pos) {.p={term.c.x, term.c.y, IS_SET(MODE_ALTSCREEN) ? 0 : histOff}}; 59 + historyMove(s, 0, 0); 60 + uint32_t strSz=size(&searchStr), maxIter=rows()*term.col+strSz, wIdx=0; 61 + for (uint32_t i=0, wi = 0; wIdx<strSz && ++i<=maxIter; historyMove(s, 0, 0), wi=wIdx) { 62 + wIdx = (getU32(&searchStr, wIdx, s>0)==cChar())?wIdx+1:0; 63 + if (wi && !wIdx) historyMove(-(int)(s*wi), 0, 0); 64 + } 65 + if (wIdx == strSz && wIdx) historyMove(-(int)(s*strSz), 0, 0); 66 + else applyPos(p); 67 + markSearchMatches(all); 68 + return wIdx == strSz; 69 + } 70 + /// Execute series of normal-mode commands from char array / decoded from dynamic array 71 + ExitState pressKeys(char const* s, size_t e) { 72 + ExitState x=success; 73 + for (size_t i=0; i<e && (x=(!s[i] ? x : kPressHist(&s[i], 1, 0, NULL))); ++i); 74 + return x; 75 + } 76 + static ExitState executeCommand(uint32_t *cs, size_t z) { 77 + ExitState x=success; 78 + char dc [32]; 79 + for (size_t i=0; i<z && (x=kPressHist(dc, utf8encode(cs[i],dc),0,NULL));++i); 80 + return x; 81 + } 82 + /// Get character for overlay, if the overlay (st) has something to show, else normal char. 83 + static void getChar(DynamicArray *st, Glyph *glyphChange, int y, int xEnd, int width, int x) { 84 + if (x < xEnd - min(min(width,xEnd), size(st))) *glyphChange = term.line[y][x]; 85 + else if (x<xEnd) glyphChange->u = *((Rune*)(st->content + (size(st)+x-xEnd)*st->elSize)); 86 + } 87 + /// Expand "infix" expression: for instance (w =>) l b | | v e | | y 88 + static ExitState expandExpression(char l) { // ({ =>) l ? { \n | l | v / } \n | h | y 89 + int a=state.cmd.infix==infix_a, yank=state.cmd.op=='y', lc=tolower(l), found=1; 90 + state.cmd.infix = infix_none; 91 + if(!yank && state.cmd.op!=visual && state.cmd.op!=visualLine) return failed; 92 + char mot[11] = {'l', 0, 'b', 0, 0, 'v', 0, 'e', 0, 0, (char)(yank ? 'y' : 0)}; 93 + if (lc == 'w') mot[2] = (char) ('b' - lc + l), mot[7] = (char) ((a ? 'w' : 'e') - lc + l), mot[9]=(char)(a?'h':0); 94 + else { 95 + mot[1]='?', mot[3]=mot[8]='\n', mot[6]='/', mot[4]=(char)(a?0:'l'), mot[9]=(char)(a?0:'h'); 96 + for (int i=found=0; !found && i < 6; ++i) 97 + if ((found=contains(l,braces[i],2))) mot[2]=braces[i][0], mot[7]=braces[i][1]; 98 + } 99 + if (!found) return failed; 100 + assign(&lCmd, &cCmd); 101 + empty(&cCmd); 102 + state.cmd = defaultNormalMode.cmd; 103 + return pressKeys(mot, 11); 104 + } 105 + 106 + ExitState executeMotion(char const cs, KeySym const *const ks) { 107 + state.m.c = state.m.c < 1u ? 1u : state.m.c; 108 + if (ks && *ks == XK_d) historyMove(0, 0, term.row / 2); 109 + else if (ks && *ks == XK_u) historyMove(0, 0, -term.row / 2); 110 + else if (ks && *ks == XK_f) historyMove(0, 0, term.row-1+(term.c.y=0)); 111 + else if (ks && *ks == XK_b) historyMove(0, 0, -(term.c.y=term.row-1)); 112 + else if (ks && *ks == XK_h) overlay = !overlay; 113 + else if (cs == 'K') historyMove(0, 0, -(int)state.m.c); 114 + else if (cs == 'J') historyMove(0, 0, (int)state.m.c); 115 + else if (cs == 'k') historyMove(0, -(int)state.m.c, 0); 116 + else if (cs == 'j') historyMove(0, (int)state.m.c, 0); 117 + else if (cs == 'h') historyMove(-(int)state.m.c, 0, 0); 118 + else if (cs == 'l') historyMove( (int)state.m.c, 0, 0); 119 + else if (cs == 'H') term.c.y = 0; 120 + else if (cs == 'M') term.c.y = term.bot / 2; 121 + else if (cs == 'L') term.c.y = term.bot; 122 + else if (cs == 's' || cs == 'S') altToggle = cs == 's' ? !altToggle : 1; 123 + else if (cs == 'G' || cs == 'g') { 124 + if (cs == 'G') term.c = c[0] = c[IS_SET(MODE_ALTSCREEN)+1]; 125 + if (!IS_SET(MODE_ALTSCREEN)) term.line = &buf[histOff=insertOff]; 126 + } else if (cs == '0') term.c.x = 0; 127 + else if (cs == '$') term.c.x = term.col-1; 128 + else if (cs == 't') sel.type = sel.type==SEL_REGULAR ? SEL_RECTANGULAR : SEL_REGULAR; 129 + else if (cs == 'n' || cs == 'N') { 130 + int const d = ((cs=='N')!=(state.m.search==bw))?-1:1; 131 + for (uint32_t i = state.m.c; i && findString(d, 0); --i); 132 + } else if (contains(cs, "wWeEbB", 6)) { 133 + int const low=cs<=90, off=tolower(cs)!='w', sgn=(tolower(cs)=='b')?-1:1; 134 + size_t const l=strlen(wDelL), s=strlen(wDelS), maxIt=rows()*term.col; 135 + for (int it=0, on=0; state.m.c > 0 && it < maxIt; ++it) { 136 + // If an offset is to be performed in beginning or not in beginning, move in history. 137 + if ((off || it) && historyMove(sgn, 0, 0)) break; 138 + // Determine if the category of the current letter changed since last iteration. 139 + int n = 1<<(contains(cChar(),wDelS,s) ?(2-low) :!contains(cChar(),wDelL,l)), 140 + found = (on|=n)^n && ((off ?on^n :n)!=1); 141 + // If a reverse offset is to be performed and this is the last letter: 142 + if (found && off) historyMove(-sgn, 0, 0); 143 + // Terminate iteration: reset #it and old n value #on and decrease operation count: 144 + if (found) it=-1, on=0, --state.m.c; 145 + } 146 + } else return failed; 147 + state.m.c = 0; 148 + return state.cmd.op == yank ? exitMotion : success; 149 + } 150 + 151 + ExitState kPressHist(char const *cs, size_t len, int ctrl, KeySym const *kSym) { 152 + historyOpToggle(1, 1); 153 + int const prevYOff=IS_SET(MODE_ALTSCREEN)?0:histOff, search=state.m.search&&state.m.active, 154 + prevAltToggle=altToggle, prevOverlay=overlay; 155 + int const noOp=!state.cmd.op&&!state.cmd.infix, num=len==1&&BETWEEN(cs[0],48,57), 156 + esc=kSym&&*kSym==XK_Escape, ret=(kSym&&*kSym==XK_Return)||(len==1&&cs[0]=='\n'), 157 + quantifier=num&&(cs[0]!='0'||state.m.c), ins=!search &&noOp &&len &&cs[0]=='i'; 158 + exited = 0; 159 + ExitState result = success; 160 + if (esc || ret || ins) { result = exitMotion, len = 0; 161 + } else if (kSym && *kSym == XK_BackSpace) { 162 + if ((search || state.m.c) && size(&cCmd)) pop(&cCmd); 163 + if (search) { 164 + if (size(&searchStr)) pop(&searchStr); 165 + else result = exitMotion; 166 + if (!size(&searchStr)) tfulldirt(); 167 + applyPos(state.m.searchPos); 168 + findString(state.m.search==fw ? 1 : -1, 1); 169 + } else if (state.m.c) state.m.c /= 10; 170 + len = 0; 171 + } else if (search) { 172 + if (len >= 1) decodeTo(cs, len, &searchStr); 173 + applyPos(state.m.searchPos); 174 + findString(state.m.search==fw ? 1 : -1, 1); 175 + } else if (len == 0) { result = failed; 176 + } else if (quantifier) { state.m.c = min(SHRT_MAX, (int)state.m.c*10+cs[0]-48); 177 + } else if (state.cmd.infix && state.cmd.op && (result = expandExpression(cs[0]), len=0)) { 178 + } else if (cs[0] == 'd') { state = defaultNormalMode; result = exitMotion; state.m.active = 1; 179 + } else if (cs[0] == '.') { 180 + if (size(&cCmd)) assign(&lCmd, &cCmd); 181 + empty(&cCmd); 182 + executeCommand((uint32_t*) lCmd.content, size(&lCmd)); 183 + empty(&cCmd); 184 + len = 0; 185 + } else if (cs[0] == 'r') { tfulldirt(); 186 + } else if (cs[0] == 'c') { 187 + empty(&lCmd); 188 + empty(&cCmd); 189 + empty(&searchStr); 190 + tfulldirt(); 191 + len = 0; 192 + } else if (cs[0] == fw || cs[0] == bw) { 193 + empty(&searchStr); 194 + state.m.search = (Search) cs[0]; 195 + state.m.searchPos = (Pos){.p={term.c.x, term.c.y, prevYOff}}; 196 + state.m.active = 1; 197 + } else if (cs[0]==infix_i || cs[0]==infix_a) { state.cmd.infix=(Infix) cs[0]; 198 + } else if (cs[0] == 'y') { 199 + if (state.cmd.op) { 200 + result = (state.cmd.op == yank || state.cmd.op == visualLine) ? exitOp : exitMotion; 201 + if (state.cmd.op == yank) selstart(0, term.c.y, 0); 202 + } else selstart(term.c.x, term.c.y, 0); 203 + state.cmd.op = yank; 204 + } else if (cs[0] == visual || cs[0] == visualLine) { 205 + if (state.cmd.op != (Op) cs[0]) { 206 + state.cmd = defaultNormalMode.cmd; 207 + state.cmd.op = (Op) cs[0]; 208 + selstart(cs[0] == visualLine ?0 :term.c.x, term.c.y, 0); 209 + } else result = exitOp; 210 + } else if (!(result =executeMotion((char) (len?cs[0]:0), ctrl?kSym:NULL))) { 211 + result=failed; 212 + for (size_t i = 0; !ctrl && i < amountNmKeys; ++i) 213 + if (cs[0]==nmKeys[i][0] && 214 + failed!=(result=pressKeys(&nmKeys[i][1], strlen(nmKeys[i])-1))) goto end; 215 + } // Operation/Motion finished if valid: update cmd string, extend selection, update search 216 + if (result != failed) { 217 + if (len == 1 && !ctrl) decodeTo(cs, len, &cCmd); 218 + if ((state.cmd.op == visualLine) || ((state.cmd.op == yank) && (result == exitOp))) { 219 + int const off = term.c.y + (IS_SET(MODE_ALTSCREEN) ? 0 : histOff) < sel.ob.y; //< Selection start below end. 220 + sel.ob.x = off ? term.col - 1 : 0; 221 + selextend(off ? 0 : term.col-1, term.c.y, sel.type, 0); 222 + } else if (sel.oe.x != -1) { 223 + selextend(term.c.x, term.c.y, sel.type, 0); 224 + } 225 + } // Set repaint for motion or status bar 226 + if (!IS_SET(MODE_ALTSCREEN) && prevYOff != histOff) tfulldirt(); 227 + // Terminate Motion / operation if thus indicated 228 + if (result == exitMotion) { 229 + if (!state.m.active) result = (exited=noOp) ? finish : exitOp; 230 + state.m.active = (int) (state.m.c = 0u); 231 + } 232 + if (result == exitOp || result == finish) { 233 + if (state.cmd.op == yank) { 234 + xsetsel(getsel()); 235 + xclipcopy(); 236 + } 237 + state = defaultNormalMode; 238 + selclear(); 239 + if (!esc) assign(&lCmd, &cCmd); 240 + empty(&cCmd); 241 + } // Update the content displayed in the history overlay 242 + styleCmd = style[state.cmd.op==yank ? 1 : (state.cmd.op==visual ? 2 : 243 + (state.cmd.op==visualLine ? 3 :0))]; 244 + int const posLin = !IS_SET(MODE_ALTSCREEN) ? rangeY(insertOff-histOff):0, h=rows()-term.row; 245 + if (!posLin || posLin==h || !h) strcpy(posBuffer, posLin ? " [BOT] " : " [TOP] "); 246 + else sprintf(posBuffer, " % 3d%c ", min(100, max(0, (int)(.5 + posLin * 100. / h))),'%'); 247 + if ((overlay || overlay!=prevOverlay) && term.col>9 && term.row>4) { 248 + if (!term.dirty[term.row-1]) xdrawline(term.line[term.row-1], term.col*2/3, term.row-1, term.col-1); 249 + if (!term.dirty[term.row-2]) xdrawline(term.line[term.row-2], term.col*2/3, term.row-2, term.col-1); 250 + } 251 + if (result==finish) altToggle = 0; 252 + if (altToggle != prevAltToggle) tswapscreen(); 253 + end: 254 + historyOpToggle(-1, 1); 255 + return result; 256 + } 257 + 258 + void historyOverlay(int x, int y, Glyph* g) { 259 + if (!histMode) return; 260 + TCursor const *cHist = histOp ? &term.c : &c[0]; 261 + if(overlay && term.col > 9 && term.row > 4 && (x > (2*term.col/3)) && (y >= (term.row-2))) { 262 + *g = (y == term.row - 2) ? styleSearch : styleCmd; 263 + if (y == term.row-2) getChar(&searchStr, g, term.row-2, term.col-2, term.col/3, x); 264 + else if (x > term.col - 7) g->u = (Rune)(posBuffer[x - term.col + 7]); 265 + else getChar(size(&cCmd) ?&cCmd :&lCmd, g, term.row-1, term.col-7, term.col/3-6, x); 266 + } else if (highlighted(x, y)) g->bg = highlightBg, g->fg = highlightFg; 267 + else if ((x==cHist->x) ^ (y==cHist->y)) g->bg = currentBg; 268 + else if (x==cHist->x) g->mode^=ATTR_REVERSE; 269 + } 270 + void historyPreDraw() { 271 + static Pos op = {.p={0, 0, 0}}; 272 + historyOpToggle(1, 0); 273 + // Draw the cursor cross if changed 274 + if (term.c.y >= term.row || op.p[1] >= term.row) tfulldirt(); 275 + else if (exited || (op.p[1] != term.c.y)) term.dirty[term.c.y] = term.dirty[op.p[1]] = 1; 276 + for (int i=0; (exited || term.c.x != op.p[0]) && i<term.row; ++i) if (!term.dirty[i]) { 277 + xdrawline(term.line[i], term.c.x, i, term.c.x + 1); 278 + xdrawline(term.line[i], op.p[0], i, op.p[0] + 1); 279 + } 280 + // Update search results either only for lines with new content or all results if exiting 281 + markSearchMatches(exited); 282 + op = (Pos){.p = {term.c.x, term.c.y, 0}}; 283 + historyOpToggle(-1, 0); 284 + }
+8
cfg/st/normalMode.h
··· 1 + void normalMode(); 2 + void historyPreDraw(); 3 + void historyOverlay(int x, int y, Glyph* g); 4 + void historyModeToggle(int start); 5 + void historyOpToggle(int, int); 6 + typedef enum {failed=0, success=1, exitMotion=2, exitOp=3, finish=4} ExitState; 7 + ExitState kPressHist(char const *txt, size_t len, int ctrl, KeySym const *kSym); 8 + ExitState pressKeys(char const* s, size_t e);
+5
cfg/st/shell.nix
··· 1 + { pkgs ? import <nixpkgs> {} }: 2 + 3 + pkgs.mkShell { 4 + nativeBuildInputs = with pkgs; [ pkgconfig xorg.libX11 xorg.libXft fontconfig harfbuzz ]; 5 + }
+13
cfg/st/st-copyout
··· 1 + #!/bin/sh 2 + # Using external pipe with st, give a dmenu prompt of recent commands, 3 + # allowing the user to copy the output of one. 4 + # xclip required for this script. 5 + # By Jaywalker and Luke 6 + tmpfile=$(mktemp /tmp/st-cmd-output.XXXXXX) 7 + trap 'rm "$tmpfile"' 0 1 15 8 + sed -n "w $tmpfile" 9 + sed -i 's/\x0//g' "$tmpfile" 10 + ps1="$(grep "\S" "$tmpfile" | tail -n 1 | sed 's/^\s*//' | cut -d' ' -f1)" 11 + chosen="$(grep -F "$ps1" "$tmpfile" | sed '$ d' | tac | dmenu -p "Copy which command's output?" -i -l 10 | sed 's/[^^]/[&]/g; s/\^/\\^/g')" 12 + eps1="$(echo "$ps1" | sed 's/[^^]/[&]/g; s/\^/\\^/g')" 13 + awk "/^$chosen$/{p=1;print;next} p&&/$eps1/{p=0};p" "$tmpfile" | xclip -selection clipboard
cfg/st/st-urlhandler

This is a binary file and will not be displayed.

+197
cfg/st/st.1
··· 1 + .TH ST 1 st\-VERSION 2 + .SH NAME 3 + st \- simple terminal (Luke Smith (https://lukesmith.xyz)'s build) 4 + .SH SYNOPSIS 5 + .B st 6 + .RB [ \-aiv ] 7 + .RB [ \-c 8 + .IR class ] 9 + .RB [ \-f 10 + .IR font ] 11 + .RB [ \-g 12 + .IR geometry ] 13 + .RB [ \-n 14 + .IR name ] 15 + .RB [ \-o 16 + .IR iofile ] 17 + .RB [ \-T 18 + .IR title ] 19 + .RB [ \-t 20 + .IR title ] 21 + .RB [ \-l 22 + .IR line ] 23 + .RB [ \-w 24 + .IR windowid ] 25 + .RB [[ \-e ] 26 + .IR command 27 + .RI [ arguments ...]] 28 + .PP 29 + .B st 30 + .RB [ \-aiv ] 31 + .RB [ \-c 32 + .IR class ] 33 + .RB [ \-f 34 + .IR font ] 35 + .RB [ \-g 36 + .IR geometry ] 37 + .RB [ \-n 38 + .IR name ] 39 + .RB [ \-o 40 + .IR iofile ] 41 + .RB [ \-T 42 + .IR title ] 43 + .RB [ \-t 44 + .IR title ] 45 + .RB [ \-w 46 + .IR windowid ] 47 + .RB \-l 48 + .IR line 49 + .RI [ stty_args ...] 50 + .SH DESCRIPTION 51 + .B st 52 + is a simple terminal emulator. 53 + .SH OPTIONS 54 + .TP 55 + .B \-a 56 + disable alternate screens in terminal 57 + .TP 58 + .BI \-c " class" 59 + defines the window class (default $TERM). 60 + .TP 61 + .BI \-f " font" 62 + defines the 63 + .I font 64 + to use when st is run. 65 + .TP 66 + .BI \-g " geometry" 67 + defines the X11 geometry string. 68 + The form is [=][<cols>{xX}<rows>][{+-}<xoffset>{+-}<yoffset>]. See 69 + .BR XParseGeometry (3) 70 + for further details. 71 + .TP 72 + .B \-i 73 + will fixate the position given with the -g option. 74 + .TP 75 + .BI \-n " name" 76 + defines the window instance name (default $TERM). 77 + .TP 78 + .BI \-o " iofile" 79 + writes all the I/O to 80 + .I iofile. 81 + This feature is useful when recording st sessions. A value of "-" means 82 + standard output. 83 + .TP 84 + .BI \-T " title" 85 + defines the window title (default 'st'). 86 + .TP 87 + .BI \-t " title" 88 + defines the window title (default 'st'). 89 + .TP 90 + .BI \-w " windowid" 91 + embeds st within the window identified by 92 + .I windowid 93 + .TP 94 + .BI \-l " line" 95 + use a tty 96 + .I line 97 + instead of a pseudo terminal. 98 + .I line 99 + should be a (pseudo-)serial device (e.g. /dev/ttyS0 on Linux for serial port 100 + 0). 101 + When this flag is given 102 + remaining arguments are used as flags for 103 + .BR stty(1). 104 + By default st initializes the serial line to 8 bits, no parity, 1 stop bit 105 + and a 38400 baud rate. The speed is set by appending it as last argument 106 + (e.g. 'st -l /dev/ttyS0 115200'). Arguments before the last one are 107 + .BR stty(1) 108 + flags. If you want to set odd parity on 115200 baud use for example 'st -l 109 + /dev/ttyS0 parenb parodd 115200'. Set the number of bits by using for 110 + example 'st -l /dev/ttyS0 cs7 115200'. See 111 + .BR stty(1) 112 + for more arguments and cases. 113 + .TP 114 + .B \-v 115 + prints version information to stderr, then exits. 116 + .TP 117 + .BI \-e " command " [ " arguments " "... ]" 118 + st executes 119 + .I command 120 + instead of the shell. If this is used it 121 + .B must be the last option 122 + on the command line, as in xterm / rxvt. 123 + This option is only intended for compatibility, 124 + and all the remaining arguments are used as a command 125 + even without it. 126 + .SH SHORTCUTS 127 + .TP 128 + .B Alt-j/k or Alt-Up/Down or Alt-Mouse Wheel 129 + Scroll up/down one line at a time. 130 + .TP 131 + .B Alt-u/d or Alt-Page Up/Page Down 132 + Scroll up/down one screen at a time. 133 + .TP 134 + .B Alt-Shift-k/j or Alt-Shift-Page Up/Page Down or Alt-Shift-Mouse Wheel 135 + Increase or decrease font size. 136 + .TP 137 + .B Alt-Home 138 + Reset to default font size. 139 + .TP 140 + .B Shift-Insert or Alt-v 141 + Paste from clipboard. 142 + .TP 143 + .B Alt-c 144 + Copy to clipboard. 145 + .TP 146 + .B Alt-p 147 + Paste/input primary selection. 148 + .TP 149 + .B Alt-l 150 + Show dmenu menu of all URLs on screen and choose one to open. 151 + .TP 152 + .B Alt-y 153 + Show dmenu menu of all URLs on screen and choose one to copy. 154 + .TP 155 + .B Alt-o 156 + Show dmenu menu of all recently run commands and copy the output of the chosen command to the clipboard. 157 + .I xclip 158 + required. 159 + .TP 160 + .B Alt-a/s 161 + Increase or decrease opacity/alpha value (make window more or less transparent). 162 + .TP 163 + .B Break 164 + Send a break in the serial line. 165 + Break key is obtained in PC keyboards 166 + pressing at the same time control and pause. 167 + .TP 168 + .B Ctrl-Print Screen 169 + Toggle if st should print to the 170 + .I iofile. 171 + .TP 172 + .B Shift-Print Screen 173 + Print the full screen to the 174 + .I iofile. 175 + .TP 176 + .B Print Screen 177 + Print the selection to the 178 + .I iofile. 179 + .TP 180 + .B Alt-Ctrl 181 + Launch dmenu to enter a unicode codepoint and send the corresponding glyph 182 + to st. 183 + .SH CUSTOMIZATION 184 + .B st 185 + can be customized by creating a custom config.h and (re)compiling the source 186 + code. This keeps it fast, secure and simple. 187 + .SH AUTHORS 188 + See the LICENSE file for the authors. 189 + .SH LICENSE 190 + See the LICENSE file for the terms of redistribution. 191 + .SH SEE ALSO 192 + .BR tabbed (1), 193 + .BR utmp (1), 194 + .BR stty (1) 195 + .SH BUGS 196 + See the TODO file in the distribution. 197 +
+2816
cfg/st/st.c
··· 1 + /* See LICENSE for license details. */ 2 + #include <ctype.h> 3 + #include <errno.h> 4 + #include <fcntl.h> 5 + #include <limits.h> 6 + #include <pwd.h> 7 + #include <stdarg.h> 8 + #include <stdio.h> 9 + #include <stdlib.h> 10 + #include <string.h> 11 + #include <signal.h> 12 + #include <sys/ioctl.h> 13 + #include <sys/select.h> 14 + #include <sys/types.h> 15 + #include <sys/wait.h> 16 + #include <termios.h> 17 + #include <time.h> 18 + #include <unistd.h> 19 + #include <wchar.h> 20 + 21 + #include "st.h" 22 + #include "win.h" 23 + 24 + #if defined(__linux) 25 + #include <pty.h> 26 + #elif defined(__OpenBSD__) || defined(__NetBSD__) || defined(__APPLE__) 27 + #include <util.h> 28 + #elif defined(__FreeBSD__) || defined(__DragonFly__) 29 + #include <libutil.h> 30 + #endif 31 + 32 + /* Arbitrary sizes */ 33 + #define UTF_INVALID 0xFFFD 34 + #define UTF_SIZ 4 35 + #define ESC_BUF_SIZ (128*UTF_SIZ) 36 + #define ESC_ARG_SIZ 16 37 + #define STR_BUF_SIZ ESC_BUF_SIZ 38 + #define STR_ARG_SIZ ESC_ARG_SIZ 39 + #define HISTSIZE 2000 40 + 41 + /* macros */ 42 + #define IS_SET(flag) ((term.mode & (flag)) != 0) 43 + #define NUMMAXLEN(x) ((int)(sizeof(x) * 2.56 + 0.5) + 1) 44 + #define ISCONTROLC0(c) (BETWEEN(c, 0, 0x1f) || (c) == '\177') 45 + #define ISCONTROLC1(c) (BETWEEN(c, 0x80, 0x9f)) 46 + #define ISCONTROL(c) (ISCONTROLC0(c) || ISCONTROLC1(c)) 47 + #define ISDELIM(u) (u && wcschr(worddelimiters, u)) 48 + #define TLINE(y) ((y) < term.scr ? term.hist[((y) + term.histi - \ 49 + term.scr + HISTSIZE + 1) % HISTSIZE] : \ 50 + term.line[(y) - term.scr]) 51 + 52 + #define TLINE_HIST(y) ((y) <= HISTSIZE-term.row+2 ? term.hist[(y)] : term.line[(y-HISTSIZE+term.row-3)]) 53 + 54 + /* constants */ 55 + #define ISO14755CMD "dmenu -w \"$WINDOWID\" -p codepoint: </dev/null" 56 + 57 + enum term_mode { 58 + MODE_WRAP = 1 << 0, 59 + MODE_INSERT = 1 << 1, 60 + MODE_ALTSCREEN = 1 << 2, 61 + MODE_CRLF = 1 << 3, 62 + MODE_ECHO = 1 << 4, 63 + MODE_PRINT = 1 << 5, 64 + MODE_UTF8 = 1 << 6, 65 + MODE_SIXEL = 1 << 7, 66 + }; 67 + 68 + enum cursor_movement { 69 + CURSOR_SAVE, 70 + CURSOR_LOAD 71 + }; 72 + 73 + enum cursor_state { 74 + CURSOR_DEFAULT = 0, 75 + CURSOR_WRAPNEXT = 1, 76 + CURSOR_ORIGIN = 2 77 + }; 78 + 79 + enum charset { 80 + CS_GRAPHIC0, 81 + CS_GRAPHIC1, 82 + CS_UK, 83 + CS_USA, 84 + CS_MULTI, 85 + CS_GER, 86 + CS_FIN 87 + }; 88 + 89 + enum escape_state { 90 + ESC_START = 1, 91 + ESC_CSI = 2, 92 + ESC_STR = 4, /* OSC, PM, APC */ 93 + ESC_ALTCHARSET = 8, 94 + ESC_STR_END = 16, /* a final string was encountered */ 95 + ESC_TEST = 32, /* Enter in test mode */ 96 + ESC_UTF8 = 64, 97 + ESC_DCS =128, 98 + }; 99 + 100 + typedef struct { 101 + Glyph attr; /* current char attributes */ 102 + int x; 103 + int y; 104 + char state; 105 + } TCursor; 106 + 107 + typedef struct { 108 + int mode; 109 + int type; 110 + int snap; 111 + /* 112 + * Selection variables: 113 + * nb – normalized coordinates of the beginning of the selection 114 + * ne – normalized coordinates of the end of the selection 115 + * ob – original coordinates of the beginning of the selection 116 + * oe – original coordinates of the end of the selection 117 + */ 118 + struct { 119 + int x, y; 120 + } nb, ne, ob, oe; 121 + 122 + int alt; 123 + } Selection; 124 + 125 + /* Internal representation of the screen */ 126 + typedef struct { 127 + int row; /* nb row */ 128 + int col; /* nb col */ 129 + int maxcol; 130 + Line *line; /* screen */ 131 + Line *alt; /* alternate screen */ 132 + Line hist[HISTSIZE]; /* history buffer */ 133 + int histi; /* history index */ 134 + int scr; /* scroll back */ 135 + int *dirty; /* dirtyness of lines */ 136 + TCursor c; /* cursor */ 137 + int ocx; /* old cursor col */ 138 + int ocy; /* old cursor row */ 139 + int top; /* top scroll limit */ 140 + int bot; /* bottom scroll limit */ 141 + int mode; /* terminal mode flags */ 142 + int esc; /* escape state flags */ 143 + char trantbl[4]; /* charset table translation */ 144 + int charset; /* current charset */ 145 + int icharset; /* selected charset for sequence */ 146 + int *tabs; 147 + struct timespec last_ximspot_update; 148 + } Term; 149 + 150 + /* CSI Escape sequence structs */ 151 + /* ESC '[' [[ [<priv>] <arg> [;]] <mode> [<mode>]] */ 152 + typedef struct { 153 + char buf[ESC_BUF_SIZ]; /* raw string */ 154 + int len; /* raw string length */ 155 + char priv; 156 + int arg[ESC_ARG_SIZ]; 157 + int narg; /* nb of args */ 158 + char mode[2]; 159 + } CSIEscape; 160 + 161 + /* STR Escape sequence structs */ 162 + /* ESC type [[ [<priv>] <arg> [;]] <mode>] ESC '\' */ 163 + typedef struct { 164 + char type; /* ESC type ... */ 165 + char buf[STR_BUF_SIZ]; /* raw string */ 166 + int len; /* raw string length */ 167 + char *args[STR_ARG_SIZ]; 168 + int narg; /* nb of args */ 169 + } STREscape; 170 + 171 + static void execsh(char *, char **); 172 + static char *getcwd_by_pid(pid_t pid); 173 + static void stty(char **); 174 + static void sigchld(int); 175 + static void ttywriteraw(const char *, size_t); 176 + 177 + static void csidump(void); 178 + static void csihandle(void); 179 + static void csiparse(void); 180 + static void csireset(void); 181 + static int eschandle(uchar); 182 + static void strdump(void); 183 + static void strhandle(void); 184 + static void strparse(void); 185 + static void strreset(void); 186 + 187 + static void tprinter(char *, size_t); 188 + static void tdumpsel(void); 189 + static void tdumpline(int); 190 + static void tdump(void); 191 + static void tclearregion(int, int, int, int); 192 + static void tcursor(int); 193 + static void tdeletechar(int); 194 + static void tdeleteline(int); 195 + static void tinsertblank(int); 196 + static void tinsertblankline(int); 197 + static int tlinelen(int); 198 + static void tmoveto(int, int); 199 + static void tmoveato(int, int); 200 + static void tnewline(int); 201 + static void tputtab(int); 202 + static void tputc(Rune); 203 + static void treset(void); 204 + static void tscrollup(int, int, int); 205 + static void tscrolldown(int, int, int); 206 + static void tsetattr(int *, int); 207 + static void tsetchar(Rune, Glyph *, int, int); 208 + static void tsetdirt(int, int); 209 + static void tsetscroll(int, int); 210 + static void tswapscreen(void); 211 + static void tsetmode(int, int, int *, int); 212 + static int twrite(const char *, int, int); 213 + static void tfulldirt(void); 214 + static void tcontrolcode(uchar ); 215 + static void tdectest(char ); 216 + static void tdefutf8(char); 217 + static int32_t tdefcolor(int *, int *, int); 218 + static void tdeftran(char); 219 + static void tstrsequence(uchar); 220 + 221 + static void drawregion(int, int, int, int); 222 + 223 + static void selnormalize(void); 224 + static void selscroll(int, int); 225 + static void selsnap(int *, int *, int); 226 + 227 + static size_t utf8decode(const char *, Rune *, size_t); 228 + static Rune utf8decodebyte(char, size_t *); 229 + static char utf8encodebyte(Rune, size_t); 230 + static size_t utf8validate(Rune *, size_t); 231 + 232 + static char *base64dec(const char *); 233 + static char base64dec_getc(const char **); 234 + 235 + static ssize_t xwrite(int, const char *, size_t); 236 + 237 + /* Globals */ 238 + static Term term; 239 + static Selection sel; 240 + static CSIEscape csiescseq; 241 + static STREscape strescseq; 242 + static int iofd = 1; 243 + static int cmdfd; 244 + static pid_t pid; 245 + 246 + static uchar utfbyte[UTF_SIZ + 1] = {0x80, 0, 0xC0, 0xE0, 0xF0}; 247 + static uchar utfmask[UTF_SIZ + 1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8}; 248 + static Rune utfmin[UTF_SIZ + 1] = { 0, 0, 0x80, 0x800, 0x10000}; 249 + static Rune utfmax[UTF_SIZ + 1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF}; 250 + 251 + ssize_t 252 + xwrite(int fd, const char *s, size_t len) 253 + { 254 + size_t aux = len; 255 + ssize_t r; 256 + 257 + while (len > 0) { 258 + r = write(fd, s, len); 259 + if (r < 0) 260 + return r; 261 + len -= r; 262 + s += r; 263 + } 264 + 265 + return aux; 266 + } 267 + 268 + void * 269 + xmalloc(size_t len) 270 + { 271 + void *p; 272 + 273 + if (!(p = malloc(len))) 274 + die("malloc: %s\n", strerror(errno)); 275 + 276 + return p; 277 + } 278 + 279 + void * 280 + xrealloc(void *p, size_t len) 281 + { 282 + if ((p = realloc(p, len)) == NULL) 283 + die("realloc: %s\n", strerror(errno)); 284 + 285 + return p; 286 + } 287 + 288 + char * 289 + xstrdup(char *s) 290 + { 291 + if ((s = strdup(s)) == NULL) 292 + die("strdup: %s\n", strerror(errno)); 293 + 294 + return s; 295 + } 296 + 297 + size_t 298 + utf8decode(const char *c, Rune *u, size_t clen) 299 + { 300 + size_t i, j, len, type; 301 + Rune udecoded; 302 + 303 + *u = UTF_INVALID; 304 + if (!clen) 305 + return 0; 306 + udecoded = utf8decodebyte(c[0], &len); 307 + if (!BETWEEN(len, 1, UTF_SIZ)) 308 + return 1; 309 + for (i = 1, j = 1; i < clen && j < len; ++i, ++j) { 310 + udecoded = (udecoded << 6) | utf8decodebyte(c[i], &type); 311 + if (type != 0) 312 + return j; 313 + } 314 + if (j < len) 315 + return 0; 316 + *u = udecoded; 317 + utf8validate(u, len); 318 + 319 + return len; 320 + } 321 + 322 + Rune 323 + utf8decodebyte(char c, size_t *i) 324 + { 325 + for (*i = 0; *i < LEN(utfmask); ++(*i)) 326 + if (((uchar)c & utfmask[*i]) == utfbyte[*i]) 327 + return (uchar)c & ~utfmask[*i]; 328 + 329 + return 0; 330 + } 331 + 332 + size_t 333 + utf8encode(Rune u, char *c) 334 + { 335 + size_t len, i; 336 + 337 + len = utf8validate(&u, 0); 338 + if (len > UTF_SIZ) 339 + return 0; 340 + 341 + for (i = len - 1; i != 0; --i) { 342 + c[i] = utf8encodebyte(u, 0); 343 + u >>= 6; 344 + } 345 + c[0] = utf8encodebyte(u, len); 346 + 347 + return len; 348 + } 349 + 350 + char 351 + utf8encodebyte(Rune u, size_t i) 352 + { 353 + return utfbyte[i] | (u & ~utfmask[i]); 354 + } 355 + 356 + size_t 357 + utf8validate(Rune *u, size_t i) 358 + { 359 + if (!BETWEEN(*u, utfmin[i], utfmax[i]) || BETWEEN(*u, 0xD800, 0xDFFF)) 360 + *u = UTF_INVALID; 361 + for (i = 1; *u > utfmax[i]; ++i) 362 + ; 363 + 364 + return i; 365 + } 366 + 367 + static const char base64_digits[] = { 368 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 369 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 0, 0, 370 + 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 0, 0, 0, -1, 0, 0, 0, 0, 1, 371 + 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 372 + 22, 23, 24, 25, 0, 0, 0, 0, 0, 0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 373 + 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 0, 374 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 375 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 376 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 377 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 378 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 379 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 380 + }; 381 + 382 + char 383 + base64dec_getc(const char **src) 384 + { 385 + while (**src && !isprint(**src)) (*src)++; 386 + return *((*src)++); 387 + } 388 + 389 + char * 390 + base64dec(const char *src) 391 + { 392 + size_t in_len = strlen(src); 393 + char *result, *dst; 394 + 395 + if (in_len % 4) 396 + in_len += 4 - (in_len % 4); 397 + result = dst = xmalloc(in_len / 4 * 3 + 1); 398 + while (*src) { 399 + int a = base64_digits[(unsigned char) base64dec_getc(&src)]; 400 + int b = base64_digits[(unsigned char) base64dec_getc(&src)]; 401 + int c = base64_digits[(unsigned char) base64dec_getc(&src)]; 402 + int d = base64_digits[(unsigned char) base64dec_getc(&src)]; 403 + 404 + *dst++ = (a << 2) | ((b & 0x30) >> 4); 405 + if (c == -1) 406 + break; 407 + *dst++ = ((b & 0x0f) << 4) | ((c & 0x3c) >> 2); 408 + if (d == -1) 409 + break; 410 + *dst++ = ((c & 0x03) << 6) | d; 411 + } 412 + *dst = '\0'; 413 + return result; 414 + } 415 + 416 + void 417 + selinit(void) 418 + { 419 + sel.mode = SEL_IDLE; 420 + sel.snap = 0; 421 + sel.ob.x = -1; 422 + } 423 + 424 + int 425 + tlinelen(int y) 426 + { 427 + int i = term.col; 428 + 429 + if (TLINE(y)[i - 1].mode & ATTR_WRAP) 430 + return i; 431 + 432 + while (i > 0 && TLINE(y)[i - 1].u == ' ') 433 + --i; 434 + 435 + return i; 436 + } 437 + 438 + int 439 + tlinehistlen(int y) 440 + { 441 + int i = term.col; 442 + 443 + if (TLINE_HIST(y)[i - 1].mode & ATTR_WRAP) 444 + return i; 445 + 446 + while (i > 0 && TLINE_HIST(y)[i - 1].u == ' ') 447 + --i; 448 + 449 + return i; 450 + } 451 + 452 + void 453 + selstart(int col, int row, int snap) 454 + { 455 + selclear(); 456 + sel.mode = SEL_EMPTY; 457 + sel.type = SEL_REGULAR; 458 + sel.alt = IS_SET(MODE_ALTSCREEN); 459 + sel.snap = snap; 460 + sel.oe.x = sel.ob.x = col; 461 + sel.oe.y = sel.ob.y = row; 462 + selnormalize(); 463 + 464 + if (sel.snap != 0) 465 + sel.mode = SEL_READY; 466 + tsetdirt(sel.nb.y, sel.ne.y); 467 + } 468 + 469 + void 470 + selextend(int col, int row, int type, int done) 471 + { 472 + int oldey, oldex, oldsby, oldsey, oldtype; 473 + 474 + if (sel.mode == SEL_IDLE) 475 + return; 476 + if (done && sel.mode == SEL_EMPTY) { 477 + selclear(); 478 + return; 479 + } 480 + 481 + oldey = sel.oe.y; 482 + oldex = sel.oe.x; 483 + oldsby = sel.nb.y; 484 + oldsey = sel.ne.y; 485 + oldtype = sel.type; 486 + 487 + sel.oe.x = col; 488 + sel.oe.y = row; 489 + selnormalize(); 490 + sel.type = type; 491 + 492 + if (oldey != sel.oe.y || oldex != sel.oe.x || oldtype != sel.type || sel.mode == SEL_EMPTY) 493 + tsetdirt(MIN(sel.nb.y, oldsby), MAX(sel.ne.y, oldsey)); 494 + 495 + sel.mode = done ? SEL_IDLE : SEL_READY; 496 + } 497 + 498 + void 499 + selnormalize(void) 500 + { 501 + int i; 502 + 503 + if (sel.type == SEL_REGULAR && sel.ob.y != sel.oe.y) { 504 + sel.nb.x = sel.ob.y < sel.oe.y ? sel.ob.x : sel.oe.x; 505 + sel.ne.x = sel.ob.y < sel.oe.y ? sel.oe.x : sel.ob.x; 506 + } else { 507 + sel.nb.x = MIN(sel.ob.x, sel.oe.x); 508 + sel.ne.x = MAX(sel.ob.x, sel.oe.x); 509 + } 510 + sel.nb.y = MIN(sel.ob.y, sel.oe.y); 511 + sel.ne.y = MAX(sel.ob.y, sel.oe.y); 512 + 513 + selsnap(&sel.nb.x, &sel.nb.y, -1); 514 + selsnap(&sel.ne.x, &sel.ne.y, +1); 515 + 516 + /* expand selection over line breaks */ 517 + if (sel.type == SEL_RECTANGULAR) 518 + return; 519 + i = tlinelen(sel.nb.y); 520 + if (i < sel.nb.x) 521 + sel.nb.x = i; 522 + if (tlinelen(sel.ne.y) <= sel.ne.x) 523 + sel.ne.x = term.col - 1; 524 + } 525 + 526 + int 527 + selected(int x, int y) 528 + { 529 + if (sel.mode == SEL_EMPTY || sel.ob.x == -1 || 530 + sel.alt != IS_SET(MODE_ALTSCREEN)) 531 + return 0; 532 + 533 + if (sel.type == SEL_RECTANGULAR) 534 + return BETWEEN(y, sel.nb.y, sel.ne.y) 535 + && BETWEEN(x, sel.nb.x, sel.ne.x); 536 + 537 + return BETWEEN(y, sel.nb.y, sel.ne.y) 538 + && (y != sel.nb.y || x >= sel.nb.x) 539 + && (y != sel.ne.y || x <= sel.ne.x); 540 + } 541 + 542 + void 543 + selsnap(int *x, int *y, int direction) 544 + { 545 + int newx, newy, xt, yt; 546 + int delim, prevdelim; 547 + Glyph *gp, *prevgp; 548 + 549 + switch (sel.snap) { 550 + case SNAP_WORD: 551 + /* 552 + * Snap around if the word wraps around at the end or 553 + * beginning of a line. 554 + */ 555 + prevgp = &TLINE(*y)[*x]; 556 + prevdelim = ISDELIM(prevgp->u); 557 + for (;;) { 558 + newx = *x + direction; 559 + newy = *y; 560 + if (!BETWEEN(newx, 0, term.col - 1)) { 561 + newy += direction; 562 + newx = (newx + term.col) % term.col; 563 + if (!BETWEEN(newy, 0, term.row - 1)) 564 + break; 565 + 566 + if (direction > 0) 567 + yt = *y, xt = *x; 568 + else 569 + yt = newy, xt = newx; 570 + if (!(TLINE(yt)[xt].mode & ATTR_WRAP)) 571 + break; 572 + } 573 + 574 + if (newx >= tlinelen(newy)) 575 + break; 576 + 577 + gp = &TLINE(newy)[newx]; 578 + delim = ISDELIM(gp->u); 579 + if (!(gp->mode & ATTR_WDUMMY) && (delim != prevdelim 580 + || (delim && gp->u != prevgp->u))) 581 + break; 582 + 583 + *x = newx; 584 + *y = newy; 585 + prevgp = gp; 586 + prevdelim = delim; 587 + } 588 + break; 589 + case SNAP_LINE: 590 + /* 591 + * Snap around if the the previous line or the current one 592 + * has set ATTR_WRAP at its end. Then the whole next or 593 + * previous line will be selected. 594 + */ 595 + *x = (direction < 0) ? 0 : term.col - 1; 596 + if (direction < 0) { 597 + for (; *y > 0; *y += direction) { 598 + if (!(TLINE(*y-1)[term.col-1].mode 599 + & ATTR_WRAP)) { 600 + break; 601 + } 602 + } 603 + } else if (direction > 0) { 604 + for (; *y < term.row-1; *y += direction) { 605 + if (!(TLINE(*y)[term.col-1].mode 606 + & ATTR_WRAP)) { 607 + break; 608 + } 609 + } 610 + } 611 + break; 612 + } 613 + } 614 + 615 + char * 616 + getsel(void) 617 + { 618 + char *str, *ptr; 619 + int y, bufsize, lastx, linelen; 620 + Glyph *gp, *last; 621 + 622 + if (sel.ob.x == -1) 623 + return NULL; 624 + 625 + bufsize = (term.col+1) * (sel.ne.y-sel.nb.y+1) * UTF_SIZ; 626 + ptr = str = xmalloc(bufsize); 627 + 628 + /* append every set & selected glyph to the selection */ 629 + for (y = sel.nb.y; y <= sel.ne.y; y++) { 630 + if ((linelen = tlinelen(y)) == 0) { 631 + *ptr++ = '\n'; 632 + continue; 633 + } 634 + 635 + if (sel.type == SEL_RECTANGULAR) { 636 + gp = &TLINE(y)[sel.nb.x]; 637 + lastx = sel.ne.x; 638 + } else { 639 + gp = &TLINE(y)[sel.nb.y == y ? sel.nb.x : 0]; 640 + lastx = (sel.ne.y == y) ? sel.ne.x : term.col-1; 641 + } 642 + last = &TLINE(y)[MIN(lastx, linelen-1)]; 643 + while (last >= gp && last->u == ' ') 644 + --last; 645 + 646 + for ( ; gp <= last; ++gp) { 647 + if (gp->mode & ATTR_WDUMMY) 648 + continue; 649 + 650 + ptr += utf8encode(gp->u, ptr); 651 + } 652 + 653 + /* 654 + * Copy and pasting of line endings is inconsistent 655 + * in the inconsistent terminal and GUI world. 656 + * The best solution seems like to produce '\n' when 657 + * something is copied from st and convert '\n' to 658 + * '\r', when something to be pasted is received by 659 + * st. 660 + * FIXME: Fix the computer world. 661 + */ 662 + if ((y < sel.ne.y || lastx >= linelen) && !(last->mode & ATTR_WRAP)) 663 + *ptr++ = '\n'; 664 + } 665 + *ptr = 0; 666 + return str; 667 + } 668 + 669 + void 670 + selclear(void) 671 + { 672 + if (sel.ob.x == -1) 673 + return; 674 + sel.mode = SEL_IDLE; 675 + sel.ob.x = -1; 676 + tsetdirt(sel.nb.y, sel.ne.y); 677 + } 678 + 679 + void 680 + die(const char *errstr, ...) 681 + { 682 + va_list ap; 683 + 684 + va_start(ap, errstr); 685 + vfprintf(stderr, errstr, ap); 686 + va_end(ap); 687 + exit(1); 688 + } 689 + 690 + void 691 + execsh(char *cmd, char **args) 692 + { 693 + char *sh, *prog; 694 + const struct passwd *pw; 695 + 696 + errno = 0; 697 + if ((pw = getpwuid(getuid())) == NULL) { 698 + if (errno) 699 + die("getpwuid: %s\n", strerror(errno)); 700 + else 701 + die("who are you?\n"); 702 + } 703 + 704 + if ((sh = getenv("SHELL")) == NULL) 705 + sh = (pw->pw_shell[0]) ? pw->pw_shell : cmd; 706 + 707 + if (args) 708 + prog = args[0]; 709 + else if (utmp) 710 + prog = utmp; 711 + else 712 + prog = sh; 713 + DEFAULT(args, ((char *[]) {prog, NULL})); 714 + 715 + unsetenv("COLUMNS"); 716 + unsetenv("LINES"); 717 + unsetenv("TERMCAP"); 718 + setenv("LOGNAME", pw->pw_name, 1); 719 + setenv("USER", pw->pw_name, 1); 720 + setenv("SHELL", sh, 1); 721 + setenv("HOME", pw->pw_dir, 1); 722 + setenv("TERM", termname, 1); 723 + 724 + signal(SIGCHLD, SIG_DFL); 725 + signal(SIGHUP, SIG_DFL); 726 + signal(SIGINT, SIG_DFL); 727 + signal(SIGQUIT, SIG_DFL); 728 + signal(SIGTERM, SIG_DFL); 729 + signal(SIGALRM, SIG_DFL); 730 + 731 + execvp(prog, args); 732 + _exit(1); 733 + } 734 + 735 + void 736 + sigchld(int a) 737 + { 738 + int stat; 739 + pid_t p; 740 + 741 + if ((p = waitpid(pid, &stat, WNOHANG)) < 0) 742 + die("waiting for pid %hd failed: %s\n", pid, strerror(errno)); 743 + 744 + if (pid != p) 745 + return; 746 + 747 + if (WIFEXITED(stat) && WEXITSTATUS(stat)) 748 + die("child exited with status %d\n", WEXITSTATUS(stat)); 749 + else if (WIFSIGNALED(stat)) 750 + die("child terminated due to signal %d\n", WTERMSIG(stat)); 751 + exit(0); 752 + } 753 + 754 + void 755 + stty(char **args) 756 + { 757 + char cmd[_POSIX_ARG_MAX], **p, *q, *s; 758 + size_t n, siz; 759 + 760 + if ((n = strlen(stty_args)) > sizeof(cmd)-1) 761 + die("incorrect stty parameters\n"); 762 + memcpy(cmd, stty_args, n); 763 + q = cmd + n; 764 + siz = sizeof(cmd) - n; 765 + for (p = args; p && (s = *p); ++p) { 766 + if ((n = strlen(s)) > siz-1) 767 + die("stty parameter length too long\n"); 768 + *q++ = ' '; 769 + memcpy(q, s, n); 770 + q += n; 771 + siz -= n + 1; 772 + } 773 + *q = '\0'; 774 + if (system(cmd) != 0) 775 + perror("Couldn't call stty"); 776 + } 777 + 778 + int 779 + ttynew(char *line, char *cmd, char *out, char **args) 780 + { 781 + int m, s; 782 + 783 + if (out) { 784 + term.mode |= MODE_PRINT; 785 + iofd = (!strcmp(out, "-")) ? 786 + 1 : open(out, O_WRONLY | O_CREAT, 0666); 787 + if (iofd < 0) { 788 + fprintf(stderr, "Error opening %s:%s\n", 789 + out, strerror(errno)); 790 + } 791 + } 792 + 793 + if (line) { 794 + if ((cmdfd = open(line, O_RDWR)) < 0) 795 + die("open line '%s' failed: %s\n", 796 + line, strerror(errno)); 797 + dup2(cmdfd, 0); 798 + stty(args); 799 + return cmdfd; 800 + } 801 + 802 + /* seems to work fine on linux, openbsd and freebsd */ 803 + if (openpty(&m, &s, NULL, NULL, NULL) < 0) 804 + die("openpty failed: %s\n", strerror(errno)); 805 + 806 + switch (pid = fork()) { 807 + case -1: 808 + die("fork failed: %s\n", strerror(errno)); 809 + break; 810 + case 0: 811 + close(iofd); 812 + setsid(); /* create a new process group */ 813 + dup2(s, 0); 814 + dup2(s, 1); 815 + dup2(s, 2); 816 + if (ioctl(s, TIOCSCTTY, NULL) < 0) 817 + die("ioctl TIOCSCTTY failed: %s\n", strerror(errno)); 818 + close(s); 819 + close(m); 820 + #ifdef __OpenBSD__ 821 + if (pledge("stdio getpw proc exec", NULL) == -1) 822 + die("pledge\n"); 823 + #endif 824 + execsh(cmd, args); 825 + break; 826 + default: 827 + #ifdef __OpenBSD__ 828 + if (pledge("stdio rpath tty proc", NULL) == -1) 829 + die("pledge\n"); 830 + #endif 831 + close(s); 832 + cmdfd = m; 833 + signal(SIGCHLD, sigchld); 834 + break; 835 + } 836 + return cmdfd; 837 + } 838 + 839 + size_t 840 + ttyread(void) 841 + { 842 + static char buf[BUFSIZ]; 843 + static int buflen = 0; 844 + int written; 845 + int ret; 846 + 847 + /* append read bytes to unprocessed bytes */ 848 + if ((ret = read(cmdfd, buf+buflen, LEN(buf)-buflen)) < 0) 849 + die("couldn't read from shell: %s\n", strerror(errno)); 850 + buflen += ret; 851 + 852 + written = twrite(buf, buflen, 0); 853 + buflen -= written; 854 + /* keep any uncomplete utf8 char for the next call */ 855 + if (buflen > 0) 856 + memmove(buf, buf + written, buflen); 857 + 858 + return ret; 859 + } 860 + 861 + void 862 + ttywrite(const char *s, size_t n, int may_echo) 863 + { 864 + const char *next; 865 + Arg arg = (Arg) { .i = term.scr }; 866 + 867 + kscrolldown(&arg); 868 + 869 + if (may_echo && IS_SET(MODE_ECHO)) 870 + twrite(s, n, 1); 871 + 872 + if (!IS_SET(MODE_CRLF)) { 873 + ttywriteraw(s, n); 874 + return; 875 + } 876 + 877 + /* This is similar to how the kernel handles ONLCR for ttys */ 878 + while (n > 0) { 879 + if (*s == '\r') { 880 + next = s + 1; 881 + ttywriteraw("\r\n", 2); 882 + } else { 883 + next = memchr(s, '\r', n); 884 + DEFAULT(next, s + n); 885 + ttywriteraw(s, next - s); 886 + } 887 + n -= next - s; 888 + s = next; 889 + } 890 + } 891 + 892 + void 893 + ttywriteraw(const char *s, size_t n) 894 + { 895 + fd_set wfd, rfd; 896 + ssize_t r; 897 + size_t lim = 256; 898 + 899 + /* 900 + * Remember that we are using a pty, which might be a modem line. 901 + * Writing too much will clog the line. That's why we are doing this 902 + * dance. 903 + * FIXME: Migrate the world to Plan 9. 904 + */ 905 + while (n > 0) { 906 + FD_ZERO(&wfd); 907 + FD_ZERO(&rfd); 908 + FD_SET(cmdfd, &wfd); 909 + FD_SET(cmdfd, &rfd); 910 + 911 + /* Check if we can write. */ 912 + if (pselect(cmdfd+1, &rfd, &wfd, NULL, NULL, NULL) < 0) { 913 + if (errno == EINTR) 914 + continue; 915 + die("select failed: %s\n", strerror(errno)); 916 + } 917 + if (FD_ISSET(cmdfd, &wfd)) { 918 + /* 919 + * Only write the bytes written by ttywrite() or the 920 + * default of 256. This seems to be a reasonable value 921 + * for a serial line. Bigger values might clog the I/O. 922 + */ 923 + if ((r = write(cmdfd, s, (n < lim)? n : lim)) < 0) 924 + goto write_error; 925 + if (r < n) { 926 + /* 927 + * We weren't able to write out everything. 928 + * This means the buffer is getting full 929 + * again. Empty it. 930 + */ 931 + if (n < lim) 932 + lim = ttyread(); 933 + n -= r; 934 + s += r; 935 + } else { 936 + /* All bytes have been written. */ 937 + break; 938 + } 939 + } 940 + if (FD_ISSET(cmdfd, &rfd)) 941 + lim = ttyread(); 942 + } 943 + return; 944 + 945 + write_error: 946 + die("write error on tty: %s\n", strerror(errno)); 947 + } 948 + 949 + void 950 + ttyresize(int tw, int th) 951 + { 952 + struct winsize w; 953 + 954 + w.ws_row = term.row; 955 + w.ws_col = term.col; 956 + w.ws_xpixel = tw; 957 + w.ws_ypixel = th; 958 + if (ioctl(cmdfd, TIOCSWINSZ, &w) < 0) 959 + fprintf(stderr, "Couldn't set window size: %s\n", strerror(errno)); 960 + } 961 + 962 + void 963 + ttyhangup() 964 + { 965 + /* Send SIGHUP to shell */ 966 + kill(pid, SIGHUP); 967 + } 968 + 969 + int 970 + tattrset(int attr) 971 + { 972 + int i, j; 973 + 974 + for (i = 0; i < term.row-1; i++) { 975 + for (j = 0; j < term.col-1; j++) { 976 + if (term.line[i][j].mode & attr) 977 + return 1; 978 + } 979 + } 980 + 981 + return 0; 982 + } 983 + 984 + void 985 + tsetdirt(int top, int bot) 986 + { 987 + int i; 988 + 989 + LIMIT(top, 0, term.row-1); 990 + LIMIT(bot, 0, term.row-1); 991 + 992 + for (i = top; i <= bot; i++) 993 + term.dirty[i] = 1; 994 + } 995 + 996 + void 997 + tsetdirtattr(int attr) 998 + { 999 + int i, j; 1000 + 1001 + for (i = 0; i < term.row-1; i++) { 1002 + for (j = 0; j < term.col-1; j++) { 1003 + if (term.line[i][j].mode & attr) { 1004 + tsetdirt(i, i); 1005 + break; 1006 + } 1007 + } 1008 + } 1009 + } 1010 + 1011 + void 1012 + tfulldirt(void) 1013 + { 1014 + tsetdirt(0, term.row-1); 1015 + } 1016 + 1017 + void 1018 + tcursor(int mode) 1019 + { 1020 + static TCursor c[2]; 1021 + int alt = IS_SET(MODE_ALTSCREEN); 1022 + 1023 + if (mode == CURSOR_SAVE) { 1024 + c[alt] = term.c; 1025 + } else if (mode == CURSOR_LOAD) { 1026 + term.c = c[alt]; 1027 + tmoveto(c[alt].x, c[alt].y); 1028 + } 1029 + } 1030 + 1031 + void 1032 + treset(void) 1033 + { 1034 + uint i; 1035 + 1036 + term.c = (TCursor){{ 1037 + .mode = ATTR_NULL, 1038 + .fg = defaultfg, 1039 + .bg = defaultbg 1040 + }, .x = 0, .y = 0, .state = CURSOR_DEFAULT}; 1041 + 1042 + memset(term.tabs, 0, term.col * sizeof(*term.tabs)); 1043 + for (i = tabspaces; i < term.col; i += tabspaces) 1044 + term.tabs[i] = 1; 1045 + term.top = 0; 1046 + term.bot = term.row - 1; 1047 + term.mode = MODE_WRAP|MODE_UTF8; 1048 + memset(term.trantbl, CS_USA, sizeof(term.trantbl)); 1049 + term.charset = 0; 1050 + 1051 + for (i = 0; i < 2; i++) { 1052 + tmoveto(0, 0); 1053 + tcursor(CURSOR_SAVE); 1054 + tclearregion(0, 0, term.col-1, term.row-1); 1055 + tswapscreen(); 1056 + } 1057 + } 1058 + 1059 + void 1060 + tnew(int col, int row) 1061 + { 1062 + term = (Term){ .c = { .attr = { .fg = defaultfg, .bg = defaultbg } } }; 1063 + clock_gettime(CLOCK_MONOTONIC, &term.last_ximspot_update); 1064 + tresize(col, row); 1065 + treset(); 1066 + } 1067 + 1068 + int tisaltscr(void) 1069 + { 1070 + return IS_SET(MODE_ALTSCREEN); 1071 + } 1072 + 1073 + void 1074 + tswapscreen(void) 1075 + { 1076 + Line *tmp = term.line; 1077 + 1078 + term.line = term.alt; 1079 + term.alt = tmp; 1080 + term.mode ^= MODE_ALTSCREEN; 1081 + tfulldirt(); 1082 + } 1083 + 1084 + void 1085 + newterm(const Arg* a) 1086 + { 1087 + switch (fork()) { 1088 + case -1: 1089 + die("fork failed: %s\n", strerror(errno)); 1090 + break; 1091 + case 0: 1092 + chdir(getcwd_by_pid(pid)); 1093 + execlp("st", "./st", NULL); 1094 + break; 1095 + } 1096 + } 1097 + 1098 + static char *getcwd_by_pid(pid_t pid) { 1099 + char buf[32]; 1100 + snprintf(buf, sizeof buf, "/proc/%d/cwd", pid); 1101 + return realpath(buf, NULL); 1102 + } 1103 + 1104 + void 1105 + kscrolldown(const Arg* a) 1106 + { 1107 + int n = a->i; 1108 + 1109 + if (n < 0) 1110 + n = term.row + n; 1111 + 1112 + if (n > term.scr) 1113 + n = term.scr; 1114 + 1115 + if (term.scr > 0) { 1116 + term.scr -= n; 1117 + selscroll(0, -n); 1118 + tfulldirt(); 1119 + } 1120 + } 1121 + 1122 + void 1123 + kscrollup(const Arg* a) 1124 + { 1125 + int n = a->i; 1126 + 1127 + if (n < 0) 1128 + n = term.row + n; 1129 + 1130 + if (term.scr <= HISTSIZE-n) { 1131 + term.scr += n; 1132 + selscroll(0, n); 1133 + tfulldirt(); 1134 + } 1135 + } 1136 + 1137 + void 1138 + tscrolldown(int orig, int n, int copyhist) 1139 + { 1140 + int i; 1141 + Line temp; 1142 + 1143 + LIMIT(n, 0, term.bot-orig+1); 1144 + 1145 + if (copyhist) { 1146 + term.histi = (term.histi - 1 + HISTSIZE) % HISTSIZE; 1147 + temp = term.hist[term.histi]; 1148 + term.hist[term.histi] = term.line[term.bot]; 1149 + term.line[term.bot] = temp; 1150 + } 1151 + 1152 + tsetdirt(orig, term.bot-n); 1153 + tclearregion(0, term.bot-n+1, term.col-1, term.bot); 1154 + 1155 + for (i = term.bot; i >= orig+n; i--) { 1156 + temp = term.line[i]; 1157 + term.line[i] = term.line[i-n]; 1158 + term.line[i-n] = temp; 1159 + } 1160 + 1161 + selscroll(orig, n); 1162 + } 1163 + 1164 + void 1165 + tscrollup(int orig, int n, int copyhist) 1166 + { 1167 + int i; 1168 + Line temp; 1169 + 1170 + LIMIT(n, 0, term.bot-orig+1); 1171 + 1172 + if (copyhist) { 1173 + term.histi = (term.histi + 1) % HISTSIZE; 1174 + temp = term.hist[term.histi]; 1175 + term.hist[term.histi] = term.line[orig]; 1176 + term.line[orig] = temp; 1177 + } 1178 + 1179 + if (term.scr > 0 && term.scr < HISTSIZE) 1180 + term.scr = MIN(term.scr + n, HISTSIZE-1); 1181 + 1182 + tclearregion(0, orig, term.col-1, orig+n-1); 1183 + tsetdirt(orig+n, term.bot); 1184 + 1185 + for (i = orig; i <= term.bot-n; i++) { 1186 + temp = term.line[i]; 1187 + term.line[i] = term.line[i+n]; 1188 + term.line[i+n] = temp; 1189 + } 1190 + 1191 + selscroll(orig, -n); 1192 + } 1193 + 1194 + void 1195 + selscroll(int orig, int n) 1196 + { 1197 + if (sel.ob.x == -1) 1198 + return; 1199 + 1200 + if (BETWEEN(sel.ob.y, orig, term.bot) || BETWEEN(sel.oe.y, orig, term.bot)) { 1201 + if ((sel.ob.y += n) > term.bot || (sel.oe.y += n) < term.top) { 1202 + selclear(); 1203 + return; 1204 + } 1205 + if (sel.type == SEL_RECTANGULAR) { 1206 + if (sel.ob.y < term.top) 1207 + sel.ob.y = term.top; 1208 + if (sel.oe.y > term.bot) 1209 + sel.oe.y = term.bot; 1210 + } else { 1211 + if (sel.ob.y < term.top) { 1212 + sel.ob.y = term.top; 1213 + sel.ob.x = 0; 1214 + } 1215 + if (sel.oe.y > term.bot) { 1216 + sel.oe.y = term.bot; 1217 + sel.oe.x = term.col; 1218 + } 1219 + } 1220 + selnormalize(); 1221 + } 1222 + } 1223 + 1224 + void 1225 + tnewline(int first_col) 1226 + { 1227 + int y = term.c.y; 1228 + 1229 + if (y == term.bot) { 1230 + tscrollup(term.top, 1, 1); 1231 + } else { 1232 + y++; 1233 + } 1234 + tmoveto(first_col ? 0 : term.c.x, y); 1235 + } 1236 + 1237 + void 1238 + csiparse(void) 1239 + { 1240 + char *p = csiescseq.buf, *np; 1241 + long int v; 1242 + 1243 + csiescseq.narg = 0; 1244 + if (*p == '?') { 1245 + csiescseq.priv = 1; 1246 + p++; 1247 + } 1248 + 1249 + csiescseq.buf[csiescseq.len] = '\0'; 1250 + while (p < csiescseq.buf+csiescseq.len) { 1251 + np = NULL; 1252 + v = strtol(p, &np, 10); 1253 + if (np == p) 1254 + v = 0; 1255 + if (v == LONG_MAX || v == LONG_MIN) 1256 + v = -1; 1257 + csiescseq.arg[csiescseq.narg++] = v; 1258 + p = np; 1259 + if (*p != ';' || csiescseq.narg == ESC_ARG_SIZ) 1260 + break; 1261 + p++; 1262 + } 1263 + csiescseq.mode[0] = *p++; 1264 + csiescseq.mode[1] = (p < csiescseq.buf+csiescseq.len) ? *p : '\0'; 1265 + } 1266 + 1267 + /* for absolute user moves, when decom is set */ 1268 + void 1269 + tmoveato(int x, int y) 1270 + { 1271 + tmoveto(x, y + ((term.c.state & CURSOR_ORIGIN) ? term.top: 0)); 1272 + } 1273 + 1274 + void 1275 + tmoveto(int x, int y) 1276 + { 1277 + int miny, maxy; 1278 + 1279 + if (term.c.state & CURSOR_ORIGIN) { 1280 + miny = term.top; 1281 + maxy = term.bot; 1282 + } else { 1283 + miny = 0; 1284 + maxy = term.row - 1; 1285 + } 1286 + term.c.state &= ~CURSOR_WRAPNEXT; 1287 + term.c.x = LIMIT(x, 0, term.col-1); 1288 + term.c.y = LIMIT(y, miny, maxy); 1289 + } 1290 + 1291 + void 1292 + tsetchar(Rune u, Glyph *attr, int x, int y) 1293 + { 1294 + static char *vt100_0[62] = { /* 0x41 - 0x7e */ 1295 + "↑", "↓", "→", "←", "█", "▚", "☃", /* A - G */ 1296 + 0, 0, 0, 0, 0, 0, 0, 0, /* H - O */ 1297 + 0, 0, 0, 0, 0, 0, 0, 0, /* P - W */ 1298 + 0, 0, 0, 0, 0, 0, 0, " ", /* X - _ */ 1299 + "◆", "▒", "␉", "␌", "␍", "␊", "°", "±", /* ` - g */ 1300 + "␤", "␋", "┘", "┐", "┌", "└", "┼", "⎺", /* h - o */ 1301 + "⎻", "─", "⎼", "⎽", "├", "┤", "┴", "┬", /* p - w */ 1302 + "│", "≤", "≥", "π", "≠", "£", "·", /* x - ~ */ 1303 + }; 1304 + 1305 + /* 1306 + * The table is proudly stolen from rxvt. 1307 + */ 1308 + if (term.trantbl[term.charset] == CS_GRAPHIC0 && 1309 + BETWEEN(u, 0x41, 0x7e) && vt100_0[u - 0x41]) 1310 + utf8decode(vt100_0[u - 0x41], &u, UTF_SIZ); 1311 + 1312 + if (term.line[y][x].mode & ATTR_WIDE) { 1313 + if (x+1 < term.col) { 1314 + term.line[y][x+1].u = ' '; 1315 + term.line[y][x+1].mode &= ~ATTR_WDUMMY; 1316 + } 1317 + } else if (term.line[y][x].mode & ATTR_WDUMMY) { 1318 + term.line[y][x-1].u = ' '; 1319 + term.line[y][x-1].mode &= ~ATTR_WIDE; 1320 + } 1321 + 1322 + term.dirty[y] = 1; 1323 + term.line[y][x] = *attr; 1324 + term.line[y][x].u = u; 1325 + 1326 + if (isboxdraw(u)) 1327 + term.line[y][x].mode |= ATTR_BOXDRAW; 1328 + } 1329 + 1330 + void 1331 + tclearregion(int x1, int y1, int x2, int y2) 1332 + { 1333 + int x, y, temp; 1334 + Glyph *gp; 1335 + 1336 + if (x1 > x2) 1337 + temp = x1, x1 = x2, x2 = temp; 1338 + if (y1 > y2) 1339 + temp = y1, y1 = y2, y2 = temp; 1340 + 1341 + LIMIT(x1, 0, term.maxcol-1); 1342 + LIMIT(x2, 0, term.maxcol-1); 1343 + LIMIT(y1, 0, term.row-1); 1344 + LIMIT(y2, 0, term.row-1); 1345 + 1346 + for (y = y1; y <= y2; y++) { 1347 + term.dirty[y] = 1; 1348 + for (x = x1; x <= x2; x++) { 1349 + gp = &term.line[y][x]; 1350 + if (selected(x, y)) 1351 + selclear(); 1352 + gp->fg = term.c.attr.fg; 1353 + gp->bg = term.c.attr.bg; 1354 + gp->mode = 0; 1355 + gp->u = ' '; 1356 + } 1357 + } 1358 + } 1359 + 1360 + void 1361 + tdeletechar(int n) 1362 + { 1363 + int dst, src, size; 1364 + Glyph *line; 1365 + 1366 + LIMIT(n, 0, term.col - term.c.x); 1367 + 1368 + dst = term.c.x; 1369 + src = term.c.x + n; 1370 + size = term.col - src; 1371 + line = term.line[term.c.y]; 1372 + 1373 + memmove(&line[dst], &line[src], size * sizeof(Glyph)); 1374 + tclearregion(term.col-n, term.c.y, term.col-1, term.c.y); 1375 + } 1376 + 1377 + void 1378 + tinsertblank(int n) 1379 + { 1380 + int dst, src, size; 1381 + Glyph *line; 1382 + 1383 + LIMIT(n, 0, term.col - term.c.x); 1384 + 1385 + dst = term.c.x + n; 1386 + src = term.c.x; 1387 + size = term.col - dst; 1388 + line = term.line[term.c.y]; 1389 + 1390 + memmove(&line[dst], &line[src], size * sizeof(Glyph)); 1391 + tclearregion(src, term.c.y, dst - 1, term.c.y); 1392 + } 1393 + 1394 + void 1395 + tinsertblankline(int n) 1396 + { 1397 + if (BETWEEN(term.c.y, term.top, term.bot)) 1398 + tscrolldown(term.c.y, n, 0); 1399 + } 1400 + 1401 + void 1402 + tdeleteline(int n) 1403 + { 1404 + if (BETWEEN(term.c.y, term.top, term.bot)) 1405 + tscrollup(term.c.y, n, 0); 1406 + } 1407 + 1408 + int32_t 1409 + tdefcolor(int *attr, int *npar, int l) 1410 + { 1411 + int32_t idx = -1; 1412 + uint r, g, b; 1413 + 1414 + switch (attr[*npar + 1]) { 1415 + case 2: /* direct color in RGB space */ 1416 + if (*npar + 4 >= l) { 1417 + fprintf(stderr, 1418 + "erresc(38): Incorrect number of parameters (%d)\n", 1419 + *npar); 1420 + break; 1421 + } 1422 + r = attr[*npar + 2]; 1423 + g = attr[*npar + 3]; 1424 + b = attr[*npar + 4]; 1425 + *npar += 4; 1426 + if (!BETWEEN(r, 0, 255) || !BETWEEN(g, 0, 255) || !BETWEEN(b, 0, 255)) 1427 + fprintf(stderr, "erresc: bad rgb color (%u,%u,%u)\n", 1428 + r, g, b); 1429 + else 1430 + idx = TRUECOLOR(r, g, b); 1431 + break; 1432 + case 5: /* indexed color */ 1433 + if (*npar + 2 >= l) { 1434 + fprintf(stderr, 1435 + "erresc(38): Incorrect number of parameters (%d)\n", 1436 + *npar); 1437 + break; 1438 + } 1439 + *npar += 2; 1440 + if (!BETWEEN(attr[*npar], 0, 255)) 1441 + fprintf(stderr, "erresc: bad fgcolor %d\n", attr[*npar]); 1442 + else 1443 + idx = attr[*npar]; 1444 + break; 1445 + case 0: /* implemented defined (only foreground) */ 1446 + case 1: /* transparent */ 1447 + case 3: /* direct color in CMY space */ 1448 + case 4: /* direct color in CMYK space */ 1449 + default: 1450 + fprintf(stderr, 1451 + "erresc(38): gfx attr %d unknown\n", attr[*npar]); 1452 + break; 1453 + } 1454 + 1455 + return idx; 1456 + } 1457 + 1458 + void 1459 + tsetattr(int *attr, int l) 1460 + { 1461 + int i; 1462 + int32_t idx; 1463 + 1464 + for (i = 0; i < l; i++) { 1465 + switch (attr[i]) { 1466 + case 0: 1467 + term.c.attr.mode &= ~( 1468 + ATTR_BOLD | 1469 + ATTR_FAINT | 1470 + ATTR_ITALIC | 1471 + ATTR_UNDERLINE | 1472 + ATTR_BLINK | 1473 + ATTR_REVERSE | 1474 + ATTR_INVISIBLE | 1475 + ATTR_STRUCK ); 1476 + term.c.attr.fg = defaultfg; 1477 + term.c.attr.bg = defaultbg; 1478 + break; 1479 + case 1: 1480 + term.c.attr.mode |= ATTR_BOLD; 1481 + break; 1482 + case 2: 1483 + term.c.attr.mode |= ATTR_FAINT; 1484 + break; 1485 + case 3: 1486 + term.c.attr.mode |= ATTR_ITALIC; 1487 + break; 1488 + case 4: 1489 + term.c.attr.mode |= ATTR_UNDERLINE; 1490 + break; 1491 + case 5: /* slow blink */ 1492 + /* FALLTHROUGH */ 1493 + case 6: /* rapid blink */ 1494 + term.c.attr.mode |= ATTR_BLINK; 1495 + break; 1496 + case 7: 1497 + term.c.attr.mode |= ATTR_REVERSE; 1498 + break; 1499 + case 8: 1500 + term.c.attr.mode |= ATTR_INVISIBLE; 1501 + break; 1502 + case 9: 1503 + term.c.attr.mode |= ATTR_STRUCK; 1504 + break; 1505 + case 22: 1506 + term.c.attr.mode &= ~(ATTR_BOLD | ATTR_FAINT); 1507 + break; 1508 + case 23: 1509 + term.c.attr.mode &= ~ATTR_ITALIC; 1510 + break; 1511 + case 24: 1512 + term.c.attr.mode &= ~ATTR_UNDERLINE; 1513 + break; 1514 + case 25: 1515 + term.c.attr.mode &= ~ATTR_BLINK; 1516 + break; 1517 + case 27: 1518 + term.c.attr.mode &= ~ATTR_REVERSE; 1519 + break; 1520 + case 28: 1521 + term.c.attr.mode &= ~ATTR_INVISIBLE; 1522 + break; 1523 + case 29: 1524 + term.c.attr.mode &= ~ATTR_STRUCK; 1525 + break; 1526 + case 38: 1527 + if ((idx = tdefcolor(attr, &i, l)) >= 0) 1528 + term.c.attr.fg = idx; 1529 + break; 1530 + case 39: 1531 + term.c.attr.fg = defaultfg; 1532 + break; 1533 + case 48: 1534 + if ((idx = tdefcolor(attr, &i, l)) >= 0) 1535 + term.c.attr.bg = idx; 1536 + break; 1537 + case 49: 1538 + term.c.attr.bg = defaultbg; 1539 + break; 1540 + default: 1541 + if (BETWEEN(attr[i], 30, 37)) { 1542 + term.c.attr.fg = attr[i] - 30; 1543 + } else if (BETWEEN(attr[i], 40, 47)) { 1544 + term.c.attr.bg = attr[i] - 40; 1545 + } else if (BETWEEN(attr[i], 90, 97)) { 1546 + term.c.attr.fg = attr[i] - 90 + 8; 1547 + } else if (BETWEEN(attr[i], 100, 107)) { 1548 + term.c.attr.bg = attr[i] - 100 + 8; 1549 + } else { 1550 + fprintf(stderr, 1551 + "erresc(default): gfx attr %d unknown\n", 1552 + attr[i]); 1553 + csidump(); 1554 + } 1555 + break; 1556 + } 1557 + } 1558 + } 1559 + 1560 + void 1561 + tsetscroll(int t, int b) 1562 + { 1563 + int temp; 1564 + 1565 + LIMIT(t, 0, term.row-1); 1566 + LIMIT(b, 0, term.row-1); 1567 + if (t > b) { 1568 + temp = t; 1569 + t = b; 1570 + b = temp; 1571 + } 1572 + term.top = t; 1573 + term.bot = b; 1574 + } 1575 + 1576 + void 1577 + tsetmode(int priv, int set, int *args, int narg) 1578 + { 1579 + int alt, *lim; 1580 + 1581 + for (lim = args + narg; args < lim; ++args) { 1582 + if (priv) { 1583 + switch (*args) { 1584 + case 1: /* DECCKM -- Cursor key */ 1585 + xsetmode(set, MODE_APPCURSOR); 1586 + break; 1587 + case 5: /* DECSCNM -- Reverse video */ 1588 + xsetmode(set, MODE_REVERSE); 1589 + break; 1590 + case 6: /* DECOM -- Origin */ 1591 + MODBIT(term.c.state, set, CURSOR_ORIGIN); 1592 + tmoveato(0, 0); 1593 + break; 1594 + case 7: /* DECAWM -- Auto wrap */ 1595 + MODBIT(term.mode, set, MODE_WRAP); 1596 + break; 1597 + case 0: /* Error (IGNORED) */ 1598 + case 2: /* DECANM -- ANSI/VT52 (IGNORED) */ 1599 + case 3: /* DECCOLM -- Column (IGNORED) */ 1600 + case 4: /* DECSCLM -- Scroll (IGNORED) */ 1601 + case 8: /* DECARM -- Auto repeat (IGNORED) */ 1602 + case 18: /* DECPFF -- Printer feed (IGNORED) */ 1603 + case 19: /* DECPEX -- Printer extent (IGNORED) */ 1604 + case 42: /* DECNRCM -- National characters (IGNORED) */ 1605 + case 12: /* att610 -- Start blinking cursor (IGNORED) */ 1606 + break; 1607 + case 25: /* DECTCEM -- Text Cursor Enable Mode */ 1608 + xsetmode(!set, MODE_HIDE); 1609 + break; 1610 + case 9: /* X10 mouse compatibility mode */ 1611 + xsetpointermotion(0); 1612 + xsetmode(0, MODE_MOUSE); 1613 + xsetmode(set, MODE_MOUSEX10); 1614 + break; 1615 + case 1000: /* 1000: report button press */ 1616 + xsetpointermotion(0); 1617 + xsetmode(0, MODE_MOUSE); 1618 + xsetmode(set, MODE_MOUSEBTN); 1619 + break; 1620 + case 1002: /* 1002: report motion on button press */ 1621 + xsetpointermotion(0); 1622 + xsetmode(0, MODE_MOUSE); 1623 + xsetmode(set, MODE_MOUSEMOTION); 1624 + break; 1625 + case 1003: /* 1003: enable all mouse motions */ 1626 + xsetpointermotion(set); 1627 + xsetmode(0, MODE_MOUSE); 1628 + xsetmode(set, MODE_MOUSEMANY); 1629 + break; 1630 + case 1004: /* 1004: send focus events to tty */ 1631 + xsetmode(set, MODE_FOCUS); 1632 + break; 1633 + case 1006: /* 1006: extended reporting mode */ 1634 + xsetmode(set, MODE_MOUSESGR); 1635 + break; 1636 + case 1034: 1637 + xsetmode(set, MODE_8BIT); 1638 + break; 1639 + case 1049: /* swap screen & set/restore cursor as xterm */ 1640 + if (!allowaltscreen) 1641 + break; 1642 + tcursor((set) ? CURSOR_SAVE : CURSOR_LOAD); 1643 + /* FALLTHROUGH */ 1644 + case 47: /* swap screen */ 1645 + case 1047: 1646 + if (!allowaltscreen) 1647 + break; 1648 + alt = IS_SET(MODE_ALTSCREEN); 1649 + if (alt) { 1650 + tclearregion(0, 0, term.col-1, 1651 + term.row-1); 1652 + } 1653 + if (set ^ alt) /* set is always 1 or 0 */ 1654 + tswapscreen(); 1655 + if (*args != 1049) 1656 + break; 1657 + /* FALLTHROUGH */ 1658 + case 1048: 1659 + tcursor((set) ? CURSOR_SAVE : CURSOR_LOAD); 1660 + break; 1661 + case 2004: /* 2004: bracketed paste mode */ 1662 + xsetmode(set, MODE_BRCKTPASTE); 1663 + break; 1664 + /* Not implemented mouse modes. See comments there. */ 1665 + case 1001: /* mouse highlight mode; can hang the 1666 + terminal by design when implemented. */ 1667 + case 1005: /* UTF-8 mouse mode; will confuse 1668 + applications not supporting UTF-8 1669 + and luit. */ 1670 + case 1015: /* urxvt mangled mouse mode; incompatible 1671 + and can be mistaken for other control 1672 + codes. */ 1673 + break; 1674 + default: 1675 + fprintf(stderr, 1676 + "erresc: unknown private set/reset mode %d\n", 1677 + *args); 1678 + break; 1679 + } 1680 + } else { 1681 + switch (*args) { 1682 + case 0: /* Error (IGNORED) */ 1683 + break; 1684 + case 2: 1685 + xsetmode(set, MODE_KBDLOCK); 1686 + break; 1687 + case 4: /* IRM -- Insertion-replacement */ 1688 + MODBIT(term.mode, set, MODE_INSERT); 1689 + break; 1690 + case 12: /* SRM -- Send/Receive */ 1691 + MODBIT(term.mode, !set, MODE_ECHO); 1692 + break; 1693 + case 20: /* LNM -- Linefeed/new line */ 1694 + MODBIT(term.mode, set, MODE_CRLF); 1695 + break; 1696 + default: 1697 + fprintf(stderr, 1698 + "erresc: unknown set/reset mode %d\n", 1699 + *args); 1700 + break; 1701 + } 1702 + } 1703 + } 1704 + } 1705 + 1706 + void 1707 + csihandle(void) 1708 + { 1709 + char buf[40]; 1710 + int len; 1711 + 1712 + switch (csiescseq.mode[0]) { 1713 + default: 1714 + unknown: 1715 + fprintf(stderr, "erresc: unknown csi "); 1716 + csidump(); 1717 + /* die(""); */ 1718 + break; 1719 + case '@': /* ICH -- Insert <n> blank char */ 1720 + DEFAULT(csiescseq.arg[0], 1); 1721 + tinsertblank(csiescseq.arg[0]); 1722 + break; 1723 + case 'A': /* CUU -- Cursor <n> Up */ 1724 + DEFAULT(csiescseq.arg[0], 1); 1725 + tmoveto(term.c.x, term.c.y-csiescseq.arg[0]); 1726 + break; 1727 + case 'B': /* CUD -- Cursor <n> Down */ 1728 + case 'e': /* VPR --Cursor <n> Down */ 1729 + DEFAULT(csiescseq.arg[0], 1); 1730 + tmoveto(term.c.x, term.c.y+csiescseq.arg[0]); 1731 + break; 1732 + case 'i': /* MC -- Media Copy */ 1733 + switch (csiescseq.arg[0]) { 1734 + case 0: 1735 + tdump(); 1736 + break; 1737 + case 1: 1738 + tdumpline(term.c.y); 1739 + break; 1740 + case 2: 1741 + tdumpsel(); 1742 + break; 1743 + case 4: 1744 + term.mode &= ~MODE_PRINT; 1745 + break; 1746 + case 5: 1747 + term.mode |= MODE_PRINT; 1748 + break; 1749 + } 1750 + break; 1751 + case 'c': /* DA -- Device Attributes */ 1752 + if (csiescseq.arg[0] == 0) 1753 + ttywrite(vtiden, strlen(vtiden), 0); 1754 + break; 1755 + case 'C': /* CUF -- Cursor <n> Forward */ 1756 + case 'a': /* HPR -- Cursor <n> Forward */ 1757 + DEFAULT(csiescseq.arg[0], 1); 1758 + tmoveto(term.c.x+csiescseq.arg[0], term.c.y); 1759 + break; 1760 + case 'D': /* CUB -- Cursor <n> Backward */ 1761 + DEFAULT(csiescseq.arg[0], 1); 1762 + tmoveto(term.c.x-csiescseq.arg[0], term.c.y); 1763 + break; 1764 + case 'E': /* CNL -- Cursor <n> Down and first col */ 1765 + DEFAULT(csiescseq.arg[0], 1); 1766 + tmoveto(0, term.c.y+csiescseq.arg[0]); 1767 + break; 1768 + case 'F': /* CPL -- Cursor <n> Up and first col */ 1769 + DEFAULT(csiescseq.arg[0], 1); 1770 + tmoveto(0, term.c.y-csiescseq.arg[0]); 1771 + break; 1772 + case 'g': /* TBC -- Tabulation clear */ 1773 + switch (csiescseq.arg[0]) { 1774 + case 0: /* clear current tab stop */ 1775 + term.tabs[term.c.x] = 0; 1776 + break; 1777 + case 3: /* clear all the tabs */ 1778 + memset(term.tabs, 0, term.col * sizeof(*term.tabs)); 1779 + break; 1780 + default: 1781 + goto unknown; 1782 + } 1783 + break; 1784 + case 'G': /* CHA -- Move to <col> */ 1785 + case '`': /* HPA */ 1786 + DEFAULT(csiescseq.arg[0], 1); 1787 + tmoveto(csiescseq.arg[0]-1, term.c.y); 1788 + break; 1789 + case 'H': /* CUP -- Move to <row> <col> */ 1790 + case 'f': /* HVP */ 1791 + DEFAULT(csiescseq.arg[0], 1); 1792 + DEFAULT(csiescseq.arg[1], 1); 1793 + tmoveato(csiescseq.arg[1]-1, csiescseq.arg[0]-1); 1794 + break; 1795 + case 'I': /* CHT -- Cursor Forward Tabulation <n> tab stops */ 1796 + DEFAULT(csiescseq.arg[0], 1); 1797 + tputtab(csiescseq.arg[0]); 1798 + break; 1799 + case 'J': /* ED -- Clear screen */ 1800 + switch (csiescseq.arg[0]) { 1801 + case 0: /* below */ 1802 + tclearregion(term.c.x, term.c.y, term.col-1, term.c.y); 1803 + if (term.c.y < term.row-1) { 1804 + tclearregion(0, term.c.y+1, term.col-1, 1805 + term.row-1); 1806 + } 1807 + break; 1808 + case 1: /* above */ 1809 + if (term.c.y > 1) 1810 + tclearregion(0, 0, term.col-1, term.c.y-1); 1811 + tclearregion(0, term.c.y, term.c.x, term.c.y); 1812 + break; 1813 + case 2: /* all */ 1814 + tclearregion(0, 0, term.col-1, term.row-1); 1815 + break; 1816 + default: 1817 + goto unknown; 1818 + } 1819 + break; 1820 + case 'K': /* EL -- Clear line */ 1821 + switch (csiescseq.arg[0]) { 1822 + case 0: /* right */ 1823 + tclearregion(term.c.x, term.c.y, term.col-1, 1824 + term.c.y); 1825 + break; 1826 + case 1: /* left */ 1827 + tclearregion(0, term.c.y, term.c.x, term.c.y); 1828 + break; 1829 + case 2: /* all */ 1830 + tclearregion(0, term.c.y, term.col-1, term.c.y); 1831 + break; 1832 + } 1833 + break; 1834 + case 'S': /* SU -- Scroll <n> line up */ 1835 + DEFAULT(csiescseq.arg[0], 1); 1836 + tscrollup(term.top, csiescseq.arg[0], 0); 1837 + break; 1838 + case 'T': /* SD -- Scroll <n> line down */ 1839 + DEFAULT(csiescseq.arg[0], 1); 1840 + tscrolldown(term.top, csiescseq.arg[0], 0); 1841 + break; 1842 + case 'L': /* IL -- Insert <n> blank lines */ 1843 + DEFAULT(csiescseq.arg[0], 1); 1844 + tinsertblankline(csiescseq.arg[0]); 1845 + break; 1846 + case 'l': /* RM -- Reset Mode */ 1847 + tsetmode(csiescseq.priv, 0, csiescseq.arg, csiescseq.narg); 1848 + break; 1849 + case 'M': /* DL -- Delete <n> lines */ 1850 + DEFAULT(csiescseq.arg[0], 1); 1851 + tdeleteline(csiescseq.arg[0]); 1852 + break; 1853 + case 'X': /* ECH -- Erase <n> char */ 1854 + DEFAULT(csiescseq.arg[0], 1); 1855 + tclearregion(term.c.x, term.c.y, 1856 + term.c.x + csiescseq.arg[0] - 1, term.c.y); 1857 + break; 1858 + case 'P': /* DCH -- Delete <n> char */ 1859 + DEFAULT(csiescseq.arg[0], 1); 1860 + tdeletechar(csiescseq.arg[0]); 1861 + break; 1862 + case 'Z': /* CBT -- Cursor Backward Tabulation <n> tab stops */ 1863 + DEFAULT(csiescseq.arg[0], 1); 1864 + tputtab(-csiescseq.arg[0]); 1865 + break; 1866 + case 'd': /* VPA -- Move to <row> */ 1867 + DEFAULT(csiescseq.arg[0], 1); 1868 + tmoveato(term.c.x, csiescseq.arg[0]-1); 1869 + break; 1870 + case 'h': /* SM -- Set terminal mode */ 1871 + tsetmode(csiescseq.priv, 1, csiescseq.arg, csiescseq.narg); 1872 + break; 1873 + case 'm': /* SGR -- Terminal attribute (color) */ 1874 + tsetattr(csiescseq.arg, csiescseq.narg); 1875 + break; 1876 + case 'n': /* DSR – Device Status Report (cursor position) */ 1877 + if (csiescseq.arg[0] == 6) { 1878 + len = snprintf(buf, sizeof(buf),"\033[%i;%iR", 1879 + term.c.y+1, term.c.x+1); 1880 + ttywrite(buf, len, 0); 1881 + } 1882 + break; 1883 + case 'r': /* DECSTBM -- Set Scrolling Region */ 1884 + if (csiescseq.priv) { 1885 + goto unknown; 1886 + } else { 1887 + DEFAULT(csiescseq.arg[0], 1); 1888 + DEFAULT(csiescseq.arg[1], term.row); 1889 + tsetscroll(csiescseq.arg[0]-1, csiescseq.arg[1]-1); 1890 + tmoveato(0, 0); 1891 + } 1892 + break; 1893 + case 's': /* DECSC -- Save cursor position (ANSI.SYS) */ 1894 + tcursor(CURSOR_SAVE); 1895 + break; 1896 + case 'u': /* DECRC -- Restore cursor position (ANSI.SYS) */ 1897 + tcursor(CURSOR_LOAD); 1898 + break; 1899 + case ' ': 1900 + switch (csiescseq.mode[1]) { 1901 + case 'q': /* DECSCUSR -- Set Cursor Style */ 1902 + if (xsetcursor(csiescseq.arg[0])) 1903 + goto unknown; 1904 + break; 1905 + default: 1906 + goto unknown; 1907 + } 1908 + break; 1909 + } 1910 + } 1911 + 1912 + void 1913 + csidump(void) 1914 + { 1915 + int i; 1916 + uint c; 1917 + 1918 + fprintf(stderr, "ESC["); 1919 + for (i = 0; i < csiescseq.len; i++) { 1920 + c = csiescseq.buf[i] & 0xff; 1921 + if (isprint(c)) { 1922 + putc(c, stderr); 1923 + } else if (c == '\n') { 1924 + fprintf(stderr, "(\\n)"); 1925 + } else if (c == '\r') { 1926 + fprintf(stderr, "(\\r)"); 1927 + } else if (c == 0x1b) { 1928 + fprintf(stderr, "(\\e)"); 1929 + } else { 1930 + fprintf(stderr, "(%02x)", c); 1931 + } 1932 + } 1933 + putc('\n', stderr); 1934 + } 1935 + 1936 + void 1937 + csireset(void) 1938 + { 1939 + memset(&csiescseq, 0, sizeof(csiescseq)); 1940 + } 1941 + 1942 + void 1943 + strhandle(void) 1944 + { 1945 + char *p = NULL, *dec; 1946 + int j, narg, par; 1947 + 1948 + term.esc &= ~(ESC_STR_END|ESC_STR); 1949 + strparse(); 1950 + par = (narg = strescseq.narg) ? atoi(strescseq.args[0]) : 0; 1951 + 1952 + switch (strescseq.type) { 1953 + case ']': /* OSC -- Operating System Command */ 1954 + switch (par) { 1955 + case 0: 1956 + case 1: 1957 + case 2: 1958 + if (narg > 1) 1959 + xsettitle(strescseq.args[1]); 1960 + return; 1961 + case 52: 1962 + if (narg > 2) { 1963 + dec = base64dec(strescseq.args[2]); 1964 + if (dec) { 1965 + xsetsel(dec); 1966 + xclipcopy(); 1967 + } else { 1968 + fprintf(stderr, "erresc: invalid base64\n"); 1969 + } 1970 + } 1971 + return; 1972 + case 4: /* color set */ 1973 + case 10: /* foreground set */ 1974 + case 11: /* background set */ 1975 + case 12: /* cursor color */ 1976 + if ((par == 4 && narg < 3) || narg < 2) 1977 + break; 1978 + p = strescseq.args[((par == 4) ? 2 : 1)]; 1979 + /* FALLTHROUGH */ 1980 + case 104: /* color reset, here p = NULL */ 1981 + if (par == 10) 1982 + j = defaultfg; 1983 + else if (par == 11) 1984 + j = defaultbg; 1985 + else if (par == 12) 1986 + j = defaultcs; 1987 + else 1988 + j = (narg > 1) ? atoi(strescseq.args[1]) : -1; 1989 + 1990 + if (xsetcolorname(j, p)) { 1991 + if (par == 104 && narg <= 1) 1992 + return; /* color reset without parameter */ 1993 + fprintf(stderr, "erresc: invalid color j=%d, p=%s\n", 1994 + j, p ? p : "(null)"); 1995 + } else { 1996 + /* 1997 + * TODO if defaultbg color is changed, borders 1998 + * are dirty 1999 + */ 2000 + if (j == defaultbg) 2001 + xclearwin(); 2002 + redraw(); 2003 + } 2004 + return; 2005 + } 2006 + break; 2007 + case 'k': /* old title set compatibility */ 2008 + xsettitle(strescseq.args[0]); 2009 + return; 2010 + case 'P': /* DCS -- Device Control String */ 2011 + term.mode |= ESC_DCS; 2012 + case '_': /* APC -- Application Program Command */ 2013 + case '^': /* PM -- Privacy Message */ 2014 + return; 2015 + } 2016 + 2017 + fprintf(stderr, "erresc: unknown str "); 2018 + strdump(); 2019 + } 2020 + 2021 + void 2022 + strparse(void) 2023 + { 2024 + int c; 2025 + char *p = strescseq.buf; 2026 + 2027 + strescseq.narg = 0; 2028 + strescseq.buf[strescseq.len] = '\0'; 2029 + 2030 + if (*p == '\0') 2031 + return; 2032 + 2033 + while (strescseq.narg < STR_ARG_SIZ) { 2034 + strescseq.args[strescseq.narg++] = p; 2035 + while ((c = *p) != ';' && c != '\0') 2036 + ++p; 2037 + if (c == '\0') 2038 + return; 2039 + *p++ = '\0'; 2040 + } 2041 + } 2042 + 2043 + void 2044 + strdump(void) 2045 + { 2046 + int i; 2047 + uint c; 2048 + 2049 + fprintf(stderr, "ESC%c", strescseq.type); 2050 + for (i = 0; i < strescseq.len; i++) { 2051 + c = strescseq.buf[i] & 0xff; 2052 + if (c == '\0') { 2053 + putc('\n', stderr); 2054 + return; 2055 + } else if (isprint(c)) { 2056 + putc(c, stderr); 2057 + } else if (c == '\n') { 2058 + fprintf(stderr, "(\\n)"); 2059 + } else if (c == '\r') { 2060 + fprintf(stderr, "(\\r)"); 2061 + } else if (c == 0x1b) { 2062 + fprintf(stderr, "(\\e)"); 2063 + } else { 2064 + fprintf(stderr, "(%02x)", c); 2065 + } 2066 + } 2067 + fprintf(stderr, "ESC\\\n"); 2068 + } 2069 + 2070 + void 2071 + strreset(void) 2072 + { 2073 + memset(&strescseq, 0, sizeof(strescseq)); 2074 + } 2075 + 2076 + void 2077 + sendbreak(const Arg *arg) 2078 + { 2079 + if (tcsendbreak(cmdfd, 0)) 2080 + perror("Error sending break"); 2081 + } 2082 + 2083 + void 2084 + tprinter(char *s, size_t len) 2085 + { 2086 + if (iofd != -1 && xwrite(iofd, s, len) < 0) { 2087 + perror("Error writing to output file"); 2088 + close(iofd); 2089 + iofd = -1; 2090 + } 2091 + } 2092 + 2093 + void 2094 + externalpipe(const Arg *arg) 2095 + { 2096 + int to[2]; 2097 + char buf[UTF_SIZ]; 2098 + void (*oldsigpipe)(int); 2099 + Glyph *bp, *end; 2100 + int lastpos, n, newline; 2101 + 2102 + if (pipe(to) == -1) 2103 + return; 2104 + 2105 + switch (fork()) { 2106 + case -1: 2107 + close(to[0]); 2108 + close(to[1]); 2109 + return; 2110 + case 0: 2111 + dup2(to[0], STDIN_FILENO); 2112 + close(to[0]); 2113 + close(to[1]); 2114 + execvp(((char **)arg->v)[0], (char **)arg->v); 2115 + fprintf(stderr, "st: execvp %s\n", ((char **)arg->v)[0]); 2116 + perror("failed"); 2117 + exit(0); 2118 + } 2119 + 2120 + close(to[0]); 2121 + /* ignore sigpipe for now, in case child exists early */ 2122 + oldsigpipe = signal(SIGPIPE, SIG_IGN); 2123 + newline = 0; 2124 + /* modify externalpipe patch to pipe history too */ 2125 + for (n = 0; n <= HISTSIZE + 2; n++) { 2126 + bp = TLINE_HIST(n); 2127 + lastpos = MIN(tlinehistlen(n) +1, term.col) - 1; 2128 + if (lastpos < 0) 2129 + break; 2130 + if (lastpos == 0) 2131 + continue; 2132 + end = &bp[lastpos + 1]; 2133 + for (; bp < end; ++bp) 2134 + if (xwrite(to[1], buf, utf8encode(bp->u, buf)) < 0) 2135 + break; 2136 + if ((newline = TLINE_HIST(n)[lastpos].mode & ATTR_WRAP)) 2137 + continue; 2138 + if (xwrite(to[1], "\n", 1) < 0) 2139 + break; 2140 + newline = 0; 2141 + } 2142 + if (newline) 2143 + (void)xwrite(to[1], "\n", 1); 2144 + close(to[1]); 2145 + /* restore */ 2146 + signal(SIGPIPE, oldsigpipe); 2147 + } 2148 + 2149 + void 2150 + iso14755(const Arg *arg) 2151 + { 2152 + FILE *p; 2153 + char *us, *e, codepoint[9], uc[UTF_SIZ]; 2154 + unsigned long utf32; 2155 + 2156 + if (!(p = popen(ISO14755CMD, "r"))) 2157 + return; 2158 + 2159 + us = fgets(codepoint, sizeof(codepoint), p); 2160 + pclose(p); 2161 + 2162 + if (!us || *us == '\0' || *us == '-' || strlen(us) > 7) 2163 + return; 2164 + if ((utf32 = strtoul(us, &e, 16)) == ULONG_MAX || 2165 + (*e != '\n' && *e != '\0')) 2166 + return; 2167 + 2168 + ttywrite(uc, utf8encode(utf32, uc), 1); 2169 + } 2170 + 2171 + void 2172 + toggleprinter(const Arg *arg) 2173 + { 2174 + term.mode ^= MODE_PRINT; 2175 + } 2176 + 2177 + void 2178 + printscreen(const Arg *arg) 2179 + { 2180 + tdump(); 2181 + } 2182 + 2183 + void 2184 + printsel(const Arg *arg) 2185 + { 2186 + tdumpsel(); 2187 + } 2188 + 2189 + void 2190 + tdumpsel(void) 2191 + { 2192 + char *ptr; 2193 + 2194 + if ((ptr = getsel())) { 2195 + tprinter(ptr, strlen(ptr)); 2196 + free(ptr); 2197 + } 2198 + } 2199 + 2200 + void 2201 + tdumpline(int n) 2202 + { 2203 + char buf[UTF_SIZ]; 2204 + Glyph *bp, *end; 2205 + 2206 + bp = &term.line[n][0]; 2207 + end = &bp[MIN(tlinelen(n), term.col) - 1]; 2208 + if (bp != end || bp->u != ' ') { 2209 + for ( ;bp <= end; ++bp) 2210 + tprinter(buf, utf8encode(bp->u, buf)); 2211 + } 2212 + tprinter("\n", 1); 2213 + } 2214 + 2215 + void 2216 + tdump(void) 2217 + { 2218 + int i; 2219 + 2220 + for (i = 0; i < term.row; ++i) 2221 + tdumpline(i); 2222 + } 2223 + 2224 + void 2225 + tputtab(int n) 2226 + { 2227 + uint x = term.c.x; 2228 + 2229 + if (n > 0) { 2230 + while (x < term.col && n--) 2231 + for (++x; x < term.col && !term.tabs[x]; ++x) 2232 + /* nothing */ ; 2233 + } else if (n < 0) { 2234 + while (x > 0 && n++) 2235 + for (--x; x > 0 && !term.tabs[x]; --x) 2236 + /* nothing */ ; 2237 + } 2238 + term.c.x = LIMIT(x, 0, term.col-1); 2239 + } 2240 + 2241 + void 2242 + tdefutf8(char ascii) 2243 + { 2244 + if (ascii == 'G') 2245 + term.mode |= MODE_UTF8; 2246 + else if (ascii == '@') 2247 + term.mode &= ~MODE_UTF8; 2248 + } 2249 + 2250 + void 2251 + tdeftran(char ascii) 2252 + { 2253 + static char cs[] = "0B"; 2254 + static int vcs[] = {CS_GRAPHIC0, CS_USA}; 2255 + char *p; 2256 + 2257 + if ((p = strchr(cs, ascii)) == NULL) { 2258 + fprintf(stderr, "esc unhandled charset: ESC ( %c\n", ascii); 2259 + } else { 2260 + term.trantbl[term.icharset] = vcs[p - cs]; 2261 + } 2262 + } 2263 + 2264 + void 2265 + tdectest(char c) 2266 + { 2267 + int x, y; 2268 + 2269 + if (c == '8') { /* DEC screen alignment test. */ 2270 + for (x = 0; x < term.col; ++x) { 2271 + for (y = 0; y < term.row; ++y) 2272 + tsetchar('E', &term.c.attr, x, y); 2273 + } 2274 + } 2275 + } 2276 + 2277 + void 2278 + tstrsequence(uchar c) 2279 + { 2280 + strreset(); 2281 + 2282 + switch (c) { 2283 + case 0x90: /* DCS -- Device Control String */ 2284 + c = 'P'; 2285 + term.esc |= ESC_DCS; 2286 + break; 2287 + case 0x9f: /* APC -- Application Program Command */ 2288 + c = '_'; 2289 + break; 2290 + case 0x9e: /* PM -- Privacy Message */ 2291 + c = '^'; 2292 + break; 2293 + case 0x9d: /* OSC -- Operating System Command */ 2294 + c = ']'; 2295 + break; 2296 + } 2297 + strescseq.type = c; 2298 + term.esc |= ESC_STR; 2299 + } 2300 + 2301 + void 2302 + tcontrolcode(uchar ascii) 2303 + { 2304 + switch (ascii) { 2305 + case '\t': /* HT */ 2306 + tputtab(1); 2307 + return; 2308 + case '\b': /* BS */ 2309 + tmoveto(term.c.x-1, term.c.y); 2310 + return; 2311 + case '\r': /* CR */ 2312 + tmoveto(0, term.c.y); 2313 + return; 2314 + case '\f': /* LF */ 2315 + case '\v': /* VT */ 2316 + case '\n': /* LF */ 2317 + /* go to first col if the mode is set */ 2318 + tnewline(IS_SET(MODE_CRLF)); 2319 + return; 2320 + case '\a': /* BEL */ 2321 + if (term.esc & ESC_STR_END) { 2322 + /* backwards compatibility to xterm */ 2323 + strhandle(); 2324 + } else { 2325 + xbell(); 2326 + } 2327 + break; 2328 + case '\033': /* ESC */ 2329 + csireset(); 2330 + term.esc &= ~(ESC_CSI|ESC_ALTCHARSET|ESC_TEST); 2331 + term.esc |= ESC_START; 2332 + return; 2333 + case '\016': /* SO (LS1 -- Locking shift 1) */ 2334 + case '\017': /* SI (LS0 -- Locking shift 0) */ 2335 + term.charset = 1 - (ascii - '\016'); 2336 + return; 2337 + case '\032': /* SUB */ 2338 + tsetchar('?', &term.c.attr, term.c.x, term.c.y); 2339 + case '\030': /* CAN */ 2340 + csireset(); 2341 + break; 2342 + case '\005': /* ENQ (IGNORED) */ 2343 + case '\000': /* NUL (IGNORED) */ 2344 + case '\021': /* XON (IGNORED) */ 2345 + case '\023': /* XOFF (IGNORED) */ 2346 + case 0177: /* DEL (IGNORED) */ 2347 + return; 2348 + case 0x80: /* TODO: PAD */ 2349 + case 0x81: /* TODO: HOP */ 2350 + case 0x82: /* TODO: BPH */ 2351 + case 0x83: /* TODO: NBH */ 2352 + case 0x84: /* TODO: IND */ 2353 + break; 2354 + case 0x85: /* NEL -- Next line */ 2355 + tnewline(1); /* always go to first col */ 2356 + break; 2357 + case 0x86: /* TODO: SSA */ 2358 + case 0x87: /* TODO: ESA */ 2359 + break; 2360 + case 0x88: /* HTS -- Horizontal tab stop */ 2361 + term.tabs[term.c.x] = 1; 2362 + break; 2363 + case 0x89: /* TODO: HTJ */ 2364 + case 0x8a: /* TODO: VTS */ 2365 + case 0x8b: /* TODO: PLD */ 2366 + case 0x8c: /* TODO: PLU */ 2367 + case 0x8d: /* TODO: RI */ 2368 + case 0x8e: /* TODO: SS2 */ 2369 + case 0x8f: /* TODO: SS3 */ 2370 + case 0x91: /* TODO: PU1 */ 2371 + case 0x92: /* TODO: PU2 */ 2372 + case 0x93: /* TODO: STS */ 2373 + case 0x94: /* TODO: CCH */ 2374 + case 0x95: /* TODO: MW */ 2375 + case 0x96: /* TODO: SPA */ 2376 + case 0x97: /* TODO: EPA */ 2377 + case 0x98: /* TODO: SOS */ 2378 + case 0x99: /* TODO: SGCI */ 2379 + break; 2380 + case 0x9a: /* DECID -- Identify Terminal */ 2381 + ttywrite(vtiden, strlen(vtiden), 0); 2382 + break; 2383 + case 0x9b: /* TODO: CSI */ 2384 + case 0x9c: /* TODO: ST */ 2385 + break; 2386 + case 0x90: /* DCS -- Device Control String */ 2387 + case 0x9d: /* OSC -- Operating System Command */ 2388 + case 0x9e: /* PM -- Privacy Message */ 2389 + case 0x9f: /* APC -- Application Program Command */ 2390 + tstrsequence(ascii); 2391 + return; 2392 + } 2393 + /* only CAN, SUB, \a and C1 chars interrupt a sequence */ 2394 + term.esc &= ~(ESC_STR_END|ESC_STR); 2395 + } 2396 + 2397 + /* 2398 + * returns 1 when the sequence is finished and it hasn't to read 2399 + * more characters for this sequence, otherwise 0 2400 + */ 2401 + int 2402 + eschandle(uchar ascii) 2403 + { 2404 + switch (ascii) { 2405 + case '[': 2406 + term.esc |= ESC_CSI; 2407 + return 0; 2408 + case '#': 2409 + term.esc |= ESC_TEST; 2410 + return 0; 2411 + case '%': 2412 + term.esc |= ESC_UTF8; 2413 + return 0; 2414 + case 'P': /* DCS -- Device Control String */ 2415 + case '_': /* APC -- Application Program Command */ 2416 + case '^': /* PM -- Privacy Message */ 2417 + case ']': /* OSC -- Operating System Command */ 2418 + case 'k': /* old title set compatibility */ 2419 + tstrsequence(ascii); 2420 + return 0; 2421 + case 'n': /* LS2 -- Locking shift 2 */ 2422 + case 'o': /* LS3 -- Locking shift 3 */ 2423 + term.charset = 2 + (ascii - 'n'); 2424 + break; 2425 + case '(': /* GZD4 -- set primary charset G0 */ 2426 + case ')': /* G1D4 -- set secondary charset G1 */ 2427 + case '*': /* G2D4 -- set tertiary charset G2 */ 2428 + case '+': /* G3D4 -- set quaternary charset G3 */ 2429 + term.icharset = ascii - '('; 2430 + term.esc |= ESC_ALTCHARSET; 2431 + return 0; 2432 + case 'D': /* IND -- Linefeed */ 2433 + if (term.c.y == term.bot) { 2434 + tscrollup(term.top, 1, 1); 2435 + } else { 2436 + tmoveto(term.c.x, term.c.y+1); 2437 + } 2438 + break; 2439 + case 'E': /* NEL -- Next line */ 2440 + tnewline(1); /* always go to first col */ 2441 + break; 2442 + case 'H': /* HTS -- Horizontal tab stop */ 2443 + term.tabs[term.c.x] = 1; 2444 + break; 2445 + case 'M': /* RI -- Reverse index */ 2446 + if (term.c.y == term.top) { 2447 + tscrolldown(term.top, 1, 1); 2448 + } else { 2449 + tmoveto(term.c.x, term.c.y-1); 2450 + } 2451 + break; 2452 + case 'Z': /* DECID -- Identify Terminal */ 2453 + ttywrite(vtiden, strlen(vtiden), 0); 2454 + break; 2455 + case 'c': /* RIS -- Reset to initial state */ 2456 + treset(); 2457 + resettitle(); 2458 + xloadcols(); 2459 + break; 2460 + case '=': /* DECPAM -- Application keypad */ 2461 + xsetmode(1, MODE_APPKEYPAD); 2462 + break; 2463 + case '>': /* DECPNM -- Normal keypad */ 2464 + xsetmode(0, MODE_APPKEYPAD); 2465 + break; 2466 + case '7': /* DECSC -- Save Cursor */ 2467 + tcursor(CURSOR_SAVE); 2468 + break; 2469 + case '8': /* DECRC -- Restore Cursor */ 2470 + tcursor(CURSOR_LOAD); 2471 + break; 2472 + case '\\': /* ST -- String Terminator */ 2473 + if (term.esc & ESC_STR_END) 2474 + strhandle(); 2475 + break; 2476 + default: 2477 + fprintf(stderr, "erresc: unknown sequence ESC 0x%02X '%c'\n", 2478 + (uchar) ascii, isprint(ascii)? ascii:'.'); 2479 + break; 2480 + } 2481 + return 1; 2482 + } 2483 + 2484 + void 2485 + tputc(Rune u) 2486 + { 2487 + char c[UTF_SIZ]; 2488 + int control; 2489 + int width, len; 2490 + Glyph *gp; 2491 + 2492 + control = ISCONTROL(u); 2493 + if (!IS_SET(MODE_UTF8) && !IS_SET(MODE_SIXEL)) { 2494 + c[0] = u; 2495 + width = len = 1; 2496 + } else { 2497 + len = utf8encode(u, c); 2498 + if (!control && (width = wcwidth(u)) == -1) { 2499 + memcpy(c, "\357\277\275", 4); /* UTF_INVALID */ 2500 + width = 1; 2501 + } 2502 + } 2503 + 2504 + if (IS_SET(MODE_PRINT)) 2505 + tprinter(c, len); 2506 + 2507 + /* 2508 + * STR sequence must be checked before anything else 2509 + * because it uses all following characters until it 2510 + * receives a ESC, a SUB, a ST or any other C1 control 2511 + * character. 2512 + */ 2513 + if (term.esc & ESC_STR) { 2514 + if (u == '\a' || u == 030 || u == 032 || u == 033 || 2515 + ISCONTROLC1(u)) { 2516 + term.esc &= ~(ESC_START|ESC_STR|ESC_DCS); 2517 + if (IS_SET(MODE_SIXEL)) { 2518 + /* TODO: render sixel */; 2519 + term.mode &= ~MODE_SIXEL; 2520 + return; 2521 + } 2522 + term.esc |= ESC_STR_END; 2523 + goto check_control_code; 2524 + } 2525 + 2526 + if (IS_SET(MODE_SIXEL)) { 2527 + /* TODO: implement sixel mode */ 2528 + return; 2529 + } 2530 + if (term.esc&ESC_DCS && strescseq.len == 0 && u == 'q') 2531 + term.mode |= MODE_SIXEL; 2532 + 2533 + if (strescseq.len+len >= sizeof(strescseq.buf)-1) { 2534 + /* 2535 + * Here is a bug in terminals. If the user never sends 2536 + * some code to stop the str or esc command, then st 2537 + * will stop responding. But this is better than 2538 + * silently failing with unknown characters. At least 2539 + * then users will report back. 2540 + * 2541 + * In the case users ever get fixed, here is the code: 2542 + */ 2543 + /* 2544 + * term.esc = 0; 2545 + * strhandle(); 2546 + */ 2547 + return; 2548 + } 2549 + 2550 + memmove(&strescseq.buf[strescseq.len], c, len); 2551 + strescseq.len += len; 2552 + return; 2553 + } 2554 + 2555 + check_control_code: 2556 + /* 2557 + * Actions of control codes must be performed as soon they arrive 2558 + * because they can be embedded inside a control sequence, and 2559 + * they must not cause conflicts with sequences. 2560 + */ 2561 + if (control) { 2562 + tcontrolcode(u); 2563 + /* 2564 + * control codes are not shown ever 2565 + */ 2566 + return; 2567 + } else if (term.esc & ESC_START) { 2568 + if (term.esc & ESC_CSI) { 2569 + csiescseq.buf[csiescseq.len++] = u; 2570 + if (BETWEEN(u, 0x40, 0x7E) 2571 + || csiescseq.len >= \ 2572 + sizeof(csiescseq.buf)-1) { 2573 + term.esc = 0; 2574 + csiparse(); 2575 + csihandle(); 2576 + } 2577 + return; 2578 + } else if (term.esc & ESC_UTF8) { 2579 + tdefutf8(u); 2580 + } else if (term.esc & ESC_ALTCHARSET) { 2581 + tdeftran(u); 2582 + } else if (term.esc & ESC_TEST) { 2583 + tdectest(u); 2584 + } else { 2585 + if (!eschandle(u)) 2586 + return; 2587 + /* sequence already finished */ 2588 + } 2589 + term.esc = 0; 2590 + /* 2591 + * All characters which form part of a sequence are not 2592 + * printed 2593 + */ 2594 + return; 2595 + } 2596 + if (sel.ob.x != -1 && BETWEEN(term.c.y, sel.ob.y, sel.oe.y)) 2597 + selclear(); 2598 + 2599 + gp = &term.line[term.c.y][term.c.x]; 2600 + if (IS_SET(MODE_WRAP) && (term.c.state & CURSOR_WRAPNEXT)) { 2601 + gp->mode |= ATTR_WRAP; 2602 + tnewline(1); 2603 + gp = &term.line[term.c.y][term.c.x]; 2604 + } 2605 + 2606 + if (IS_SET(MODE_INSERT) && term.c.x+width < term.col) 2607 + memmove(gp+width, gp, (term.col - term.c.x - width) * sizeof(Glyph)); 2608 + 2609 + if (term.c.x+width > term.col) { 2610 + tnewline(1); 2611 + gp = &term.line[term.c.y][term.c.x]; 2612 + } 2613 + 2614 + tsetchar(u, &term.c.attr, term.c.x, term.c.y); 2615 + 2616 + if (width == 2) { 2617 + gp->mode |= ATTR_WIDE; 2618 + if (term.c.x+1 < term.col) { 2619 + gp[1].u = '\0'; 2620 + gp[1].mode = ATTR_WDUMMY; 2621 + } 2622 + } 2623 + if (term.c.x+width < term.col) { 2624 + tmoveto(term.c.x+width, term.c.y); 2625 + } else { 2626 + term.c.state |= CURSOR_WRAPNEXT; 2627 + } 2628 + } 2629 + 2630 + int 2631 + twrite(const char *buf, int buflen, int show_ctrl) 2632 + { 2633 + int charsize; 2634 + Rune u; 2635 + int n; 2636 + 2637 + for (n = 0; n < buflen; n += charsize) { 2638 + if (IS_SET(MODE_UTF8) && !IS_SET(MODE_SIXEL)) { 2639 + /* process a complete utf8 char */ 2640 + charsize = utf8decode(buf + n, &u, buflen - n); 2641 + if (charsize == 0) 2642 + break; 2643 + } else { 2644 + u = buf[n] & 0xFF; 2645 + charsize = 1; 2646 + } 2647 + if (show_ctrl && ISCONTROL(u)) { 2648 + if (u & 0x80) { 2649 + u &= 0x7f; 2650 + tputc('^'); 2651 + tputc('['); 2652 + } else if (u != '\n' && u != '\r' && u != '\t') { 2653 + u ^= 0x40; 2654 + tputc('^'); 2655 + } 2656 + } 2657 + tputc(u); 2658 + } 2659 + return n; 2660 + } 2661 + 2662 + void 2663 + tresize(int col, int row) 2664 + { 2665 + int i, j; 2666 + int tmp; 2667 + int minrow, mincol; 2668 + int *bp; 2669 + TCursor c; 2670 + 2671 + tmp = col; 2672 + if (!term.maxcol) 2673 + term.maxcol = term.col; 2674 + col = MAX(col, term.maxcol); 2675 + minrow = MIN(row, term.row); 2676 + mincol = MIN(col, term.maxcol); 2677 + 2678 + if (col < 1 || row < 1) { 2679 + fprintf(stderr, 2680 + "tresize: error resizing to %dx%d\n", col, row); 2681 + return; 2682 + } 2683 + 2684 + /* 2685 + * slide screen to keep cursor where we expect it - 2686 + * tscrollup would work here, but we can optimize to 2687 + * memmove because we're freeing the earlier lines 2688 + */ 2689 + for (i = 0; i <= term.c.y - row; i++) { 2690 + free(term.line[i]); 2691 + free(term.alt[i]); 2692 + } 2693 + /* ensure that both src and dst are not NULL */ 2694 + if (i > 0) { 2695 + memmove(term.line, term.line + i, row * sizeof(Line)); 2696 + memmove(term.alt, term.alt + i, row * sizeof(Line)); 2697 + } 2698 + for (i += row; i < term.row; i++) { 2699 + free(term.line[i]); 2700 + free(term.alt[i]); 2701 + } 2702 + 2703 + /* resize to new height */ 2704 + term.line = xrealloc(term.line, row * sizeof(Line)); 2705 + term.alt = xrealloc(term.alt, row * sizeof(Line)); 2706 + term.dirty = xrealloc(term.dirty, row * sizeof(*term.dirty)); 2707 + term.tabs = xrealloc(term.tabs, col * sizeof(*term.tabs)); 2708 + 2709 + for (i = 0; i < HISTSIZE; i++) { 2710 + term.hist[i] = xrealloc(term.hist[i], col * sizeof(Glyph)); 2711 + for (j = mincol; j < col; j++) { 2712 + term.hist[i][j] = term.c.attr; 2713 + term.hist[i][j].u = ' '; 2714 + } 2715 + } 2716 + 2717 + /* resize each row to new width, zero-pad if needed */ 2718 + for (i = 0; i < minrow; i++) { 2719 + term.line[i] = xrealloc(term.line[i], col * sizeof(Glyph)); 2720 + term.alt[i] = xrealloc(term.alt[i], col * sizeof(Glyph)); 2721 + } 2722 + 2723 + /* allocate any new rows */ 2724 + for (/* i = minrow */; i < row; i++) { 2725 + term.line[i] = xmalloc(col * sizeof(Glyph)); 2726 + term.alt[i] = xmalloc(col * sizeof(Glyph)); 2727 + } 2728 + 2729 + if (col > term.maxcol) { 2730 + bp = term.tabs + term.maxcol; 2731 + memset(bp, 0, sizeof(*term.tabs) * (col - term.maxcol)); 2732 + while (--bp > term.tabs && !*bp) 2733 + /* nothing */ ; 2734 + for (bp += tabspaces; bp < term.tabs + col; bp += tabspaces) 2735 + *bp = 1; 2736 + } 2737 + /* update terminal size */ 2738 + term.col = tmp; 2739 + term.maxcol = col; 2740 + term.row = row; 2741 + /* reset scrolling region */ 2742 + tsetscroll(0, row-1); 2743 + /* make use of the LIMIT in tmoveto */ 2744 + tmoveto(term.c.x, term.c.y); 2745 + /* Clearing both screens (it makes dirty all lines) */ 2746 + c = term.c; 2747 + for (i = 0; i < 2; i++) { 2748 + if (mincol < col && 0 < minrow) { 2749 + tclearregion(mincol, 0, col - 1, minrow - 1); 2750 + } 2751 + if (0 < col && minrow < row) { 2752 + tclearregion(0, minrow, col - 1, row - 1); 2753 + } 2754 + tswapscreen(); 2755 + tcursor(CURSOR_LOAD); 2756 + } 2757 + term.c = c; 2758 + } 2759 + 2760 + void 2761 + resettitle(void) 2762 + { 2763 + xsettitle(NULL); 2764 + } 2765 + 2766 + void 2767 + drawregion(int x1, int y1, int x2, int y2) 2768 + { 2769 + int y; 2770 + for (y = y1; y < y2; y++) { 2771 + if (!term.dirty[y]) 2772 + continue; 2773 + 2774 + term.dirty[y] = 0; 2775 + xdrawline(TLINE(y), x1, y, x2); 2776 + } 2777 + } 2778 + 2779 + void 2780 + draw(void) 2781 + { 2782 + int cx = term.c.x; 2783 + 2784 + if (!xstartdraw()) 2785 + return; 2786 + 2787 + /* adjust cursor position */ 2788 + LIMIT(term.ocx, 0, term.col-1); 2789 + LIMIT(term.ocy, 0, term.row-1); 2790 + if (term.line[term.ocy][term.ocx].mode & ATTR_WDUMMY) 2791 + term.ocx--; 2792 + if (term.line[term.c.y][cx].mode & ATTR_WDUMMY) 2793 + cx--; 2794 + 2795 + drawregion(0, 0, term.col, term.row); 2796 + if (term.scr == 0) 2797 + xdrawcursor(cx, term.c.y, term.line[term.c.y][cx], 2798 + term.ocx, term.ocy, term.line[term.ocy][term.ocx], 2799 + term.line[term.ocy], term.col); 2800 + term.ocx = cx, term.ocy = term.c.y; 2801 + xfinishdraw(); 2802 + 2803 + struct timespec now; 2804 + clock_gettime(CLOCK_MONOTONIC, &now); 2805 + if (ximspot_update_interval && TIMEDIFF(now, term.last_ximspot_update) > ximspot_update_interval) { 2806 + xximspot(term.ocx, term.ocy); 2807 + term.last_ximspot_update = now; 2808 + } 2809 + } 2810 + 2811 + void 2812 + redraw(void) 2813 + { 2814 + tfulldirt(); 2815 + draw(); 2816 + }
+7
cfg/st/st.desktop
··· 1 + [Desktop Entry] 2 + Type=Application 3 + Name=st 4 + Comment=simple-terminal emulator for X 5 + Icon=utilities-terminal 6 + Exec=st 7 + Categories=System;TerminalEmulator
cfg/st/st.h

This is a binary file and will not be displayed.

+222
cfg/st/st.info
··· 1 + st| simpleterm, 2 + acsc=+C\,D-A.B0E``aaffgghFiGjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~, 3 + am, 4 + bce, 5 + bel=^G, 6 + blink=\E[5m, 7 + bold=\E[1m, 8 + cbt=\E[Z, 9 + cvvis=\E[?25h, 10 + civis=\E[?25l, 11 + clear=\E[H\E[2J, 12 + cnorm=\E[?12l\E[?25h, 13 + colors#8, 14 + cols#80, 15 + cr=^M, 16 + csr=\E[%i%p1%d;%p2%dr, 17 + cub=\E[%p1%dD, 18 + cub1=^H, 19 + cud1=^J, 20 + cud=\E[%p1%dB, 21 + cuf1=\E[C, 22 + cuf=\E[%p1%dC, 23 + cup=\E[%i%p1%d;%p2%dH, 24 + cuu1=\E[A, 25 + cuu=\E[%p1%dA, 26 + dch=\E[%p1%dP, 27 + dch1=\E[P, 28 + dim=\E[2m, 29 + dl=\E[%p1%dM, 30 + dl1=\E[M, 31 + ech=\E[%p1%dX, 32 + ed=\E[J, 33 + el=\E[K, 34 + el1=\E[1K, 35 + enacs=\E)0, 36 + flash=\E[?5h$<80/>\E[?5l, 37 + fsl=^G, 38 + home=\E[H, 39 + hpa=\E[%i%p1%dG, 40 + hs, 41 + ht=^I, 42 + hts=\EH, 43 + ich=\E[%p1%d@, 44 + il1=\E[L, 45 + il=\E[%p1%dL, 46 + ind=^J, 47 + indn=\E[%p1%dS, 48 + invis=\E[8m, 49 + is2=\E[4l\E>\E[?1034l, 50 + it#8, 51 + kel=\E[1;2F, 52 + ked=\E[1;5F, 53 + ka1=\E[1~, 54 + ka3=\E[5~, 55 + kc1=\E[4~, 56 + kc3=\E[6~, 57 + kbs=\177, 58 + kcbt=\E[Z, 59 + kb2=\EOu, 60 + kcub1=\EOD, 61 + kcud1=\EOB, 62 + kcuf1=\EOC, 63 + kcuu1=\EOA, 64 + kDC=\E[3;2~, 65 + kent=\EOM, 66 + kEND=\E[1;2F, 67 + kIC=\E[2;2~, 68 + kNXT=\E[6;2~, 69 + kPRV=\E[5;2~, 70 + kHOM=\E[1;2H, 71 + kLFT=\E[1;2D, 72 + kRIT=\E[1;2C, 73 + kind=\E[1;2B, 74 + kri=\E[1;2A, 75 + kclr=\E[3;5~, 76 + kdl1=\E[3;2~, 77 + kdch1=\E[3~, 78 + kich1=\E[2~, 79 + kend=\E[4~, 80 + kf1=\EOP, 81 + kf2=\EOQ, 82 + kf3=\EOR, 83 + kf4=\EOS, 84 + kf5=\E[15~, 85 + kf6=\E[17~, 86 + kf7=\E[18~, 87 + kf8=\E[19~, 88 + kf9=\E[20~, 89 + kf10=\E[21~, 90 + kf11=\E[23~, 91 + kf12=\E[24~, 92 + kf13=\E[1;2P, 93 + kf14=\E[1;2Q, 94 + kf15=\E[1;2R, 95 + kf16=\E[1;2S, 96 + kf17=\E[15;2~, 97 + kf18=\E[17;2~, 98 + kf19=\E[18;2~, 99 + kf20=\E[19;2~, 100 + kf21=\E[20;2~, 101 + kf22=\E[21;2~, 102 + kf23=\E[23;2~, 103 + kf24=\E[24;2~, 104 + kf25=\E[1;5P, 105 + kf26=\E[1;5Q, 106 + kf27=\E[1;5R, 107 + kf28=\E[1;5S, 108 + kf29=\E[15;5~, 109 + kf30=\E[17;5~, 110 + kf31=\E[18;5~, 111 + kf32=\E[19;5~, 112 + kf33=\E[20;5~, 113 + kf34=\E[21;5~, 114 + kf35=\E[23;5~, 115 + kf36=\E[24;5~, 116 + kf37=\E[1;6P, 117 + kf38=\E[1;6Q, 118 + kf39=\E[1;6R, 119 + kf40=\E[1;6S, 120 + kf41=\E[15;6~, 121 + kf42=\E[17;6~, 122 + kf43=\E[18;6~, 123 + kf44=\E[19;6~, 124 + kf45=\E[20;6~, 125 + kf46=\E[21;6~, 126 + kf47=\E[23;6~, 127 + kf48=\E[24;6~, 128 + kf49=\E[1;3P, 129 + kf50=\E[1;3Q, 130 + kf51=\E[1;3R, 131 + kf52=\E[1;3S, 132 + kf53=\E[15;3~, 133 + kf54=\E[17;3~, 134 + kf55=\E[18;3~, 135 + kf56=\E[19;3~, 136 + kf57=\E[20;3~, 137 + kf58=\E[21;3~, 138 + kf59=\E[23;3~, 139 + kf60=\E[24;3~, 140 + kf61=\E[1;4P, 141 + kf62=\E[1;4Q, 142 + kf63=\E[1;4R, 143 + khome=\E[1~, 144 + kil1=\E[2;5~, 145 + krmir=\E[2;2~, 146 + knp=\E[6~, 147 + kmous=\E[M, 148 + kpp=\E[5~, 149 + lines#24, 150 + mir, 151 + msgr, 152 + npc, 153 + op=\E[39;49m, 154 + pairs#64, 155 + mc0=\E[i, 156 + mc4=\E[4i, 157 + mc5=\E[5i, 158 + rc=\E8, 159 + rev=\E[7m, 160 + ri=\EM, 161 + ritm=\E[23m, 162 + rmacs=\E(B, 163 + rmcup=\E[?1049l, 164 + rmir=\E[4l, 165 + rmkx=\E[?1l\E>, 166 + rmso=\E[27m, 167 + rmul=\E[24m, 168 + rs1=\Ec, 169 + rs2=\E[4l\E>\E[?1034l, 170 + sc=\E7, 171 + setab=\E[4%p1%dm, 172 + setaf=\E[3%p1%dm, 173 + setb=\E[4%?%p1%{1}%=%t4%e%p1%{3}%=%t6%e%p1%{4}%=%t1%e%p1%{6}%=%t3%e%p1%d%;m, 174 + setf=\E[3%?%p1%{1}%=%t4%e%p1%{3}%=%t6%e%p1%{4}%=%t1%e%p1%{6}%=%t3%e%p1%d%;m, 175 + sgr0=\E[0m, 176 + sgr=%?%p9%t\E(0%e\E(B%;\E[0%?%p6%t;1%;%?%p2%t;4%;%?%p1%p3%|%t;7%;%?%p4%t;5%;%?%p7%t;8%;m, 177 + sitm=\E[3m, 178 + smacs=\E(0, 179 + smcup=\E[?1049h, 180 + smir=\E[4h, 181 + smkx=\E[?1h\E=, 182 + smso=\E[7m, 183 + smul=\E[4m, 184 + tbc=\E[3g, 185 + tsl=\E]0;, 186 + xenl, 187 + vpa=\E[%i%p1%dd, 188 + # XTerm extensions 189 + rmxx=\E[29m, 190 + smxx=\E[9m, 191 + # tmux extensions, see TERMINFO EXTENSIONS in tmux(1) 192 + Tc, 193 + Ms=\E]52;%p1%s;%p2%s\007, 194 + Se=\E[2 q, 195 + Ss=\E[%p1%d q, 196 + 197 + st-256color| simpleterm with 256 colors, 198 + use=st, 199 + ccc, 200 + colors#256, 201 + oc=\E]104\007, 202 + pairs#32767, 203 + # Nicked from xterm-256color 204 + initc=\E]4;%p1%d;rgb\:%p2%{255}%*%{1000}%/%2.2X/%p3%{255}%*%{1000}%/%2.2X/%p4%{255}%*%{1000}%/%2.2X\E\\, 205 + setab=\E[%?%p1%{8}%<%t4%p1%d%e%p1%{16}%<%t10%p1%{8}%-%d%e48;5;%p1%d%;m, 206 + setaf=\E[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;m, 207 + 208 + st-meta| simpleterm with meta key, 209 + use=st, 210 + km, 211 + rmm=\E[?1034l, 212 + smm=\E[?1034h, 213 + rs2=\E[4l\E>\E[?1034h, 214 + is2=\E[4l\E>\E[?1034h, 215 + 216 + st-meta-256color| simpleterm with meta key and 256 colors, 217 + use=st-256color, 218 + km, 219 + rmm=\E[?1034l, 220 + smm=\E[?1034h, 221 + rs2=\E[4l\E>\E[?1034h, 222 + is2=\E[4l\E>\E[?1034h,
+23
cfg/st/utils.h
··· 1 + /// Dynamic memory-chunk, with (1) datatype size, (2/3) initialized / allocated chunk, (4) content 2 + typedef struct { uint8_t const elSize; uint32_t init, alloc; char* content; } DynamicArray; 3 + #define UTF8_ARRAY {4, 0, 0, NULL} 4 + 5 + static inline int p_alloc(DynamicArray *s, uint32_t amount) { 6 + uint32_t const diff=s->init+s->elSize*amount-s->alloc, nas=s->alloc+max(diff,15)*s->elSize; 7 + if (s->alloc < s->init + s->elSize * amount) { 8 + char* tmp = realloc(s->content, nas); 9 + if (!tmp) return 0; 10 + s->alloc = nas, s->content = tmp; 11 + } 12 + return 1; 13 + } 14 + static inline char *view(DynamicArray * s, uint32_t i) { return s->content + i*s->elSize; } 15 + static inline char *end(DynamicArray *s, uint32_t i) { return s->content +s->init-(i+1)*s->elSize; } 16 + static inline uint32_t getU32(DynamicArray* s, uint32_t i, int b) { return *((uint32_t*) (b ?view(s,i) :end(s,i))); } 17 + static char *expand(DynamicArray *s) { if (!p_alloc(s, 1)) return NULL; s->init += s->elSize; return end(s, 0); } 18 + static inline void pop(DynamicArray* s) { s->init -= s->elSize; } 19 + static inline void empty(DynamicArray* s) { s->init = 0; } 20 + static inline int size(DynamicArray const * s) { return s->init / s->elSize; } 21 + static inline void assign(DynamicArray* s, DynamicArray const *o) { 22 + if (p_alloc(s, size(o))) memcpy(s->content, o->content, (s->init=o->init)); 23 + }
+40
cfg/st/win.h
··· 1 + /* See LICENSE for license details. */ 2 + 3 + enum win_mode { 4 + MODE_VISIBLE = 1 << 0, 5 + MODE_FOCUSED = 1 << 1, 6 + MODE_APPKEYPAD = 1 << 2, 7 + MODE_MOUSEBTN = 1 << 3, 8 + MODE_MOUSEMOTION = 1 << 4, 9 + MODE_REVERSE = 1 << 5, 10 + MODE_KBDLOCK = 1 << 6, 11 + MODE_HIDE = 1 << 7, 12 + MODE_APPCURSOR = 1 << 8, 13 + MODE_MOUSESGR = 1 << 9, 14 + MODE_8BIT = 1 << 10, 15 + MODE_BLINK = 1 << 11, 16 + MODE_FBLINK = 1 << 12, 17 + MODE_FOCUS = 1 << 13, 18 + MODE_MOUSEX10 = 1 << 14, 19 + MODE_MOUSEMANY = 1 << 15, 20 + MODE_BRCKTPASTE = 1 << 16, 21 + MODE_NUMLOCK = 1 << 17, 22 + MODE_MOUSE = MODE_MOUSEBTN|MODE_MOUSEMOTION|MODE_MOUSEX10\ 23 + |MODE_MOUSEMANY, 24 + }; 25 + 26 + void xbell(void); 27 + void xclipcopy(void); 28 + void xdrawcursor(int, int, Glyph, int, int, Glyph, Line, int); 29 + void xdrawline(Line, int, int, int); 30 + void xfinishdraw(void); 31 + void xloadcols(void); 32 + int xsetcolorname(int, const char *); 33 + void xsettitle(char *); 34 + int xsetcursor(int); 35 + void xsetmode(int, unsigned int); 36 + void xsetpointermotion(int); 37 + void xsetsel(char *); 38 + int xstartdraw(void); 39 + void xximspot(int, int); 40 + void xclearwin(void);
+2377
cfg/st/x.c
··· 1 + /* See LICENSE for license details. */ 2 + #include <errno.h> 3 + #include <math.h> 4 + #include <limits.h> 5 + #include <locale.h> 6 + #include <signal.h> 7 + #include <sys/select.h> 8 + #include <time.h> 9 + #include <unistd.h> 10 + #include <libgen.h> 11 + #include <X11/Xatom.h> 12 + #include <X11/Xlib.h> 13 + #include <X11/cursorfont.h> 14 + #include <X11/keysym.h> 15 + #include <X11/Xft/Xft.h> 16 + #include <X11/XKBlib.h> 17 + #include <X11/Xresource.h> 18 + 19 + static char *argv0; 20 + #include "arg.h" 21 + #include "st.h" 22 + #include "win.h" 23 + #include "hb.h" 24 + 25 + /* types used in config.h */ 26 + typedef struct { 27 + uint mod; 28 + KeySym keysym; 29 + void (*func)(const Arg *); 30 + const Arg arg; 31 + } Shortcut; 32 + 33 + typedef struct { 34 + uint b; 35 + uint mask; 36 + char *s; 37 + } MouseShortcut; 38 + 39 + typedef struct { 40 + KeySym k; 41 + uint mask; 42 + char *s; 43 + /* three-valued logic variables: 0 indifferent, 1 on, -1 off */ 44 + signed char appkey; /* application keypad */ 45 + signed char appcursor; /* application cursor */ 46 + } Key; 47 + 48 + /* Xresources preferences */ 49 + enum resource_type { 50 + STRING = 0, 51 + INTEGER = 1, 52 + FLOAT = 2 53 + }; 54 + 55 + typedef struct { 56 + char *name; 57 + enum resource_type type; 58 + void *dst; 59 + } ResourcePref; 60 + 61 + /* X modifiers */ 62 + #define XK_ANY_MOD UINT_MAX 63 + #define XK_NO_MOD 0 64 + #define XK_SWITCH_MOD (1<<13) 65 + 66 + /* function definitions used in config.h */ 67 + static void clipcopy(const Arg *); 68 + static void clippaste(const Arg *); 69 + static void numlock(const Arg *); 70 + static void selpaste(const Arg *); 71 + static void changealpha(const Arg *); 72 + static void zoom(const Arg *); 73 + static void zoomabs(const Arg *); 74 + static void zoomreset(const Arg *); 75 + 76 + /* config.h for applying patches and the configuration. */ 77 + #include "config.h" 78 + 79 + /* XEMBED messages */ 80 + #define XEMBED_FOCUS_IN 4 81 + #define XEMBED_FOCUS_OUT 5 82 + 83 + /* macros */ 84 + #define IS_SET(flag) ((win.mode & (flag)) != 0) 85 + #define TRUERED(x) (((x) & 0xff0000) >> 8) 86 + #define TRUEGREEN(x) (((x) & 0xff00)) 87 + #define TRUEBLUE(x) (((x) & 0xff) << 8) 88 + 89 + typedef XftDraw *Draw; 90 + typedef XftColor Color; 91 + typedef XftGlyphFontSpec GlyphFontSpec; 92 + 93 + /* Purely graphic info */ 94 + typedef struct { 95 + int tw, th; /* tty width and height */ 96 + int w, h; /* window width and height */ 97 + int hborderpx, vborderpx; 98 + int ch; /* char height */ 99 + int cw; /* char width */ 100 + int cyo; /* char y offset */ 101 + int mode; /* window state/mode flags */ 102 + int cursor; /* cursor style */ 103 + } TermWindow; 104 + 105 + typedef struct { 106 + Display *dpy; 107 + Colormap cmap; 108 + Window win; 109 + Drawable buf; 110 + GlyphFontSpec *specbuf; /* font spec buffer used for rendering */ 111 + Atom xembed, wmdeletewin, netwmname, netwmpid; 112 + XIM xim; 113 + XIC xic; 114 + Draw draw; 115 + Visual *vis; 116 + XSetWindowAttributes attrs; 117 + int scr; 118 + int isfixed; /* is fixed geometry? */ 119 + int depth; /* bit depth */ 120 + int l, t; /* left and top offset */ 121 + int gm; /* geometry mask */ 122 + } XWindow; 123 + 124 + typedef struct { 125 + Atom xtarget; 126 + char *primary, *clipboard; 127 + struct timespec tclick1; 128 + struct timespec tclick2; 129 + } XSelection; 130 + 131 + /* Font structure */ 132 + #define Font Font_ 133 + typedef struct { 134 + int height; 135 + int width; 136 + int ascent; 137 + int descent; 138 + int badslant; 139 + int badweight; 140 + short lbearing; 141 + short rbearing; 142 + XftFont *match; 143 + FcFontSet *set; 144 + FcPattern *pattern; 145 + } Font; 146 + 147 + /* Drawing Context */ 148 + typedef struct { 149 + Color *col; 150 + size_t collen; 151 + Font font, bfont, ifont, ibfont; 152 + GC gc; 153 + } DC; 154 + 155 + static inline ushort sixd_to_16bit(int); 156 + static int xmakeglyphfontspecs(XftGlyphFontSpec *, const Glyph *, int, int, int); 157 + static void xdrawglyphfontspecs(const XftGlyphFontSpec *, Glyph, int, int, int, int); 158 + static void xdrawglyph(Glyph, int, int); 159 + static void xclear(int, int, int, int); 160 + static int xgeommasktogravity(int); 161 + static void ximopen(Display *); 162 + static void ximinstantiate(Display *, XPointer, XPointer); 163 + static void ximdestroy(XIM, XPointer, XPointer); 164 + static void xinit(int, int); 165 + static void cresize(int, int); 166 + static void xresize(int, int); 167 + static void xhints(void); 168 + static int xloadcolor(int, const char *, Color *); 169 + static int xloadfont(Font *, FcPattern *); 170 + static void xloadfonts(char *, double); 171 + static int xloadsparefont(FcPattern *, int); 172 + static void xloadsparefonts(void); 173 + static void xunloadfont(Font *); 174 + static void xunloadfonts(void); 175 + static void xsetenv(void); 176 + static void xseturgency(int); 177 + static int evcol(XEvent *); 178 + static int evrow(XEvent *); 179 + 180 + static void expose(XEvent *); 181 + static void visibility(XEvent *); 182 + static void unmap(XEvent *); 183 + static void kpress(XEvent *); 184 + static void cmessage(XEvent *); 185 + static void resize(XEvent *); 186 + static void focus(XEvent *); 187 + static void brelease(XEvent *); 188 + static void bpress(XEvent *); 189 + static void bmotion(XEvent *); 190 + static void propnotify(XEvent *); 191 + static void selnotify(XEvent *); 192 + static void selclear_(XEvent *); 193 + static void selrequest(XEvent *); 194 + static void setsel(char *, Time); 195 + static void mousesel(XEvent *, int); 196 + static void mousereport(XEvent *); 197 + static char *kmap(KeySym, uint); 198 + static int match(uint, uint); 199 + 200 + static void run(void); 201 + static void usage(void); 202 + 203 + static void (*handler[LASTEvent])(XEvent *) = { 204 + [KeyPress] = kpress, 205 + [ClientMessage] = cmessage, 206 + [ConfigureNotify] = resize, 207 + [VisibilityNotify] = visibility, 208 + [UnmapNotify] = unmap, 209 + [Expose] = expose, 210 + [FocusIn] = focus, 211 + [FocusOut] = focus, 212 + [MotionNotify] = bmotion, 213 + [ButtonPress] = bpress, 214 + [ButtonRelease] = brelease, 215 + /* 216 + * Uncomment if you want the selection to disappear when you select something 217 + * different in another window. 218 + */ 219 + /* [SelectionClear] = selclear_, */ 220 + [SelectionNotify] = selnotify, 221 + /* 222 + * PropertyNotify is only turned on when there is some INCR transfer happening 223 + * for the selection retrieval. 224 + */ 225 + [PropertyNotify] = propnotify, 226 + [SelectionRequest] = selrequest, 227 + }; 228 + 229 + /* Globals */ 230 + static DC dc; 231 + static XWindow xw; 232 + static XSelection xsel; 233 + static TermWindow win; 234 + 235 + /* Font Ring Cache */ 236 + enum { 237 + FRC_NORMAL, 238 + FRC_ITALIC, 239 + FRC_BOLD, 240 + FRC_ITALICBOLD 241 + }; 242 + 243 + typedef struct { 244 + XftFont *font; 245 + int flags; 246 + Rune unicodep; 247 + } Fontcache; 248 + 249 + /* Fontcache is an array now. A new font will be appended to the array. */ 250 + static Fontcache *frc = NULL; 251 + static int frclen = 0; 252 + static int frccap = 0; 253 + static char *usedfont = NULL; 254 + static double usedfontsize = 0; 255 + static double defaultfontsize = 0; 256 + 257 + static char *opt_alpha = NULL; 258 + static char *opt_class = NULL; 259 + static char **opt_cmd = NULL; 260 + static char *opt_embed = NULL; 261 + static char *opt_font = NULL; 262 + static char *opt_io = NULL; 263 + static char *opt_line = NULL; 264 + static char *opt_name = NULL; 265 + static char *opt_title = NULL; 266 + 267 + static int oldbutton = 3; /* button event on startup: 3 = release */ 268 + static int cursorblinks = 0; 269 + 270 + void 271 + clipcopy(const Arg *dummy) 272 + { 273 + Atom clipboard; 274 + 275 + free(xsel.clipboard); 276 + xsel.clipboard = NULL; 277 + 278 + if (xsel.primary != NULL) { 279 + xsel.clipboard = xstrdup(xsel.primary); 280 + clipboard = XInternAtom(xw.dpy, "CLIPBOARD", 0); 281 + XSetSelectionOwner(xw.dpy, clipboard, xw.win, CurrentTime); 282 + } 283 + } 284 + 285 + void 286 + clippaste(const Arg *dummy) 287 + { 288 + Atom clipboard; 289 + 290 + clipboard = XInternAtom(xw.dpy, "CLIPBOARD", 0); 291 + XConvertSelection(xw.dpy, clipboard, xsel.xtarget, clipboard, 292 + xw.win, CurrentTime); 293 + } 294 + 295 + void 296 + selpaste(const Arg *dummy) 297 + { 298 + XConvertSelection(xw.dpy, XA_PRIMARY, xsel.xtarget, XA_PRIMARY, 299 + xw.win, CurrentTime); 300 + } 301 + 302 + void 303 + numlock(const Arg *dummy) 304 + { 305 + win.mode ^= MODE_NUMLOCK; 306 + } 307 + 308 + void 309 + changealpha(const Arg *arg) 310 + { 311 + if(alpha > 1 && arg->f == 2 ) 312 + alpha = 1; 313 + if((alpha > 0 && arg->f < 0) || (alpha < 1 && arg->f > 0)) 314 + alpha += arg->f; 315 + if(alpha < 0) 316 + alpha = 0; 317 + if(alpha > 1) 318 + alpha = 1; 319 + 320 + xloadcols(); 321 + redraw(); 322 + } 323 + 324 + void 325 + zoom(const Arg *arg) 326 + { 327 + Arg larg; 328 + 329 + larg.f = usedfontsize + arg->f; 330 + zoomabs(&larg); 331 + } 332 + 333 + void 334 + zoomabs(const Arg *arg) 335 + { 336 + xunloadfonts(); 337 + xloadfonts(usedfont, arg->f); 338 + xloadsparefonts(); 339 + cresize(0, 0); 340 + redraw(); 341 + xhints(); 342 + } 343 + 344 + void 345 + zoomreset(const Arg *arg) 346 + { 347 + Arg larg; 348 + 349 + if (defaultfontsize > 0) { 350 + larg.f = defaultfontsize; 351 + zoomabs(&larg); 352 + } 353 + } 354 + 355 + int 356 + evcol(XEvent *e) 357 + { 358 + int x = e->xbutton.x - borderpx; 359 + LIMIT(x, 0, win.tw - 1); 360 + return x / win.cw; 361 + } 362 + 363 + int 364 + evrow(XEvent *e) 365 + { 366 + int y = e->xbutton.y - borderpx; 367 + LIMIT(y, 0, win.th - 1); 368 + return y / win.ch; 369 + } 370 + 371 + void 372 + mousesel(XEvent *e, int done) 373 + { 374 + int type, seltype = SEL_REGULAR; 375 + uint state = e->xbutton.state & ~(Button1Mask | forceselmod); 376 + 377 + for (type = 1; type < LEN(selmasks); ++type) { 378 + if (match(selmasks[type], state)) { 379 + seltype = type; 380 + break; 381 + } 382 + } 383 + selextend(evcol(e), evrow(e), seltype, done); 384 + if (done) 385 + setsel(getsel(), e->xbutton.time); 386 + } 387 + 388 + void 389 + mousereport(XEvent *e) 390 + { 391 + int len, x = evcol(e), y = evrow(e), 392 + button = e->xbutton.button, state = e->xbutton.state; 393 + char buf[40]; 394 + static int ox, oy; 395 + 396 + /* from urxvt */ 397 + if (e->xbutton.type == MotionNotify) { 398 + if (x == ox && y == oy) 399 + return; 400 + if (!IS_SET(MODE_MOUSEMOTION) && !IS_SET(MODE_MOUSEMANY)) 401 + return; 402 + /* MOUSE_MOTION: no reporting if no button is pressed */ 403 + if (IS_SET(MODE_MOUSEMOTION) && oldbutton == 3) 404 + return; 405 + 406 + button = oldbutton + 32; 407 + ox = x; 408 + oy = y; 409 + } else { 410 + if (!IS_SET(MODE_MOUSESGR) && e->xbutton.type == ButtonRelease) { 411 + button = 3; 412 + } else { 413 + button -= Button1; 414 + if (button >= 3) 415 + button += 64 - 3; 416 + } 417 + if (e->xbutton.type == ButtonPress) { 418 + oldbutton = button; 419 + ox = x; 420 + oy = y; 421 + } else if (e->xbutton.type == ButtonRelease) { 422 + oldbutton = 3; 423 + /* MODE_MOUSEX10: no button release reporting */ 424 + if (IS_SET(MODE_MOUSEX10)) 425 + return; 426 + if (button == 64 || button == 65) 427 + return; 428 + } 429 + } 430 + 431 + if (!IS_SET(MODE_MOUSEX10)) { 432 + button += ((state & ShiftMask ) ? 4 : 0) 433 + + ((state & Mod4Mask ) ? 8 : 0) 434 + + ((state & ControlMask) ? 16 : 0); 435 + } 436 + 437 + if (IS_SET(MODE_MOUSESGR)) { 438 + len = snprintf(buf, sizeof(buf), "\033[<%d;%d;%d%c", 439 + button, x+1, y+1, 440 + e->xbutton.type == ButtonRelease ? 'm' : 'M'); 441 + } else if (x < 223 && y < 223) { 442 + len = snprintf(buf, sizeof(buf), "\033[M%c%c%c", 443 + 32+button, 32+x+1, 32+y+1); 444 + } else { 445 + return; 446 + } 447 + 448 + ttywrite(buf, len, 0); 449 + } 450 + 451 + void 452 + bpress(XEvent *e) 453 + { 454 + struct timespec now; 455 + MouseShortcut *ms; 456 + MouseKey *mk; 457 + int snap; 458 + 459 + if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forceselmod)) { 460 + mousereport(e); 461 + return; 462 + } 463 + 464 + if (tisaltscr()) { 465 + for (ms = mshortcuts; ms < mshortcuts + LEN(mshortcuts); ms++) { 466 + if (e->xbutton.button == ms->b 467 + && match(ms->mask, e->xbutton.state)) { 468 + ttywrite(ms->s, strlen(ms->s), 1); 469 + return; 470 + } 471 + } 472 + } 473 + 474 + for (mk = mkeys; mk < mkeys + LEN(mkeys); mk++) { 475 + if (e->xbutton.button == mk->b 476 + && match(mk->mask, e->xbutton.state)) { 477 + mk->func(&mk->arg); 478 + return; 479 + } 480 + } 481 + 482 + if (e->xbutton.button == Button1) { 483 + /* 484 + * If the user clicks below predefined timeouts specific 485 + * snapping behaviour is exposed. 486 + */ 487 + clock_gettime(CLOCK_MONOTONIC, &now); 488 + if (TIMEDIFF(now, xsel.tclick2) <= tripleclicktimeout) { 489 + snap = SNAP_LINE; 490 + } else if (TIMEDIFF(now, xsel.tclick1) <= doubleclicktimeout) { 491 + snap = SNAP_WORD; 492 + } else { 493 + snap = 0; 494 + } 495 + xsel.tclick2 = xsel.tclick1; 496 + xsel.tclick1 = now; 497 + 498 + selstart(evcol(e), evrow(e), snap); 499 + } 500 + } 501 + 502 + void 503 + propnotify(XEvent *e) 504 + { 505 + XPropertyEvent *xpev; 506 + Atom clipboard = XInternAtom(xw.dpy, "CLIPBOARD", 0); 507 + 508 + xpev = &e->xproperty; 509 + if (xpev->state == PropertyNewValue && 510 + (xpev->atom == XA_PRIMARY || 511 + xpev->atom == clipboard)) { 512 + selnotify(e); 513 + } 514 + } 515 + 516 + void 517 + selnotify(XEvent *e) 518 + { 519 + ulong nitems, ofs, rem; 520 + int format; 521 + uchar *data, *last, *repl; 522 + Atom type, incratom, property = None; 523 + 524 + incratom = XInternAtom(xw.dpy, "INCR", 0); 525 + 526 + ofs = 0; 527 + if (e->type == SelectionNotify) 528 + property = e->xselection.property; 529 + else if (e->type == PropertyNotify) 530 + property = e->xproperty.atom; 531 + 532 + if (property == None) 533 + return; 534 + 535 + do { 536 + if (XGetWindowProperty(xw.dpy, xw.win, property, ofs, 537 + BUFSIZ/4, False, AnyPropertyType, 538 + &type, &format, &nitems, &rem, 539 + &data)) { 540 + fprintf(stderr, "Clipboard allocation failed\n"); 541 + return; 542 + } 543 + 544 + if (e->type == PropertyNotify && nitems == 0 && rem == 0) { 545 + /* 546 + * If there is some PropertyNotify with no data, then 547 + * this is the signal of the selection owner that all 548 + * data has been transferred. We won't need to receive 549 + * PropertyNotify events anymore. 550 + */ 551 + MODBIT(xw.attrs.event_mask, 0, PropertyChangeMask); 552 + XChangeWindowAttributes(xw.dpy, xw.win, CWEventMask, 553 + &xw.attrs); 554 + } 555 + 556 + if (type == incratom) { 557 + /* 558 + * Activate the PropertyNotify events so we receive 559 + * when the selection owner does send us the next 560 + * chunk of data. 561 + */ 562 + MODBIT(xw.attrs.event_mask, 1, PropertyChangeMask); 563 + XChangeWindowAttributes(xw.dpy, xw.win, CWEventMask, 564 + &xw.attrs); 565 + 566 + /* 567 + * Deleting the property is the transfer start signal. 568 + */ 569 + XDeleteProperty(xw.dpy, xw.win, (int)property); 570 + continue; 571 + } 572 + 573 + /* 574 + * As seen in getsel: 575 + * Line endings are inconsistent in the terminal and GUI world 576 + * copy and pasting. When receiving some selection data, 577 + * replace all '\n' with '\r'. 578 + * FIXME: Fix the computer world. 579 + */ 580 + repl = data; 581 + last = data + nitems * format / 8; 582 + while ((repl = memchr(repl, '\n', last - repl))) { 583 + *repl++ = '\r'; 584 + } 585 + 586 + if (IS_SET(MODE_BRCKTPASTE) && ofs == 0) 587 + ttywrite("\033[200~", 6, 0); 588 + ttywrite((char *)data, nitems * format / 8, 1); 589 + if (IS_SET(MODE_BRCKTPASTE) && rem == 0) 590 + ttywrite("\033[201~", 6, 0); 591 + XFree(data); 592 + /* number of 32-bit chunks returned */ 593 + ofs += nitems * format / 32; 594 + } while (rem > 0); 595 + 596 + /* 597 + * Deleting the property again tells the selection owner to send the 598 + * next data chunk in the property. 599 + */ 600 + XDeleteProperty(xw.dpy, xw.win, (int)property); 601 + } 602 + 603 + void 604 + xclipcopy(void) 605 + { 606 + clipcopy(NULL); 607 + } 608 + 609 + void 610 + selclear_(XEvent *e) 611 + { 612 + selclear(); 613 + } 614 + 615 + void 616 + selrequest(XEvent *e) 617 + { 618 + XSelectionRequestEvent *xsre; 619 + XSelectionEvent xev; 620 + Atom xa_targets, string, clipboard; 621 + char *seltext; 622 + 623 + xsre = (XSelectionRequestEvent *) e; 624 + xev.type = SelectionNotify; 625 + xev.requestor = xsre->requestor; 626 + xev.selection = xsre->selection; 627 + xev.target = xsre->target; 628 + xev.time = xsre->time; 629 + if (xsre->property == None) 630 + xsre->property = xsre->target; 631 + 632 + /* reject */ 633 + xev.property = None; 634 + 635 + xa_targets = XInternAtom(xw.dpy, "TARGETS", 0); 636 + if (xsre->target == xa_targets) { 637 + /* respond with the supported type */ 638 + string = xsel.xtarget; 639 + XChangeProperty(xsre->display, xsre->requestor, xsre->property, 640 + XA_ATOM, 32, PropModeReplace, 641 + (uchar *) &string, 1); 642 + xev.property = xsre->property; 643 + } else if (xsre->target == xsel.xtarget || xsre->target == XA_STRING) { 644 + /* 645 + * xith XA_STRING non ascii characters may be incorrect in the 646 + * requestor. It is not our problem, use utf8. 647 + */ 648 + clipboard = XInternAtom(xw.dpy, "CLIPBOARD", 0); 649 + if (xsre->selection == XA_PRIMARY) { 650 + seltext = xsel.primary; 651 + } else if (xsre->selection == clipboard) { 652 + seltext = xsel.clipboard; 653 + } else { 654 + fprintf(stderr, 655 + "Unhandled clipboard selection 0x%lx\n", 656 + xsre->selection); 657 + return; 658 + } 659 + if (seltext != NULL) { 660 + XChangeProperty(xsre->display, xsre->requestor, 661 + xsre->property, xsre->target, 662 + 8, PropModeReplace, 663 + (uchar *)seltext, strlen(seltext)); 664 + xev.property = xsre->property; 665 + } 666 + } 667 + 668 + /* all done, send a notification to the listener */ 669 + if (!XSendEvent(xsre->display, xsre->requestor, 1, 0, (XEvent *) &xev)) 670 + fprintf(stderr, "Error sending SelectionNotify event\n"); 671 + } 672 + 673 + void 674 + setsel(char *str, Time t) 675 + { 676 + if (!str) 677 + return; 678 + 679 + free(xsel.primary); 680 + xsel.primary = str; 681 + 682 + XSetSelectionOwner(xw.dpy, XA_PRIMARY, xw.win, t); 683 + if (XGetSelectionOwner(xw.dpy, XA_PRIMARY) != xw.win) 684 + selclear(); 685 + } 686 + 687 + void 688 + xsetsel(char *str) 689 + { 690 + setsel(str, CurrentTime); 691 + } 692 + 693 + void 694 + brelease(XEvent *e) 695 + { 696 + if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forceselmod)) { 697 + mousereport(e); 698 + return; 699 + } 700 + if (e->xbutton.button == Button3) 701 + selpaste(NULL); 702 + else if (e->xbutton.button == Button1) 703 + mousesel(e, 1); 704 + } 705 + 706 + void 707 + bmotion(XEvent *e) 708 + { 709 + if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forceselmod)) { 710 + mousereport(e); 711 + return; 712 + } 713 + 714 + mousesel(e, 0); 715 + } 716 + 717 + void 718 + cresize(int width, int height) 719 + { 720 + int col, row; 721 + 722 + if (width != 0) 723 + win.w = width; 724 + if (height != 0) 725 + win.h = height; 726 + 727 + col = (win.w - 2 * borderpx) / win.cw; 728 + row = (win.h - 2 * borderpx) / win.ch; 729 + col = MAX(1, col); 730 + row = MAX(1, row); 731 + 732 + tresize(col, row); 733 + xresize(col, row); 734 + ttyresize(win.tw, win.th); 735 + } 736 + 737 + void 738 + xresize(int col, int row) 739 + { 740 + win.tw = col * win.cw; 741 + win.th = row * win.ch; 742 + 743 + XFreePixmap(xw.dpy, xw.buf); 744 + xw.buf = XCreatePixmap(xw.dpy, xw.win, win.w, win.h, 745 + xw.depth); 746 + XftDrawChange(xw.draw, xw.buf); 747 + xclear(0, 0, win.w, win.h); 748 + 749 + /* resize to new width */ 750 + xw.specbuf = xrealloc(xw.specbuf, col * sizeof(GlyphFontSpec)); 751 + } 752 + 753 + ushort 754 + sixd_to_16bit(int x) 755 + { 756 + return x == 0 ? 0 : 0x3737 + 0x2828 * x; 757 + } 758 + 759 + int 760 + xloadcolor(int i, const char *name, Color *ncolor) 761 + { 762 + XRenderColor color = { .alpha = 0xffff }; 763 + 764 + if (!name) { 765 + if (BETWEEN(i, 16, 255)) { /* 256 color */ 766 + if (i < 6*6*6+16) { /* same colors as xterm */ 767 + color.red = sixd_to_16bit( ((i-16)/36)%6 ); 768 + color.green = sixd_to_16bit( ((i-16)/6) %6 ); 769 + color.blue = sixd_to_16bit( ((i-16)/1) %6 ); 770 + } else { /* greyscale */ 771 + color.red = 0x0808 + 0x0a0a * (i - (6*6*6+16)); 772 + color.green = color.blue = color.red; 773 + } 774 + return XftColorAllocValue(xw.dpy, xw.vis, 775 + xw.cmap, &color, ncolor); 776 + } else 777 + name = colorname[i]; 778 + } 779 + 780 + return XftColorAllocName(xw.dpy, xw.vis, xw.cmap, name, ncolor); 781 + } 782 + 783 + void 784 + xloadcols(void) 785 + { 786 + int i; 787 + static int loaded; 788 + Color *cp; 789 + 790 + if (loaded) { 791 + for (cp = dc.col; cp < &dc.col[dc.collen]; ++cp) 792 + XftColorFree(xw.dpy, xw.vis, xw.cmap, cp); 793 + } else { 794 + dc.collen = MAX(LEN(colorname), 256); 795 + dc.col = xmalloc(dc.collen * sizeof(Color)); 796 + } 797 + 798 + for (i = 0; i < dc.collen; i++) 799 + if (!xloadcolor(i, NULL, &dc.col[i])) { 800 + if (colorname[i]) 801 + die("could not allocate color '%s'\n", colorname[i]); 802 + else 803 + die("could not allocate color %d\n", i); 804 + } 805 + 806 + /* set alpha value of bg color */ 807 + if (opt_alpha) 808 + alpha = strtof(opt_alpha, NULL); 809 + dc.col[defaultbg].color.alpha = (unsigned short)(0xffff * alpha); 810 + dc.col[defaultbg].color.red = 811 + ((unsigned short)(dc.col[defaultbg].color.red * alpha)) & 0xff00; 812 + dc.col[defaultbg].color.green = 813 + ((unsigned short)(dc.col[defaultbg].color.green * alpha)) & 0xff00; 814 + dc.col[defaultbg].color.blue = 815 + ((unsigned short)(dc.col[defaultbg].color.blue * alpha)) & 0xff00; 816 + dc.col[defaultbg].pixel &= 0x00FFFFFF; 817 + dc.col[defaultbg].pixel |= (unsigned char)(0xff * alpha) << 24; 818 + loaded = 1; 819 + } 820 + 821 + int 822 + xsetcolorname(int x, const char *name) 823 + { 824 + Color ncolor; 825 + 826 + if (!BETWEEN(x, 0, dc.collen)) 827 + return 1; 828 + 829 + if (!xloadcolor(x, name, &ncolor)) 830 + return 1; 831 + 832 + XftColorFree(xw.dpy, xw.vis, xw.cmap, &dc.col[x]); 833 + dc.col[x] = ncolor; 834 + if (x == defaultbg) 835 + dc.col[defaultbg].color.alpha = (unsigned short)(0xffff * alpha); 836 + 837 + return 0; 838 + } 839 + 840 + /* 841 + * Absolute coordinates. 842 + */ 843 + void 844 + xclear(int x1, int y1, int x2, int y2) 845 + { 846 + XftDrawRect(xw.draw, 847 + &dc.col[IS_SET(MODE_REVERSE)? defaultfg : defaultbg], 848 + x1, y1, x2-x1, y2-y1); 849 + } 850 + 851 + void 852 + xclearwin(void) 853 + { 854 + xclear(0, 0, win.w, win.h); 855 + } 856 + 857 + 858 + void 859 + xhints(void) 860 + { 861 + XClassHint class = {opt_name ? opt_name : "st", 862 + opt_class ? opt_class : "St"}; 863 + XWMHints wm = {.flags = InputHint, .input = 1}; 864 + XSizeHints *sizeh; 865 + 866 + sizeh = XAllocSizeHints(); 867 + 868 + sizeh->flags = PSize | PResizeInc | PBaseSize | PMinSize; 869 + sizeh->height = win.h; 870 + sizeh->width = win.w; 871 + sizeh->height_inc = 1; 872 + sizeh->width_inc = 1; 873 + sizeh->base_height = 2 * borderpx; 874 + sizeh->base_width = 2 * borderpx; 875 + sizeh->min_height = win.ch + 2 * borderpx; 876 + sizeh->min_width = win.cw + 2 * borderpx; 877 + if (xw.isfixed) { 878 + sizeh->flags |= PMaxSize; 879 + sizeh->min_width = sizeh->max_width = win.w; 880 + sizeh->min_height = sizeh->max_height = win.h; 881 + } 882 + if (xw.gm & (XValue|YValue)) { 883 + sizeh->flags |= USPosition | PWinGravity; 884 + sizeh->x = xw.l; 885 + sizeh->y = xw.t; 886 + sizeh->win_gravity = xgeommasktogravity(xw.gm); 887 + } 888 + 889 + XSetWMProperties(xw.dpy, xw.win, NULL, NULL, NULL, 0, sizeh, &wm, 890 + &class); 891 + XFree(sizeh); 892 + } 893 + 894 + int 895 + xgeommasktogravity(int mask) 896 + { 897 + switch (mask & (XNegative|YNegative)) { 898 + case 0: 899 + return NorthWestGravity; 900 + case XNegative: 901 + return NorthEastGravity; 902 + case YNegative: 903 + return SouthWestGravity; 904 + } 905 + 906 + return SouthEastGravity; 907 + } 908 + 909 + int 910 + xloadfont(Font *f, FcPattern *pattern) 911 + { 912 + FcPattern *configured; 913 + FcPattern *match; 914 + FcResult result; 915 + XGlyphInfo extents; 916 + int wantattr, haveattr; 917 + 918 + /* 919 + * Manually configure instead of calling XftMatchFont 920 + * so that we can use the configured pattern for 921 + * "missing glyph" lookups. 922 + */ 923 + configured = FcPatternDuplicate(pattern); 924 + if (!configured) 925 + return 1; 926 + 927 + FcConfigSubstitute(NULL, configured, FcMatchPattern); 928 + XftDefaultSubstitute(xw.dpy, xw.scr, configured); 929 + 930 + match = FcFontMatch(NULL, configured, &result); 931 + if (!match) { 932 + FcPatternDestroy(configured); 933 + return 1; 934 + } 935 + 936 + if (!(f->match = XftFontOpenPattern(xw.dpy, match))) { 937 + FcPatternDestroy(configured); 938 + FcPatternDestroy(match); 939 + return 1; 940 + } 941 + 942 + if ((XftPatternGetInteger(pattern, "slant", 0, &wantattr) == 943 + XftResultMatch)) { 944 + /* 945 + * Check if xft was unable to find a font with the appropriate 946 + * slant but gave us one anyway. Try to mitigate. 947 + */ 948 + if ((XftPatternGetInteger(f->match->pattern, "slant", 0, 949 + &haveattr) != XftResultMatch) || haveattr < wantattr) { 950 + f->badslant = 1; 951 + fputs("font slant does not match\n", stderr); 952 + } 953 + } 954 + 955 + if ((XftPatternGetInteger(pattern, "weight", 0, &wantattr) == 956 + XftResultMatch)) { 957 + if ((XftPatternGetInteger(f->match->pattern, "weight", 0, 958 + &haveattr) != XftResultMatch) || haveattr != wantattr) { 959 + f->badweight = 1; 960 + fputs("font weight does not match\n", stderr); 961 + } 962 + } 963 + 964 + XftTextExtentsUtf8(xw.dpy, f->match, 965 + (const FcChar8 *) ascii_printable, 966 + strlen(ascii_printable), &extents); 967 + 968 + f->set = NULL; 969 + f->pattern = configured; 970 + 971 + f->ascent = f->match->ascent; 972 + f->descent = f->match->descent; 973 + f->lbearing = 0; 974 + f->rbearing = f->match->max_advance_width; 975 + 976 + f->height = f->ascent + f->descent; 977 + f->width = DIVCEIL(extents.xOff, strlen(ascii_printable)); 978 + 979 + return 0; 980 + } 981 + 982 + void 983 + xloadfonts(char *fontstr, double fontsize) 984 + { 985 + FcPattern *pattern; 986 + double fontval; 987 + 988 + if (fontstr[0] == '-') 989 + pattern = XftXlfdParse(fontstr, False, False); 990 + else 991 + pattern = FcNameParse((FcChar8 *)fontstr); 992 + 993 + if (!pattern) 994 + die("can't open font %s\n", fontstr); 995 + 996 + if (fontsize > 1) { 997 + FcPatternDel(pattern, FC_PIXEL_SIZE); 998 + FcPatternDel(pattern, FC_SIZE); 999 + FcPatternAddDouble(pattern, FC_PIXEL_SIZE, (double)fontsize); 1000 + usedfontsize = fontsize; 1001 + } else { 1002 + if (FcPatternGetDouble(pattern, FC_PIXEL_SIZE, 0, &fontval) == 1003 + FcResultMatch) { 1004 + usedfontsize = fontval; 1005 + } else if (FcPatternGetDouble(pattern, FC_SIZE, 0, &fontval) == 1006 + FcResultMatch) { 1007 + usedfontsize = -1; 1008 + } else { 1009 + /* 1010 + * Default font size is 12, if none given. This is to 1011 + * have a known usedfontsize value. 1012 + */ 1013 + FcPatternAddDouble(pattern, FC_PIXEL_SIZE, 12); 1014 + usedfontsize = 12; 1015 + } 1016 + defaultfontsize = usedfontsize; 1017 + } 1018 + 1019 + if (xloadfont(&dc.font, pattern)) 1020 + die("can't open font %s\n", fontstr); 1021 + 1022 + if (usedfontsize < 0) { 1023 + FcPatternGetDouble(dc.font.match->pattern, 1024 + FC_PIXEL_SIZE, 0, &fontval); 1025 + usedfontsize = fontval; 1026 + if (fontsize == 0) 1027 + defaultfontsize = fontval; 1028 + } 1029 + 1030 + /* Setting character width and height. */ 1031 + win.cw = ceilf(dc.font.width * cwscale); 1032 + win.ch = ceilf(dc.font.height * chscale); 1033 + win.cyo = ceilf(dc.font.height * (chscale - 1) / 2); 1034 + 1035 + FcPatternDel(pattern, FC_SLANT); 1036 + FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ITALIC); 1037 + if (xloadfont(&dc.ifont, pattern)) 1038 + die("can't open font %s\n", fontstr); 1039 + 1040 + FcPatternDel(pattern, FC_WEIGHT); 1041 + FcPatternAddInteger(pattern, FC_WEIGHT, FC_WEIGHT_BOLD); 1042 + if (xloadfont(&dc.ibfont, pattern)) 1043 + die("can't open font %s\n", fontstr); 1044 + 1045 + FcPatternDel(pattern, FC_SLANT); 1046 + FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ROMAN); 1047 + if (xloadfont(&dc.bfont, pattern)) 1048 + die("can't open font %s\n", fontstr); 1049 + 1050 + FcPatternDestroy(pattern); 1051 + } 1052 + 1053 + int 1054 + xloadsparefont(FcPattern *pattern, int flags) 1055 + { 1056 + FcPattern *match; 1057 + FcResult result; 1058 + 1059 + match = FcFontMatch(NULL, pattern, &result); 1060 + if (!match) { 1061 + return 1; 1062 + } 1063 + 1064 + if (!(frc[frclen].font = XftFontOpenPattern(xw.dpy, match))) { 1065 + FcPatternDestroy(match); 1066 + return 1; 1067 + } 1068 + 1069 + frc[frclen].flags = flags; 1070 + /* Believe U+0000 glyph will present in each default font */ 1071 + frc[frclen].unicodep = 0; 1072 + frclen++; 1073 + 1074 + return 0; 1075 + } 1076 + 1077 + void 1078 + xloadsparefonts(void) 1079 + { 1080 + FcPattern *pattern; 1081 + double sizeshift, fontval; 1082 + int fc; 1083 + char **fp; 1084 + 1085 + if (frclen != 0) 1086 + die("can't embed spare fonts. cache isn't empty"); 1087 + 1088 + /* Calculate count of spare fonts */ 1089 + fc = sizeof(font2) / sizeof(*font2); 1090 + if (fc == 0) 1091 + return; 1092 + 1093 + /* Allocate memory for cache entries. */ 1094 + if (frccap < 4 * fc) { 1095 + frccap += 4 * fc - frccap; 1096 + frc = xrealloc(frc, frccap * sizeof(Fontcache)); 1097 + } 1098 + 1099 + for (fp = font2; fp - font2 < fc; ++fp) { 1100 + 1101 + if (**fp == '-') 1102 + pattern = XftXlfdParse(*fp, False, False); 1103 + else 1104 + pattern = FcNameParse((FcChar8 *)*fp); 1105 + 1106 + if (!pattern) 1107 + die("can't open spare font %s\n", *fp); 1108 + 1109 + if (defaultfontsize > 0) { 1110 + sizeshift = usedfontsize - defaultfontsize; 1111 + if (sizeshift != 0 && 1112 + FcPatternGetDouble(pattern, FC_PIXEL_SIZE, 0, &fontval) == 1113 + FcResultMatch) { 1114 + fontval += sizeshift; 1115 + FcPatternDel(pattern, FC_PIXEL_SIZE); 1116 + FcPatternDel(pattern, FC_SIZE); 1117 + FcPatternAddDouble(pattern, FC_PIXEL_SIZE, fontval); 1118 + } 1119 + } 1120 + 1121 + FcPatternAddBool(pattern, FC_SCALABLE, 1); 1122 + 1123 + FcConfigSubstitute(NULL, pattern, FcMatchPattern); 1124 + XftDefaultSubstitute(xw.dpy, xw.scr, pattern); 1125 + 1126 + if (xloadsparefont(pattern, FRC_NORMAL)) 1127 + die("can't open spare font %s\n", *fp); 1128 + 1129 + FcPatternDel(pattern, FC_SLANT); 1130 + FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ITALIC); 1131 + if (xloadsparefont(pattern, FRC_ITALIC)) 1132 + die("can't open spare font %s\n", *fp); 1133 + 1134 + FcPatternDel(pattern, FC_WEIGHT); 1135 + FcPatternAddInteger(pattern, FC_WEIGHT, FC_WEIGHT_BOLD); 1136 + if (xloadsparefont(pattern, FRC_ITALICBOLD)) 1137 + die("can't open spare font %s\n", *fp); 1138 + 1139 + FcPatternDel(pattern, FC_SLANT); 1140 + FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ROMAN); 1141 + if (xloadsparefont(pattern, FRC_BOLD)) 1142 + die("can't open spare font %s\n", *fp); 1143 + 1144 + FcPatternDestroy(pattern); 1145 + } 1146 + } 1147 + 1148 + void 1149 + xunloadfont(Font *f) 1150 + { 1151 + XftFontClose(xw.dpy, f->match); 1152 + FcPatternDestroy(f->pattern); 1153 + if (f->set) 1154 + FcFontSetDestroy(f->set); 1155 + } 1156 + 1157 + void 1158 + xunloadfonts(void) 1159 + { 1160 + /* Clear Harfbuzz font cache. */ 1161 + hbunloadfonts(); 1162 + 1163 + /* Free the loaded fonts in the font cache. */ 1164 + while (frclen > 0) 1165 + XftFontClose(xw.dpy, frc[--frclen].font); 1166 + 1167 + xunloadfont(&dc.font); 1168 + xunloadfont(&dc.bfont); 1169 + xunloadfont(&dc.ifont); 1170 + xunloadfont(&dc.ibfont); 1171 + } 1172 + 1173 + void 1174 + ximopen(Display *dpy) 1175 + { 1176 + XIMCallback destroy = { .client_data = NULL, .callback = ximdestroy }; 1177 + 1178 + if ((xw.xim = XOpenIM(xw.dpy, NULL, NULL, NULL)) == NULL) { 1179 + XSetLocaleModifiers("@im=local"); 1180 + if ((xw.xim = XOpenIM(xw.dpy, NULL, NULL, NULL)) == NULL) { 1181 + XSetLocaleModifiers("@im="); 1182 + if ((xw.xim = XOpenIM(xw.dpy, NULL, NULL, NULL)) == NULL) 1183 + die("XOpenIM failed. Could not open input device.\n"); 1184 + } 1185 + } 1186 + if (XSetIMValues(xw.xim, XNDestroyCallback, &destroy, NULL) != NULL) 1187 + die("XSetIMValues failed. Could not set input method value.\n"); 1188 + xw.xic = XCreateIC(xw.xim, XNInputStyle, XIMPreeditNothing | XIMStatusNothing, 1189 + XNClientWindow, xw.win, XNFocusWindow, xw.win, NULL); 1190 + if (xw.xic == NULL) 1191 + die("XCreateIC failed. Could not obtain input method.\n"); 1192 + } 1193 + 1194 + void 1195 + ximinstantiate(Display *dpy, XPointer client, XPointer call) 1196 + { 1197 + ximopen(dpy); 1198 + XUnregisterIMInstantiateCallback(xw.dpy, NULL, NULL, NULL, 1199 + ximinstantiate, NULL); 1200 + } 1201 + 1202 + void 1203 + ximdestroy(XIM xim, XPointer client, XPointer call) 1204 + { 1205 + xw.xim = NULL; 1206 + XRegisterIMInstantiateCallback(xw.dpy, NULL, NULL, NULL, 1207 + ximinstantiate, NULL); 1208 + } 1209 + 1210 + void 1211 + xinit(int cols, int rows) 1212 + { 1213 + XGCValues gcvalues; 1214 + Cursor cursor; 1215 + Window parent; 1216 + pid_t thispid = getpid(); 1217 + XColor xmousefg, xmousebg; 1218 + XWindowAttributes attr; 1219 + XVisualInfo vis; 1220 + 1221 + xw.scr = XDefaultScreen(xw.dpy); 1222 + 1223 + if (!(opt_embed && (parent = strtol(opt_embed, NULL, 0)))) { 1224 + parent = XRootWindow(xw.dpy, xw.scr); 1225 + xw.depth = 32; 1226 + } else { 1227 + XGetWindowAttributes(xw.dpy, parent, &attr); 1228 + xw.depth = attr.depth; 1229 + } 1230 + 1231 + XMatchVisualInfo(xw.dpy, xw.scr, xw.depth, TrueColor, &vis); 1232 + xw.vis = vis.visual; 1233 + 1234 + /* font */ 1235 + if (!FcInit()) 1236 + die("could not init fontconfig.\n"); 1237 + 1238 + usedfont = (opt_font == NULL)? font : opt_font; 1239 + xloadfonts(usedfont, 0); 1240 + 1241 + /* spare fonts */ 1242 + xloadsparefonts(); 1243 + 1244 + /* colors */ 1245 + xw.cmap = XCreateColormap(xw.dpy, parent, xw.vis, None); 1246 + xloadcols(); 1247 + 1248 + /* adjust fixed window geometry */ 1249 + win.w = 2 * win.hborderpx + cols * win.cw; 1250 + win.h = 2 * win.vborderpx + rows * win.ch; 1251 + if (xw.gm & XNegative) 1252 + xw.l += DisplayWidth(xw.dpy, xw.scr) - win.w - 2; 1253 + if (xw.gm & YNegative) 1254 + xw.t += DisplayHeight(xw.dpy, xw.scr) - win.h - 2; 1255 + 1256 + /* Events */ 1257 + xw.attrs.background_pixel = dc.col[defaultbg].pixel; 1258 + xw.attrs.border_pixel = dc.col[defaultbg].pixel; 1259 + xw.attrs.bit_gravity = NorthWestGravity; 1260 + xw.attrs.event_mask = FocusChangeMask | KeyPressMask | KeyReleaseMask 1261 + | ExposureMask | VisibilityChangeMask | StructureNotifyMask 1262 + | ButtonMotionMask | ButtonPressMask | ButtonReleaseMask; 1263 + xw.attrs.colormap = xw.cmap; 1264 + 1265 + xw.win = XCreateWindow(xw.dpy, parent, xw.l, xw.t, 1266 + win.w, win.h, 0, xw.depth, InputOutput, 1267 + xw.vis, CWBackPixel | CWBorderPixel | CWBitGravity 1268 + | CWEventMask | CWColormap, &xw.attrs); 1269 + 1270 + memset(&gcvalues, 0, sizeof(gcvalues)); 1271 + gcvalues.graphics_exposures = False; 1272 + xw.buf = XCreatePixmap(xw.dpy, xw.win, win.w, win.h, xw.depth); 1273 + dc.gc = XCreateGC(xw.dpy, xw.buf, GCGraphicsExposures, &gcvalues); 1274 + XSetForeground(xw.dpy, dc.gc, dc.col[defaultbg].pixel); 1275 + XFillRectangle(xw.dpy, xw.buf, dc.gc, 0, 0, win.w, win.h); 1276 + 1277 + /* font spec buffer */ 1278 + xw.specbuf = xmalloc(cols * sizeof(GlyphFontSpec)); 1279 + 1280 + /* Xft rendering context */ 1281 + xw.draw = XftDrawCreate(xw.dpy, xw.buf, xw.vis, xw.cmap); 1282 + 1283 + /* input methods */ 1284 + ximopen(xw.dpy); 1285 + 1286 + /* white cursor, black outline */ 1287 + cursor = XCreateFontCursor(xw.dpy, mouseshape); 1288 + XDefineCursor(xw.dpy, xw.win, cursor); 1289 + 1290 + if (XParseColor(xw.dpy, xw.cmap, colorname[mousefg], &xmousefg) == 0) { 1291 + xmousefg.red = 0xffff; 1292 + xmousefg.green = 0xffff; 1293 + xmousefg.blue = 0xffff; 1294 + } 1295 + 1296 + if (XParseColor(xw.dpy, xw.cmap, colorname[mousebg], &xmousebg) == 0) { 1297 + xmousebg.red = 0x0000; 1298 + xmousebg.green = 0x0000; 1299 + xmousebg.blue = 0x0000; 1300 + } 1301 + 1302 + XRecolorCursor(xw.dpy, cursor, &xmousefg, &xmousebg); 1303 + 1304 + xw.xembed = XInternAtom(xw.dpy, "_XEMBED", False); 1305 + xw.wmdeletewin = XInternAtom(xw.dpy, "WM_DELETE_WINDOW", False); 1306 + xw.netwmname = XInternAtom(xw.dpy, "_NET_WM_NAME", False); 1307 + XSetWMProtocols(xw.dpy, xw.win, &xw.wmdeletewin, 1); 1308 + 1309 + xw.netwmpid = XInternAtom(xw.dpy, "_NET_WM_PID", False); 1310 + XChangeProperty(xw.dpy, xw.win, xw.netwmpid, XA_CARDINAL, 32, 1311 + PropModeReplace, (uchar *)&thispid, 1); 1312 + 1313 + win.mode = MODE_NUMLOCK; 1314 + resettitle(); 1315 + XMapWindow(xw.dpy, xw.win); 1316 + xhints(); 1317 + XSync(xw.dpy, False); 1318 + 1319 + clock_gettime(CLOCK_MONOTONIC, &xsel.tclick1); 1320 + clock_gettime(CLOCK_MONOTONIC, &xsel.tclick2); 1321 + xsel.primary = NULL; 1322 + xsel.clipboard = NULL; 1323 + xsel.xtarget = XInternAtom(xw.dpy, "UTF8_STRING", 0); 1324 + if (xsel.xtarget == None) 1325 + xsel.xtarget = XA_STRING; 1326 + 1327 + boxdraw_xinit(xw.dpy, xw.cmap, xw.draw, xw.vis); 1328 + } 1329 + 1330 + int 1331 + xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x, int y) 1332 + { 1333 + float winx = borderpx + x * win.cw, winy = borderpx + y * win.ch, xp, yp; 1334 + ushort mode, prevmode = USHRT_MAX; 1335 + Font *font = &dc.font; 1336 + int frcflags = FRC_NORMAL; 1337 + float runewidth = win.cw; 1338 + Rune rune; 1339 + FT_UInt glyphidx; 1340 + FcResult fcres; 1341 + FcPattern *fcpattern, *fontpattern; 1342 + FcFontSet *fcsets[] = { NULL }; 1343 + FcCharSet *fccharset; 1344 + int i, f, numspecs = 0; 1345 + 1346 + for (i = 0, xp = winx, yp = winy + font->ascent + win.cyo; i < len; ++i) { 1347 + /* Fetch rune and mode for current glyph. */ 1348 + rune = glyphs[i].u; 1349 + mode = glyphs[i].mode; 1350 + 1351 + /* Skip dummy wide-character spacing. */ 1352 + if (mode & ATTR_WDUMMY) 1353 + continue; 1354 + 1355 + /* Determine font for glyph if different from previous glyph. */ 1356 + if (prevmode != mode) { 1357 + prevmode = mode; 1358 + font = &dc.font; 1359 + frcflags = FRC_NORMAL; 1360 + runewidth = win.cw * ((mode & ATTR_WIDE) ? 2.0f : 1.0f); 1361 + if ((mode & ATTR_ITALIC) && (mode & ATTR_BOLD)) { 1362 + font = &dc.ibfont; 1363 + frcflags = FRC_ITALICBOLD; 1364 + } else if (mode & ATTR_ITALIC) { 1365 + font = &dc.ifont; 1366 + frcflags = FRC_ITALIC; 1367 + } else if (mode & ATTR_BOLD) { 1368 + font = &dc.bfont; 1369 + frcflags = FRC_BOLD; 1370 + } 1371 + yp = winy + font->ascent + win.cyo; 1372 + } 1373 + 1374 + if (mode & ATTR_BOXDRAW) { 1375 + /* minor shoehorning: boxdraw uses only this ushort */ 1376 + glyphidx = boxdrawindex(&glyphs[i]); 1377 + } else { 1378 + /* Lookup character index with default font. */ 1379 + glyphidx = XftCharIndex(xw.dpy, font->match, rune); 1380 + } 1381 + if (glyphidx) { 1382 + specs[numspecs].font = font->match; 1383 + specs[numspecs].glyph = glyphidx; 1384 + specs[numspecs].x = (short)xp; 1385 + specs[numspecs].y = (short)yp; 1386 + xp += runewidth; 1387 + numspecs++; 1388 + continue; 1389 + } 1390 + 1391 + /* Fallback on font cache, search the font cache for match. */ 1392 + for (f = 0; f < frclen; f++) { 1393 + glyphidx = XftCharIndex(xw.dpy, frc[f].font, rune); 1394 + /* Everything correct. */ 1395 + if (glyphidx && frc[f].flags == frcflags) 1396 + break; 1397 + /* We got a default font for a not found glyph. */ 1398 + if (!glyphidx && frc[f].flags == frcflags 1399 + && frc[f].unicodep == rune) { 1400 + break; 1401 + } 1402 + } 1403 + 1404 + /* Nothing was found. Use fontconfig to find matching font. */ 1405 + if (f >= frclen) { 1406 + if (!font->set) 1407 + font->set = FcFontSort(0, font->pattern, 1408 + 1, 0, &fcres); 1409 + fcsets[0] = font->set; 1410 + 1411 + /* 1412 + * Nothing was found in the cache. Now use 1413 + * some dozen of Fontconfig calls to get the 1414 + * font for one single character. 1415 + * 1416 + * Xft and fontconfig are design failures. 1417 + */ 1418 + fcpattern = FcPatternDuplicate(font->pattern); 1419 + fccharset = FcCharSetCreate(); 1420 + 1421 + FcCharSetAddChar(fccharset, rune); 1422 + FcPatternAddCharSet(fcpattern, FC_CHARSET, 1423 + fccharset); 1424 + FcPatternAddBool(fcpattern, FC_SCALABLE, 1); 1425 + 1426 + FcConfigSubstitute(0, fcpattern, 1427 + FcMatchPattern); 1428 + FcDefaultSubstitute(fcpattern); 1429 + 1430 + fontpattern = FcFontSetMatch(0, fcsets, 1, 1431 + fcpattern, &fcres); 1432 + 1433 + /* Allocate memory for the new cache entry. */ 1434 + if (frclen >= frccap) { 1435 + frccap += 16; 1436 + frc = xrealloc(frc, frccap * sizeof(Fontcache)); 1437 + } 1438 + 1439 + frc[frclen].font = XftFontOpenPattern(xw.dpy, 1440 + fontpattern); 1441 + if (!frc[frclen].font) 1442 + die("XftFontOpenPattern failed seeking fallback font: %s\n", 1443 + strerror(errno)); 1444 + frc[frclen].flags = frcflags; 1445 + frc[frclen].unicodep = rune; 1446 + 1447 + glyphidx = XftCharIndex(xw.dpy, frc[frclen].font, rune); 1448 + 1449 + f = frclen; 1450 + frclen++; 1451 + 1452 + FcPatternDestroy(fcpattern); 1453 + FcCharSetDestroy(fccharset); 1454 + } 1455 + 1456 + specs[numspecs].font = frc[f].font; 1457 + specs[numspecs].glyph = glyphidx; 1458 + specs[numspecs].x = (short)xp; 1459 + specs[numspecs].y = (short)yp; 1460 + xp += runewidth; 1461 + numspecs++; 1462 + } 1463 + 1464 + /* Harfbuzz transformation for ligatures. */ 1465 + hbtransform(specs, glyphs, len, x, y); 1466 + 1467 + return numspecs; 1468 + } 1469 + 1470 + void 1471 + xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, int y, int dmode) 1472 + { 1473 + int charlen = len * ((base.mode & ATTR_WIDE) ? 2 : 1); 1474 + int winx = borderpx + x * win.cw, winy = borderpx + y * win.ch, 1475 + width = charlen * win.cw; 1476 + Color *fg, *bg, *temp, revfg, revbg, truefg, truebg; 1477 + XRenderColor colfg, colbg; 1478 + 1479 + /* Fallback on color display for attributes not supported by the font */ 1480 + if (base.mode & ATTR_ITALIC && base.mode & ATTR_BOLD) { 1481 + if (dc.ibfont.badslant || dc.ibfont.badweight) 1482 + base.fg = defaultattr; 1483 + } else if ((base.mode & ATTR_ITALIC && dc.ifont.badslant) || 1484 + (base.mode & ATTR_BOLD && dc.bfont.badweight)) { 1485 + base.fg = defaultattr; 1486 + } 1487 + 1488 + if (IS_TRUECOL(base.fg)) { 1489 + colfg.alpha = 0xffff; 1490 + colfg.red = TRUERED(base.fg); 1491 + colfg.green = TRUEGREEN(base.fg); 1492 + colfg.blue = TRUEBLUE(base.fg); 1493 + XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colfg, &truefg); 1494 + fg = &truefg; 1495 + } else { 1496 + fg = &dc.col[base.fg]; 1497 + } 1498 + 1499 + if (IS_TRUECOL(base.bg)) { 1500 + colbg.alpha = 0xffff; 1501 + colbg.green = TRUEGREEN(base.bg); 1502 + colbg.red = TRUERED(base.bg); 1503 + colbg.blue = TRUEBLUE(base.bg); 1504 + XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colbg, &truebg); 1505 + bg = &truebg; 1506 + } else { 1507 + bg = &dc.col[base.bg]; 1508 + } 1509 + 1510 + if (IS_SET(MODE_REVERSE)) { 1511 + if (fg == &dc.col[defaultfg]) { 1512 + fg = &dc.col[defaultbg]; 1513 + } else { 1514 + colfg.red = ~fg->color.red; 1515 + colfg.green = ~fg->color.green; 1516 + colfg.blue = ~fg->color.blue; 1517 + colfg.alpha = fg->color.alpha; 1518 + XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colfg, 1519 + &revfg); 1520 + fg = &revfg; 1521 + } 1522 + 1523 + if (bg == &dc.col[defaultbg]) { 1524 + bg = &dc.col[defaultfg]; 1525 + } else { 1526 + colbg.red = ~bg->color.red; 1527 + colbg.green = ~bg->color.green; 1528 + colbg.blue = ~bg->color.blue; 1529 + colbg.alpha = bg->color.alpha; 1530 + XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colbg, 1531 + &revbg); 1532 + bg = &revbg; 1533 + } 1534 + } 1535 + 1536 + if ((base.mode & ATTR_BOLD_FAINT) == ATTR_FAINT) { 1537 + colfg.red = fg->color.red / 2; 1538 + colfg.green = fg->color.green / 2; 1539 + colfg.blue = fg->color.blue / 2; 1540 + colfg.alpha = fg->color.alpha; 1541 + XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colfg, &revfg); 1542 + fg = &revfg; 1543 + } 1544 + 1545 + if (base.mode & ATTR_REVERSE) { 1546 + temp = fg; 1547 + fg = bg; 1548 + bg = temp; 1549 + } 1550 + 1551 + if (base.mode & ATTR_BLINK && win.mode & MODE_BLINK) 1552 + fg = bg; 1553 + 1554 + if (base.mode & ATTR_INVISIBLE) 1555 + fg = bg; 1556 + 1557 + if (dmode & DRAW_BG) { 1558 + /* Intelligent cleaning up of the borders. */ 1559 + if (x == 0) { 1560 + xclear(0, (y == 0)? 0 : winy, borderpx, 1561 + winy + win.ch + 1562 + ((winy + win.ch >= borderpx + win.th)? win.h : 0)); 1563 + } 1564 + if (winx + width >= borderpx + win.tw) { 1565 + xclear(winx + width, (y == 0)? 0 : winy, win.w, 1566 + ((winy + win.ch >= borderpx + win.th)? win.h : (winy + win.ch))); 1567 + } 1568 + if (y == 0) 1569 + xclear(winx, 0, winx + width, borderpx); 1570 + if (winy + win.ch >= borderpx + win.th) 1571 + xclear(winx, winy + win.ch, winx + width, win.h); 1572 + 1573 + /* Fill the background */ 1574 + XftDrawRect(xw.draw, bg, winx, winy, width, win.ch); 1575 + } 1576 + 1577 + if (dmode & DRAW_FG) { 1578 + if (base.mode & ATTR_BOXDRAW) { 1579 + drawboxes(winx, winy, width / len, win.ch, fg, bg, specs, len); 1580 + } else { 1581 + /* Render the glyphs. */ 1582 + XftDrawGlyphFontSpec(xw.draw, fg, specs, len); 1583 + } 1584 + 1585 + /* Render underline and strikethrough. */ 1586 + if (base.mode & ATTR_UNDERLINE) { 1587 + XftDrawRect(xw.draw, fg, winx, winy + win.cyo + dc.font.ascent + 1, 1588 + width, 1); 1589 + } 1590 + 1591 + if (base.mode & ATTR_STRUCK) { 1592 + XftDrawRect(xw.draw, fg, winx, winy + win.cyo + 2 * dc.font.ascent / 3, 1593 + width, 1); 1594 + } 1595 + } 1596 + } 1597 + 1598 + void 1599 + xdrawglyph(Glyph g, int x, int y) 1600 + { 1601 + int numspecs; 1602 + XftGlyphFontSpec spec; 1603 + 1604 + numspecs = xmakeglyphfontspecs(&spec, &g, 1, x, y); 1605 + xdrawglyphfontspecs(&spec, g, numspecs, x, y, DRAW_BG | DRAW_FG); 1606 + } 1607 + 1608 + void 1609 + xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og, Line line, int len) 1610 + { 1611 + Color drawcol; 1612 + 1613 + /* remove the old cursor */ 1614 + if (selected(ox, oy)) 1615 + og.mode ^= ATTR_REVERSE; 1616 + 1617 + /* Redraw the line where cursor was previously. 1618 + * It will restore the ligatures broken by the cursor. */ 1619 + xdrawline(line, 0, oy, len); 1620 + 1621 + if (IS_SET(MODE_HIDE) || !IS_SET(MODE_FOCUSED)) return; 1622 + 1623 + /* 1624 + * Select the right color for the right mode. 1625 + */ 1626 + g.mode &= ATTR_BOLD|ATTR_ITALIC|ATTR_UNDERLINE|ATTR_STRUCK|ATTR_WIDE|ATTR_BOXDRAW; 1627 + 1628 + if (IS_SET(MODE_REVERSE)) { 1629 + g.mode |= ATTR_REVERSE; 1630 + g.bg = defaultfg; 1631 + if (selected(cx, cy)) { 1632 + drawcol = dc.col[defaultcs]; 1633 + g.fg = defaultrcs; 1634 + } else { 1635 + drawcol = dc.col[defaultrcs]; 1636 + g.fg = defaultcs; 1637 + } 1638 + } else { 1639 + if (selected(cx, cy)) { 1640 + g.fg = defaultfg; 1641 + g.bg = defaultrcs; 1642 + } else { 1643 + g.fg = defaultbg; 1644 + g.bg = defaultcs; 1645 + } 1646 + drawcol = dc.col[g.bg]; 1647 + } 1648 + 1649 + /* draw the new one */ 1650 + if (IS_SET(MODE_FOCUSED)) { 1651 + switch (win.cursor) { 1652 + case 0: /* Blinking block */ 1653 + case 1: /* Blinking block (default) */ 1654 + if (IS_SET(MODE_BLINK)) 1655 + break; 1656 + /* FALLTHROUGH */ 1657 + case 2: /* Steady block */ 1658 + xdrawglyph(g, cx, cy); 1659 + break; 1660 + case 3: /* Blinking underline */ 1661 + if (IS_SET(MODE_BLINK)) 1662 + break; 1663 + /* FALLTHROUGH */ 1664 + case 4: /* Steady underline */ 1665 + XftDrawRect(xw.draw, &drawcol, 1666 + borderpx + cx * win.cw, 1667 + borderpx + (cy + 1) * win.ch - \ 1668 + cursorthickness, 1669 + win.cw, cursorthickness); 1670 + break; 1671 + case 5: /* Blinking bar */ 1672 + if (IS_SET(MODE_BLINK)) 1673 + break; 1674 + /* FALLTHROUGH */ 1675 + case 6: /* Steady bar */ 1676 + XftDrawRect(xw.draw, &drawcol, 1677 + borderpx + cx * win.cw, 1678 + borderpx + cy * win.ch, 1679 + cursorthickness, win.ch); 1680 + break; 1681 + case 7: /* Blinking st cursor */ 1682 + if (IS_SET(MODE_BLINK)) 1683 + break; 1684 + } 1685 + } else { 1686 + XftDrawRect(xw.draw, &drawcol, 1687 + borderpx + cx * win.cw, 1688 + borderpx + cy * win.ch, 1689 + win.cw - 1, 1); 1690 + XftDrawRect(xw.draw, &drawcol, 1691 + borderpx + cx * win.cw, 1692 + borderpx + cy * win.ch, 1693 + 1, win.ch - 1); 1694 + XftDrawRect(xw.draw, &drawcol, 1695 + borderpx + (cx + 1) * win.cw - 1, 1696 + borderpx + cy * win.ch, 1697 + 1, win.ch - 1); 1698 + XftDrawRect(xw.draw, &drawcol, 1699 + borderpx + cx * win.cw, 1700 + borderpx + (cy + 1) * win.ch - 1, 1701 + win.cw, 1); 1702 + } 1703 + } 1704 + 1705 + void 1706 + xsetenv(void) 1707 + { 1708 + char buf[sizeof(long) * 8 + 1]; 1709 + 1710 + snprintf(buf, sizeof(buf), "%lu", xw.win); 1711 + setenv("WINDOWID", buf, 1); 1712 + } 1713 + 1714 + void 1715 + xsettitle(char *p) 1716 + { 1717 + XTextProperty prop; 1718 + DEFAULT(p, opt_title); 1719 + 1720 + Xutf8TextListToTextProperty(xw.dpy, &p, 1, XUTF8StringStyle, 1721 + &prop); 1722 + XSetWMName(xw.dpy, xw.win, &prop); 1723 + XSetTextProperty(xw.dpy, xw.win, &prop, xw.netwmname); 1724 + XFree(prop.value); 1725 + } 1726 + 1727 + int 1728 + xstartdraw(void) 1729 + { 1730 + return IS_SET(MODE_VISIBLE); 1731 + } 1732 + 1733 + void 1734 + xdrawline(Line line, int x1, int y1, int x2) 1735 + { 1736 + int i, x, ox, numspecs, numspecs_cached; 1737 + Glyph base, new; 1738 + XftGlyphFontSpec *specs; 1739 + 1740 + numspecs_cached = xmakeglyphfontspecs(xw.specbuf, &line[x1], x2 - x1, x1, y1); 1741 + 1742 + /* Draw line in 2 passes: background and foreground. This way wide glyphs 1743 + won't get truncated (#223) */ 1744 + for (int dmode = DRAW_BG; dmode <= DRAW_FG; dmode <<= 1) { 1745 + specs = xw.specbuf; 1746 + numspecs = numspecs_cached; 1747 + i = ox = 0; 1748 + for (x = x1; x < x2 && i < numspecs; x++) { 1749 + new = line[x]; 1750 + if (new.mode == ATTR_WDUMMY) 1751 + continue; 1752 + if (selected(x, y1)) 1753 + new.mode ^= ATTR_REVERSE; 1754 + if (i > 0 && ATTRCMP(base, new)) { 1755 + xdrawglyphfontspecs(specs, base, i, ox, y1, dmode); 1756 + specs += i; 1757 + numspecs -= i; 1758 + i = 0; 1759 + } 1760 + if (i == 0) { 1761 + ox = x; 1762 + base = new; 1763 + } 1764 + i++; 1765 + } 1766 + if (i > 0) 1767 + xdrawglyphfontspecs(specs, base, i, ox, y1, dmode); 1768 + } 1769 + } 1770 + 1771 + void 1772 + xfinishdraw(void) 1773 + { 1774 + XCopyArea(xw.dpy, xw.buf, xw.win, dc.gc, 0, 0, win.w, 1775 + win.h, 0, 0); 1776 + XSetForeground(xw.dpy, dc.gc, 1777 + dc.col[IS_SET(MODE_REVERSE)? 1778 + defaultfg : defaultbg].pixel); 1779 + } 1780 + 1781 + void 1782 + xximspot(int x, int y) 1783 + { 1784 + XPoint spot = { borderpx + x * win.cw, borderpx + (y + 1) * win.ch }; 1785 + XVaNestedList attr = XVaCreateNestedList(0, XNSpotLocation, &spot, NULL); 1786 + 1787 + XSetICValues(xw.xic, XNPreeditAttributes, attr, NULL); 1788 + XFree(attr); 1789 + } 1790 + 1791 + void 1792 + expose(XEvent *ev) 1793 + { 1794 + redraw(); 1795 + } 1796 + 1797 + void 1798 + visibility(XEvent *ev) 1799 + { 1800 + XVisibilityEvent *e = &ev->xvisibility; 1801 + 1802 + MODBIT(win.mode, e->state != VisibilityFullyObscured, MODE_VISIBLE); 1803 + } 1804 + 1805 + void 1806 + unmap(XEvent *ev) 1807 + { 1808 + win.mode &= ~MODE_VISIBLE; 1809 + } 1810 + 1811 + void 1812 + xsetpointermotion(int set) 1813 + { 1814 + MODBIT(xw.attrs.event_mask, set, PointerMotionMask); 1815 + XChangeWindowAttributes(xw.dpy, xw.win, CWEventMask, &xw.attrs); 1816 + } 1817 + 1818 + void 1819 + xsetmode(int set, unsigned int flags) 1820 + { 1821 + int mode = win.mode; 1822 + MODBIT(win.mode, set, flags); 1823 + if ((win.mode & MODE_REVERSE) != (mode & MODE_REVERSE)) 1824 + redraw(); 1825 + } 1826 + 1827 + int 1828 + xsetcursor(int cursor) 1829 + { 1830 + DEFAULT(cursor, 1); 1831 + if (!BETWEEN(cursor, 0, 8)) /* 7-8: st extensions */ 1832 + return 1; 1833 + win.cursor = cursor; 1834 + cursorblinks = win.cursor == 0 || win.cursor == 1 || 1835 + win.cursor == 3 || win.cursor == 5 || 1836 + win.cursor == 7; 1837 + return 0; 1838 + } 1839 + 1840 + void 1841 + xseturgency(int add) 1842 + { 1843 + XWMHints *h = XGetWMHints(xw.dpy, xw.win); 1844 + 1845 + MODBIT(h->flags, add, XUrgencyHint); 1846 + XSetWMHints(xw.dpy, xw.win, h); 1847 + XFree(h); 1848 + } 1849 + 1850 + void 1851 + xbell(void) 1852 + { 1853 + if (!(IS_SET(MODE_FOCUSED))) 1854 + xseturgency(1); 1855 + if (bellvolume) 1856 + XkbBell(xw.dpy, xw.win, bellvolume, (Atom)NULL); 1857 + } 1858 + 1859 + void 1860 + focus(XEvent *ev) 1861 + { 1862 + XFocusChangeEvent *e = &ev->xfocus; 1863 + 1864 + if (e->mode == NotifyGrab) 1865 + return; 1866 + 1867 + if (ev->type == FocusIn) { 1868 + XSetICFocus(xw.xic); 1869 + win.mode |= MODE_FOCUSED; 1870 + xseturgency(0); 1871 + if (IS_SET(MODE_FOCUS)) 1872 + ttywrite("\033[I", 3, 0); 1873 + } else { 1874 + XUnsetICFocus(xw.xic); 1875 + win.mode &= ~MODE_FOCUSED; 1876 + if (IS_SET(MODE_FOCUS)) 1877 + ttywrite("\033[O", 3, 0); 1878 + } 1879 + } 1880 + 1881 + int 1882 + match(uint mask, uint state) 1883 + { 1884 + return mask == XK_ANY_MOD || mask == (state & ~ignoremod); 1885 + } 1886 + 1887 + char* 1888 + kmap(KeySym k, uint state) 1889 + { 1890 + Key *kp; 1891 + int i; 1892 + 1893 + /* Check for mapped keys out of X11 function keys. */ 1894 + for (i = 0; i < LEN(mappedkeys); i++) { 1895 + if (mappedkeys[i] == k) 1896 + break; 1897 + } 1898 + if (i == LEN(mappedkeys)) { 1899 + if ((k & 0xFFFF) < 0xFD00) 1900 + return NULL; 1901 + } 1902 + 1903 + for (kp = key; kp < key + LEN(key); kp++) { 1904 + if (kp->k != k) 1905 + continue; 1906 + 1907 + if (!match(kp->mask, state)) 1908 + continue; 1909 + 1910 + if (IS_SET(MODE_APPKEYPAD) ? kp->appkey < 0 : kp->appkey > 0) 1911 + continue; 1912 + if (IS_SET(MODE_NUMLOCK) && kp->appkey == 2) 1913 + continue; 1914 + 1915 + if (IS_SET(MODE_APPCURSOR) ? kp->appcursor < 0 : kp->appcursor > 0) 1916 + continue; 1917 + 1918 + return kp->s; 1919 + } 1920 + 1921 + return NULL; 1922 + } 1923 + 1924 + void 1925 + kpress(XEvent *ev) 1926 + { 1927 + XKeyEvent *e = &ev->xkey; 1928 + KeySym ksym; 1929 + char buf[32], *customkey; 1930 + int len; 1931 + Rune c; 1932 + Status status; 1933 + Shortcut *bp; 1934 + 1935 + if (IS_SET(MODE_KBDLOCK)) 1936 + return; 1937 + 1938 + len = XmbLookupString(xw.xic, e, buf, sizeof buf, &ksym, &status); 1939 + /* 1. shortcuts */ 1940 + for (bp = shortcuts; bp < shortcuts + LEN(shortcuts); bp++) { 1941 + if (ksym == bp->keysym && match(bp->mod, e->state)) { 1942 + bp->func(&(bp->arg)); 1943 + return; 1944 + } 1945 + } 1946 + 1947 + /* 2. custom keys from config.h */ 1948 + if ((customkey = kmap(ksym, e->state))) { 1949 + ttywrite(customkey, strlen(customkey), 1); 1950 + return; 1951 + } 1952 + 1953 + /* 3. composed string from input method */ 1954 + if (len == 0) 1955 + return; 1956 + if (len == 1 && e->state & Mod1Mask) { 1957 + if (IS_SET(MODE_8BIT)) { 1958 + if (*buf < 0177) { 1959 + c = *buf | 0x80; 1960 + len = utf8encode(c, buf); 1961 + } 1962 + } else { 1963 + buf[1] = buf[0]; 1964 + buf[0] = '\033'; 1965 + len = 2; 1966 + } 1967 + } 1968 + ttywrite(buf, len, 1); 1969 + } 1970 + 1971 + void 1972 + cmessage(XEvent *e) 1973 + { 1974 + /* 1975 + * See xembed specs 1976 + * http://standards.freedesktop.org/xembed-spec/xembed-spec-latest.html 1977 + */ 1978 + if (e->xclient.message_type == xw.xembed && e->xclient.format == 32) { 1979 + if (e->xclient.data.l[1] == XEMBED_FOCUS_IN) { 1980 + win.mode |= MODE_FOCUSED; 1981 + xseturgency(0); 1982 + } else if (e->xclient.data.l[1] == XEMBED_FOCUS_OUT) { 1983 + win.mode &= ~MODE_FOCUSED; 1984 + } 1985 + } else if (e->xclient.data.l[0] == xw.wmdeletewin) { 1986 + ttyhangup(); 1987 + exit(0); 1988 + } 1989 + } 1990 + 1991 + void 1992 + resize(XEvent *e) 1993 + { 1994 + if (e->xconfigure.width == win.w && e->xconfigure.height == win.h) 1995 + return; 1996 + 1997 + cresize(e->xconfigure.width, e->xconfigure.height); 1998 + } 1999 + 2000 + void 2001 + run(void) 2002 + { 2003 + XEvent ev; 2004 + int w = win.w, h = win.h; 2005 + fd_set rfd; 2006 + int xfd = XConnectionNumber(xw.dpy), ttyfd, xev, drawing; 2007 + struct timespec seltv, *tv, now, lastblink, trigger; 2008 + double timeout; 2009 + 2010 + /* Waiting for window mapping */ 2011 + do { 2012 + XNextEvent(xw.dpy, &ev); 2013 + /* 2014 + * This XFilterEvent call is required because of XOpenIM. It 2015 + * does filter out the key event and some client message for 2016 + * the input method too. 2017 + */ 2018 + if (XFilterEvent(&ev, None)) 2019 + continue; 2020 + if (ev.type == ConfigureNotify) { 2021 + w = ev.xconfigure.width; 2022 + h = ev.xconfigure.height; 2023 + } 2024 + } while (ev.type != MapNotify); 2025 + 2026 + ttyfd = ttynew(opt_line, shell, opt_io, opt_cmd); 2027 + cresize(w, h); 2028 + 2029 + for (timeout = -1, drawing = 0, lastblink = (struct timespec){0};;) { 2030 + FD_ZERO(&rfd); 2031 + FD_SET(ttyfd, &rfd); 2032 + FD_SET(xfd, &rfd); 2033 + 2034 + if (XPending(xw.dpy)) 2035 + timeout = 0; /* existing events might not set xfd */ 2036 + 2037 + seltv.tv_sec = timeout / 1E3; 2038 + seltv.tv_nsec = 1E6 * (timeout - 1E3 * seltv.tv_sec); 2039 + tv = timeout >= 0 ? &seltv : NULL; 2040 + 2041 + if (pselect(MAX(xfd, ttyfd)+1, &rfd, NULL, NULL, tv, NULL) < 0) { 2042 + if (errno == EINTR) 2043 + continue; 2044 + die("select failed: %s\n", strerror(errno)); 2045 + } 2046 + clock_gettime(CLOCK_MONOTONIC, &now); 2047 + 2048 + if (FD_ISSET(ttyfd, &rfd)) 2049 + ttyread(); 2050 + 2051 + xev = 0; 2052 + while (XPending(xw.dpy)) { 2053 + xev = 1; 2054 + XNextEvent(xw.dpy, &ev); 2055 + if (XFilterEvent(&ev, None)) 2056 + continue; 2057 + if (handler[ev.type]) 2058 + (handler[ev.type])(&ev); 2059 + } 2060 + 2061 + /* 2062 + * To reduce flicker and tearing, when new content or event 2063 + * triggers drawing, we first wait a bit to ensure we got 2064 + * everything, and if nothing new arrives - we draw. 2065 + * We start with trying to wait minlatency ms. If more content 2066 + * arrives sooner, we retry with shorter and shorter preiods, 2067 + * and eventually draw even without idle after maxlatency ms. 2068 + * Typically this results in low latency while interacting, 2069 + * maximum latency intervals during `cat huge.txt`, and perfect 2070 + * sync with periodic updates from animations/key-repeats/etc. 2071 + */ 2072 + if (FD_ISSET(ttyfd, &rfd) || xev) { 2073 + if (!drawing) { 2074 + trigger = now; 2075 + if (IS_SET(MODE_BLINK)) { 2076 + win.mode ^= MODE_BLINK; 2077 + } 2078 + lastblink = now; 2079 + drawing = 1; 2080 + } 2081 + timeout = (maxlatency - TIMEDIFF(now, trigger)) \ 2082 + / maxlatency * minlatency; 2083 + if (timeout > 0) 2084 + continue; /* we have time, try to find idle */ 2085 + } 2086 + 2087 + /* idle detected or maxlatency exhausted -> draw */ 2088 + timeout = -1; 2089 + if (blinktimeout && (cursorblinks || tattrset(ATTR_BLINK))) { 2090 + timeout = blinktimeout - TIMEDIFF(now, lastblink); 2091 + if (timeout <= 0) { 2092 + if (-timeout > blinktimeout) /* start visible */ 2093 + win.mode |= MODE_BLINK; 2094 + win.mode ^= MODE_BLINK; 2095 + tsetdirtattr(ATTR_BLINK); 2096 + lastblink = now; 2097 + timeout = blinktimeout; 2098 + } 2099 + } 2100 + 2101 + draw(); 2102 + XFlush(xw.dpy); 2103 + drawing = 0; 2104 + } 2105 + } 2106 + 2107 + #define XRESOURCE_LOAD_META(NAME) \ 2108 + if(!XrmGetResource(xrdb, "st." NAME, "st." NAME, &type, &ret)) \ 2109 + XrmGetResource(xrdb, "*." NAME, "*." NAME, &type, &ret); \ 2110 + if (ret.addr != NULL && !strncmp("String", type, 64)) 2111 + 2112 + #define XRESOURCE_LOAD_STRING(NAME, DST) \ 2113 + XRESOURCE_LOAD_META(NAME) \ 2114 + DST = ret.addr; 2115 + 2116 + #define XRESOURCE_LOAD_CHAR(NAME, DST) \ 2117 + XRESOURCE_LOAD_META(NAME) \ 2118 + DST = ret.addr[0]; 2119 + 2120 + #define XRESOURCE_LOAD_INTEGER(NAME, DST) \ 2121 + XRESOURCE_LOAD_META(NAME) \ 2122 + DST = strtoul(ret.addr, NULL, 10); 2123 + 2124 + #define XRESOURCE_LOAD_FLOAT(NAME, DST) \ 2125 + XRESOURCE_LOAD_META(NAME) \ 2126 + DST = strtof(ret.addr, NULL); 2127 + 2128 + void 2129 + xrdb_load(void) 2130 + { 2131 + /* XXX */ 2132 + char *xrm; 2133 + char *type; 2134 + XrmDatabase xrdb; 2135 + XrmValue ret; 2136 + Display *dpy; 2137 + 2138 + if(!(dpy = XOpenDisplay(NULL))) 2139 + die("Can't open display\n"); 2140 + 2141 + XrmInitialize(); 2142 + xrm = XResourceManagerString(dpy); 2143 + 2144 + if (xrm != NULL) { 2145 + xrdb = XrmGetStringDatabase(xrm); 2146 + 2147 + /* handling colors here without macros to do via loop. */ 2148 + int i = 0; 2149 + char loadValue[12] = ""; 2150 + for (i = 0; i < 256; i++) 2151 + { 2152 + sprintf(loadValue, "%s%d", "st.color", i); 2153 + 2154 + if(!XrmGetResource(xrdb, loadValue, loadValue, &type, &ret)) 2155 + { 2156 + sprintf(loadValue, "%s%d", "*.color", i); 2157 + if (!XrmGetResource(xrdb, loadValue, loadValue, &type, &ret)) 2158 + /* reset if not found (unless in range for defaults). */ 2159 + if (i > 15) 2160 + colorname[i] = NULL; 2161 + } 2162 + 2163 + if (ret.addr != NULL && !strncmp("String", type, 64)) 2164 + colorname[i] = ret.addr; 2165 + } 2166 + 2167 + XRESOURCE_LOAD_STRING("foreground", colorname[defaultfg]); 2168 + XRESOURCE_LOAD_STRING("background", colorname[defaultbg]); 2169 + XRESOURCE_LOAD_STRING("cursorfg", colorname[defaultcs]) 2170 + else { 2171 + // this looks confusing because we are chaining off of the if 2172 + // in the macro. probably we should be wrapping everything blocks 2173 + // so this isn't possible... 2174 + defaultcs = defaultfg; 2175 + } 2176 + XRESOURCE_LOAD_STRING("reverse-cursor", colorname[defaultrcs]) 2177 + else { 2178 + // see above. 2179 + defaultrcs = defaultbg; 2180 + } 2181 + 2182 + XRESOURCE_LOAD_STRING("font", font); 2183 + XRESOURCE_LOAD_STRING("termname", termname); 2184 + 2185 + /* XRESOURCE_LOAD_INTEGER("xfps", xfps); */ 2186 + /* XRESOURCE_LOAD_INTEGER("actionfps", actionfps); */ 2187 + XRESOURCE_LOAD_INTEGER("blinktimeout", blinktimeout); 2188 + XRESOURCE_LOAD_INTEGER("bellvolume", bellvolume); 2189 + XRESOURCE_LOAD_INTEGER("borderpx", borderpx); 2190 + /* XRESOURCE_LOAD_INTEGER("borderless", borderless); */ 2191 + XRESOURCE_LOAD_INTEGER("cursorshape", cursorshape); 2192 + 2193 + /* cursorblinkstate = 1; // in case if cursor shape was changed from a blinking one to a non-blinking */ 2194 + /* XRESOURCE_LOAD_INTEGER("cursorthickness", cursorthickness); */ 2195 + /* XRESOURCE_LOAD_INTEGER("cursorblinkstyle", cursorblinkstyle); */ 2196 + /* XRESOURCE_LOAD_INTEGER("cursorblinkontype", cursorblinkontype); */ 2197 + 2198 + /* todo: https://github.com/gnotclub/xst/commit/1e82647b0e04077e975679a4b4cf1eb02b04e6bc */ 2199 + /* XRESOURCE_LOAD_INTEGER("mouseScrollLines", mousescrolllines); */ 2200 + 2201 + XRESOURCE_LOAD_FLOAT("cwscale", cwscale); 2202 + XRESOURCE_LOAD_FLOAT("chscale", chscale); 2203 + 2204 + /* XRESOURCE_LOAD_CHAR("prompt_char", prompt_char); */ 2205 + 2206 + } 2207 + XFlush(dpy); 2208 + } 2209 + 2210 + void 2211 + reload(int sig) 2212 + { 2213 + xrdb_load(); 2214 + 2215 + /* colors, fonts */ 2216 + xloadcols(); 2217 + xunloadfonts(); 2218 + xloadfonts(font, 0); 2219 + 2220 + /* pretend the window just got resized */ 2221 + cresize(win.w, win.h); 2222 + 2223 + redraw(); 2224 + 2225 + /* triggers re-render if we're visible. */ 2226 + ttywrite("\033[O", 3, 1); 2227 + 2228 + signal(SIGUSR1, reload); 2229 + } 2230 + 2231 + int 2232 + resource_load(XrmDatabase db, char *name, enum resource_type rtype, void *dst) 2233 + { 2234 + char **sdst = dst; 2235 + int *idst = dst; 2236 + float *fdst = dst; 2237 + 2238 + char fullname[256]; 2239 + char fullclass[256]; 2240 + char *type; 2241 + XrmValue ret; 2242 + 2243 + snprintf(fullname, sizeof(fullname), "%s.%s", 2244 + opt_name ? opt_name : "st", name); 2245 + snprintf(fullclass, sizeof(fullclass), "%s.%s", 2246 + opt_class ? opt_class : "St", name); 2247 + fullname[sizeof(fullname) - 1] = fullclass[sizeof(fullclass) - 1] = '\0'; 2248 + 2249 + XrmGetResource(db, fullname, fullclass, &type, &ret); 2250 + if (ret.addr == NULL || strncmp("String", type, 64)) 2251 + return 1; 2252 + 2253 + switch (rtype) { 2254 + case STRING: 2255 + *sdst = ret.addr; 2256 + break; 2257 + case INTEGER: 2258 + *idst = strtoul(ret.addr, NULL, 10); 2259 + break; 2260 + case FLOAT: 2261 + *fdst = strtof(ret.addr, NULL); 2262 + break; 2263 + } 2264 + return 0; 2265 + } 2266 + 2267 + void 2268 + config_init(void) 2269 + { 2270 + char *resm; 2271 + XrmDatabase db; 2272 + ResourcePref *p; 2273 + 2274 + XrmInitialize(); 2275 + resm = XResourceManagerString(xw.dpy); 2276 + if (!resm) 2277 + return; 2278 + 2279 + db = XrmGetStringDatabase(resm); 2280 + for (p = resources; p < resources + LEN(resources); p++) 2281 + resource_load(db, p->name, p->type, p->dst); 2282 + } 2283 + 2284 + void 2285 + usage(void) 2286 + { 2287 + die("usage: %s [-aiv] [-c class] [-f font] [-g geometry]" 2288 + " [-n name] [-o file]\n" 2289 + " [-T title] [-t title] [-w windowid]" 2290 + " [[-e] command [args ...]]\n" 2291 + " %s [-aiv] [-c class] [-f font] [-g geometry]" 2292 + " [-n name] [-o file]\n" 2293 + " [-T title] [-t title] [-w windowid] -l line" 2294 + " [stty_args ...]\n", argv0, argv0); 2295 + } 2296 + 2297 + int 2298 + main(int argc, char *argv[]) 2299 + { 2300 + xw.l = xw.t = 0; 2301 + xw.isfixed = False; 2302 + xsetcursor(cursorshape); 2303 + 2304 + ARGBEGIN { 2305 + case 'a': 2306 + allowaltscreen = 0; 2307 + break; 2308 + case 'A': 2309 + opt_alpha = EARGF(usage()); 2310 + break; 2311 + case 'c': 2312 + opt_class = EARGF(usage()); 2313 + break; 2314 + case 'e': 2315 + if (argc > 0) 2316 + --argc, ++argv; 2317 + goto run; 2318 + case 'f': 2319 + opt_font = EARGF(usage()); 2320 + break; 2321 + case 'g': 2322 + xw.gm = XParseGeometry(EARGF(usage()), 2323 + &xw.l, &xw.t, &cols, &rows); 2324 + break; 2325 + case 'i': 2326 + xw.isfixed = 1; 2327 + break; 2328 + case 'o': 2329 + opt_io = EARGF(usage()); 2330 + break; 2331 + case 'l': 2332 + opt_line = EARGF(usage()); 2333 + break; 2334 + case 'n': 2335 + opt_name = EARGF(usage()); 2336 + break; 2337 + case 't': 2338 + case 'T': 2339 + opt_title = EARGF(usage()); 2340 + break; 2341 + case 'w': 2342 + opt_embed = EARGF(usage()); 2343 + break; 2344 + case 'v': 2345 + die("%s " VERSION "\n", argv0); 2346 + break; 2347 + default: 2348 + usage(); 2349 + } ARGEND; 2350 + 2351 + run: 2352 + if (argc > 0) /* eat all remaining arguments */ 2353 + opt_cmd = argv; 2354 + 2355 + if (!opt_title) 2356 + opt_title = (opt_line || !opt_cmd) ? "st" : opt_cmd[0]; 2357 + 2358 + setlocale(LC_CTYPE, ""); 2359 + XSetLocaleModifiers(""); 2360 + xrdb_load(); 2361 + signal(SIGUSR1, reload); 2362 + 2363 + if(!(xw.dpy = XOpenDisplay(NULL))) 2364 + die("Can't open display\n"); 2365 + 2366 + config_init(); 2367 + cols = MAX(cols, 1); 2368 + rows = MAX(rows, 1); 2369 + signal(SIGUSR1, reload); 2370 + tnew(cols, rows); 2371 + xinit(cols, rows); 2372 + xsetenv(); 2373 + selinit(); 2374 + run(); 2375 + 2376 + return 0; 2377 + }
+22
cfg/starship.toml
··· 1 + # Get editor completions based on the config schema 2 + "$schema" = 'https://starship.rs/config-schema.json' 3 + 4 + format = "[](bold #cba6f7) $directory [❯](bold #a6e3a1)[❯](bold #89b4fa)[❯](bold #fab387) " 5 + right_format = "$git_branch" 6 + 7 + # Inserts a blank line between shell prompts 8 + add_newline = false 9 + 10 + # Replace the "❯" symbol in the prompt with "➜" 11 + [character] # The name of the module we are configuring is "character" 12 + success_symbol = "[❯](bold green)[❯](bold blue)[❯](bold orange)" # The "success_symbol" segment is being set to "➜" with the color "bold green" 13 + 14 + # Disable the package module, hiding it from the prompt completely 15 + [package] 16 + disabled = true 17 + 18 + [git_branch] 19 + format = "[](bold #cba6f7) [❯](bold #89b4fa)[❯](bold #fab387) [$branch](bold #f5c2e7)" 20 + 21 + [directory] 22 + format = "[$path](#f5c2e7)"
+136
cfg/sxhkd/sxhkdrc
··· 1 + # 2 + # wm independent hotkeys 3 + # 4 + 5 + # terminal emulator 6 + super + Return 7 + $HOME/.config/st/st -c st 8 + 9 + # program launcher 10 + super + d 11 + rofi -show drun 12 + 13 + super + shift + d 14 + discord 15 + 16 + super + shift + w 17 + firefox 18 + 19 + super + shift + s 20 + spotify 21 + 22 + # make sxhkd reload its configuration files: 23 + super + Escape 24 + pkill -USR1 -x sxhkd 25 + 26 + Print 27 + flameshot gui 28 + 29 + # 30 + # bspwm hotkeys 31 + # 32 + 33 + # quit/restart bspwm 34 + super + alt + {q,r} 35 + bspc {quit,wm -r} 36 + 37 + # close and kill 38 + super + {_,shift + }q 39 + bspc node -{c,k} 40 + 41 + # alternate between the tiled and monocle layout 42 + super + m 43 + bspc desktop -l next 44 + 45 + # send the newest marked node to the newest preselected node 46 + super + y 47 + bspc node newest.marked.local -n newest.!automatic.local 48 + 49 + # swap the current node and the biggest window 50 + super + g 51 + bspc node -s biggest.window 52 + 53 + # 54 + # state/flags 55 + # 56 + 57 + # set the window state 58 + super + {t,shift + t,f} 59 + bspc node -t {tiled,pseudo_tiled,fullscreen} 60 + 61 + super + @space 62 + bspc node -t floating 63 + 64 + # set the node flags 65 + super + ctrl + {m,x,y,z} 66 + bspc node -g {marked,locked,sticky,private} 67 + 68 + # 69 + # focus/swap 70 + # 71 + 72 + # focus the node in the given direction 73 + super + {_,shift + }{h,j,k,l} 74 + bspc node -{f,s} {west,south,north,east} 75 + 76 + # focus the node for the given path jump 77 + super + {p,b,comma,period} 78 + bspc node -f @{parent,brother,first,second} 79 + 80 + # focus the next/previous window in the current desktop 81 + super + {_,shift + }c 82 + bspc node -f {next,prev}.local.!hidden.window 83 + 84 + # focus the next/previous desktop in the current monitor 85 + super + {left,right} 86 + bspc desktop -f {prev,next} 87 + 88 + # focus the last node/desktop 89 + super + {grave,Tab} 90 + bspc {node,desktop} -f last 91 + 92 + # focus the older or newer node in the focus history 93 + super + {o,i} 94 + bspc wm -h off; \ 95 + bspc node {older,newer} -f; \ 96 + bspc wm -h on 97 + 98 + # focus or send to the given desktop 99 + super + {_,shift + }{1-9,0} 100 + bspc {desktop -f,node -d} '^{1-9,10}' 101 + 102 + # 103 + # preselect 104 + # 105 + 106 + # preselect the direction 107 + super + ctrl + {h,j,k,l} 108 + bspc node -p {west,south,north,east} 109 + 110 + # preselect the ratio 111 + super + ctrl + {1-9} 112 + bspc node -o 0.{1-9} 113 + 114 + # cancel the preselection for the focused node 115 + super + ctrl + space 116 + bspc node -p cancel 117 + 118 + # cancel the preselection for the focused desktop 119 + super + ctrl + shift + space 120 + bspc query -N -d | xargs -I id -n 1 bspc node id -p cancel 121 + 122 + # 123 + # move/resize 124 + # 125 + 126 + # expand a window by moving one of its side outward 127 + super + alt + {h,j,k,l} 128 + bspc node -z {left -20 0,bottom 0 20,top 0 -20,right 20 0} 129 + 130 + # contract a window by moving one of its side inward 131 + super + alt + shift + {h,j,k,l} 132 + bspc node -z {right -20 0,top 0 20,bottom 0 -20,left 20 0} 133 + 134 + # move a floating window 135 + super + {Left,Down,Up,Right} 136 + bspc node -v {-20 0,0 20,0 -20,20 0}
+21
cfg/sxhkd/sxhkdrc-xfce
··· 1 + # terminal emulator 2 + super + Return 3 + kitty 4 + 5 + # program launcher 6 + super + d 7 + rofi -show drun 8 + 9 + super + shift + d 10 + discord 11 + 12 + super + shift + w 13 + firefox 14 + 15 + super + shift + s 16 + spotify 17 + 18 + # make sxhkd reload its configuration files: 19 + super + Escape 20 + pkill -USR1 -x sxhkd 21 +
cfg/wallpaper.png

This is a binary file and will not be displayed.

+39
home/.zshrc
··· 1 + autoload -U compinit 2 + compinit 3 + 4 + export _JAVA_AWT_WM_NONREPARENTING=1 5 + 6 + alias ls='exa --icons -a' 7 + alias la='exa --icons -la' 8 + alias tree='exa --icons --tree' 9 + alias _='sudo' 10 + alias please='sudo' 11 + alias tb='nc termbin.com 9999' 12 + alias rpi='ssh root@rpi' 13 + alias server='ssh root@server' 14 + alias hp='server' 15 + alias ssn='systemctl shutdown' 16 + alias sr='systemctl reboot' 17 + alias docker='sudo docker' 18 + alias grep='grep --color=auto' 19 + alias vim='nvim' 20 + alias :q='exit' 21 + alias :wq='echo wtf do you idiot wanna write this is a fucking shell' 22 + alias wttr='curl wttr.in' 23 + alias clear='clear && fetch' 24 + alias ewwrs='eww kill && eww daemon && eww open bar' 25 + alias cat='bat' 26 + alias r='ranger' 27 + alias c='clear' 28 + alias cr='c && r' 29 + alias %='source ~/.zshrc' 30 + 31 + export EDITOR=nvim 32 + export PATH=$HOME/.local/bin:$PATH 33 + 34 + startup() { 35 + fetch 36 + } 37 + 38 + startup 39 + eval "$(starship init zsh)"
showcase.mp4

This is a binary file and will not be displayed.

showcase.png

This is a binary file and will not be displayed.