From ba6ec3719355b13a463800073b3a2fec46790257 Mon Sep 17 00:00:00 2001 From: coast Date: Thu, 10 Jul 2025 08:58:07 +0330 Subject: [PATCH] readded dwm and added some more dots --- .zshrc | 2 +- config/picom/picom.conf | 90 +- config/picom/picom.conf~ | 124 +- suckless/dmenu/LICENSE | 30 + suckless/dmenu/Makefile | 58 + suckless/dmenu/README | 24 + suckless/dmenu/arg.h | 49 + suckless/dmenu/config.def.h | 23 + suckless/dmenu/config.h | 23 + suckless/dmenu/config.mk | 32 + suckless/dmenu/dmenu | Bin 0 -> 42296 bytes suckless/dmenu/dmenu.1 | 194 + suckless/dmenu/dmenu.c | 795 ++++ suckless/dmenu/dmenu.o | Bin 0 -> 32224 bytes suckless/dmenu/dmenu_path | 13 + suckless/dmenu/dmenu_run | 2 + suckless/dmenu/drw.c | 448 ++ suckless/dmenu/drw.h | 58 + suckless/dmenu/drw.o | Bin 0 -> 11464 bytes suckless/dmenu/stest | Bin 0 -> 16288 bytes suckless/dmenu/stest.1 | 90 + suckless/dmenu/stest.c | 109 + suckless/dmenu/stest.o | Bin 0 -> 5344 bytes suckless/dmenu/util.c | 37 + suckless/dmenu/util.h | 9 + suckless/dmenu/util.o | Bin 0 -> 2472 bytes suckless/dwm | 1 + suckless/slstatus/LICENSE | 43 + suckless/slstatus/Makefile | 69 + suckless/slstatus/arg.h | 33 + suckless/slstatus/components/battery.c | 247 ++ suckless/slstatus/components/battery.o | Bin 0 -> 5208 bytes suckless/slstatus/components/cat.c | 32 + suckless/slstatus/components/cat.o | Bin 0 -> 2128 bytes suckless/slstatus/components/cpu.c | 157 + suckless/slstatus/components/cpu.o | Bin 0 -> 3168 bytes suckless/slstatus/components/datetime.c | 20 + suckless/slstatus/components/datetime.o | Bin 0 -> 1960 bytes suckless/slstatus/components/disk.c | 59 + suckless/slstatus/components/disk.o | Bin 0 -> 3168 bytes suckless/slstatus/components/entropy.c | 29 + suckless/slstatus/components/entropy.o | Bin 0 -> 1824 bytes suckless/slstatus/components/hostname.c | 17 + suckless/slstatus/components/hostname.o | Bin 0 -> 1680 bytes suckless/slstatus/components/ip.c | 61 + suckless/slstatus/components/ip.o | Bin 0 -> 2592 bytes suckless/slstatus/components/kernel_release.c | 19 + suckless/slstatus/components/kernel_release.o | Bin 0 -> 1872 bytes .../slstatus/components/keyboard_indicators.c | 50 + .../slstatus/components/keyboard_indicators.o | Bin 0 -> 2448 bytes suckless/slstatus/components/keymap.c | 86 + suckless/slstatus/components/keymap.o | Bin 0 -> 4048 bytes suckless/slstatus/components/load_avg.c | 19 + suckless/slstatus/components/load_avg.o | Bin 0 -> 1904 bytes suckless/slstatus/components/netspeeds.c | 129 + suckless/slstatus/components/netspeeds.o | Bin 0 -> 2824 bytes suckless/slstatus/components/num_files.c | 32 + suckless/slstatus/components/num_files.o | Bin 0 -> 2192 bytes suckless/slstatus/components/pixVol.sh | 10 + suckless/slstatus/components/ram.c | 212 + suckless/slstatus/components/ram.o | Bin 0 -> 3128 bytes suckless/slstatus/components/run_command.c | 31 + suckless/slstatus/components/run_command.o | Bin 0 -> 2144 bytes suckless/slstatus/components/swap.c | 274 ++ suckless/slstatus/components/swap.o | Bin 0 -> 3928 bytes suckless/slstatus/components/temperature.c | 73 + suckless/slstatus/components/temperature.o | Bin 0 -> 1744 bytes suckless/slstatus/components/uptime.c | 34 + suckless/slstatus/components/uptime.o | Bin 0 -> 2024 bytes suckless/slstatus/components/user.c | 33 + suckless/slstatus/components/user.o | Bin 0 -> 2240 bytes suckless/slstatus/components/volume.c | 219 + suckless/slstatus/components/volume.o | Bin 0 -> 3632 bytes suckless/slstatus/components/wifi.c | 267 ++ suckless/slstatus/components/wifi.o | Bin 0 -> 4320 bytes suckless/slstatus/config.def.h | 81 + suckless/slstatus/config.h | 76 + suckless/slstatus/config.h~ | 77 + suckless/slstatus/config.mk | 22 + suckless/slstatus/slstatus | Bin 0 -> 31248 bytes suckless/slstatus/slstatus.1 | 47 + suckless/slstatus/slstatus.c | 134 + suckless/slstatus/slstatus.h | 84 + suckless/slstatus/slstatus.o | Bin 0 -> 6184 bytes suckless/slstatus/util.c | 141 + suckless/slstatus/util.h | 16 + suckless/slstatus/util.o | Bin 0 -> 5592 bytes suckless/st/LEGACY | 17 + suckless/st/LICENSE | 34 + suckless/st/Makefile | 52 + suckless/st/README | 34 + suckless/st/TODO | 28 + suckless/st/arg.h | 50 + suckless/st/boxdraw.c | 194 + suckless/st/boxdraw_data.h | 214 + suckless/st/config.def.h | 517 +++ suckless/st/config.h | 479 +++ suckless/st/config.h.save | 486 +++ suckless/st/config.h.save.1 | 486 +++ suckless/st/config.h.save.2 | 486 +++ suckless/st/config.h.save.3 | 486 +++ suckless/st/config.h~ | 479 +++ suckless/st/config.mk | 38 + suckless/st/graphics.c | 3812 +++++++++++++++++ suckless/st/graphics.h | 107 + suckless/st/hb.c | 125 + suckless/st/hb.h | 14 + suckless/st/hb.o | Bin 0 -> 4304 bytes suckless/st/icat-mini.sh | 800 ++++ suckless/st/khash.h | 627 +++ suckless/st/kvec.h | 90 + suckless/st/rowcolumn_diacritics_helpers.c | 391 ++ suckless/st/st | Bin 0 -> 120544 bytes ...st-alpha-changealpha-20230519-b44f2ad.diff | 194 + suckless/st/st.1 | 177 + suckless/st/st.c | 2799 ++++++++++++ suckless/st/st.h | 130 + suckless/st/st.info | 243 ++ suckless/st/st.o | Bin 0 -> 82832 bytes suckless/st/win.h | 41 + suckless/st/x.c | 2319 ++++++++++ suckless/st/x.o | Bin 0 -> 86904 bytes 122 files changed, 21005 insertions(+), 88 deletions(-) create mode 100644 suckless/dmenu/LICENSE create mode 100644 suckless/dmenu/Makefile create mode 100644 suckless/dmenu/README create mode 100644 suckless/dmenu/arg.h create mode 100644 suckless/dmenu/config.def.h create mode 100644 suckless/dmenu/config.h create mode 100644 suckless/dmenu/config.mk create mode 100755 suckless/dmenu/dmenu create mode 100644 suckless/dmenu/dmenu.1 create mode 100644 suckless/dmenu/dmenu.c create mode 100644 suckless/dmenu/dmenu.o create mode 100644 suckless/dmenu/dmenu_path create mode 100644 suckless/dmenu/dmenu_run create mode 100644 suckless/dmenu/drw.c create mode 100644 suckless/dmenu/drw.h create mode 100644 suckless/dmenu/drw.o create mode 100755 suckless/dmenu/stest create mode 100644 suckless/dmenu/stest.1 create mode 100644 suckless/dmenu/stest.c create mode 100644 suckless/dmenu/stest.o create mode 100644 suckless/dmenu/util.c create mode 100644 suckless/dmenu/util.h create mode 100644 suckless/dmenu/util.o create mode 160000 suckless/dwm create mode 100644 suckless/slstatus/LICENSE create mode 100644 suckless/slstatus/Makefile create mode 100644 suckless/slstatus/arg.h create mode 100644 suckless/slstatus/components/battery.c create mode 100644 suckless/slstatus/components/battery.o create mode 100644 suckless/slstatus/components/cat.c create mode 100644 suckless/slstatus/components/cat.o create mode 100644 suckless/slstatus/components/cpu.c create mode 100644 suckless/slstatus/components/cpu.o create mode 100644 suckless/slstatus/components/datetime.c create mode 100644 suckless/slstatus/components/datetime.o create mode 100644 suckless/slstatus/components/disk.c create mode 100644 suckless/slstatus/components/disk.o create mode 100644 suckless/slstatus/components/entropy.c create mode 100644 suckless/slstatus/components/entropy.o create mode 100644 suckless/slstatus/components/hostname.c create mode 100644 suckless/slstatus/components/hostname.o create mode 100644 suckless/slstatus/components/ip.c create mode 100644 suckless/slstatus/components/ip.o create mode 100644 suckless/slstatus/components/kernel_release.c create mode 100644 suckless/slstatus/components/kernel_release.o create mode 100644 suckless/slstatus/components/keyboard_indicators.c create mode 100644 suckless/slstatus/components/keyboard_indicators.o create mode 100644 suckless/slstatus/components/keymap.c create mode 100644 suckless/slstatus/components/keymap.o create mode 100644 suckless/slstatus/components/load_avg.c create mode 100644 suckless/slstatus/components/load_avg.o create mode 100644 suckless/slstatus/components/netspeeds.c create mode 100644 suckless/slstatus/components/netspeeds.o create mode 100644 suckless/slstatus/components/num_files.c create mode 100644 suckless/slstatus/components/num_files.o create mode 100644 suckless/slstatus/components/pixVol.sh create mode 100644 suckless/slstatus/components/ram.c create mode 100644 suckless/slstatus/components/ram.o create mode 100644 suckless/slstatus/components/run_command.c create mode 100644 suckless/slstatus/components/run_command.o create mode 100644 suckless/slstatus/components/swap.c create mode 100644 suckless/slstatus/components/swap.o create mode 100644 suckless/slstatus/components/temperature.c create mode 100644 suckless/slstatus/components/temperature.o create mode 100644 suckless/slstatus/components/uptime.c create mode 100644 suckless/slstatus/components/uptime.o create mode 100644 suckless/slstatus/components/user.c create mode 100644 suckless/slstatus/components/user.o create mode 100644 suckless/slstatus/components/volume.c create mode 100644 suckless/slstatus/components/volume.o create mode 100644 suckless/slstatus/components/wifi.c create mode 100644 suckless/slstatus/components/wifi.o create mode 100644 suckless/slstatus/config.def.h create mode 100644 suckless/slstatus/config.h create mode 100644 suckless/slstatus/config.h~ create mode 100644 suckless/slstatus/config.mk create mode 100755 suckless/slstatus/slstatus create mode 100644 suckless/slstatus/slstatus.1 create mode 100644 suckless/slstatus/slstatus.c create mode 100644 suckless/slstatus/slstatus.h create mode 100644 suckless/slstatus/slstatus.o create mode 100644 suckless/slstatus/util.c create mode 100644 suckless/slstatus/util.h create mode 100644 suckless/slstatus/util.o create mode 100644 suckless/st/LEGACY create mode 100644 suckless/st/LICENSE create mode 100644 suckless/st/Makefile create mode 100644 suckless/st/README create mode 100644 suckless/st/TODO create mode 100644 suckless/st/arg.h create mode 100644 suckless/st/boxdraw.c create mode 100644 suckless/st/boxdraw_data.h create mode 100644 suckless/st/config.def.h create mode 100644 suckless/st/config.h create mode 100644 suckless/st/config.h.save create mode 100644 suckless/st/config.h.save.1 create mode 100644 suckless/st/config.h.save.2 create mode 100644 suckless/st/config.h.save.3 create mode 100644 suckless/st/config.h~ create mode 100644 suckless/st/config.mk create mode 100644 suckless/st/graphics.c create mode 100644 suckless/st/graphics.h create mode 100644 suckless/st/hb.c create mode 100644 suckless/st/hb.h create mode 100644 suckless/st/hb.o create mode 100755 suckless/st/icat-mini.sh create mode 100644 suckless/st/khash.h create mode 100644 suckless/st/kvec.h create mode 100644 suckless/st/rowcolumn_diacritics_helpers.c create mode 100755 suckless/st/st create mode 100644 suckless/st/st-alpha-changealpha-20230519-b44f2ad.diff create mode 100644 suckless/st/st.1 create mode 100644 suckless/st/st.c create mode 100644 suckless/st/st.h create mode 100644 suckless/st/st.info create mode 100644 suckless/st/st.o create mode 100644 suckless/st/win.h create mode 100644 suckless/st/x.c create mode 100644 suckless/st/x.o diff --git a/.zshrc b/.zshrc index c15d81b..a23c180 100644 --- a/.zshrc +++ b/.zshrc @@ -16,5 +16,5 @@ source /usr/share/zsh/site-functions/zsh-autosuggestions.zsh && fpath=(/usr/shar autoload -U colors && colors && setopt prompt_subst ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE="fg=5" ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE="fg=12" -PROMPT='%F{33}[%f%F{75}!%f%F{33}%n%f%F{33}@%f%F{33}%m%f %F{75}%~%f%F{33}]%f%F{75}%% ' +PROMPT='%F{240}[%f%F{245}!%f%F{240}%n%f%F{240}@%f%F{240}%m%f %F{245}%~%f%F{240}]%f%F{245}%% ' source ~/.zprofile diff --git a/config/picom/picom.conf b/config/picom/picom.conf index 7356882..fd52f76 100644 --- a/config/picom/picom.conf +++ b/config/picom/picom.conf @@ -1,4 +1,3 @@ -# Speedy controlled animations animations = true; animation-stiffness-in-tag = 120; animation-stiffness-tag-change = 90.0; @@ -6,7 +5,6 @@ animation-window-mass = 0.3; animation-dampening = 5; animation-clamping = false; -# Zoom, but FAST animation-for-open-window = "zoom"; animation-for-unmap-window = "zoom"; animation-for-transient-window = "zoom"; @@ -17,7 +15,6 @@ animation-for-workspace-switch-out = "zoom"; animation-max-size = 20; -# Fading transitions (FASTER) enable-fading-prev-tag = true; enable-fading-next-tag = true; fading = true; @@ -25,7 +22,6 @@ fade-in-step = 0.07; fade-out-step = 0.06; fade-delta = 5; -# Shadow stuff shadow = true; shadow-radius = 12; shadow-offset-x = -5; @@ -33,10 +29,19 @@ shadow-offset-y = -5; shadow-opacity = 0.7; shadow-color = "#000000"; shadow-exclude = [ - "class_g = 'slop'" + "class_g = 'slop'", + "class_g = 'maim'", + "class_g = 'import'", + "class_g = 'imagemagick'", + "name = 'slop'", + "name = 'select-region'", + "name = 'select region'", + "window_type = 'utility'", + "window_type = 'notification'", + "window_type = 'dock'", + "_NET_WM_WINDOW_TYPE@:32a *= '_NET_WM_WINDOW_TYPE_DOCK'" ]; -# Blur (still spicy) blur-background = true; blur-background-frame = true; blur-method = "dual_kawase"; @@ -46,21 +51,27 @@ blur-background-fixed = false; blur-exclude = [ "class_g = 'slop'", "class_g = 'maim'", - "window_type = 'dock'" + "class_g = 'import'", + "class_g = 'imagemagick'", + "name = 'slop'", + "name = 'select-region'", + "name = 'select region'", + "window_type = 'utility'", + "window_type = 'notification'", + "window_type = 'dock'", + "_NET_WM_WINDOW_TYPE@:32a *= '_NET_WM_WINDOW_TYPE_DOCK'" ]; -# Corners -corner-radius = 10; rounded-corners-exclude = [ "class_g = 'slop'", "class_g = 'maim'" ]; -# Opacity rules opacity-rule = [ "93:class_g = 'discord'", "93:class_g = 'spotify'", "80:class_g = 'st'", + "80:class_g = 'urxvt'", "80:class_g = 'dmenu'", "85:class_g = 'dwm'", "100:class_g = 'floorp'", @@ -68,16 +79,16 @@ opacity-rule = [ "100:class_g = 'slop'" ]; -# Focus and animation exclude focus-exclude = [ "class_g = 'slop'", "class_g = 'maim'" ]; + animation-exclude = [ - "class_g = 'slop'" + "class_g = 'slop'", + "class_g = 'maim'" ]; -# General stuff daemon = false; backend = "glx"; dithered-present = false; @@ -96,22 +107,41 @@ window-shader-fg = "default"; transparent-clipping = false; log-level = "warn"; -# Wintypes (with fast popup animations) wintypes: { - tooltip = { fade = true; shadow = true; opacity = 0.95; focus = true; animations = true; animation-for-open-window = "zoom"; }; - dock = { shadow = false; clip-shadow-above = true; }; - dnd = { shadow = false; }; - popup_menu = { opacity = 0.95; animations = true; shadow = true; animation-for-open-window = "zoom"; }; - dropdown_menu = { opacity = 0.95; animations = true; shadow = true; animation-for-open-window = "zoom"; }; - unknown = { fade = false; shadow = false; opacity = 1.0; focus = false; full-shadow = false; clip-shadow-above = false; animations = false; }; + tooltip = { + fade = true; + shadow = true; + opacity = 0.95; + focus = true; + animations = true; + animation-for-open-window = "zoom"; + }; + dock = { + shadow = false; + clip-shadow-above = true; + }; + dnd = { + shadow = false; + }; + popup_menu = { + opacity = 0.95; + animations = true; + shadow = true; + animation-for-open-window = "zoom"; + }; + dropdown_menu = { + opacity = 0.95; + animations = true; + shadow = true; + animation-for-open-window = "zoom"; + }; + unknown = { + fade = false; + shadow = false; + opacity = 1.0; + focus = false; + full-shadow = false; + clip-shadow-above = false; + animations = false; + }; }; - -# Global exclusion -blur-exclude = [ - "class_g = 'slop'", - "class_g = 'screenie'", - "window_type = 'utility'", - "window_type = 'notification'", - "_NET_WM_WINDOW_TYPE@:32a *= '_NET_WM_WINDOW_TYPE_DOCK'", - "name = 'slop'" -]; diff --git a/config/picom/picom.conf~ b/config/picom/picom.conf~ index 7ab9458..7356882 100644 --- a/config/picom/picom.conf~ +++ b/config/picom/picom.conf~ @@ -1,63 +1,42 @@ -# Animation settings - controlled zoom +# Speedy controlled animations animations = true; -animation-stiffness-in-tag = 80; -animation-stiffness-tag-change = 35.0; -animation-window-mass = 0.6; -animation-dampening = 9; +animation-stiffness-in-tag = 120; +animation-stiffness-tag-change = 90.0; +animation-window-mass = 0.3; +animation-dampening = 5; animation-clamping = false; -# Animation styles with controlled zoom effect -animation-for-open-window = "zoom"; # Kept zoom for main windows + +# Zoom, but FAST +animation-for-open-window = "zoom"; animation-for-unmap-window = "zoom"; -animation-for-transient-window = "zoom"; # Changed to squeeze for popups to limit screen space usage +animation-for-transient-window = "zoom"; animation-for-prev-tag = "zoom"; animation-for-next-tag = "zoom"; -# Additional animation control -animation-for-workspace-switch-in = "zoom"; # Control workspace transitions -animation-for-workspace-switch-out = "zoom"; # Control workspace transitions -# Animation size limits (new parameters) -animation-max-size = 50; # Limit maximum animation expansion -# Tag transition fading +animation-for-workspace-switch-in = "zoom"; +animation-for-workspace-switch-out = "zoom"; + +animation-max-size = 20; + +# Fading transitions (FASTER) enable-fading-prev-tag = true; enable-fading-next-tag = true; -# Shadow settings +fading = true; +fade-in-step = 0.07; +fade-out-step = 0.06; +fade-delta = 5; + +# Shadow stuff shadow = true; -shadow-radius = 15; +shadow-radius = 12; shadow-offset-x = -5; shadow-offset-y = -5; -shadow-opacity = 0.8; -shadow-color = "#000000" +shadow-opacity = 0.7; +shadow-color = "#000000"; shadow-exclude = [ "class_g = 'slop'" ]; -# Fading settings -fading = true; -fade-in-step = 0.025; -fade-out-step = 0.015; -fade-delta = 15; -fade-exclude = [ - "class_g = 'slop'" -]; -# Focus settings -focus-exclude = [ - "class_g = 'slop'", - "class_g = 'maim'" -]; -# Opacity rules -opacity-rule = [ - "93:class_g = 'discord'", - "80:class_g = 'st'", - "80:class_g = 'dmenu'", - "85:class_g = 'dwm'", - "100:class_g = 'floorp'", - "100:class_g = 'slop'" -]; -# Corner settings -corner-radius = 12; -rounded-corners-exclude = [ - "class_g = 'slop'", - "class_g = 'maim'", -]; -# Blur settings + +# Blur (still spicy) blur-background = true; blur-background-frame = true; blur-method = "dual_kawase"; @@ -67,12 +46,38 @@ blur-background-fixed = false; blur-exclude = [ "class_g = 'slop'", "class_g = 'maim'", + "window_type = 'dock'" +]; + +# Corners +corner-radius = 10; +rounded-corners-exclude = [ + "class_g = 'slop'", + "class_g = 'maim'" +]; + +# Opacity rules +opacity-rule = [ + "93:class_g = 'discord'", + "93:class_g = 'spotify'", + "80:class_g = 'st'", + "80:class_g = 'dmenu'", + "85:class_g = 'dwm'", + "100:class_g = 'floorp'", + "100:class_g = 'firefox'", + "100:class_g = 'slop'" +]; + +# Focus and animation exclude +focus-exclude = [ + "class_g = 'slop'", + "class_g = 'maim'" ]; -# Animation exclude animation-exclude = [ "class_g = 'slop'" ]; -# General settings + +# General stuff daemon = false; backend = "glx"; dithered-present = false; @@ -90,18 +95,23 @@ xrender-sync-fence = true; window-shader-fg = "default"; transparent-clipping = false; log-level = "warn"; -# Window type specific settings - special handling for popups + +# Wintypes (with fast popup animations) wintypes: { - tooltip = { fade = true; shadow = true; opacity = 0.95; focus = true; animations = true; animation-for-open-window = "squeeze"; }; + tooltip = { fade = true; shadow = true; opacity = 0.95; focus = true; animations = true; animation-for-open-window = "zoom"; }; dock = { shadow = false; clip-shadow-above = true; }; dnd = { shadow = false; }; - popup_menu = { opacity = 0.95; animations = true; shadow = true; animation-for-open-window = "squeeze"; }; - dropdown_menu = { opacity = 0.95; animations = true; shadow = true; animation-for-open-window = "squeeze"; }; - # Add slop to wintypes for specific handling + popup_menu = { opacity = 0.95; animations = true; shadow = true; animation-for-open-window = "zoom"; }; + dropdown_menu = { opacity = 0.95; animations = true; shadow = true; animation-for-open-window = "zoom"; }; unknown = { fade = false; shadow = false; opacity = 1.0; focus = false; full-shadow = false; clip-shadow-above = false; animations = false; }; }; -# Global exclusion for slop -unredir-if-possible-exclude = [ - "class_g = 'slop'" +# Global exclusion +blur-exclude = [ + "class_g = 'slop'", + "class_g = 'screenie'", + "window_type = 'utility'", + "window_type = 'notification'", + "_NET_WM_WINDOW_TYPE@:32a *= '_NET_WM_WINDOW_TYPE_DOCK'", + "name = 'slop'" ]; diff --git a/suckless/dmenu/LICENSE b/suckless/dmenu/LICENSE new file mode 100644 index 0000000..2a64b28 --- /dev/null +++ b/suckless/dmenu/LICENSE @@ -0,0 +1,30 @@ +MIT/X Consortium License + +© 2006-2019 Anselm R Garbe +© 2006-2008 Sander van Dijk +© 2006-2007 Michał Janeczek +© 2007 Kris Maglione +© 2009 Gottox +© 2009 Markus Schnalke +© 2009 Evan Gates +© 2010-2012 Connor Lane Smith +© 2014-2022 Hiltjo Posthuma +© 2015-2019 Quentin Rameau + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/suckless/dmenu/Makefile b/suckless/dmenu/Makefile new file mode 100644 index 0000000..458c524 --- /dev/null +++ b/suckless/dmenu/Makefile @@ -0,0 +1,58 @@ +# dmenu - dynamic menu +# See LICENSE file for copyright and license details. + +include config.mk + +SRC = drw.c dmenu.c stest.c util.c +OBJ = $(SRC:.c=.o) + +all: dmenu stest + +.c.o: + $(CC) -c $(CFLAGS) $< + +config.h: + cp config.def.h $@ + +$(OBJ): arg.h config.h config.mk drw.h + +dmenu: dmenu.o drw.o util.o + $(CC) -o $@ dmenu.o drw.o util.o $(LDFLAGS) + +stest: stest.o + $(CC) -o $@ stest.o $(LDFLAGS) + +clean: + rm -f dmenu stest $(OBJ) dmenu-$(VERSION).tar.gz + +dist: clean + mkdir -p dmenu-$(VERSION) + cp LICENSE Makefile README arg.h config.def.h config.mk dmenu.1\ + drw.h util.h dmenu_path dmenu_run stest.1 $(SRC)\ + dmenu-$(VERSION) + tar -cf dmenu-$(VERSION).tar dmenu-$(VERSION) + gzip dmenu-$(VERSION).tar + rm -rf dmenu-$(VERSION) + +install: all + mkdir -p $(DESTDIR)$(PREFIX)/bin + cp -f dmenu dmenu_path dmenu_run stest $(DESTDIR)$(PREFIX)/bin + chmod 755 $(DESTDIR)$(PREFIX)/bin/dmenu + chmod 755 $(DESTDIR)$(PREFIX)/bin/dmenu_path + chmod 755 $(DESTDIR)$(PREFIX)/bin/dmenu_run + chmod 755 $(DESTDIR)$(PREFIX)/bin/stest + mkdir -p $(DESTDIR)$(MANPREFIX)/man1 + sed "s/VERSION/$(VERSION)/g" < dmenu.1 > $(DESTDIR)$(MANPREFIX)/man1/dmenu.1 + sed "s/VERSION/$(VERSION)/g" < stest.1 > $(DESTDIR)$(MANPREFIX)/man1/stest.1 + chmod 644 $(DESTDIR)$(MANPREFIX)/man1/dmenu.1 + chmod 644 $(DESTDIR)$(MANPREFIX)/man1/stest.1 + +uninstall: + rm -f $(DESTDIR)$(PREFIX)/bin/dmenu\ + $(DESTDIR)$(PREFIX)/bin/dmenu_path\ + $(DESTDIR)$(PREFIX)/bin/dmenu_run\ + $(DESTDIR)$(PREFIX)/bin/stest\ + $(DESTDIR)$(MANPREFIX)/man1/dmenu.1\ + $(DESTDIR)$(MANPREFIX)/man1/stest.1 + +.PHONY: all clean dist install uninstall diff --git a/suckless/dmenu/README b/suckless/dmenu/README new file mode 100644 index 0000000..a8fcdfe --- /dev/null +++ b/suckless/dmenu/README @@ -0,0 +1,24 @@ +dmenu - dynamic menu +==================== +dmenu is an efficient dynamic menu for X. + + +Requirements +------------ +In order to build dmenu you need the Xlib header files. + + +Installation +------------ +Edit config.mk to match your local setup (dmenu is installed into +the /usr/local namespace by default). + +Afterwards enter the following command to build and install dmenu +(if necessary as root): + + make clean install + + +Running dmenu +------------- +See the man page for details. diff --git a/suckless/dmenu/arg.h b/suckless/dmenu/arg.h new file mode 100644 index 0000000..e94e02b --- /dev/null +++ b/suckless/dmenu/arg.h @@ -0,0 +1,49 @@ +/* + * Copy me if you can. + * by 20h + */ + +#ifndef ARG_H__ +#define ARG_H__ + +extern char *argv0; + +/* use main(int argc, char *argv[]) */ +#define ARGBEGIN for (argv0 = *argv, argv++, argc--;\ + argv[0] && argv[0][0] == '-'\ + && argv[0][1];\ + argc--, argv++) {\ + char argc_;\ + char **argv_;\ + int brk_;\ + if (argv[0][1] == '-' && argv[0][2] == '\0') {\ + argv++;\ + argc--;\ + break;\ + }\ + for (brk_ = 0, argv[0]++, argv_ = argv;\ + argv[0][0] && !brk_;\ + argv[0]++) {\ + if (argv_ != argv)\ + break;\ + argc_ = argv[0][0];\ + switch (argc_) + +#define ARGEND }\ + } + +#define ARGC() argc_ + +#define EARGF(x) ((argv[0][1] == '\0' && argv[1] == NULL)?\ + ((x), abort(), (char *)0) :\ + (brk_ = 1, (argv[0][1] != '\0')?\ + (&argv[0][1]) :\ + (argc--, argv++, argv[0]))) + +#define ARGF() ((argv[0][1] == '\0' && argv[1] == NULL)?\ + (char *)0 :\ + (brk_ = 1, (argv[0][1] != '\0')?\ + (&argv[0][1]) :\ + (argc--, argv++, argv[0]))) + +#endif diff --git a/suckless/dmenu/config.def.h b/suckless/dmenu/config.def.h new file mode 100644 index 0000000..1edb647 --- /dev/null +++ b/suckless/dmenu/config.def.h @@ -0,0 +1,23 @@ +/* See LICENSE file for copyright and license details. */ +/* Default settings; can be overriden by command line. */ + +static int topbar = 1; /* -b option; if 0, dmenu appears at bottom */ +/* -fn option overrides fonts[0]; default X11 font or font set */ +static const char *fonts[] = { + "monospace:size=10" +}; +static const char *prompt = NULL; /* -p option; prompt to the left of input field */ +static const char *colors[SchemeLast][2] = { + /* fg bg */ + [SchemeNorm] = { "#bbbbbb", "#222222" }, + [SchemeSel] = { "#eeeeee", "#005577" }, + [SchemeOut] = { "#000000", "#00ffff" }, +}; +/* -l option; if nonzero, dmenu uses vertical list with given number of lines */ +static unsigned int lines = 0; + +/* + * Characters not considered part of a word while deleting words + * for example: " /?\"&[]" + */ +static const char worddelimiters[] = " "; diff --git a/suckless/dmenu/config.h b/suckless/dmenu/config.h new file mode 100644 index 0000000..ad70a45 --- /dev/null +++ b/suckless/dmenu/config.h @@ -0,0 +1,23 @@ +/* See LICENSE file for copyright and license details. */ +/* Default settings; can be overriden by command line. */ + +static int topbar = 0; /* -b option; if 0, dmenu appears at bottom */ +/* -fn option overrides fonts[0]; default X11 font or font set */ +static const char *fonts[] = { + "monospace:size=10" +}; +static const char *prompt = NULL; /* -p option; prompt to the left of input field */ +static const char *colors[SchemeLast][2] = { + /* fg bg */ + [SchemeNorm] = { "#bbbbbb", "#222222" }, + [SchemeSel] = { "#eeeeee", "#005577" }, + [SchemeOut] = { "#000000", "#00ffff" }, +}; +/* -l option; if nonzero, dmenu uses vertical list with given number of lines */ +static unsigned int lines = 0; + +/* + * Characters not considered part of a word while deleting words + * for example: " /?\"&[]" + */ +static const char worddelimiters[] = " "; diff --git a/suckless/dmenu/config.mk b/suckless/dmenu/config.mk new file mode 100644 index 0000000..137f7c8 --- /dev/null +++ b/suckless/dmenu/config.mk @@ -0,0 +1,32 @@ +# dmenu version +VERSION = 5.3 + +# paths +PREFIX = /usr/local +MANPREFIX = $(PREFIX)/share/man + +X11INC = /usr/X11R6/include +X11LIB = /usr/X11R6/lib + +# Xinerama, comment if you don't want it +XINERAMALIBS = -lXinerama +XINERAMAFLAGS = -DXINERAMA + +# freetype +FREETYPELIBS = -lfontconfig -lXft +FREETYPEINC = /usr/include/freetype2 +# OpenBSD (uncomment) +#FREETYPEINC = $(X11INC)/freetype2 +#MANPREFIX = ${PREFIX}/man + +# includes and libs +INCS = -I$(X11INC) -I$(FREETYPEINC) +LIBS = -L$(X11LIB) -lX11 $(XINERAMALIBS) $(FREETYPELIBS) + +# flags +CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700 -D_POSIX_C_SOURCE=200809L -DVERSION=\"$(VERSION)\" $(XINERAMAFLAGS) +CFLAGS = -std=c99 -pedantic -Wall -Os $(INCS) $(CPPFLAGS) +LDFLAGS = $(LIBS) + +# compiler and linker +CC = cc diff --git a/suckless/dmenu/dmenu b/suckless/dmenu/dmenu new file mode 100755 index 0000000000000000000000000000000000000000..12d70df8f58d0ac8b30b5349313de4c3f35d7f9b GIT binary patch literal 42296 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 Pf96qDVz{AzfffEI*k|rE literal 0 HcmV?d00001 diff --git a/suckless/dmenu/dmenu.1 b/suckless/dmenu/dmenu.1 new file mode 100644 index 0000000..323f93c --- /dev/null +++ b/suckless/dmenu/dmenu.1 @@ -0,0 +1,194 @@ +.TH DMENU 1 dmenu\-VERSION +.SH NAME +dmenu \- dynamic menu +.SH SYNOPSIS +.B dmenu +.RB [ \-bfiv ] +.RB [ \-l +.IR lines ] +.RB [ \-m +.IR monitor ] +.RB [ \-p +.IR prompt ] +.RB [ \-fn +.IR font ] +.RB [ \-nb +.IR color ] +.RB [ \-nf +.IR color ] +.RB [ \-sb +.IR color ] +.RB [ \-sf +.IR color ] +.RB [ \-w +.IR windowid ] +.P +.BR dmenu_run " ..." +.SH DESCRIPTION +.B dmenu +is a dynamic menu for X, which reads a list of newline\-separated items from +stdin. When the user selects an item and presses Return, their choice is printed +to stdout and dmenu terminates. Entering text will narrow the items to those +matching the tokens in the input. +.P +.B dmenu_run +is a script used by +.IR dwm (1) +which lists programs in the user's $PATH and runs the result in their $SHELL. +.SH OPTIONS +.TP +.B \-b +dmenu appears at the bottom of the screen. +.TP +.B \-f +dmenu grabs the keyboard before reading stdin if not reading from a tty. This +is faster, but will lock up X until stdin reaches end\-of\-file. +.TP +.B \-i +dmenu matches menu items case insensitively. +.TP +.BI \-l " lines" +dmenu lists items vertically, with the given number of lines. +.TP +.BI \-m " monitor" +dmenu is displayed on the monitor number supplied. Monitor numbers are starting +from 0. +.TP +.BI \-p " prompt" +defines the prompt to be displayed to the left of the input field. +.TP +.BI \-fn " font" +defines the font or font set used. +.TP +.BI \-nb " color" +defines the normal background color. +.IR #RGB , +.IR #RRGGBB , +and X color names are supported. +.TP +.BI \-nf " color" +defines the normal foreground color. +.TP +.BI \-sb " color" +defines the selected background color. +.TP +.BI \-sf " color" +defines the selected foreground color. +.TP +.B \-v +prints version information to stdout, then exits. +.TP +.BI \-w " windowid" +embed into windowid. +.SH USAGE +dmenu is completely controlled by the keyboard. Items are selected using the +arrow keys, page up, page down, home, and end. +.TP +.B Tab +Copy the selected item to the input field. +.TP +.B Return +Confirm selection. Prints the selected item to stdout and exits, returning +success. +.TP +.B Ctrl-Return +Confirm selection. Prints the selected item to stdout and continues. +.TP +.B Shift\-Return +Confirm input. Prints the input text to stdout and exits, returning success. +.TP +.B Escape +Exit without selecting an item, returning failure. +.TP +.B Ctrl-Left +Move cursor to the start of the current word +.TP +.B Ctrl-Right +Move cursor to the end of the current word +.TP +.B C\-a +Home +.TP +.B C\-b +Left +.TP +.B C\-c +Escape +.TP +.B C\-d +Delete +.TP +.B C\-e +End +.TP +.B C\-f +Right +.TP +.B C\-g +Escape +.TP +.B C\-h +Backspace +.TP +.B C\-i +Tab +.TP +.B C\-j +Return +.TP +.B C\-J +Shift-Return +.TP +.B C\-k +Delete line right +.TP +.B C\-m +Return +.TP +.B C\-M +Shift-Return +.TP +.B C\-n +Down +.TP +.B C\-p +Up +.TP +.B C\-u +Delete line left +.TP +.B C\-w +Delete word left +.TP +.B C\-y +Paste from primary X selection +.TP +.B C\-Y +Paste from X clipboard +.TP +.B M\-b +Move cursor to the start of the current word +.TP +.B M\-f +Move cursor to the end of the current word +.TP +.B M\-g +Home +.TP +.B M\-G +End +.TP +.B M\-h +Up +.TP +.B M\-j +Page down +.TP +.B M\-k +Page up +.TP +.B M\-l +Down +.SH SEE ALSO +.IR dwm (1), +.IR stest (1) diff --git a/suckless/dmenu/dmenu.c b/suckless/dmenu/dmenu.c new file mode 100644 index 0000000..fd49549 --- /dev/null +++ b/suckless/dmenu/dmenu.c @@ -0,0 +1,795 @@ +/* See LICENSE file for copyright and license details. */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#ifdef XINERAMA +#include +#endif +#include + +#include "drw.h" +#include "util.h" + +/* macros */ +#define INTERSECT(x,y,w,h,r) (MAX(0, MIN((x)+(w),(r).x_org+(r).width) - MAX((x),(r).x_org)) \ + * MAX(0, MIN((y)+(h),(r).y_org+(r).height) - MAX((y),(r).y_org))) +#define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad) + +/* enums */ +enum { SchemeNorm, SchemeSel, SchemeOut, SchemeLast }; /* color schemes */ + +struct item { + char *text; + struct item *left, *right; + int out; +}; + +static char text[BUFSIZ] = ""; +static char *embed; +static int bh, mw, mh; +static int inputw = 0, promptw; +static int lrpad; /* sum of left and right padding */ +static size_t cursor; +static struct item *items = NULL; +static struct item *matches, *matchend; +static struct item *prev, *curr, *next, *sel; +static int mon = -1, screen; + +static Atom clip, utf8; +static Display *dpy; +static Window root, parentwin, win; +static XIC xic; + +static Drw *drw; +static Clr *scheme[SchemeLast]; + +#include "config.h" + +static int (*fstrncmp)(const char *, const char *, size_t) = strncmp; +static char *(*fstrstr)(const char *, const char *) = strstr; + +static unsigned int +textw_clamp(const char *str, unsigned int n) +{ + unsigned int w = drw_fontset_getwidth_clamp(drw, str, n) + lrpad; + return MIN(w, n); +} + +static void +appenditem(struct item *item, struct item **list, struct item **last) +{ + if (*last) + (*last)->right = item; + else + *list = item; + + item->left = *last; + item->right = NULL; + *last = item; +} + +static void +calcoffsets(void) +{ + int i, n; + + if (lines > 0) + n = lines * bh; + else + n = mw - (promptw + inputw + TEXTW("<") + TEXTW(">")); + /* calculate which items will begin the next page and previous page */ + for (i = 0, next = curr; next; next = next->right) + if ((i += (lines > 0) ? bh : textw_clamp(next->text, n)) > n) + break; + for (i = 0, prev = curr; prev && prev->left; prev = prev->left) + if ((i += (lines > 0) ? bh : textw_clamp(prev->left->text, n)) > n) + break; +} + +static void +cleanup(void) +{ + size_t i; + + XUngrabKeyboard(dpy, CurrentTime); + for (i = 0; i < SchemeLast; i++) + free(scheme[i]); + for (i = 0; items && items[i].text; ++i) + free(items[i].text); + free(items); + drw_free(drw); + XSync(dpy, False); + XCloseDisplay(dpy); +} + +static char * +cistrstr(const char *h, const char *n) +{ + size_t i; + + if (!n[0]) + return (char *)h; + + for (; *h; ++h) { + for (i = 0; n[i] && tolower((unsigned char)n[i]) == + tolower((unsigned char)h[i]); ++i) + ; + if (n[i] == '\0') + return (char *)h; + } + return NULL; +} + +static int +drawitem(struct item *item, int x, int y, int w) +{ + if (item == sel) + drw_setscheme(drw, scheme[SchemeSel]); + else if (item->out) + drw_setscheme(drw, scheme[SchemeOut]); + else + drw_setscheme(drw, scheme[SchemeNorm]); + + return drw_text(drw, x, y, w, bh, lrpad / 2, item->text, 0); +} + +static void +drawmenu(void) +{ + unsigned int curpos; + struct item *item; + int x = 0, y = 0, w; + + drw_setscheme(drw, scheme[SchemeNorm]); + drw_rect(drw, 0, 0, mw, mh, 1, 1); + + if (prompt && *prompt) { + drw_setscheme(drw, scheme[SchemeSel]); + x = drw_text(drw, x, 0, promptw, bh, lrpad / 2, prompt, 0); + } + /* draw input field */ + w = (lines > 0 || !matches) ? mw - x : inputw; + drw_setscheme(drw, scheme[SchemeNorm]); + drw_text(drw, x, 0, w, bh, lrpad / 2, text, 0); + + curpos = TEXTW(text) - TEXTW(&text[cursor]); + if ((curpos += lrpad / 2 - 1) < w) { + drw_setscheme(drw, scheme[SchemeNorm]); + drw_rect(drw, x + curpos, 2, 2, bh - 4, 1, 0); + } + + if (lines > 0) { + /* draw vertical list */ + for (item = curr; item != next; item = item->right) + drawitem(item, x, y += bh, mw - x); + } else if (matches) { + /* draw horizontal list */ + x += inputw; + w = TEXTW("<"); + if (curr->left) { + drw_setscheme(drw, scheme[SchemeNorm]); + drw_text(drw, x, 0, w, bh, lrpad / 2, "<", 0); + } + x += w; + for (item = curr; item != next; item = item->right) + x = drawitem(item, x, 0, textw_clamp(item->text, mw - x - TEXTW(">"))); + if (next) { + w = TEXTW(">"); + drw_setscheme(drw, scheme[SchemeNorm]); + drw_text(drw, mw - w, 0, w, bh, lrpad / 2, ">", 0); + } + } + drw_map(drw, win, 0, 0, mw, mh); +} + +static void +grabfocus(void) +{ + struct timespec ts = { .tv_sec = 0, .tv_nsec = 10000000 }; + Window focuswin; + int i, revertwin; + + for (i = 0; i < 100; ++i) { + XGetInputFocus(dpy, &focuswin, &revertwin); + if (focuswin == win) + return; + XSetInputFocus(dpy, win, RevertToParent, CurrentTime); + nanosleep(&ts, NULL); + } + die("cannot grab focus"); +} + +static void +grabkeyboard(void) +{ + struct timespec ts = { .tv_sec = 0, .tv_nsec = 1000000 }; + int i; + + if (embed) + return; + /* try to grab keyboard, we may have to wait for another process to ungrab */ + for (i = 0; i < 1000; i++) { + if (XGrabKeyboard(dpy, DefaultRootWindow(dpy), True, GrabModeAsync, + GrabModeAsync, CurrentTime) == GrabSuccess) + return; + nanosleep(&ts, NULL); + } + die("cannot grab keyboard"); +} + +static void +match(void) +{ + static char **tokv = NULL; + static int tokn = 0; + + char buf[sizeof text], *s; + int i, tokc = 0; + size_t len, textsize; + struct item *item, *lprefix, *lsubstr, *prefixend, *substrend; + + strcpy(buf, text); + /* separate input text into tokens to be matched individually */ + for (s = strtok(buf, " "); s; tokv[tokc - 1] = s, s = strtok(NULL, " ")) + if (++tokc > tokn && !(tokv = realloc(tokv, ++tokn * sizeof *tokv))) + die("cannot realloc %zu bytes:", tokn * sizeof *tokv); + len = tokc ? strlen(tokv[0]) : 0; + + matches = lprefix = lsubstr = matchend = prefixend = substrend = NULL; + textsize = strlen(text) + 1; + for (item = items; item && item->text; item++) { + for (i = 0; i < tokc; i++) + if (!fstrstr(item->text, tokv[i])) + break; + if (i != tokc) /* not all tokens match */ + continue; + /* exact matches go first, then prefixes, then substrings */ + if (!tokc || !fstrncmp(text, item->text, textsize)) + appenditem(item, &matches, &matchend); + else if (!fstrncmp(tokv[0], item->text, len)) + appenditem(item, &lprefix, &prefixend); + else + appenditem(item, &lsubstr, &substrend); + } + if (lprefix) { + if (matches) { + matchend->right = lprefix; + lprefix->left = matchend; + } else + matches = lprefix; + matchend = prefixend; + } + if (lsubstr) { + if (matches) { + matchend->right = lsubstr; + lsubstr->left = matchend; + } else + matches = lsubstr; + matchend = substrend; + } + curr = sel = matches; + calcoffsets(); +} + +static void +insert(const char *str, ssize_t n) +{ + if (strlen(text) + n > sizeof text - 1) + return; + /* move existing text out of the way, insert new text, and update cursor */ + memmove(&text[cursor + n], &text[cursor], sizeof text - cursor - MAX(n, 0)); + if (n > 0) + memcpy(&text[cursor], str, n); + cursor += n; + match(); +} + +static size_t +nextrune(int inc) +{ + ssize_t n; + + /* return location of next utf8 rune in the given direction (+1 or -1) */ + for (n = cursor + inc; n + inc >= 0 && (text[n] & 0xc0) == 0x80; n += inc) + ; + return n; +} + +static void +movewordedge(int dir) +{ + if (dir < 0) { /* move cursor to the start of the word*/ + while (cursor > 0 && strchr(worddelimiters, text[nextrune(-1)])) + cursor = nextrune(-1); + while (cursor > 0 && !strchr(worddelimiters, text[nextrune(-1)])) + cursor = nextrune(-1); + } else { /* move cursor to the end of the word */ + while (text[cursor] && strchr(worddelimiters, text[cursor])) + cursor = nextrune(+1); + while (text[cursor] && !strchr(worddelimiters, text[cursor])) + cursor = nextrune(+1); + } +} + +static void +keypress(XKeyEvent *ev) +{ + char buf[64]; + int len; + KeySym ksym = NoSymbol; + Status status; + + len = XmbLookupString(xic, ev, buf, sizeof buf, &ksym, &status); + switch (status) { + default: /* XLookupNone, XBufferOverflow */ + return; + case XLookupChars: /* composed string from input method */ + goto insert; + case XLookupKeySym: + case XLookupBoth: /* a KeySym and a string are returned: use keysym */ + break; + } + + if (ev->state & ControlMask) { + switch(ksym) { + case XK_a: ksym = XK_Home; break; + case XK_b: ksym = XK_Left; break; + case XK_c: ksym = XK_Escape; break; + case XK_d: ksym = XK_Delete; break; + case XK_e: ksym = XK_End; break; + case XK_f: ksym = XK_Right; break; + case XK_g: ksym = XK_Escape; break; + case XK_h: ksym = XK_BackSpace; break; + case XK_i: ksym = XK_Tab; break; + case XK_j: /* fallthrough */ + case XK_J: /* fallthrough */ + case XK_m: /* fallthrough */ + case XK_M: ksym = XK_Return; ev->state &= ~ControlMask; break; + case XK_n: ksym = XK_Down; break; + case XK_p: ksym = XK_Up; break; + + case XK_k: /* delete right */ + text[cursor] = '\0'; + match(); + break; + case XK_u: /* delete left */ + insert(NULL, 0 - cursor); + break; + case XK_w: /* delete word */ + while (cursor > 0 && strchr(worddelimiters, text[nextrune(-1)])) + insert(NULL, nextrune(-1) - cursor); + while (cursor > 0 && !strchr(worddelimiters, text[nextrune(-1)])) + insert(NULL, nextrune(-1) - cursor); + break; + case XK_y: /* paste selection */ + case XK_Y: + XConvertSelection(dpy, (ev->state & ShiftMask) ? clip : XA_PRIMARY, + utf8, utf8, win, CurrentTime); + return; + case XK_Left: + case XK_KP_Left: + movewordedge(-1); + goto draw; + case XK_Right: + case XK_KP_Right: + movewordedge(+1); + goto draw; + case XK_Return: + case XK_KP_Enter: + break; + case XK_bracketleft: + cleanup(); + exit(1); + default: + return; + } + } else if (ev->state & Mod1Mask) { + switch(ksym) { + case XK_b: + movewordedge(-1); + goto draw; + case XK_f: + movewordedge(+1); + goto draw; + case XK_g: ksym = XK_Home; break; + case XK_G: ksym = XK_End; break; + case XK_h: ksym = XK_Up; break; + case XK_j: ksym = XK_Next; break; + case XK_k: ksym = XK_Prior; break; + case XK_l: ksym = XK_Down; break; + default: + return; + } + } + + switch(ksym) { + default: +insert: + if (!iscntrl((unsigned char)*buf)) + insert(buf, len); + break; + case XK_Delete: + case XK_KP_Delete: + if (text[cursor] == '\0') + return; + cursor = nextrune(+1); + /* fallthrough */ + case XK_BackSpace: + if (cursor == 0) + return; + insert(NULL, nextrune(-1) - cursor); + break; + case XK_End: + case XK_KP_End: + if (text[cursor] != '\0') { + cursor = strlen(text); + break; + } + if (next) { + /* jump to end of list and position items in reverse */ + curr = matchend; + calcoffsets(); + curr = prev; + calcoffsets(); + while (next && (curr = curr->right)) + calcoffsets(); + } + sel = matchend; + break; + case XK_Escape: + cleanup(); + exit(1); + case XK_Home: + case XK_KP_Home: + if (sel == matches) { + cursor = 0; + break; + } + sel = curr = matches; + calcoffsets(); + break; + case XK_Left: + case XK_KP_Left: + if (cursor > 0 && (!sel || !sel->left || lines > 0)) { + cursor = nextrune(-1); + break; + } + if (lines > 0) + return; + /* fallthrough */ + case XK_Up: + case XK_KP_Up: + if (sel && sel->left && (sel = sel->left)->right == curr) { + curr = prev; + calcoffsets(); + } + break; + case XK_Next: + case XK_KP_Next: + if (!next) + return; + sel = curr = next; + calcoffsets(); + break; + case XK_Prior: + case XK_KP_Prior: + if (!prev) + return; + sel = curr = prev; + calcoffsets(); + break; + case XK_Return: + case XK_KP_Enter: + puts((sel && !(ev->state & ShiftMask)) ? sel->text : text); + if (!(ev->state & ControlMask)) { + cleanup(); + exit(0); + } + if (sel) + sel->out = 1; + break; + case XK_Right: + case XK_KP_Right: + if (text[cursor] != '\0') { + cursor = nextrune(+1); + break; + } + if (lines > 0) + return; + /* fallthrough */ + case XK_Down: + case XK_KP_Down: + if (sel && sel->right && (sel = sel->right) == next) { + curr = next; + calcoffsets(); + } + break; + case XK_Tab: + if (!sel) + return; + cursor = strnlen(sel->text, sizeof text - 1); + memcpy(text, sel->text, cursor); + text[cursor] = '\0'; + match(); + break; + } + +draw: + drawmenu(); +} + +static void +paste(void) +{ + char *p, *q; + int di; + unsigned long dl; + Atom da; + + /* we have been given the current selection, now insert it into input */ + if (XGetWindowProperty(dpy, win, utf8, 0, (sizeof text / 4) + 1, False, + utf8, &da, &di, &dl, &dl, (unsigned char **)&p) + == Success && p) { + insert(p, (q = strchr(p, '\n')) ? q - p : (ssize_t)strlen(p)); + XFree(p); + } + drawmenu(); +} + +static void +readstdin(void) +{ + char *line = NULL; + size_t i, itemsiz = 0, linesiz = 0; + ssize_t len; + + /* read each line from stdin and add it to the item list */ + for (i = 0; (len = getline(&line, &linesiz, stdin)) != -1; i++) { + if (i + 1 >= itemsiz) { + itemsiz += 256; + if (!(items = realloc(items, itemsiz * sizeof(*items)))) + die("cannot realloc %zu bytes:", itemsiz * sizeof(*items)); + } + if (line[len - 1] == '\n') + line[len - 1] = '\0'; + if (!(items[i].text = strdup(line))) + die("strdup:"); + + items[i].out = 0; + } + free(line); + if (items) + items[i].text = NULL; + lines = MIN(lines, i); +} + +static void +run(void) +{ + XEvent ev; + + while (!XNextEvent(dpy, &ev)) { + if (XFilterEvent(&ev, win)) + continue; + switch(ev.type) { + case DestroyNotify: + if (ev.xdestroywindow.window != win) + break; + cleanup(); + exit(1); + case Expose: + if (ev.xexpose.count == 0) + drw_map(drw, win, 0, 0, mw, mh); + break; + case FocusIn: + /* regrab focus from parent window */ + if (ev.xfocus.window != win) + grabfocus(); + break; + case KeyPress: + keypress(&ev.xkey); + break; + case SelectionNotify: + if (ev.xselection.property == utf8) + paste(); + break; + case VisibilityNotify: + if (ev.xvisibility.state != VisibilityUnobscured) + XRaiseWindow(dpy, win); + break; + } + } +} + +static void +setup(void) +{ + int x, y, i, j; + unsigned int du; + XSetWindowAttributes swa; + XIM xim; + Window w, dw, *dws; + XWindowAttributes wa; + XClassHint ch = {"dmenu", "dmenu"}; +#ifdef XINERAMA + XineramaScreenInfo *info; + Window pw; + int a, di, n, area = 0; +#endif + /* init appearance */ + for (j = 0; j < SchemeLast; j++) + scheme[j] = drw_scm_create(drw, colors[j], 2); + + clip = XInternAtom(dpy, "CLIPBOARD", False); + utf8 = XInternAtom(dpy, "UTF8_STRING", False); + + /* calculate menu geometry */ + bh = drw->fonts->h + 2; + lines = MAX(lines, 0); + mh = (lines + 1) * bh; +#ifdef XINERAMA + i = 0; + if (parentwin == root && (info = XineramaQueryScreens(dpy, &n))) { + XGetInputFocus(dpy, &w, &di); + if (mon >= 0 && mon < n) + i = mon; + else if (w != root && w != PointerRoot && w != None) { + /* find top-level window containing current input focus */ + do { + if (XQueryTree(dpy, (pw = w), &dw, &w, &dws, &du) && dws) + XFree(dws); + } while (w != root && w != pw); + /* find xinerama screen with which the window intersects most */ + if (XGetWindowAttributes(dpy, pw, &wa)) + for (j = 0; j < n; j++) + if ((a = INTERSECT(wa.x, wa.y, wa.width, wa.height, info[j])) > area) { + area = a; + i = j; + } + } + /* no focused window is on screen, so use pointer location instead */ + if (mon < 0 && !area && XQueryPointer(dpy, root, &dw, &dw, &x, &y, &di, &di, &du)) + for (i = 0; i < n; i++) + if (INTERSECT(x, y, 1, 1, info[i]) != 0) + break; + + x = info[i].x_org; + y = info[i].y_org + (topbar ? 0 : info[i].height - mh); + mw = info[i].width; + XFree(info); + } else +#endif + { + if (!XGetWindowAttributes(dpy, parentwin, &wa)) + die("could not get embedding window attributes: 0x%lx", + parentwin); + x = 0; + y = topbar ? 0 : wa.height - mh; + mw = wa.width; + } + promptw = (prompt && *prompt) ? TEXTW(prompt) - lrpad / 4 : 0; + inputw = mw / 3; /* input width: ~33% of monitor width */ + match(); + + /* create menu window */ + swa.override_redirect = True; + swa.background_pixel = scheme[SchemeNorm][ColBg].pixel; + swa.event_mask = ExposureMask | KeyPressMask | VisibilityChangeMask; + win = XCreateWindow(dpy, root, x, y, mw, mh, 0, + CopyFromParent, CopyFromParent, CopyFromParent, + CWOverrideRedirect | CWBackPixel | CWEventMask, &swa); + XSetClassHint(dpy, win, &ch); + + /* input methods */ + if ((xim = XOpenIM(dpy, NULL, NULL, NULL)) == NULL) + die("XOpenIM failed: could not open input device"); + + xic = XCreateIC(xim, XNInputStyle, XIMPreeditNothing | XIMStatusNothing, + XNClientWindow, win, XNFocusWindow, win, NULL); + + XMapRaised(dpy, win); + if (embed) { + XReparentWindow(dpy, win, parentwin, x, y); + XSelectInput(dpy, parentwin, FocusChangeMask | SubstructureNotifyMask); + if (XQueryTree(dpy, parentwin, &dw, &w, &dws, &du) && dws) { + for (i = 0; i < du && dws[i] != win; ++i) + XSelectInput(dpy, dws[i], FocusChangeMask); + XFree(dws); + } + grabfocus(); + } + drw_resize(drw, mw, mh); + drawmenu(); +} + +static void +usage(void) +{ + die("usage: dmenu [-bfiv] [-l lines] [-p prompt] [-fn font] [-m monitor]\n" + " [-nb color] [-nf color] [-sb color] [-sf color] [-w windowid]"); +} + +int +main(int argc, char *argv[]) +{ + XWindowAttributes wa; + int i, fast = 0; + + for (i = 1; i < argc; i++) + /* these options take no arguments */ + if (!strcmp(argv[i], "-v")) { /* prints version information */ + puts("dmenu-"VERSION); + exit(0); + } else if (!strcmp(argv[i], "-b")) /* appears at the bottom of the screen */ + topbar = 0; + else if (!strcmp(argv[i], "-f")) /* grabs keyboard before reading stdin */ + fast = 1; + else if (!strcmp(argv[i], "-i")) { /* case-insensitive item matching */ + fstrncmp = strncasecmp; + fstrstr = cistrstr; + } else if (i + 1 == argc) + usage(); + /* these options take one argument */ + else if (!strcmp(argv[i], "-l")) /* number of lines in vertical list */ + lines = atoi(argv[++i]); + else if (!strcmp(argv[i], "-m")) + mon = atoi(argv[++i]); + else if (!strcmp(argv[i], "-p")) /* adds prompt to left of input field */ + prompt = argv[++i]; + else if (!strcmp(argv[i], "-fn")) /* font or font set */ + fonts[0] = argv[++i]; + else if (!strcmp(argv[i], "-nb")) /* normal background color */ + colors[SchemeNorm][ColBg] = argv[++i]; + else if (!strcmp(argv[i], "-nf")) /* normal foreground color */ + colors[SchemeNorm][ColFg] = argv[++i]; + else if (!strcmp(argv[i], "-sb")) /* selected background color */ + colors[SchemeSel][ColBg] = argv[++i]; + else if (!strcmp(argv[i], "-sf")) /* selected foreground color */ + colors[SchemeSel][ColFg] = argv[++i]; + else if (!strcmp(argv[i], "-w")) /* embedding window id */ + embed = argv[++i]; + else + usage(); + + if (!setlocale(LC_CTYPE, "") || !XSupportsLocale()) + fputs("warning: no locale support\n", stderr); + if (!(dpy = XOpenDisplay(NULL))) + die("cannot open display"); + screen = DefaultScreen(dpy); + root = RootWindow(dpy, screen); + if (!embed || !(parentwin = strtol(embed, NULL, 0))) + parentwin = root; + if (!XGetWindowAttributes(dpy, parentwin, &wa)) + die("could not get embedding window attributes: 0x%lx", + parentwin); + drw = drw_create(dpy, screen, root, wa.width, wa.height); + if (!drw_fontset_create(drw, fonts, LENGTH(fonts))) + die("no fonts could be loaded."); + lrpad = drw->fonts->h; + +#ifdef __OpenBSD__ + if (pledge("stdio rpath", NULL) == -1) + die("pledge"); +#endif + + if (fast && !isatty(0)) { + grabkeyboard(); + readstdin(); + } else { + readstdin(); + grabkeyboard(); + } + setup(); + run(); + + return 1; /* unreachable */ +} diff --git a/suckless/dmenu/dmenu.o b/suckless/dmenu/dmenu.o new file mode 100644 index 0000000000000000000000000000000000000000..ca55188a10e709792c358b0d4a969609a5b5bc6e GIT binary patch literal 32224 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 +#include +#include +#include +#include + +#include "drw.h" +#include "util.h" + +#define UTF_INVALID 0xFFFD + +static int +utf8decode(const char *s_in, long *u, int *err) +{ + static const unsigned char lens[] = { + /* 0XXXX */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + /* 10XXX */ 0, 0, 0, 0, 0, 0, 0, 0, /* invalid */ + /* 110XX */ 2, 2, 2, 2, + /* 1110X */ 3, 3, + /* 11110 */ 4, + /* 11111 */ 0, /* invalid */ + }; + static const unsigned char leading_mask[] = { 0x7F, 0x1F, 0x0F, 0x07 }; + static const unsigned int overlong[] = { 0x0, 0x80, 0x0800, 0x10000 }; + + const unsigned char *s = (const unsigned char *)s_in; + int len = lens[*s >> 3]; + *u = UTF_INVALID; + *err = 1; + if (len == 0) + return 1; + + long cp = s[0] & leading_mask[len - 1]; + for (int i = 1; i < len; ++i) { + if (s[i] == '\0' || (s[i] & 0xC0) != 0x80) + return i; + cp = (cp << 6) | (s[i] & 0x3F); + } + /* out of range, surrogate, overlong encoding */ + if (cp > 0x10FFFF || (cp >> 11) == 0x1B || cp < overlong[len - 1]) + return len; + + *err = 0; + *u = cp; + return len; +} + +Drw * +drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h) +{ + Drw *drw = ecalloc(1, sizeof(Drw)); + + drw->dpy = dpy; + drw->screen = screen; + drw->root = root; + drw->w = w; + drw->h = h; + drw->drawable = XCreatePixmap(dpy, root, w, h, DefaultDepth(dpy, screen)); + drw->gc = XCreateGC(dpy, root, 0, NULL); + XSetLineAttributes(dpy, drw->gc, 1, LineSolid, CapButt, JoinMiter); + + return drw; +} + +void +drw_resize(Drw *drw, unsigned int w, unsigned int h) +{ + if (!drw) + return; + + drw->w = w; + drw->h = h; + if (drw->drawable) + XFreePixmap(drw->dpy, drw->drawable); + drw->drawable = XCreatePixmap(drw->dpy, drw->root, w, h, DefaultDepth(drw->dpy, drw->screen)); +} + +void +drw_free(Drw *drw) +{ + XFreePixmap(drw->dpy, drw->drawable); + XFreeGC(drw->dpy, drw->gc); + drw_fontset_free(drw->fonts); + free(drw); +} + +/* This function is an implementation detail. Library users should use + * drw_fontset_create instead. + */ +static Fnt * +xfont_create(Drw *drw, const char *fontname, FcPattern *fontpattern) +{ + Fnt *font; + XftFont *xfont = NULL; + FcPattern *pattern = NULL; + + if (fontname) { + /* Using the pattern found at font->xfont->pattern does not yield the + * same substitution results as using the pattern returned by + * FcNameParse; using the latter results in the desired fallback + * behaviour whereas the former just results in missing-character + * rectangles being drawn, at least with some fonts. */ + if (!(xfont = XftFontOpenName(drw->dpy, drw->screen, fontname))) { + fprintf(stderr, "error, cannot load font from name: '%s'\n", fontname); + return NULL; + } + if (!(pattern = FcNameParse((FcChar8 *) fontname))) { + fprintf(stderr, "error, cannot parse font name to pattern: '%s'\n", fontname); + XftFontClose(drw->dpy, xfont); + return NULL; + } + } else if (fontpattern) { + if (!(xfont = XftFontOpenPattern(drw->dpy, fontpattern))) { + fprintf(stderr, "error, cannot load font from pattern.\n"); + return NULL; + } + } else { + die("no font specified."); + } + + font = ecalloc(1, sizeof(Fnt)); + font->xfont = xfont; + font->pattern = pattern; + font->h = xfont->ascent + xfont->descent; + font->dpy = drw->dpy; + + return font; +} + +static void +xfont_free(Fnt *font) +{ + if (!font) + return; + if (font->pattern) + FcPatternDestroy(font->pattern); + XftFontClose(font->dpy, font->xfont); + free(font); +} + +Fnt* +drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount) +{ + Fnt *cur, *ret = NULL; + size_t i; + + if (!drw || !fonts) + return NULL; + + for (i = 1; i <= fontcount; i++) { + if ((cur = xfont_create(drw, fonts[fontcount - i], NULL))) { + cur->next = ret; + ret = cur; + } + } + return (drw->fonts = ret); +} + +void +drw_fontset_free(Fnt *font) +{ + if (font) { + drw_fontset_free(font->next); + xfont_free(font); + } +} + +void +drw_clr_create(Drw *drw, Clr *dest, const char *clrname) +{ + if (!drw || !dest || !clrname) + return; + + if (!XftColorAllocName(drw->dpy, DefaultVisual(drw->dpy, drw->screen), + DefaultColormap(drw->dpy, drw->screen), + clrname, dest)) + die("error, cannot allocate color '%s'", clrname); +} + +/* Wrapper to create color schemes. The caller has to call free(3) on the + * returned color scheme when done using it. */ +Clr * +drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount) +{ + size_t i; + Clr *ret; + + /* need at least two colors for a scheme */ + if (!drw || !clrnames || clrcount < 2 || !(ret = ecalloc(clrcount, sizeof(XftColor)))) + return NULL; + + for (i = 0; i < clrcount; i++) + drw_clr_create(drw, &ret[i], clrnames[i]); + return ret; +} + +void +drw_setfontset(Drw *drw, Fnt *set) +{ + if (drw) + drw->fonts = set; +} + +void +drw_setscheme(Drw *drw, Clr *scm) +{ + if (drw) + drw->scheme = scm; +} + +void +drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert) +{ + if (!drw || !drw->scheme) + return; + XSetForeground(drw->dpy, drw->gc, invert ? drw->scheme[ColBg].pixel : drw->scheme[ColFg].pixel); + if (filled) + XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h); + else + XDrawRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w - 1, h - 1); +} + +int +drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert) +{ + int ty, ellipsis_x = 0; + unsigned int tmpw, ew, ellipsis_w = 0, ellipsis_len, hash, h0, h1; + XftDraw *d = NULL; + Fnt *usedfont, *curfont, *nextfont; + int utf8strlen, utf8charlen, utf8err, render = x || y || w || h; + long utf8codepoint = 0; + const char *utf8str; + FcCharSet *fccharset; + FcPattern *fcpattern; + FcPattern *match; + XftResult result; + int charexists = 0, overflow = 0; + /* keep track of a couple codepoints for which we have no match. */ + static unsigned int nomatches[128], ellipsis_width, invalid_width; + static const char invalid[] = "�"; + + if (!drw || (render && (!drw->scheme || !w)) || !text || !drw->fonts) + return 0; + + if (!render) { + w = invert ? invert : ~invert; + } else { + XSetForeground(drw->dpy, drw->gc, drw->scheme[invert ? ColFg : ColBg].pixel); + XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h); + if (w < lpad) + return x + w; + d = XftDrawCreate(drw->dpy, drw->drawable, + DefaultVisual(drw->dpy, drw->screen), + DefaultColormap(drw->dpy, drw->screen)); + x += lpad; + w -= lpad; + } + + usedfont = drw->fonts; + if (!ellipsis_width && render) + ellipsis_width = drw_fontset_getwidth(drw, "..."); + if (!invalid_width && render) + invalid_width = drw_fontset_getwidth(drw, invalid); + while (1) { + ew = ellipsis_len = utf8err = utf8charlen = utf8strlen = 0; + utf8str = text; + nextfont = NULL; + while (*text) { + utf8charlen = utf8decode(text, &utf8codepoint, &utf8err); + for (curfont = drw->fonts; curfont; curfont = curfont->next) { + charexists = charexists || XftCharExists(drw->dpy, curfont->xfont, utf8codepoint); + if (charexists) { + drw_font_getexts(curfont, text, utf8charlen, &tmpw, NULL); + if (ew + ellipsis_width <= w) { + /* keep track where the ellipsis still fits */ + ellipsis_x = x + ew; + ellipsis_w = w - ew; + ellipsis_len = utf8strlen; + } + + if (ew + tmpw > w) { + overflow = 1; + /* called from drw_fontset_getwidth_clamp(): + * it wants the width AFTER the overflow + */ + if (!render) + x += tmpw; + else + utf8strlen = ellipsis_len; + } else if (curfont == usedfont) { + text += utf8charlen; + utf8strlen += utf8err ? 0 : utf8charlen; + ew += utf8err ? 0 : tmpw; + } else { + nextfont = curfont; + } + break; + } + } + + if (overflow || !charexists || nextfont || utf8err) + break; + else + charexists = 0; + } + + if (utf8strlen) { + if (render) { + ty = y + (h - usedfont->h) / 2 + usedfont->xfont->ascent; + XftDrawStringUtf8(d, &drw->scheme[invert ? ColBg : ColFg], + usedfont->xfont, x, ty, (XftChar8 *)utf8str, utf8strlen); + } + x += ew; + w -= ew; + } + if (utf8err && (!render || invalid_width < w)) { + if (render) + drw_text(drw, x, y, w, h, 0, invalid, invert); + x += invalid_width; + w -= invalid_width; + } + if (render && overflow) + drw_text(drw, ellipsis_x, y, ellipsis_w, h, 0, "...", invert); + + if (!*text || overflow) { + break; + } else if (nextfont) { + charexists = 0; + usedfont = nextfont; + } else { + /* Regardless of whether or not a fallback font is found, the + * character must be drawn. */ + charexists = 1; + + hash = (unsigned int)utf8codepoint; + hash = ((hash >> 16) ^ hash) * 0x21F0AAAD; + hash = ((hash >> 15) ^ hash) * 0xD35A2D97; + h0 = ((hash >> 15) ^ hash) % LENGTH(nomatches); + h1 = (hash >> 17) % LENGTH(nomatches); + /* avoid expensive XftFontMatch call when we know we won't find a match */ + if (nomatches[h0] == utf8codepoint || nomatches[h1] == utf8codepoint) + goto no_match; + + fccharset = FcCharSetCreate(); + FcCharSetAddChar(fccharset, utf8codepoint); + + if (!drw->fonts->pattern) { + /* Refer to the comment in xfont_create for more information. */ + die("the first font in the cache must be loaded from a font string."); + } + + fcpattern = FcPatternDuplicate(drw->fonts->pattern); + FcPatternAddCharSet(fcpattern, FC_CHARSET, fccharset); + FcPatternAddBool(fcpattern, FC_SCALABLE, FcTrue); + + FcConfigSubstitute(NULL, fcpattern, FcMatchPattern); + FcDefaultSubstitute(fcpattern); + match = XftFontMatch(drw->dpy, drw->screen, fcpattern, &result); + + FcCharSetDestroy(fccharset); + FcPatternDestroy(fcpattern); + + if (match) { + usedfont = xfont_create(drw, NULL, match); + if (usedfont && XftCharExists(drw->dpy, usedfont->xfont, utf8codepoint)) { + for (curfont = drw->fonts; curfont->next; curfont = curfont->next) + ; /* NOP */ + curfont->next = usedfont; + } else { + xfont_free(usedfont); + nomatches[nomatches[h0] ? h1 : h0] = utf8codepoint; +no_match: + usedfont = drw->fonts; + } + } + } + } + if (d) + XftDrawDestroy(d); + + return x + (render ? w : 0); +} + +void +drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h) +{ + if (!drw) + return; + + XCopyArea(drw->dpy, drw->drawable, win, drw->gc, x, y, w, h, x, y); + XSync(drw->dpy, False); +} + +unsigned int +drw_fontset_getwidth(Drw *drw, const char *text) +{ + if (!drw || !drw->fonts || !text) + return 0; + return drw_text(drw, 0, 0, 0, 0, 0, text, 0); +} + +unsigned int +drw_fontset_getwidth_clamp(Drw *drw, const char *text, unsigned int n) +{ + unsigned int tmp = 0; + if (drw && drw->fonts && text && n) + tmp = drw_text(drw, 0, 0, 0, 0, 0, text, n); + return MIN(n, tmp); +} + +void +drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h) +{ + XGlyphInfo ext; + + if (!font || !text) + return; + + XftTextExtentsUtf8(font->dpy, font->xfont, (XftChar8 *)text, len, &ext); + if (w) + *w = ext.xOff; + if (h) + *h = font->h; +} + +Cur * +drw_cur_create(Drw *drw, int shape) +{ + Cur *cur; + + if (!drw || !(cur = ecalloc(1, sizeof(Cur)))) + return NULL; + + cur->cursor = XCreateFontCursor(drw->dpy, shape); + + return cur; +} + +void +drw_cur_free(Drw *drw, Cur *cursor) +{ + if (!cursor) + return; + + XFreeCursor(drw->dpy, cursor->cursor); + free(cursor); +} diff --git a/suckless/dmenu/drw.h b/suckless/dmenu/drw.h new file mode 100644 index 0000000..fd7631b --- /dev/null +++ b/suckless/dmenu/drw.h @@ -0,0 +1,58 @@ +/* See LICENSE file for copyright and license details. */ + +typedef struct { + Cursor cursor; +} Cur; + +typedef struct Fnt { + Display *dpy; + unsigned int h; + XftFont *xfont; + FcPattern *pattern; + struct Fnt *next; +} Fnt; + +enum { ColFg, ColBg }; /* Clr scheme index */ +typedef XftColor Clr; + +typedef struct { + unsigned int w, h; + Display *dpy; + int screen; + Window root; + Drawable drawable; + GC gc; + Clr *scheme; + Fnt *fonts; +} Drw; + +/* Drawable abstraction */ +Drw *drw_create(Display *dpy, int screen, Window win, unsigned int w, unsigned int h); +void drw_resize(Drw *drw, unsigned int w, unsigned int h); +void drw_free(Drw *drw); + +/* Fnt abstraction */ +Fnt *drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount); +void drw_fontset_free(Fnt* set); +unsigned int drw_fontset_getwidth(Drw *drw, const char *text); +unsigned int drw_fontset_getwidth_clamp(Drw *drw, const char *text, unsigned int n); +void drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h); + +/* Colorscheme abstraction */ +void drw_clr_create(Drw *drw, Clr *dest, const char *clrname); +Clr *drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount); + +/* Cursor abstraction */ +Cur *drw_cur_create(Drw *drw, int shape); +void drw_cur_free(Drw *drw, Cur *cursor); + +/* Drawing context manipulation */ +void drw_setfontset(Drw *drw, Fnt *set); +void drw_setscheme(Drw *drw, Clr *scm); + +/* Drawing functions */ +void drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert); +int drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert); + +/* Map functions */ +void drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h); diff --git a/suckless/dmenu/drw.o b/suckless/dmenu/drw.o new file mode 100644 index 0000000000000000000000000000000000000000..69dbfa9f910b2da334855d573d810016a6cee0e0 GIT binary patch literal 11464 zcmb_hdvsexdcU%q#Cfb_Ab=MVq67iXZXzrQ!G^H-+E?)vh^&YcV)DQ!vK))ZmXCCm zIAkGNWT!j5G0+~i+n)9uI4$j=OF7UkZE0D8Ou{2uV1o%1y5|(a0XB|FU>DZq5m0~M z+!=dvvHDl%9Njzfn{U4PUh~b&)t*Rfb(P1X$>Py|piQ+Ts%bS#r|QkT+N}9CpJon~ zt;^a?_LXVxsiVe>|)~U01HjNQ@@KgUqU+Nno>_z<+oxQ5BkFq!Pby0Tu zS(CKLkw$|x z7;K=LkK**d4IegHYal$zp?@dtU=ZPGy~$qCpCTxHn0Ie9*;|{o=$rK|`fYkAmyz_i zSzo8KqwCopNI7=3Y3~fM4b|q*gf$zg*6^XGy}QOtw$>W#7&`%d>&%gNXPMqVqE5qZ zZghws3GqKD)Q9ft^>ypp&EiL7F#q6X5C(kxgBMYSeHCR#W5X-n)Sux(p1i5)BmX^L zgJaZQ^SL>6*xCcb@|oGMOco1DQBX67N>TP=VUcNH2YSsMK9^nxIG++1X6zBd*{{Dn zu+UL?6wMZ6-*67&>2S#$=KOj4Ks`8e2l8fk)MW8m{OauLOK5ig+$jo^8I$6!3xeeU zr_}8Y)w=h57Oyew_8OD*1Wfk4$!eqJ=cC0_HDh0XQ!blqd*gUj_@r4pRA;i|(>Uxr z5rqLRhe<)#`E|L>t?qQ~3@Dz<*OOKbt-V{iN<=CJDqMnLulpY;nM0%g2cD}rQfQ&T zxGrY@5MFPqjj~Tn_BOdZ>isb>iovdSJZ{?k&7AL0sQ~@{TUg6k1Dl*EaALq@Z#Ypf zL9-OU^!Wdbrnw=?zNVR4qHMxsA0Ma%Z%5FflC?Y%em}-OywRTjVT^qoEgv#RKCI@3 zH9aqIs%X<(5N*NO4p8iO&d{phE>~P;yi4=yCwo{E@GKrbA!R#sGW<2P%&($#{~Bks6PjHgW6#Hijo>`a z^QNKqt=ax(jo^HpRR_(Xlh#bTwT4AtCnH$bWq!Y!GnLs8v-1?-BtRzvMA*yg*(+Ru z;zt9fJs5lfVlXRM&(;N(8CWWfq!?D3{Sx=kZ_t8g zzH1hDH)#IBN2z(zKlnFz>wNi}#UBN!=TCrus1enDs78h+3YQjt8GH&e19}`!$U&`0 z_%|`OIamh?=8gRwfN)9DVUadayb5Py0aTmz{3>B<$LTs7Bfsl$n4>vv;JM0<1)Wu< z->Ppknm)*X$FQNS?m0EKfTSWXQ7&Ej0gsxgOlsOD)>PbCQ--H22=Btk2$Ff@{_w<$ zkg$wm!gO_}-HPqt55*5WMV_LN>x^Kaa6$9nN$Xs5_$nv@=p8OAn?Wr>_kWR0sqX)2 zDSS8*K8dv3jNdBaZeoo=w}$X2Hke3w6y7r^y&`7t_~Ww%NBx7xkb)6QPTDMud5gyu z8UB9>`XdOVo%*m9EQ>xf`RbDSe)OH-yB7OTz3J%PSVqKY-dTf(tt~ox$t*vo7vC-E zdq3Y>SQ{PrU}o{y_0id{jK3EBF%n*_wx>CU?P%o7xkxD&T34FM39%DI!ex8@KSi6~ zxa)i43-o8cE+ag6>ehcrd&D?``RKS;XQ$OZ1BQnEw>Kin{e$m;4v~hX zZ#UR`$WsQC?l7Rf*uRlK;x@Oj0r@)&&ygm$D%Xx+s3%$j2<*2C?Rmyhsy2_WG;QQe zgaQ$4CJw}~gZs-svx8V|9xC~Vc9YBP-oRK274+QRGF*K&O^{zmQ9akQE?CcPIKGs| z7&uE9?33}uW>W?Mu_T&2YJ#K|nW-={;yI?X=fb1TvEbzR-0zklG7#O6Qv2dlBg_$yadVi%d<{|@EdYyE5XM=HoqC7kA`hIh6ig!QSY+r!>-xzw zfRofa-(nIMOk!NHTW_QEQm6Tc{8gGZwg?Z>xppt5na^Mjy?D&yA3A{=0tUHqJ`ZRU zfrXtOOK0rq)8(?kPEe>djGU-7!Y9(BkNy0U#q7w)aew$oy7aT<8($|kjC|zR!-qzW zpH+N!k6wI#4}u1seNQN9&%Zy`bizNl6El&e>}s@+`vn~iI>aYjucq7KXoXi|JmN-LsXidT&b3!`%oC=p64$Q$O&uS-VrF02~NLGee zCRjMm0LT`{zEkjxuv z@i@HEkqpNwn5BWvUAoEIGquQ%Sz??Bz<4j>CX43lIiYrsw?DTk;r7S$%K^(B(s@pj?bcnLLtrS z0poNo4;e_1bYFmwWFm=YZvpVu6qhpvNlD0rn8(Vc`?iI&WDkjEY58O#lh~R`xn^}~ zD1;8p;l>b;z4Ru7@awyjyOA;*;n!$!ah)dToV^?P_fG7m2v?acOkiQl3=6(>@0bd~cmeYH+ueMl~IOv0Z2AYkc?_tq*Usc3ccds|%3k+9BeD(WhM12kW zW=4ID#aX(qxvJ0CX!sg*Uww-&(Bi9W@zu8YYL;Q_UcqM*y>Il@?yoX@b^E-nzCf{> zsye6C55Dj+k~v7|Y)a)8QV25LR|R(Wdck(Mx`pP|X@gy8*?`-A$_8ZnTjy{a7-t$k zGIuR-P`aE#T1*4iW2$8cHYz`$2e+3=4uV7LBff@BzS>r9K8^g^A!zR;TFAJ+N+-X9 zx>#*MsI)Ht!13;Wko-i@-$tv(r4#on!e`&iR`P3`?+H)UTfV0}5nss@$GZi9_k1s} zl{{PU)`8^lHbJpLP;@D6>h}&*Rfr9W`#Q0p_({FPS9^o64l#KnkAWci8%0021&@!7 zzB-dANU0k*9og)5K^H~cZHK$00nkNr?iaKd6D_xIyJJvlS11$;)!OfHg8p{#A`eYh zycppwWcDhBp09aeXXEDqeYNn997!?~P6>#L#IHo%qs`Qs2}F@N-GT@Y5Qq}sPbZfU zPO(l!(zl~dxGb{&HjYawG{pQw=T+#bP2~>$ z-(&E8Sm2KdT<#&i5ctzBd_>@f1Fo1%1^jpg{C@=h9b&2SJPH2g3iPv~ z|8(=xO^)pRq~OE%6YvRCpue&LZU{ahkqY=e13ouZpx-3u_s;_n3f~9t?yo?9cLn_Z z3iv}6@PDj;AF6=ARRJHXfS;~_*CGz4v;V>hc&GxdSHR=I$&Vw#o-!V`3%o3FzE8r= zcUIs-dnEBOze8Tpw2PgW_7@fCwXWRGP*NM9J3(i6E`@V_CX?>Zr}LdV(_L0iXr-3! z+mXnmyF~jc*$%DHGO50N=nA|NUAQB3_9pV%Lt!nuBbCc!ac5}I`m((V3m1%h=t?aV zYi*!Mm>yTqgJUbGb`?EV(&K7+G-|7pap&4&r1DlSyG!fnwpK&L)=V~^BAGjrxfCur zS_;<@+;_B&R^E=M2YM6zvenkAb+o6fSh_EzTe!z;Em)~MADv6((|4w{j@8guj3K6E z1zd6@b1~@;`%`^ua2wO|Ru}GdT4!f>KQ2X9cW1I^J4B_vINgr4uCybZj@$R&18HEEP%sBHf(9j3$ZU42Q;jppgxma4wcA&g`tUJd=OC+F-_yRVv-jb6zq675lJgZc4_I0PXwHLPLt+a(m0A!@P6NQYW zV8Z1$QP|QLM;KQWQb36KlsZcaGOYBzRJt>nN%Zz}dn5}}Zg(_XO;KIQ<+Hg-0vR_yr2SU%@X_@COx~&f1dy0R>;E;9n>>$spZ=r2+5d88-`@mKvq`!W?b{(ypCihjxe7YeT0 zzog)FzmoKa6CPbO&m%$m6#2-{} zx)VwKQw3kC;ETn%gu1U*@VVj& z_*|pl&nWcVB*N|oUHDgm|EPk~7QYHVD*si1|GNr3@jos2TrR$*(R9Rz)-aVDUAQ<# zXn*g*rC#UNIOE8kbf%N|Vu4Hh@W4R-HiiCLg?`&?G*E~S=_L6K3taM%@;|KLsvVwI z_|P{s$>)$lui9Zu!Bu~0;!7mSqw-+_pOi=B)t@W$bT^mt{+oi+8BOB;A*^`s(>#P=XK(*%D+;-aWFGOJx!vegOz|C9H%N+M3U6p|VaP&BnrGTYmWtArN9|6-{S z{-RmVZxf=ut*;R3&t>~lIcpcj5aU!2?xl45`hO__a3NQSZFG`nv#4zs@hUrn+hmiU zX(`m3ClOJ($axYguEb+X;h0F1?T@%Wtd^d~nu4%NA_@HLE_y$~UQ;esaqLykpJfj5obLt`ImG7I; zCF@gEIP;6~Dn@lTZ2}k_ecbZbi}7(9q!j5t3DI|M;^`hgAjUu9a*TVtg|XAc&k+g? zlqZD16hE}(%kh*usZ2LF;Q?_$Y!v4@3J2PM-Q($aFokAR^6VJ2o TbCK}Az4Z=B(Roci-Q)ikvLk1R literal 0 HcmV?d00001 diff --git a/suckless/dmenu/stest b/suckless/dmenu/stest new file mode 100755 index 0000000000000000000000000000000000000000..344348c8b4475cfa76e784684ed48abf70241fb0 GIT binary patch literal 16288 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