From b167600056f786e7e751fa7bbcceb124c963228e Mon Sep 17 00:00:00 2001 From: vali Date: Fri, 12 Apr 2024 21:36:26 +0200 Subject: [PATCH 01/27] schizofox fix --- hosts/vali/mars/programs.nix | 1 + modules/gui/schizofox.nix | 3 +++ 2 files changed, 4 insertions(+) diff --git a/hosts/vali/mars/programs.nix b/hosts/vali/mars/programs.nix index 1f84cdd..ecb8ccf 100644 --- a/hosts/vali/mars/programs.nix +++ b/hosts/vali/mars/programs.nix @@ -50,6 +50,7 @@ in { python3 qbittorrent rustdesk + rofi scc sherlock signal-desktop-beta diff --git a/modules/gui/schizofox.nix b/modules/gui/schizofox.nix index 561d668..223fd78 100644 --- a/modules/gui/schizofox.nix +++ b/modules/gui/schizofox.nix @@ -24,6 +24,9 @@ in { } ''; }; + Preferences = { + "ui.key.menuAccessKeyFocuses" = false; + }; extensions = { simplefox.enable = false; darkreader.enable = true; From df6ab58cae627fb09a6ee44cb63f9510f2864d8f Mon Sep 17 00:00:00 2001 From: vali Date: Fri, 12 Apr 2024 21:39:04 +0200 Subject: [PATCH 02/27] schizo fix --- modules/gui/schizofox.nix | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/modules/gui/schizofox.nix b/modules/gui/schizofox.nix index 223fd78..ae62d78 100644 --- a/modules/gui/schizofox.nix +++ b/modules/gui/schizofox.nix @@ -21,12 +21,10 @@ in { extraUserChrome = '' body { color: red !important; + ui.key.menuAccessKeyFocuses = false; } ''; }; - Preferences = { - "ui.key.menuAccessKeyFocuses" = false; - }; extensions = { simplefox.enable = false; darkreader.enable = true; From e7adb26de45969269b5cb8e72b46e7c39958ed07 Mon Sep 17 00:00:00 2001 From: vali Date: Fri, 12 Apr 2024 22:58:01 +0200 Subject: [PATCH 03/27] changed i3 stuff --- hosts/vali/mars/configuration.nix | 16 +++ hosts/vali/mars/i3/config | 190 ++++++++++++++++++++++++++++++ hosts/vali/mars/i3/default.nix | 6 + hosts/vali/mars/{ => i3}/i3.nix | 5 +- hosts/vali/mars/i3/polybar.sh | 0 hosts/vali/mars/profile.nix | 4 +- hosts/vali/mars/programs.nix | 1 + modules/gui/schizofox.nix | 134 ++++++++++----------- 8 files changed, 275 insertions(+), 81 deletions(-) create mode 100644 hosts/vali/mars/i3/config create mode 100644 hosts/vali/mars/i3/default.nix rename hosts/vali/mars/{ => i3}/i3.nix (71%) create mode 100644 hosts/vali/mars/i3/polybar.sh diff --git a/hosts/vali/mars/configuration.nix b/hosts/vali/mars/configuration.nix index 3f0b0c6..88b9672 100644 --- a/hosts/vali/mars/configuration.nix +++ b/hosts/vali/mars/configuration.nix @@ -2,7 +2,23 @@ { nixpkgs.config.allowUnfree = true; time.timeZone = "Europe/Zurich"; + # Select internationalisation properties. + i18n.defaultLocale = "en_US.UTF-8"; console.keyMap = "de"; + # enable flakes + nix.settings.experimental-features = [ "nix-command" "flakes" ]; + + # reduce file size used & automatic garbage collector + nix.settings.auto-optimise-store = true; + nix.gc = { + automatic = true; + options = "--delete-older-than 14d"; + }; + # required for nix-direnv to work and have environments not garbage collected + nix.extraOptions = '' + keep-outputs = true + keep-derivations = true + ''; security.sudo.package = pkgs.sudo.override { withInsults = true; }; security.polkit.enable = true; programs.kdeconnect.enable = true; diff --git a/hosts/vali/mars/i3/config b/hosts/vali/mars/i3/config new file mode 100644 index 0000000..1fb81fd --- /dev/null +++ b/hosts/vali/mars/i3/config @@ -0,0 +1,190 @@ +# This file has been auto-generated by i3-config-wizard(1). +# It will not be overwritten, so edit it as you like. +# +# Should you change your keyboard layout some time, delete +# this file and re-run i3-config-wizard(1). +# + +# i3 config file (v4) +# +# Please see https://i3wm.org/docs/userguide.html for a complete reference! + +set $mod Mod4 + +# Font for window titles. Will also be used by the bar unless a different font +# is used in the bar {} block below. +font pango:monospace 12 + +# This font is widely installed, provides lots of unicode glyphs, right-to-left +# text rendering and scalability on retina/hidpi displays (thanks to pango). +#font pango:DejaVu Sans Mono 8 + +# Start XDG autostart .desktop files using dex. See also +# https://wiki.archlinux.org/index.php/XDG_Autostart +exec --no-startup-id dex --autostart --environment i3 + +# The combination of xss-lock, nm-applet and pactl is a popular choice, so +# they are included here as an example. Modify as you see fit. + +# xss-lock grabs a logind suspend inhibit lock and will use i3lock to lock the +# screen before suspend. Use loginctl lock-session to lock your screen. +exec --no-startup-id xss-lock --transfer-sleep-lock -- i3lock --nofork + +# NetworkManager is the most popular way to manage wireless networks on Linux, +# and nm-applet is a desktop environment-independent system tray GUI for it. +exec --no-startup-id nm-applet + +# Use pactl to adjust volume in PulseAudio. +set $refresh_i3status killall -SIGUSR1 i3status +bindsym XF86AudioRaiseVolume exec --no-startup-id pactl set-sink-volume @DEFAULT_SINK@ +10% && $refresh_i3status +bindsym XF86AudioLowerVolume exec --no-startup-id pactl set-sink-volume @DEFAULT_SINK@ -10% && $refresh_i3status +bindsym XF86AudioMute exec --no-startup-id pactl set-sink-mute @DEFAULT_SINK@ toggle && $refresh_i3status +bindsym XF86AudioMicMute exec --no-startup-id pactl set-source-mute @DEFAULT_SOURCE@ toggle && $refresh_i3status + +# Use Mouse+$mod to drag floating windows to their wanted position +floating_modifier $mod + +# move tiling windows via drag & drop by left-clicking into the title bar, +# or left-clicking anywhere into the window while holding the floating modifier. +tiling_drag modifier titlebar + +# start a terminal +bindsym $mod+Return exec --no-startup-id alacritty + +# kill focused window +bindsym $mod+Shift+q kill + +# start dmenu (a program launcher) +bindsym $mod+d exec --no-startup-id dmenu_run +# A more modern dmenu replacement is rofi: +# There also is i3-dmenu-desktop which only displays applications shipping a +# .desktop file. It is a wrapper around dmenu, so you need that installed. +# bindcode $mod+40 exec --no-startup-id i3-dmenu-desktop + +# change focus +bindsym $mod+h focus left +bindsym $mod+j focus down +bindsym $mod+k focus up +bindsym $mod+l focus right + +# alternatively, you can use the cursor keys: +bindsym $mod+Left focus left +bindsym $mod+Down focus down +bindsym $mod+Up focus up +bindsym $mod+Right focus right + +# move focused window +bindsym $mod+Shift+h move left +bindsym $mod+Shift+j move down +bindsym $mod+Shift+k move up +bindsym $mod+Shift+l move right + +# alternatively, you can use the cursor keys: +bindsym $mod+Shift+Left move left +bindsym $mod+Shift+Down move down +bindsym $mod+Shift+Up move up +bindsym $mod+Shift+Right move right + +# split in horizontal orientation +bindsym $mod+x split h + +# split in vertical orientation +bindsym $mod+y split v + +# enter fullscreen mode for the focused container +bindsym $mod+f fullscreen toggle + +# change container layout (stacked, tabbed, toggle split) +bindsym $mod+w layout tabbed +bindsym $mod+s layout splith + +# toggle tiling / floating +bindsym $mod+Shift+space floating toggle + +# change focus between tiling / floating windows +bindsym $mod+space focus mode_toggle + +# focus the parent container +bindsym $mod+a focus parent + +# focus the child container +#bindsym $mod+d focus child +default_border pixel 3 +#smart_borders on +#hide_edge_borders smart_no_gaps +# Define names for default workspaces for which we configure key bindings later on. +# We use variables to avoid repeating the names in multiple places. +set $ws1 "1" +set $ws2 "2" +set $ws3 "3" +set $ws4 "4" +set $ws5 "5" +set $ws6 "6" +set $ws7 "7" +set $ws8 "8" +set $ws9 "9" +set $ws10 "10" + +# switch to workspace +bindsym $mod+1 workspace number $ws1 +bindsym $mod+2 workspace number $ws2 +bindsym $mod+3 workspace number $ws3 +bindsym $mod+4 workspace number $ws4 +bindsym $mod+5 workspace number $ws5 +bindsym $mod+6 workspace number $ws6 +bindsym $mod+7 workspace number $ws7 +bindsym $mod+8 workspace number $ws8 +bindsym $mod+9 workspace number $ws9 +bindsym $mod+0 workspace number $ws10 + +# move focused container to workspace +bindsym $mod+Shift+1 move container to workspace number $ws1 +bindsym $mod+Shift+2 move container to workspace number $ws2 +bindsym $mod+Shift+3 move container to workspace number $ws3 +bindsym $mod+Shift+4 move container to workspace number $ws4 +bindsym $mod+Shift+5 move container to workspace number $ws5 +bindsym $mod+Shift+6 move container to workspace number $ws6 +bindsym $mod+Shift+7 move container to workspace number $ws7 +bindsym $mod+Shift+8 move container to workspace number $ws8 +bindsym $mod+Shift+9 move container to workspace number $ws9 +bindsym $mod+Shift+0 move container to workspace number $ws10 + +# reload the configuration file +bindsym $mod+Shift+c reload +# restart i3 inplace (preserves your layout/session, can be used to upgrade i3) +bindsym $mod+Shift+r restart +# exit i3 (logs you out of your X session) +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' 'xfce-session-logout'" + +# resize window (you can also use the mouse for that) +mode "resize" { + # These bindings trigger as soon as you enter the resize mode + + # Pressing left will shrink the window’s width. + # Pressing right will grow the window’s width. + # Pressing up will shrink the window’s height. + # Pressing down will grow the window’s height. + bindsym l resize shrink width 10 px or 10 ppt + bindsym k resize grow height 10 px or 10 ppt + bindsym j resize shrink height 10 px or 10 ppt + bindsym h resize grow width 10 px or 10 ppt + + # same bindings, but for the arrow keys + bindsym Left resize shrink width 10 px or 10 ppt + bindsym Down resize grow height 10 px or 10 ppt + bindsym Up resize shrink height 10 px or 10 ppt + bindsym Right resize grow width 10 px or 10 ppt + + # back to normal: Enter or Escape or $mod+r + bindsym Return mode "default" + bindsym Escape mode "default" + bindsym $mod+r mode "default" +} + +bindsym $mod+r mode "resize" + +# Start i3bar to display a workspace bar (plus the system information i3status +# finds out, if available) +bar { + status_command i3status +} diff --git a/hosts/vali/mars/i3/default.nix b/hosts/vali/mars/i3/default.nix new file mode 100644 index 0000000..98a8265 --- /dev/null +++ b/hosts/vali/mars/i3/default.nix @@ -0,0 +1,6 @@ +_: { + imports = [ + ./i3.nix + ]; + home.file.".config/i3(config)".source = ./config; +} diff --git a/hosts/vali/mars/i3.nix b/hosts/vali/mars/i3/i3.nix similarity index 71% rename from hosts/vali/mars/i3.nix rename to hosts/vali/mars/i3/i3.nix index 3dc1dcb..0b371a0 100644 --- a/hosts/vali/mars/i3.nix +++ b/hosts/vali/mars/i3/i3.nix @@ -15,10 +15,7 @@ in { gdm.enable = true; defaultSession = "none+i3"; setupCommands = '' - LEFT='DP-2' - CENTER='HDMI-1' - RIGHT='HDMI-0' - ${pkgs.xorg.xrandr}/bin/xrandr --output $CENTER --rotate left --output $LEFT --rotate left --left-of $CENTER --output $RIGHT --right-of $CENTER + xrandr --output HDMI-1 --rotate normal --output DP-2 --rotate normal --left-of HDMI-1 --output HDMI-0 --right-of HDMI-1 ''; # ❯ xrandr --output HDMI-1 --rotate normal --output DP-2 --rotate normal --left-of HDMI-1 --output HDMI-0 --right-of HDMI-1 }; diff --git a/hosts/vali/mars/i3/polybar.sh b/hosts/vali/mars/i3/polybar.sh new file mode 100644 index 0000000..e69de29 diff --git a/hosts/vali/mars/profile.nix b/hosts/vali/mars/profile.nix index ded3887..26bce2e 100644 --- a/hosts/vali/mars/profile.nix +++ b/hosts/vali/mars/profile.nix @@ -5,8 +5,8 @@ _: { ../../../options/common/networking.nix ../../../options/common/gpu/nvidia.nix # ../../../overlay.nix -# ../../options/common/pin-registry.nix -# ../../options/common/preserve-system.nix + ../../../options/common/pin-registry.nix + ../../../options/common/preserve-system.nix #../../options/ ]; } diff --git a/hosts/vali/mars/programs.nix b/hosts/vali/mars/programs.nix index ecb8ccf..c05b2a8 100644 --- a/hosts/vali/mars/programs.nix +++ b/hosts/vali/mars/programs.nix @@ -27,6 +27,7 @@ in { "rustfmt" ]) ffmpeg_6-full + flameshot foot gcc gdb diff --git a/modules/gui/schizofox.nix b/modules/gui/schizofox.nix index ae62d78..fdd01e6 100644 --- a/modules/gui/schizofox.nix +++ b/modules/gui/schizofox.nix @@ -1,5 +1,9 @@ -{ config, inputs, lib, ... }: -with lib; let +{ + config, + inputs, + lib, + ... +}: with lib; let cfg = config.myOptions.programs.schizofox; username = config.myOptions.other.system.username; in { @@ -10,91 +14,71 @@ in { config = mkIf cfg.enable { home-manager.users.${username} = { imports = [ inputs.schizofox.homeManagerModule ]; - programs.schizofox = { enable = true; + theme = { - colors.background-darker = "181825"; - colors.background = "1e1e2e"; - colors.foreground = "cdd6f4"; - font = "Lexend"; - extraUserChrome = '' - body { - color: red !important; - ui.key.menuAccessKeyFocuses = false; - } - ''; - }; - extensions = { - simplefox.enable = false; - darkreader.enable = true; + colors = { + background-darker = "181825"; + background = "1e1e2e"; + foreground = "cdd6f4"; + }; + + font = "Lexend"; + + extraUserChrome = '' + body { + color: red !important; + } + ''; }; + search = { - defaultSearchEngine = "Brave"; - removeEngines = ["Google" "Bing" "Amazon.com" "eBay" "Twitter" "Wikipedia"]; - addEngines = [ - { - Name = "NixOS Packages"; - Description = "NixOS Unstable package search"; - Alias = "!np"; - Method = "GET"; - URLTemplate = "https://search.nixos.org/packages?channel=unstable&query={searchTerms}"; - } - { - Name = "NixOS Options"; - Description = "NixOS Unstable option search"; - Alias = "!no"; - Method = "GET"; - URLTemplate = "https://search.nixos.org/options?channel=unstable&query={searchTerms}"; - } - { - Name = "NixOS Wiki"; - Description = "NixOS Wiki search"; - Alias = "!nw"; - Method = "GET"; - URLTemplate = "https://nixos.wiki/index.php?search={searchTerms}"; - } - { - Name = "Home Manager Options"; - Description = "Home Manager option search"; - Alias = "!hm"; - Method = "GET"; - URLTemplate = "https://mipmip.github.io/home-manager-option-search?query={searchTerms}"; - } - { - Name = "Arch Wiki"; - Description = "Arch Wiki search"; - Alias = "!aw"; - Method = "GET"; - URLTemplate = "https://wiki.archlinux.org/index.php?search={searchTerms}"; - } - { - Name = "Gentoo Wiki"; - Description = "Gentoo Wiki search"; - Alias = "!gw"; - Method = "GET"; - URLTemplate = "https://wiki.gentoo.org/index.php?search={searchTerms}"; - } - { - Name = "Debian Wiki"; - Description = "Debian Wiki search"; - Alias = "!dw"; - Method = "GET"; - URLTemplate = "https://wiki.debian.org/FrontPage?action=fullsearch&value={searchTerms}"; - } - ]; + defaultSearchEngine = "Brave"; + removeEngines = ["Google" "Bing" "Amazon.com" "eBay" "Twitter" "Wikipedia"]; + searxUrl = "https://searx.be"; + searxQuery = "https://searx.be/search?q={searchTerms}&categories=general"; + addEngines = [ + { + Name = "Etherscan"; + Description = "Checking balances"; + Alias = "!eth"; + Method = "GET"; + URLTemplate = "https://etherscan.io/search?f=0&q={searchTerms}"; + } + ]; }; security = { - sanitizeOnShutdown = true; - sandbox = true; - userAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:106.0) Gecko/20100101 Firefox/106.0"; + sanitizeOnShutdown = false; + sandbox = true; + userAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:106.0) Gecko/20100101 Firefox/106.0"; }; misc = { - drmFix = false; - disableWebgl = true; + drmFix = true; + disableWebgl = false; + startPageURL = "https://startpage.com"; }; + + extensions = { + simplefox.enable = true; + darkreader.enable = true; + + extraExtensions = { + "webextension@metamask.io".install_url = "https://addons.mozilla.org/firefox/downloads/latest/ether-metamask/latest.xpi"; + }; + }; + + bookmarks = [ + { + Title = "Example"; + URL = "https://example.com"; + Favicon = "https://example.com/favicon.ico"; + Placement = "toolbar"; + Folder = "FolderName"; + } + ]; }; }; }; From 4bf051f7ddf8ffb150a28ef8ea443a0dfcde1ec7 Mon Sep 17 00:00:00 2001 From: vali Date: Sat, 13 Apr 2024 00:15:21 +0200 Subject: [PATCH 04/27] added ncmpcpp --- hosts/vali/mars/configuration.nix | 11 + hosts/vali/mars/default.nix | 2 +- hosts/vali/mars/i3/config | 10 +- hosts/vali/mars/i3/default.nix | 1 - hosts/vali/mars/i3/i3.nix | 6 +- hosts/vali/mars/programs.nix | 16 +- modules/tui/config | 598 ++++++++++++++++++++++++++++++ modules/tui/ncmpcpp.nix | 18 + 8 files changed, 641 insertions(+), 21 deletions(-) create mode 100644 modules/tui/config create mode 100644 modules/tui/ncmpcpp.nix diff --git a/hosts/vali/mars/configuration.nix b/hosts/vali/mars/configuration.nix index 88b9672..b48f6a7 100644 --- a/hosts/vali/mars/configuration.nix +++ b/hosts/vali/mars/configuration.nix @@ -22,6 +22,17 @@ security.sudo.package = pkgs.sudo.override { withInsults = true; }; security.polkit.enable = true; programs.kdeconnect.enable = true; + services.mpd = { + enable = true; + musicDirectory = "/home/vali/Nextcloud/Media/Music/"; + startWhenNeeded = true; + extraConfig = '' + audio_output { + type "pipewire" + name "My PipeWire Output" + } + ''; + }; myOptions = { other = { system = { diff --git a/hosts/vali/mars/default.nix b/hosts/vali/mars/default.nix index 1549554..edd28ce 100644 --- a/hosts/vali/mars/default.nix +++ b/hosts/vali/mars/default.nix @@ -4,7 +4,7 @@ _: { ./programs.nix ./hardware-configuration.nix ./profile.nix - ./i3.nix + ./i3 ./awesome.nix ./hypr/default.nix ]; diff --git a/hosts/vali/mars/i3/config b/hosts/vali/mars/i3/config index 1fb81fd..00e5016 100644 --- a/hosts/vali/mars/i3/config +++ b/hosts/vali/mars/i3/config @@ -22,7 +22,7 @@ font pango:monospace 12 # Start XDG autostart .desktop files using dex. See also # https://wiki.archlinux.org/index.php/XDG_Autostart exec --no-startup-id dex --autostart --environment i3 - +exec --no-startup-id xrandr --output HDMI-1 --rotate normal --output DP-2 --rotate normal --left-of HDMI-1 --output HDMI-0 --right-of HDMI-1 # The combination of xss-lock, nm-applet and pactl is a popular choice, so # they are included here as an example. Modify as you see fit. @@ -36,10 +36,10 @@ exec --no-startup-id nm-applet # Use pactl to adjust volume in PulseAudio. set $refresh_i3status killall -SIGUSR1 i3status -bindsym XF86AudioRaiseVolume exec --no-startup-id pactl set-sink-volume @DEFAULT_SINK@ +10% && $refresh_i3status -bindsym XF86AudioLowerVolume exec --no-startup-id pactl set-sink-volume @DEFAULT_SINK@ -10% && $refresh_i3status +bindsym 123 exec --no-startup-id wpctl set-volume -l 1.5 @DEFAULT_AUDIO_SINK@ 5%+ && $refresh_i3status +bindsym 122 exec --no-startup-id wpctl set-volume -l 1.5 @DEFAULT_AUDIO_SINK@ 5%+ && $refresh_i3status bindsym XF86AudioMute exec --no-startup-id pactl set-sink-mute @DEFAULT_SINK@ toggle && $refresh_i3status -bindsym XF86AudioMicMute exec --no-startup-id pactl set-source-mute @DEFAULT_SOURCE@ toggle && $refresh_i3status +bindsym 198 exec --no-startup-id pamixer --default-source -t && $refresh_i3status # Use Mouse+$mod to drag floating windows to their wanted position floating_modifier $mod @@ -111,7 +111,7 @@ bindsym $mod+a focus parent #bindsym $mod+d focus child default_border pixel 3 #smart_borders on -#hide_edge_borders smart_no_gaps +hide_edge_borders smart_no_gaps # Define names for default workspaces for which we configure key bindings later on. # We use variables to avoid repeating the names in multiple places. set $ws1 "1" diff --git a/hosts/vali/mars/i3/default.nix b/hosts/vali/mars/i3/default.nix index 98a8265..2983f9e 100644 --- a/hosts/vali/mars/i3/default.nix +++ b/hosts/vali/mars/i3/default.nix @@ -2,5 +2,4 @@ _: { imports = [ ./i3.nix ]; - home.file.".config/i3(config)".source = ./config; } diff --git a/hosts/vali/mars/i3/i3.nix b/hosts/vali/mars/i3/i3.nix index 0b371a0..378bf2f 100644 --- a/hosts/vali/mars/i3/i3.nix +++ b/hosts/vali/mars/i3/i3.nix @@ -1,10 +1,12 @@ { pkgs, lib, config, callPackage, ... }: with lib; let cfg = config.myOptions.programs.i3; + username = config.myOptions.other.system.username; in { options.myOptions.programs.i3.enable = mkEnableOption "i3"; config = mkIf cfg.enable { + home-manager.users.${username}.xdg.configFile."i3/config".source = ./config; services.xserver = { enable = true; xkb.layout = "de"; @@ -14,10 +16,6 @@ in { displayManager = { gdm.enable = true; defaultSession = "none+i3"; - setupCommands = '' - xrandr --output HDMI-1 --rotate normal --output DP-2 --rotate normal --left-of HDMI-1 --output HDMI-0 --right-of HDMI-1 - ''; -# ❯ xrandr --output HDMI-1 --rotate normal --output DP-2 --rotate normal --left-of HDMI-1 --output HDMI-0 --right-of HDMI-1 }; }; }; diff --git a/hosts/vali/mars/programs.nix b/hosts/vali/mars/programs.nix index c05b2a8..2785645 100644 --- a/hosts/vali/mars/programs.nix +++ b/hosts/vali/mars/programs.nix @@ -1,23 +1,17 @@ { config, inputs, pkgs, ... }: let - username = config.myOptions.other.system.username; + fenix = inputs.fenix.packages.${pkgs.system}; in { - home-manager.users.${username} = { - home.packages = let - fenix = inputs.fenix.packages.${pkgs.system}; - - in with pkgs; [ + environment.systemPackages = with pkgs; [ alacritty alsa-utils asciinema betterbird bibata-cursors - chromium dig easyeffects element-desktop eza - ripgrep fastfetch (fenix.complete.withComponents [ "cargo" @@ -39,6 +33,7 @@ in { krita lazygit libreoffice-fresh + ncmpcpp neofetch neovim networkmanagerapplet @@ -47,18 +42,20 @@ in { pavucontrol pcmanfm pfetch + playerctl polkit python3 qbittorrent + ripgrep rustdesk rofi scc sherlock signal-desktop-beta smartmontools + spotube st steam - strawberry-qt6 telegram-desktop texliveFull thunderbird @@ -74,5 +71,4 @@ in { zathura zip ]; - }; } diff --git a/modules/tui/config b/modules/tui/config new file mode 100644 index 0000000..88893cf --- /dev/null +++ b/modules/tui/config @@ -0,0 +1,598 @@ +############################################################## +## This is an example configuration file. Copy it to ## +## $XDG_CONFIG_HOME/ncmpcpp/config or $HOME/.ncmpcpp/config ## +## and set up your preferences. ## +############################################################## +# +##### directories ###### +## +## Directory for storing ncmpcpp related files. Changing it is useful if you +## want to store everything somewhere else and provide command line setting for +## alternative location to config file which defines that while launching +## ncmpcpp. +## +# +#ncmpcpp_directory = ~/.config/ncmpcpp +# +## +## Directory for storing downloaded lyrics. It defaults to ~/.lyrics since other +## MPD clients (eg. ncmpc) also use that location. +## +# +#lyrics_directory = ~/.lyrics +# +##### connection settings ##### +# +#mpd_host = localhost +# +#mpd_port = 6600 +# +#mpd_connection_timeout = 5 +# +## Needed for tag editor and file operations to work. +## +#mpd_music_dir = ~/music +# +#mpd_crossfade_time = 5 +# +# Exclude pattern for random song action +# http://www.boost.org/doc/libs/1_46_1/libs/regex/doc/html/boost_regex/syntax/perl_syntax.html +#random_exclude_pattern = "^(temp|midi_songs).*" +# +##### music visualizer ##### +## +## In order to make music visualizer work with MPD you need to use the fifo +## output. Its format parameter has to be set to 44100:16:1 for mono +## visualization or 44100:16:2 for stereo visualization. As an example here is +## the relevant section for mpd.conf: +## +## audio_output { +## type "fifo" +## name "Visualizer feed" +## path "/tmp/mpd.fifo" +## format "44100:16:2" +## } +## +## If the visualization on occasion diverges from the audio output, please set +## 'buffer_time' parameter of your audio output in mpd.conf to '100000' (100ms) +## or less to prevent that from happening. +## +## Note: If you're using Mopidy, an address of a udpsink gstreamer's output is +## also accepted. For example, the following section in mopidy.conf: +## +## [audio] +## output = tee name=t ! queue ! autoaudiosink t. +## ! queue ! audio/x-raw,rate=44100,channels=2,format=S16LE +## ! udpsink host=localhost port=5555 +## +## will make localhost:5555 available as a source of data for the stereo +## visualizer. +## +# +#visualizer_data_source = /tmp/mpd.fifo +# +## +## Note: Below parameter is needed for ncmpcpp to determine which output +## provides data for visualizer and reset it at the beginning of visualization +## to synchronize with audio. +## +# +#visualizer_output_name = Visualizer feed +# +## +## If you set format to 44100:16:2, make it 'yes'. +## +#visualizer_in_stereo = yes +# +## +## Note: set below to >=10 only if you have synchronization issues with +## visualization and audio. +## +# +#visualizer_sync_interval = 0 +# +## +## Note: To enable spectrum frequency visualization you need to compile ncmpcpp +## with fftw3 support. +## +# +## Available values: spectrum, wave, wave_filled, ellipse. +## +#visualizer_type = spectrum +# +#visualizer_fps = 60 +# +#visualizer_autoscale = no +# +#visualizer_look = ●▮ +# +#visualizer_color = blue, cyan, green, yellow, magenta, red +# +## Alternative subset of 256 colors for terminals that support it. +## +#visualizer_color = 47, 83, 119, 155, 191, 227, 221, 215, 209, 203, 197, 161 +# +## +## Note: The next few visualization options apply to the spectrum visualizer. +## +# +## Use unicode block characters for a smoother, more continuous look. +## This will override the visualizer_look option. With transparent terminals +## and visualizer_in_stereo set, artifacts may be visible on the bottom half of +## the visualization. +# +#visualizer_spectrum_smooth_look = yes +# +## A value between 1 and 5 inclusive. Specifying a larger value makes the +## visualizer look at a larger slice of time, which results in less jumpy +## visualizer output. +# +#visualizer_spectrum_dft_size = 2 +# +#visualizer_spectrum_gain = 10 +# +## Left-most frequency of visualizer in Hz, must be less than HZ MAX +# +#visualizer_spectrum_hz_min = 20 +# +## Right-most frequency of visualizer in Hz, must be greater than HZ MIN +# +#visualizer_spectrum_hz_max = 20000 +# +##### system encoding ##### +## +## ncmpcpp should detect your charset encoding but if it failed to do so, you +## can specify charset encoding you are using here. +## +## Note: You can see whether your ncmpcpp build supports charset detection by +## checking output of `ncmpcpp --version`. +## +## Note: Since MPD uses UTF-8 by default, setting this option makes sense only +## if your encoding is different. +## +# +#system_encoding = "" +# +##### delays ##### +# +## Time of inactivity (in seconds) after playlist highlighting will be disabled +## (0 = always on). +## +#playlist_disable_highlight_delay = 5 +# +## Defines how long messages are supposed to be visible. +## +#message_delay_time = 5 +# +##### song format ##### +## +## For a song format you can use: +## +## %l - length +## %f - filename +## %D - directory +## %a - artist +## %A - album artist +## %t - title +## %b - album +## %y - date +## %n - track number (01/12 -> 01) +## %N - full track info (01/12 -> 01/12) +## %g - genre +## %c - composer +## %p - performer +## %d - disc +## %C - comment +## %P - priority +## $R - begin right alignment +## +## If you want to make sure that a part of the format is displayed only when +## certain tags are present, you can archieve it by grouping them with brackets, +## e.g. '{%a - %t}' will be evaluated to 'ARTIST - TITLE' if both tags are +## present or '' otherwise. It is also possible to define a list of +## alternatives by providing several groups and separating them with '|', +## e.g. '{%t}|{%f}' will be evaluated to 'TITLE' or 'FILENAME' if the former is +## not present. +## +## Note: If you want to set limit on maximal length of a tag, just put the +## appropriate number between % and character that defines tag type, e.g. to +## make album take max. 20 terminal cells, use '%20b'. +## +## In addition, formats support markers used for text attributes. They are +## followed by character '$'. After that you can put: +## +## - 0 - default window color (discards all other colors) +## - 1 - black +## - 2 - red +## - 3 - green +## - 4 - yellow +## - 5 - blue +## - 6 - magenta +## - 7 - cyan +## - 8 - white +## - 9 - end of current color +## - b - bold text +## - u - underline text +## - r - reverse colors +## - a - use alternative character set +## +## If you don't want to use a non-color attribute anymore, just put it again, +## but this time insert character '/' between '$' and attribute character, +## e.g. {$b%t$/b}|{$r%f$/r} will display bolded title tag or filename with +## reversed colors. +## +## If you want to use 256 colors and/or background colors in formats (the naming +## scheme is described below in section about color definitions), it can be done +## with the syntax $(COLOR), e.g. to set the artist tag to one of the +## non-standard colors and make it have yellow background, you need to write +## $(197_yellow)%a$(end). Note that for standard colors this is interchangable +## with attributes listed above. +## +## Note: colors can be nested. +## +# +#song_list_format = {%a - }{%t}|{$8%f$9}$R{$3%l$9} +# +#song_status_format = {{%a{ "%b"{ (%y)}} - }{%t}}|{%f} +# +#song_library_format = {%n - }{%t}|{%f} +# +#alternative_header_first_line_format = $b$1$aqqu$/a$9 {%t}|{%f} $1$atqq$/a$9$/b +# +#alternative_header_second_line_format = {{$4$b%a$/b$9}{ - $7%b$9}{ ($4%y$9)}}|{%D} +# +#current_item_prefix = $(yellow)$r +# +#current_item_suffix = $/r$(end) +# +#current_item_inactive_column_prefix = $(white)$r +# +#current_item_inactive_column_suffix = $/r$(end) +# +#now_playing_prefix = $b +# +#now_playing_suffix = $/b +# +#browser_playlist_prefix = "$2playlist$9 " +# +#selected_item_prefix = $6 +# +#selected_item_suffix = $9 +# +#modified_item_prefix = $3> $9 +# +## +## Note: attributes are not supported for the following variables. +## +#song_window_title_format = {%a - }{%t}|{%f} +## +## Note: Below variables are used for sorting songs in browser. The sort mode +## determines how songs are sorted, and can be used in combination with a sort +## format to specify a custom sorting format. Available values for +## browser_sort_mode are "type", "name", "mtime", "format" and "none". +## +# +#browser_sort_mode = type +# +#browser_sort_format = {%a - }{%t}|{%f} {%l} +# +##### columns settings ##### +## +## syntax of song columns list format is "column column etc." +## +## - syntax for each column is: +## +## (width of the column)[color of the column]{displayed tag} +## +## Note: Width is by default in %, if you want a column to have fixed size, add +## 'f' after the value, e.g. (10)[white]{a} will be the column that take 10% of +## screen (so the real width will depend on actual screen size), whereas +## (10f)[white]{a} will take 10 terminal cells, no matter how wide the screen +## is. +## +## - color is optional (if you want the default one, leave the field empty). +## +## Note: You can give a column additional attributes by putting appropriate +## character after displayed tag character. Available attributes are: +## +## - r - column will be right aligned +## - E - if tag is empty, empty tag marker won't be displayed +## +## You can also: +## +## - give a column custom name by putting it after attributes, separated with +## character ':', e.g. {lr:Length} gives you right aligned column of lengths +## named "Length". +## +## - define sequence of tags, that have to be displayed in case predecessor is +## empty in a way similar to the one in classic song format, i.e. using '|' +## character, e.g. {a|c|p:Owner} creates column named "Owner" that tries to +## display artist tag and then composer and performer if previous ones are not +## available. +## +# +#song_columns_list_format = (20)[]{a} (6f)[green]{NE} (50)[white]{t|f:Title} (20)[cyan]{b} (7f)[magenta]{l} +# +##### various settings ##### +# +## +## Note: Custom command that will be executed each time song changes. Useful for +## notifications etc. +## +#execute_on_song_change = "" +# +## +## Note: Custom command that will be executed each time player state +## changes. The environment variable MPD_PLAYER_STATE is set to the current +## state (either unknown, play, pause, or stop) for its duration. +## +# +#execute_on_player_state_change = "" +# +#playlist_show_mpd_host = no +# +#playlist_show_remaining_time = no +# +#playlist_shorten_total_times = no +# +#playlist_separate_albums = no +# +## +## Note: Possible display modes: classic, columns. +## +#playlist_display_mode = columns +# +#browser_display_mode = classic +# +#search_engine_display_mode = classic +# +#playlist_editor_display_mode = classic +# +#discard_colors_if_item_is_selected = yes +# +#show_duplicate_tags = yes +# +#incremental_seeking = yes +# +#seek_time = 1 +# +#volume_change_step = 2 +# +#autocenter_mode = no +# +#centered_cursor = no +# +## +## Note: You can specify third character which will be used to build 'empty' +## part of progressbar. +## +#progressbar_look = => +# +## Available values: database, playlist. +## +#default_place_to_search_in = database +# +## Available values: classic, alternative. +## +#user_interface = classic +# +#data_fetching_delay = yes +# +## Available values: artist, album_artist, date, genre, composer, performer. +## +#media_library_primary_tag = artist +# +#media_library_albums_split_by_date = yes +# +#media_library_hide_album_dates = no +# +## Available values: wrapped, normal. +## +#default_find_mode = wrapped +# +#default_tag_editor_pattern = %n - %t +# +#header_visibility = yes +# +#statusbar_visibility = yes +# +## Show the "Connected to ..." message on startup +#connected_message_on_startup = yes +# +#titles_visibility = yes +# +#header_text_scrolling = yes +# +#cyclic_scrolling = no +# +#lyrics_fetchers = azlyrics, genius, musixmatch, sing365, metrolyrics, justsomelyrics, jahlyrics, plyrics, tekstowo, zeneszoveg, internet +# +#follow_now_playing_lyrics = no +# +#fetch_lyrics_for_current_song_in_background = no +# +#store_lyrics_in_song_dir = no +# +#generate_win32_compatible_filenames = yes +# +#allow_for_physical_item_deletion = no +# +## +## Note: If you set this variable, ncmpcpp will try to get info from last.fm in +## language you set and if it fails, it will fall back to english. Otherwise it +## will use english the first time. +## +## Note: Language has to be expressed as an ISO 639 alpha-2 code. +## +#lastfm_preferred_language = en +# +#space_add_mode = add_remove +# +#show_hidden_files_in_local_browser = no +# +## +## How shall screen switcher work? +## +## - "previous" - switch between the current and previous screen. +## - "screen1,...,screenN" - switch between given sequence of screens. +## +## Screens available for use: help, playlist, browser, search_engine, +## media_library, playlist_editor, tag_editor, outputs, visualizer, clock, +## lyrics, last_fm. +## +#screen_switcher_mode = playlist, browser +# +## +## Note: You can define startup screen by choosing screen from the list above. +## +#startup_screen = playlist +# +## +## Note: You can define startup slave screen by choosing screen from the list +## above or an empty value for no slave screen. +## +#startup_slave_screen = "" +# +#startup_slave_screen_focus = no +# +## +## Default width of locked screen (in %). Acceptable values are from 20 to 80. +## +# +#locked_screen_width_part = 50 +# +#ask_for_locked_screen_width_part = yes +# +#jump_to_now_playing_song_at_start = yes +# +#ask_before_clearing_playlists = yes +# +#clock_display_seconds = no +# +#display_volume_level = yes +# +#display_bitrate = no +# +#display_remaining_time = no +# +## Available values: none, basic, extended, perl. +## +#regular_expressions = perl +# +## +## Note: if below is enabled, ncmpcpp will ignore leading "The" word while +## sorting items in browser, tags in media library, etc. +## +#ignore_leading_the = no +# +## +## Note: if below is enabled, ncmpcpp will ignore diacritics while searching and +## filtering lists. This takes an effect only if boost was compiled with ICU +## support. +## +#ignore_diacritics = no +# +#block_search_constraints_change_if_items_found = yes +# +#mouse_support = yes +# +#mouse_list_scroll_whole_page = no +# +#lines_scrolled = 5 +# +#empty_tag_marker = +# +#tags_separator = " | " +# +#tag_editor_extended_numeration = no +# +#media_library_sort_by_mtime = no +# +#enable_window_title = yes +# +## +## Note: You can choose default search mode for search engine. Available modes +## are: +## +## - 1 - use mpd built-in searching (no regexes, pattern matching) +## +## - 2 - use ncmpcpp searching (pattern matching with support for regexes, but +## if your mpd is on a remote machine, downloading big database to process +## it can take a while +## +## - 3 - match only exact values (this mode uses mpd function for searching in +## database and local one for searching in current playlist) +## +# +#search_engine_default_search_mode = 1 +# +#external_editor = nano +# +## Note: set to yes if external editor is a console application. +## +#use_console_editor = yes +# +##### colors definitions ##### +## +## It is possible to set a background color by setting a color value +## "_", e.g. red_black will set foregound color to red +## and background color to black. +## +## In addition, for terminals that support 256 colors it is possible to set one +## of them by using a number in range [1, 256] instead of color name, +## e.g. numerical value corresponding to red_black is 2_1. To find out if the +## terminal supports 256 colors, run ncmpcpp and check out the bottom of the +## help screen for list of available colors and their numerical values. +## +## What is more, there are two special values for the background color: +## "transparent" and "current". The first one explicitly sets the background to +## be transparent, while the second one allows you to preserve current +## background color and change only the foreground one. It's used implicitly +## when background color is not specified. +## +## Moreover, it is possible to attach format information to selected color +## variables by appending to their end a colon followed by one or more format +## flags, e.g. black:b or red:ur. The following variables support this syntax: +## visualizer_color, color1, color2, empty_tag_color, volume_color, +## state_line_color, state_flags_color, progressbar_color, +## progressbar_elapsed_color, player_state_color, statusbar_time_color, +## alternative_ui_separator_color. +## +## Note: due to technical limitations of older ncurses version, if 256 colors +## are used there is a possibility that you'll be able to use only colors with +## transparent background. +# +#colors_enabled = yes +# +#empty_tag_color = cyan +# +#header_window_color = default +# +#volume_color = default +# +#state_line_color = default +# +#state_flags_color = default:b +# +#main_window_color = yellow +# +#color1 = white +# +#color2 = green +# +#progressbar_color = black:b +# +#progressbar_elapsed_color = green:b +# +#statusbar_color = default +# +#statusbar_time_color = default:b +# +#player_state_color = default:b +# +#alternative_ui_separator_color = black:b +# +#window_border_color = green +# +#active_window_border = red +# diff --git a/modules/tui/ncmpcpp.nix b/modules/tui/ncmpcpp.nix new file mode 100644 index 0000000..1ee11e0 --- /dev/null +++ b/modules/tui/ncmpcpp.nix @@ -0,0 +1,18 @@ +{ config, lib, pkgs, ... }: +with lib; let + cfg = config.myOptions.programs.ncmpcpp + username = config.myOptions.other.system.username; +in { + options.myOptions.programs.ncmpcpp.enable = mkEnableOption "ncmpcpp"; + + config = mkIf cfg.enable { + home-manager.users.${username} = { + programs.ncmpcpp = { + enable = true; + mpdMusicDir = "/home/vali/Nextcloud/Media/Music"; + xdg.configFile."ncmpcpp/config".source = ./config; + }; + }; + }; + +} From a7a8304e04de05d5040c9021e5388dd5ea213a3a Mon Sep 17 00:00:00 2001 From: vali Date: Sat, 13 Apr 2024 00:56:24 +0200 Subject: [PATCH 05/27] enabled ncmpcpp --- hosts/vali/mars/configuration.nix | 2 ++ hosts/vali/mars/programs.nix | 1 + modules/gui/schizofox.nix | 17 ++++++++++++----- modules/tui/config | 28 ++++++++++++++-------------- modules/tui/default.nix | 1 + modules/tui/ncmpcpp.nix | 4 ++-- 6 files changed, 32 insertions(+), 21 deletions(-) diff --git a/hosts/vali/mars/configuration.nix b/hosts/vali/mars/configuration.nix index b48f6a7..b03723d 100644 --- a/hosts/vali/mars/configuration.nix +++ b/hosts/vali/mars/configuration.nix @@ -1,6 +1,7 @@ { config, inputs, pkgs, ... }: { nixpkgs.config.allowUnfree = true; + # Time Zone time.timeZone = "Europe/Zurich"; # Select internationalisation properties. i18n.defaultLocale = "en_US.UTF-8"; @@ -47,6 +48,7 @@ }; programs = { vesktop.enable = true; + ncmpcpp.enable = true; ssh.enable = true; btop.enable = true; mpv.enable = true; diff --git a/hosts/vali/mars/programs.nix b/hosts/vali/mars/programs.nix index 2785645..0aed28e 100644 --- a/hosts/vali/mars/programs.nix +++ b/hosts/vali/mars/programs.nix @@ -33,6 +33,7 @@ in { krita lazygit libreoffice-fresh + moc ncmpcpp neofetch neovim diff --git a/modules/gui/schizofox.nix b/modules/gui/schizofox.nix index fdd01e6..9591915 100644 --- a/modules/gui/schizofox.nix +++ b/modules/gui/schizofox.nix @@ -40,12 +40,20 @@ in { searxQuery = "https://searx.be/search?q={searchTerms}&categories=general"; addEngines = [ { - Name = "Etherscan"; - Description = "Checking balances"; - Alias = "!eth"; + Name = "NixOS Packages"; + Description = "NixOS Unstable package serach"; + Alias = "!np"; Method = "GET"; - URLTemplate = "https://etherscan.io/search?f=0&q={searchTerms}"; + URLTemplate = "https://search.nixos.org/packages?channel=unstable&query={searchTerms}"; } + { + Name = "Home Manager Options"; + Description = "Home Manager option search"; + Alias = "!hm"; + Method = "GET"; + URLTemplate = "https://mipmip.github.io/home-manager-option-search?query={searchTerms}"; + } + ]; }; @@ -58,7 +66,6 @@ in { misc = { drmFix = true; disableWebgl = false; - startPageURL = "https://startpage.com"; }; extensions = { diff --git a/modules/tui/config b/modules/tui/config index 88893cf..e62ec46 100644 --- a/modules/tui/config +++ b/modules/tui/config @@ -12,7 +12,7 @@ ## ncmpcpp. ## # -#ncmpcpp_directory = ~/.config/ncmpcpp +ncmpcpp_directory = ~/.config/ncmpcpp # ## ## Directory for storing downloaded lyrics. It defaults to ~/.lyrics since other @@ -25,13 +25,13 @@ # #mpd_host = localhost # -#mpd_port = 6600 +mpd_port = 6600 # -#mpd_connection_timeout = 5 +mpd_connection_timeout = 5 # ## Needed for tag editor and file operations to work. ## -#mpd_music_dir = ~/music +mpd_music_dir = ~/Nextcloud/Media/Music # #mpd_crossfade_time = 5 # @@ -69,7 +69,7 @@ ## visualizer. ## # -#visualizer_data_source = /tmp/mpd.fifo +visualizer_data_source = /tmp/mpd.fifo # ## ## Note: Below parameter is needed for ncmpcpp to determine which output @@ -77,19 +77,19 @@ ## to synchronize with audio. ## # -#visualizer_output_name = Visualizer feed +visualizer_output_name = Visualizer feed # ## ## If you set format to 44100:16:2, make it 'yes'. ## -#visualizer_in_stereo = yes +visualizer_in_stereo = yes # ## ## Note: set below to >=10 only if you have synchronization issues with ## visualization and audio. ## # -#visualizer_sync_interval = 0 +visualizer_sync_interval = 0 # ## ## Note: To enable spectrum frequency visualization you need to compile ncmpcpp @@ -98,15 +98,15 @@ # ## Available values: spectrum, wave, wave_filled, ellipse. ## -#visualizer_type = spectrum +visualizer_type = wave_filled # -#visualizer_fps = 60 +visualizer_fps = 60 # -#visualizer_autoscale = no +visualizer_autoscale = no # -#visualizer_look = ●▮ +visualizer_look = ●▮ # -#visualizer_color = blue, cyan, green, yellow, magenta, red +visualizer_color = blue, cyan, green, yellow, magenta, red # ## Alternative subset of 256 colors for terminals that support it. ## @@ -121,7 +121,7 @@ ## and visualizer_in_stereo set, artifacts may be visible on the bottom half of ## the visualization. # -#visualizer_spectrum_smooth_look = yes +visualizer_spectrum_smooth_look = yes # ## A value between 1 and 5 inclusive. Specifying a larger value makes the ## visualizer look at a larger slice of time, which results in less jumpy diff --git a/modules/tui/default.nix b/modules/tui/default.nix index e425429..8cf84cb 100644 --- a/modules/tui/default.nix +++ b/modules/tui/default.nix @@ -4,5 +4,6 @@ _: { # ./helix.nix ./neovim.nix # ./newsboat.nix + ./ncmpcpp.nix ]; } diff --git a/modules/tui/ncmpcpp.nix b/modules/tui/ncmpcpp.nix index 1ee11e0..2aaa6f7 100644 --- a/modules/tui/ncmpcpp.nix +++ b/modules/tui/ncmpcpp.nix @@ -1,16 +1,16 @@ { config, lib, pkgs, ... }: with lib; let - cfg = config.myOptions.programs.ncmpcpp + cfg = config.myOptions.programs.ncmpcpp; username = config.myOptions.other.system.username; in { options.myOptions.programs.ncmpcpp.enable = mkEnableOption "ncmpcpp"; config = mkIf cfg.enable { home-manager.users.${username} = { + xdg.configFile."ncmpcpp/config".source = ./config; programs.ncmpcpp = { enable = true; mpdMusicDir = "/home/vali/Nextcloud/Media/Music"; - xdg.configFile."ncmpcpp/config".source = ./config; }; }; }; From 7b8a6a4e234a54662db690342efe691bbf27c246 Mon Sep 17 00:00:00 2001 From: vali Date: Sat, 13 Apr 2024 13:03:32 +0200 Subject: [PATCH 06/27] not working, idk why, removed awesomewm and changed xdg stuff --- hosts/vali/mars/configuration.nix | 2 +- hosts/vali/mars/default.nix | 2 - hosts/vali/mars/i3/default.nix | 3 +- hosts/vali/mars/i3/i3-new.nix | 68 +++++++++++++++++++++++++++++++ hosts/vali/mars/programs.nix | 3 +- modules/gui/qt.nix | 4 +- modules/other/xdg.nix | 11 +++-- 7 files changed, 80 insertions(+), 13 deletions(-) create mode 100644 hosts/vali/mars/i3/i3-new.nix diff --git a/hosts/vali/mars/configuration.nix b/hosts/vali/mars/configuration.nix index b03723d..6cc8107 100644 --- a/hosts/vali/mars/configuration.nix +++ b/hosts/vali/mars/configuration.nix @@ -90,7 +90,7 @@ }; }; qt = { - enable = true; + enable = false; package = pkgs.catppuccin-kde; name = "Catppuccin-Mocha-Dark"; variant = "mocha"; diff --git a/hosts/vali/mars/default.nix b/hosts/vali/mars/default.nix index edd28ce..360094d 100644 --- a/hosts/vali/mars/default.nix +++ b/hosts/vali/mars/default.nix @@ -5,7 +5,5 @@ _: { ./hardware-configuration.nix ./profile.nix ./i3 - ./awesome.nix - ./hypr/default.nix ]; } diff --git a/hosts/vali/mars/i3/default.nix b/hosts/vali/mars/i3/default.nix index 2983f9e..f7480f7 100644 --- a/hosts/vali/mars/i3/default.nix +++ b/hosts/vali/mars/i3/default.nix @@ -1,5 +1,6 @@ _: { imports = [ - ./i3.nix + ./i3.nix + # ./i3-new.nix ]; } diff --git a/hosts/vali/mars/i3/i3-new.nix b/hosts/vali/mars/i3/i3-new.nix new file mode 100644 index 0000000..a720230 --- /dev/null +++ b/hosts/vali/mars/i3/i3-new.nix @@ -0,0 +1,68 @@ +{pkgs, lib, config, ... }: +with lib; let + cfg = config.myOptions.programs.i3; + username = config.myOptions.other.system.username; + mod = "Mod4"; +in { + options.myOptions.programs.i3.enable = mkEnableOption "i3"; + + config = mkIf cfg.enable { + services.xserver = { + enable = true; + xkb.layout = "de"; + }; + xsession.windowManager.i3 = { + enable = true; + config = { + modifier = mod; + terminal = "alacritty"; + fonts ={ + names = [ "JetBrains Mono" "pango:monospace"]; + size = 12; + style = "Bold Semi-Condensed"; + }; + keybindings = lib.mkOptionDefault { + # Run stuff + "${mod}+d" = "exec --no-startup-id ${pkgs.dmenu}/bin/dmenu_run"; + "${mod}+Return" = "exec --no-startup-id alacritty"; + "${mod}+Shift+q" = "kill"; + # Focus + "${mod}+h" = "focus left"; + "${mod}+j" = "focus down"; + "${mod}+k" = "focus up"; + "${mod}+l" = "focus right"; + # Move + "${mod}+Shift+h" = "move left"; + "${mod}+Shift+j" = "move down"; + "${mod}+Shift+k" = "move up"; + "${mod}+Shift+l" = "move right"; + "XF86RaiseVolume" = "wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%+ && $refresh_i3status"; + # Toggle stuff + "${mod}+f" = "fullscreen toggle"; + }; + window = { + titlebar = false; + border = 3; + hideEdgeBorders = true; + }; + floating = { + titlebar = false; + }; + bars = [ + { + position = "bottom"; + statusCommand = "${pkgs.i3status}/bin/i3status"; + } + ]; + startup ={ + command = + "xrandr --output HDMI-1 --rotate normal --output DP-2 --rotate normal --left-of HDMI-1 --output HDMI-0 --right-of HDMI-1"; + #"dex --autostart --environment i3"; + #"nm-applet"; + #"keepassxc"; + }; + }; + }; + }; +} + diff --git a/hosts/vali/mars/programs.nix b/hosts/vali/mars/programs.nix index 0aed28e..2afb568 100644 --- a/hosts/vali/mars/programs.nix +++ b/hosts/vali/mars/programs.nix @@ -6,7 +6,7 @@ in { alacritty alsa-utils asciinema - betterbird +# betterbird bibata-cursors dig easyeffects @@ -57,6 +57,7 @@ in { spotube st steam + strawberry telegram-desktop texliveFull thunderbird diff --git a/modules/gui/qt.nix b/modules/gui/qt.nix index a448f55..3509a3b 100644 --- a/modules/gui/qt.nix +++ b/modules/gui/qt.nix @@ -58,8 +58,8 @@ in { sessionVariables = { #QT_STYLE_OVERRIDE = "kvantum"; QT_AUTO_SCREEN_SCALE_FACTOR = "1"; - QT_QPA_PLATFORM = "wayland;xcb"; - QT_WAYLAND_DISABLE_WINDOWDECORATION = "1"; +# QT_QPA_PLATFORM = "wayland;xcb"; +# QT_WAYLAND_DISABLE_WINDOWDECORATION = "1"; DISABLE_QT_COMPAT = "0"; }; }; diff --git a/modules/other/xdg.nix b/modules/other/xdg.nix index c20b7b4..8ce0370 100644 --- a/modules/other/xdg.nix +++ b/modules/other/xdg.nix @@ -5,8 +5,7 @@ username = config.myOptions.other.system.username; hmCfg = config.home-manager.users.${username}; - primary_browser = "firefox-schizo.desktop"; - secondary_browser = "firefox-unschizo.desktop"; + primary_browser = "schizofox.desktop"; mail_client = "betterbird.desktop"; file_manager = "pcmanfm.desktop"; media_player = "mpv.desktop"; @@ -74,10 +73,10 @@ in { enable = true; defaultApplications = { "text/html" = [ primary_browser secondary_browser ]; - "x-scheme-handler/http" = [ primary_browser secondary_browser ]; - "x-scheme-handler/https" = [ primary_browser secondary_browser ]; - "x-scheme-handler/about" = [ primary_browser secondary_browser ]; - "x-scheme-handler/unknown" = [ primary_browser secondary_browser ]; + "x-scheme-handler/http" = [ primary_browser ]; + "x-scheme-handler/https" = [ primary_browser ]; + "x-scheme-handler/about" = [ primary_browser ]; + "x-scheme-handler/unknown" = [ primary_browser ]; "x-scheme-handler/mailto" = [ mail_client ]; "message/rfc822" = [ mail_client ]; "x-scheme-handler/mid" = [ mail_client ]; From e8b7a7e8b6f2b1ad0a7b4898e4c2065369a6c0b3 Mon Sep 17 00:00:00 2001 From: vali Date: Sat, 13 Apr 2024 15:30:40 +0200 Subject: [PATCH 07/27] stuff --- hosts/vali/mars/configuration.nix | 2 +- modules/other/xdg.nix | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/hosts/vali/mars/configuration.nix b/hosts/vali/mars/configuration.nix index 6cc8107..b03723d 100644 --- a/hosts/vali/mars/configuration.nix +++ b/hosts/vali/mars/configuration.nix @@ -90,7 +90,7 @@ }; }; qt = { - enable = false; + enable = true; package = pkgs.catppuccin-kde; name = "Catppuccin-Mocha-Dark"; variant = "mocha"; diff --git a/modules/other/xdg.nix b/modules/other/xdg.nix index 8ce0370..6e2e0f2 100644 --- a/modules/other/xdg.nix +++ b/modules/other/xdg.nix @@ -6,7 +6,7 @@ hmCfg = config.home-manager.users.${username}; primary_browser = "schizofox.desktop"; - mail_client = "betterbird.desktop"; + mail_client = "thunderbird.desktop"; file_manager = "pcmanfm.desktop"; media_player = "mpv.desktop"; image_viewer = "imv.desktop"; @@ -72,7 +72,7 @@ in { mimeApps = { enable = true; defaultApplications = { - "text/html" = [ primary_browser secondary_browser ]; + "text/html" = [ primary_browser ]; "x-scheme-handler/http" = [ primary_browser ]; "x-scheme-handler/https" = [ primary_browser ]; "x-scheme-handler/about" = [ primary_browser ]; From 12b78099d3e7b0f529d9efbbb882e279f5eff97e Mon Sep 17 00:00:00 2001 From: vali Date: Sat, 13 Apr 2024 15:38:42 +0200 Subject: [PATCH 08/27] changed myOptions to modules --- hosts/vali/mars/i3/i3-new.nix | 6 +++--- hosts/vali/mars/i3/i3.nix | 2 +- modules/services/ssh.nix | 6 +++--- modules/tui/ncmpcpp.nix | 6 +++--- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/hosts/vali/mars/i3/i3-new.nix b/hosts/vali/mars/i3/i3-new.nix index a720230..28bdab4 100644 --- a/hosts/vali/mars/i3/i3-new.nix +++ b/hosts/vali/mars/i3/i3-new.nix @@ -1,10 +1,10 @@ {pkgs, lib, config, ... }: with lib; let - cfg = config.myOptions.programs.i3; - username = config.myOptions.other.system.username; + cfg = config.modules.programs.i3; + username = config.modules.other.system.username; mod = "Mod4"; in { - options.myOptions.programs.i3.enable = mkEnableOption "i3"; + options.modules.programs.i3.enable = mkEnableOption "i3"; config = mkIf cfg.enable { services.xserver = { diff --git a/hosts/vali/mars/i3/i3.nix b/hosts/vali/mars/i3/i3.nix index a3242ee..9e16066 100644 --- a/hosts/vali/mars/i3/i3.nix +++ b/hosts/vali/mars/i3/i3.nix @@ -1,6 +1,6 @@ { pkgs, lib, config, callPackage, ... }: with lib; let - username = config.myOptions.other.system.username; + username = config.modules.other.system.username; cfg = config.modules.programs.i3; in { options.modules.programs.i3.enable = mkEnableOption "i3"; diff --git a/modules/services/ssh.nix b/modules/services/ssh.nix index 621a741..b44d94b 100644 --- a/modules/services/ssh.nix +++ b/modules/services/ssh.nix @@ -1,9 +1,9 @@ { config, lib, pkgs, ... }: with lib; let - cfg = config.myOptions.programs.ssh; - username = config.myOptions.other.system.username; + cfg = config.modules.programs.ssh; + username = config.modules.other.system.username; in { - options.myOptions.programs.ssh.enable = mkEnableOption "ssh"; + options.modules.programs.ssh.enable = mkEnableOption "ssh"; config = mkIf cfg.enable { programs.ssh = { diff --git a/modules/tui/ncmpcpp.nix b/modules/tui/ncmpcpp.nix index 2aaa6f7..2d69da8 100644 --- a/modules/tui/ncmpcpp.nix +++ b/modules/tui/ncmpcpp.nix @@ -1,9 +1,9 @@ { config, lib, pkgs, ... }: with lib; let - cfg = config.myOptions.programs.ncmpcpp; - username = config.myOptions.other.system.username; + cfg = config.modules.programs.ncmpcpp; + username = config.modules.other.system.username; in { - options.myOptions.programs.ncmpcpp.enable = mkEnableOption "ncmpcpp"; + options.modules.programs.ncmpcpp.enable = mkEnableOption "ncmpcpp"; config = mkIf cfg.enable { home-manager.users.${username} = { From 5fa50cb0a70c7bef29bfcccd215bf27de04341ff Mon Sep 17 00:00:00 2001 From: LarsZauberer Date: Sat, 13 Apr 2024 18:34:33 +0200 Subject: [PATCH 09/27] fixed intend --- modules/cli/zsh.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/cli/zsh.nix b/modules/cli/zsh.nix index cb02c19..e5083bc 100644 --- a/modules/cli/zsh.nix +++ b/modules/cli/zsh.nix @@ -85,8 +85,8 @@ in { } ]; oh-my-zsh = mkIf cfg.ohmyzsh.enable { - enable = true; - theme = cfg.ohmyzsh.theme; + enable = true; + theme = cfg.ohmyzsh.theme; plugins = cfg.ohmyzsh.plugins; }; }; From 18b4267d150c703d3ef45419c8ecfc5b34af9bbc Mon Sep 17 00:00:00 2001 From: LarsZauberer Date: Sat, 13 Apr 2024 18:35:16 +0200 Subject: [PATCH 10/27] fix double importing --- hosts/lars/kronos/default.nix | 4 ---- 1 file changed, 4 deletions(-) diff --git a/hosts/lars/kronos/default.nix b/hosts/lars/kronos/default.nix index 30c5db4..2d68268 100644 --- a/hosts/lars/kronos/default.nix +++ b/hosts/lars/kronos/default.nix @@ -7,9 +7,5 @@ _: { ./configuration.nix ./hardware-configuration.nix ./profile.nix - ./configuration.nix - ./programs.nix - ./hardware-configuration.nix - ./profile.nix ]; } From 88c3706fdeb0d1b701ce6a7c97cd4f0a303d2b90 Mon Sep 17 00:00:00 2001 From: LarsZauberer Date: Sat, 13 Apr 2024 18:59:58 +0200 Subject: [PATCH 11/27] Firefox added --- hosts/lars/kronos/configuration.nix | 3 +++ modules/gui/default.nix | 1 + modules/gui/firefox.nix | 30 +++++++++++++++++++++++++++++ 3 files changed, 34 insertions(+) create mode 100644 modules/gui/firefox.nix diff --git a/hosts/lars/kronos/configuration.nix b/hosts/lars/kronos/configuration.nix index 0189d05..c7d1182 100644 --- a/hosts/lars/kronos/configuration.nix +++ b/hosts/lars/kronos/configuration.nix @@ -15,6 +15,9 @@ "DP-1,1920x1080@60,2560x0,1" ]; }; + firefox = { + enable = true; + }; }; services.getty.autologinUser = "lars"; diff --git a/modules/gui/default.nix b/modules/gui/default.nix index d4cd205..70631a4 100644 --- a/modules/gui/default.nix +++ b/modules/gui/default.nix @@ -11,5 +11,6 @@ _: { ./foot.nix # ./vivado.nix ./WM + ./firefox.nix ]; } diff --git a/modules/gui/firefox.nix b/modules/gui/firefox.nix new file mode 100644 index 0000000..79626a3 --- /dev/null +++ b/modules/gui/firefox.nix @@ -0,0 +1,30 @@ +{ config, lib, inputs, pkgs, ... }: +with lib; let + username = config.modules.other.system.username; + cfg = config.modules.firefox; +in { + options.modules.firefox = { + enable = mkEnableOption "firefox"; + extensions = mkOption { + description = "firefox extensions (format like https://discourse.nixos.org/t/declare-firefox-extensions-and-settings/36265)"; + type = types.attrs; + default = {}; + }; + }; + + config = mkIf cfg.enable { + home-manager.users.${username} = { + programs.firefox = (lib.mkMerge [{ + enable = true; + policies = { + ExtensionSettings = { + "uBlock0@raymondhill.net" = { + install_url = "https://addons.mozilla.org/firefox/downloads/latest/ublock-origin/latest.xpi"; + installation_mode = "force_installed"; + }; + }; + }; + } cfg.extensions]); + }; + }; +} From fd5a2015ee1c05bd34905586ab5a750354689bed Mon Sep 17 00:00:00 2001 From: LarsZauberer Date: Sat, 13 Apr 2024 19:00:23 +0200 Subject: [PATCH 12/27] Further hyprland config --- hosts/lars/hyprland.nix | 13 +++++++++++-- hosts/lars/programs.nix | 1 - 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/hosts/lars/hyprland.nix b/hosts/lars/hyprland.nix index f9178a7..4226214 100644 --- a/hosts/lars/hyprland.nix +++ b/hosts/lars/hyprland.nix @@ -11,6 +11,11 @@ in { default = ",preferred,auto,1"; type = types.listOf(types.str); }; + extra = mkOption { + description = "any extra configuration to add to the hyprland config file"; + default = {}; + type = types.attrs; + }; }; config = mkIf cfg.enable { @@ -40,7 +45,7 @@ in { home-manager.users.${username} = { wayland.windowManager.hyprland = { enable = true; - settings = { + settings = lib.mkMerge [{ # Monitor config monitor = cfg.monitor; @@ -50,6 +55,10 @@ in { kb_layout = "ch"; }; + animation = [ + "workspaces,1,10,default" + ]; + bind = [ "$mod, Q, killactive" "$mod, return, exec, alacritty" @@ -87,7 +96,7 @@ in { ) 10) ); - }; + } cfg.extra]; }; }; }; diff --git a/hosts/lars/programs.nix b/hosts/lars/programs.nix index af563c0..651a82a 100644 --- a/hosts/lars/programs.nix +++ b/hosts/lars/programs.nix @@ -46,7 +46,6 @@ in { rustdesk neovim tmux - firefox kitty nextcloud-client vscode From f8d41d4622bb58b45dc7f45297052aecd530ae5b Mon Sep 17 00:00:00 2001 From: LarsZauberer Date: Sat, 13 Apr 2024 19:03:30 +0200 Subject: [PATCH 13/27] fixed naming convention --- hosts/lars/default.nix | 4 ++++ hosts/lars/kronos/configuration.nix | 3 --- modules/gui/firefox.nix | 8 ++++---- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/hosts/lars/default.nix b/hosts/lars/default.nix index da685ac..5cded42 100644 --- a/hosts/lars/default.nix +++ b/hosts/lars/default.nix @@ -41,6 +41,10 @@ userEmail = "wasser.ian@gmail.com"; defaultBranch = "main"; }; + + firefox = { + enable = true; + }; }; services = { diff --git a/hosts/lars/kronos/configuration.nix b/hosts/lars/kronos/configuration.nix index c7d1182..0189d05 100644 --- a/hosts/lars/kronos/configuration.nix +++ b/hosts/lars/kronos/configuration.nix @@ -15,9 +15,6 @@ "DP-1,1920x1080@60,2560x0,1" ]; }; - firefox = { - enable = true; - }; }; services.getty.autologinUser = "lars"; diff --git a/modules/gui/firefox.nix b/modules/gui/firefox.nix index 79626a3..7e8ffe5 100644 --- a/modules/gui/firefox.nix +++ b/modules/gui/firefox.nix @@ -1,9 +1,9 @@ { config, lib, inputs, pkgs, ... }: with lib; let username = config.modules.other.system.username; - cfg = config.modules.firefox; + cfg = config.modules.programs.firefox; in { - options.modules.firefox = { + options.modules.programs.firefox = { enable = mkEnableOption "firefox"; extensions = mkOption { description = "firefox extensions (format like https://discourse.nixos.org/t/declare-firefox-extensions-and-settings/36265)"; @@ -14,7 +14,7 @@ in { config = mkIf cfg.enable { home-manager.users.${username} = { - programs.firefox = (lib.mkMerge [{ + programs.firefox = lib.mkMerge [{ enable = true; policies = { ExtensionSettings = { @@ -24,7 +24,7 @@ in { }; }; }; - } cfg.extensions]); + } cfg.extensions]; }; }; } From 1a1b81e1b82dd03046a6b5bf876906f6a9d70f73 Mon Sep 17 00:00:00 2001 From: LarsZauberer Date: Sat, 13 Apr 2024 19:16:54 +0200 Subject: [PATCH 14/27] Firefox fix --- hosts/lars/default.nix | 6 ++++++ modules/gui/firefox.nix | 8 ++++---- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/hosts/lars/default.nix b/hosts/lars/default.nix index 5cded42..71b892e 100644 --- a/hosts/lars/default.nix +++ b/hosts/lars/default.nix @@ -44,6 +44,12 @@ firefox = { enable = true; + extensions = { + "support@lastpass.com" = { + install_url = "https://addons.mozilla.org/de/firefox/addon/lastpass-password-manager/"; + installation_mode = "force_installed"; + }; + }; }; }; diff --git a/modules/gui/firefox.nix b/modules/gui/firefox.nix index 7e8ffe5..06125cd 100644 --- a/modules/gui/firefox.nix +++ b/modules/gui/firefox.nix @@ -14,17 +14,17 @@ in { config = mkIf cfg.enable { home-manager.users.${username} = { - programs.firefox = lib.mkMerge [{ + programs.firefox = { enable = true; policies = { - ExtensionSettings = { + ExtensionSettings = lib.mkMerge [{ "uBlock0@raymondhill.net" = { install_url = "https://addons.mozilla.org/firefox/downloads/latest/ublock-origin/latest.xpi"; installation_mode = "force_installed"; }; - }; + } cfg.extensions]; }; - } cfg.extensions]; + }; }; }; } From a68413e851c97d328f7f53887b6af0680c16bcfa Mon Sep 17 00:00:00 2001 From: LarsZauberer Date: Sat, 13 Apr 2024 19:35:09 +0200 Subject: [PATCH 15/27] Hyprland config --- hosts/lars/hyprland.nix | 23 +++++++++++++++++++++-- hosts/lars/kronos/configuration.nix | 5 +++++ hosts/lars/programs.nix | 1 + 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/hosts/lars/hyprland.nix b/hosts/lars/hyprland.nix index 4226214..dfbeee3 100644 --- a/hosts/lars/hyprland.nix +++ b/hosts/lars/hyprland.nix @@ -55,8 +55,25 @@ in { kb_layout = "ch"; }; + bezier = [ + "wind, 0.05, 0.9, 0.1, 1.05" + "winIn, 0.1, 1.1, 0.1, 1.1" + "winOut, 0.3, -0.3, 0, 1" + "liner, 1, 1, 1, 1" + ]; + animation = [ - "workspaces,1,10,default" + "windows, 1, 6, wind, slide" + "windowsIn, 1, 6, winIn, slide" + "windowsOut, 1, 5, winOut, slide" + "windowsMove, 1, 5, wind, slide" + "border, 1, 1, liner" + "borderangle, 1, 30, liner, loop" + "fade, 1, 10, default" + "workspaces, 1, 5, wind" + ]; + + exec-once = [ ]; bind = [ @@ -64,6 +81,8 @@ in { "$mod, return, exec, alacritty" "$mod SHIFT, return, exec, firefox" "$mod SHIFT, m, exit" + ", F11, exec, pamixer -d 2" + ", F12, exec, pamixer -i 2" # Application "$mod SHIFT, c, exec, code --enable-features=UseOzonePlatform --ozone-platform=wayland --disable-gpu" @@ -80,7 +99,7 @@ in { "$mod, F, fullscreen" # Screenshot - "$mod SHIFT, s, exec, grim -g 'slurp -d' - | wl-copy" + "$mod SHIFT, s, exec, grim -g '$(slurp -d)' - | wl-copy" ] ++ ( builtins.concatLists (builtins.genList ( diff --git a/hosts/lars/kronos/configuration.nix b/hosts/lars/kronos/configuration.nix index 0189d05..70ef21c 100644 --- a/hosts/lars/kronos/configuration.nix +++ b/hosts/lars/kronos/configuration.nix @@ -14,6 +14,11 @@ "DP-2,2560x1440@144,0x0,1" "DP-1,1920x1080@60,2560x0,1" ]; + extra = { + exec-once = [ + "hyprctl dispatch moveworkspacetomonitor 1 DP-2" + ]; + }; }; }; diff --git a/hosts/lars/programs.nix b/hosts/lars/programs.nix index 651a82a..459545e 100644 --- a/hosts/lars/programs.nix +++ b/hosts/lars/programs.nix @@ -52,6 +52,7 @@ in { grim slurp wl-clipboard + pavucontrol ]; }; } From e71ad0d7a455aaf8947c37b0b02702d57c8874d0 Mon Sep 17 00:00:00 2001 From: vali Date: Sat, 13 Apr 2024 20:51:58 +0200 Subject: [PATCH 16/27] added nixvim stuff --- flake.nix | 7 ++ modules/tui/neovim.nix | 143 ++++++----------------------------------- 2 files changed, 28 insertions(+), 122 deletions(-) diff --git a/flake.nix b/flake.nix index 9e0b0ea..2c61476 100644 --- a/flake.nix +++ b/flake.nix @@ -32,6 +32,13 @@ }; }; + neovim-nightly-overlay.url = "github:nix-community/neovim-nightly-overlay"; + + nixvim = { + url = "github:nix-community/nixvim"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + fenix = { url = "github:nix-community/fenix"; inputs.nixpkgs.follows = "nixpkgs"; diff --git a/modules/tui/neovim.nix b/modules/tui/neovim.nix index b19c255..e87674d 100644 --- a/modules/tui/neovim.nix +++ b/modules/tui/neovim.nix @@ -1,89 +1,48 @@ -{ - config, - inputs, - lib, - pkgs, - ... -}: with lib; let +{ config, inputs, lib, pkgs, ... }: +with lib; let cfg = config.modules.programs.neovim; username = config.modules.other.system.username; in { options.modules.programs.neovim.enable = mkEnableOption "neovim"; config = mkIf cfg.enable { - nixpkgs.overlays = [ inputs.neovim-nightly-overlay.overlay ]; - home-manager.users.${username} = { imports = [ inputs.nixvim.homeManagerModules.nixvim ]; - programs.nixvim = { enable = true; - package = pkgs.neovim-nightly; enableMan = true; defaultEditor = true; - colorscheme = "catppuccin"; - colorschemes.catppuccin = { - enable = true; - flavour = "mocha"; - transparentBackground = true; - }; - opts = { + background = "dark"; + shiftwidth = 4; + autoread = true; + cmdheight = 1; + encoding = "utf8"; + expandtab = true; + hidden = true; + ignorecase = true; + linebreak = true; + mousemoveevent = true; number = true; relativenumber = true; - autoread = true; - so = 7; - cmdheight = 1; - ignorecase = true; - smartcase = true; showmatch = true; - timeoutlen = 500; - encoding = "utf8"; - smarttab = true; - shiftwidth = 4; - tabstop = 4; - expandtab = true; - linebreak = true; + smartcase = true; smartindent = true; - updatetime = 300; - hidden = true; - background = "dark"; - mousemoveevent = true; - smoothscroll = true; + smarttab = true; + so = 7; + timeoutlen = 500; + tabstop = 4; + updatetime = 50; }; - globals = { - mapleader = " "; - }; - - keymaps = [ - { - # TODO move this to lua to be cool - # action = "vim.cmd { cmd = \"Neotree\", args = { \"toggle\" } }"; - # lua = true; - action = "Neotree toggle"; - key = "v"; - options.silent = true; - } - { - action = "vim.cmd.MarkdownPreviewToggle"; - lua = true; - key = "m"; - options.silent = true; - } - ]; + globals.mapleader = " "; plugins = { - airline = { - enable = false; - settings.theme = "catppuccin"; - }; lualine = { enable = true; theme = "catppuccin"; }; - fugitive.enable = true; treesitter = { enable = true; folding = false; @@ -106,66 +65,7 @@ in { neo-tree = { enable = true; }; - toggleterm = { - enable = true; - direction = "float"; - openMapping = ""; - shadeTerminals = true; - shadingFactor = 2; - size = 10; - }; - # TODO laytan/cloak.nvim - gitsigns = { - enable = true; - settings = { - current_line_blame = true; - numhl = true; - signcolumn = true; - word_diff = true; - on_attach = '' - function(bufnr) - local gs = package.loaded.gitsigns - - local function map(mode, l, r, opts) - opts = opts or {} - opts.buffer = bufnr - vim.keymap.set(mode, l, r, opts) - end - - -- Navigation - map('n', ']c', function() - if vim.wo.diff then return ']c' end - vim.schedule(function() gs.next_hunk() end) - return '' - end, {expr=true}) - - map('n', '[c', function() - if vim.wo.diff then return '[c' end - vim.schedule(function() gs.prev_hunk() end) - return '' - end, {expr=true}) - - -- Actions - map('n', 'hs', gs.stage_hunk) - map('n', 'hr', gs.reset_hunk) - map('v', 'hs', function() gs.stage_hunk {vim.fn.line('.'), vim.fn.line('v')} end) - map('v', 'hr', function() gs.reset_hunk {vim.fn.line('.'), vim.fn.line('v')} end) - map('n', 'hS', gs.stage_buffer) - map('n', 'hu', gs.undo_stage_hunk) - map('n', 'hR', gs.reset_buffer) - map('n', 'hp', gs.preview_hunk) - map('n', 'hb', function() gs.blame_line{full=true} end) - map('n', 'tb', gs.toggle_current_line_blame) - map('n', 'hd', gs.diffthis) - map('n', 'hD', function() gs.diffthis('~') end) - map('n', 'td', gs.toggle_deleted) - - -- Text object - map({'o', 'x'}, 'ih', ':Gitsigns select_hunk') - end - ''; - }; - }; + # TODO laytan/cloak.nvim lsp = { enable = true; servers = { @@ -181,6 +81,7 @@ in { tsserver.enable = true; java-language-server.enable = true; #pylyzer.enable = true; + rnix-lsp.enable = true; }; #onAttach = '' # vim.api.nvim_buf_set_option(bufnr, 'omnifunc', 'v:lua.vim.lsp.omnifunc') @@ -228,7 +129,6 @@ in { showParameterHints = true; }; }; - leap.enable = true; fidget.enable = true; telescope = { enable = true; @@ -242,7 +142,6 @@ in { keymapsSilent = true; }; comment.enable = true; - crates-nvim.enable = true; harpoon = { enable = true; package = pkgs.vimPlugins.harpoon.overrideAttrs { From f605203031fd0248709541b10d6cc34b580354c7 Mon Sep 17 00:00:00 2001 From: vali Date: Sat, 13 Apr 2024 20:53:03 +0200 Subject: [PATCH 17/27] removed hyprland --- hosts/vali/mars/awesome.nix | 20 -- hosts/vali/mars/hypr/default.nix | 7 - hosts/vali/mars/hypr/idle.nix | 1 - hosts/vali/mars/hypr/land.nix | 423 ------------------------------- hosts/vali/mars/hypr/lock.nix | 81 ------ 5 files changed, 532 deletions(-) delete mode 100644 hosts/vali/mars/awesome.nix delete mode 100644 hosts/vali/mars/hypr/default.nix delete mode 100644 hosts/vali/mars/hypr/idle.nix delete mode 100644 hosts/vali/mars/hypr/land.nix delete mode 100644 hosts/vali/mars/hypr/lock.nix diff --git a/hosts/vali/mars/awesome.nix b/hosts/vali/mars/awesome.nix deleted file mode 100644 index ad418a0..0000000 --- a/hosts/vali/mars/awesome.nix +++ /dev/null @@ -1,20 +0,0 @@ -{ pkgs, lib, config, ... }: -with lib; let - cfg = config.modules.programs.awesome; -in { - options.modules.programs.awesome.enable = mkEnableOption "awesome"; - - config = mkIf cfg.enable { - services.xserver = { - enable = true; - xkb.layout = "de"; - windowManager.awesome = { - enable = true; - luaModules = with pkgs.luaPackages; [ - luarocks - luadbi-mysql - ]; - }; - }; - }; -} diff --git a/hosts/vali/mars/hypr/default.nix b/hosts/vali/mars/hypr/default.nix deleted file mode 100644 index 2cf865e..0000000 --- a/hosts/vali/mars/hypr/default.nix +++ /dev/null @@ -1,7 +0,0 @@ -_: { - imports = [ - ./idle.nix - ./land.nix - ./lock.nix - ]; -} diff --git a/hosts/vali/mars/hypr/idle.nix b/hosts/vali/mars/hypr/idle.nix deleted file mode 100644 index eed7124..0000000 --- a/hosts/vali/mars/hypr/idle.nix +++ /dev/null @@ -1 +0,0 @@ -_: {} diff --git a/hosts/vali/mars/hypr/land.nix b/hosts/vali/mars/hypr/land.nix deleted file mode 100644 index 9816796..0000000 --- a/hosts/vali/mars/hypr/land.nix +++ /dev/null @@ -1,423 +0,0 @@ -{ config, inputs, lib, pkgs, ... }: - -with lib; let - - cfg = config.modules.programs.hypr.land; - username = config.modules.other.system.username; - hmCfg = config.home-manager.users.${username}; - - smwPresent = elem inputs.split-monitor-workspaces.packages.${pkgs.system}.split-monitor-workspaces cfg.extraPlugins; - - inherit (inputs.nixpkgs-wayland.packages.${pkgs.system}) foot wl-clipboard swww wlsunset; - inherit (inputs.anyrun.packages.${pkgs.system}) anyrun; - inherit (inputs.hyprland.packages.${pkgs.system}) hyprland; - inherit (inputs.hyprlock.packages.${pkgs.system}) hyprlock; -in { - options.modules.programs.hypr.land = { - enable = mkEnableOption "huperland"; - startupSound = mkOption { - type = with types; nullOr path; - description = "sound to play on hyprland startup"; - default = null; - }; - tearing = mkOption { - type = types.bool; - description = "enable tearing"; - default = false; - }; - extraSettings = mkOption { - type = types.attrs; - description = "extra per host hyprland settings"; - default = {}; - }; - extraPlugins = mkOption { - type = with types; listOf package; - description = "extra per host hyprland plugins"; - default = []; - }; - }; - - disabledModules = [ "programs/hyprland.nix" ]; - - config = mkIf cfg.enable { - nix.settings = { - substituters = [ "https://hyprland.cachix.org" ]; - trusted-public-keys = [ "hyprland.cachix.org-1:a7pgxzMz7+chwVL3/pzj6jIBMioiJM7ypFP8PwtkuGc=" ]; - }; - - environment.sessionVariables = { - XDG_CURRENT_DESKTOP = "Hyprland"; - XDG_SESSION_TYPE = "wayland"; - XDG_SESSION_DESKTOP = "Hyprland"; - - SDL_VIDEODRIVER = "wayland"; - - _JAVA_AWT_WM_NONEREPARENTING = "1"; - - CLUTTER_BACKEND = "wayland"; - - GDK_BACKEND = "wayland"; - - QT_QPA_PLATFORM = "wayland"; - - LIBSEAT_BACKEND = "logind"; - }; - - xdg.portal = { - enable = true; - extraPortals = [ - pkgs.xdg-desktop-portal-gtk - inputs.hyprland.packages.${pkgs.system}.xdg-desktop-portal-hyprland - ]; - # TODO look into and make use of this - config.common.default = "*"; - }; - - home-manager.users.${username} = { - - xdg.dataFile = mkIf (cfg.startupSound != null) { "hypr/startup_sound".source = cfg.startupSound; }; - - wayland.windowManager.hyprland = { - enable = true; - package = inputs.hyprland.packages.${pkgs.system}.hyprland; - #portalPackage = inputs.hyprland.packages.${pkgs.system}.xdg-desktop-portal-hyprland; - plugins = [] ++ cfg.extraPlugins; - # TODO make these work with the config below (infinite recursion) - # and make this file stop hanging my neovim every 2 seconds - # and figure out why it triggers E79 every single time I edit something - extraConfig = '' - bind=$mainMod, W, exec, schizofox - ${if (cfg.startupSound != null) then "exec-once=${pkgs.mpv}/bin/mpv --no-video --volume=100 ${hmCfg.xdg.dataHome}/hypr/startup_sound" else ""} - ''; - settings = { - "$mainMod" = "SUPER"; - - monitor = [ - # second monitor - "HDMI-A-1, 1920@1080, 0x0, 1" - ]; - - workspace = [ - # second monitor - "1, monitor:HDMI-A-1, default:true" - "2, monitor:HDMI-A-1" - "3, monitor:HDMI-A-1" - "4, monitor:HDMI-A-1" - "5, monitor:HDMI-A-1" - "6, monitor:HDMI-A-1" - "7, monitor:HDMI-A-1" - "8, monitor:HDMI-A-1" - "9, monitor:HDMI-A-1" - "10, monitor:HDMI-A-1" - - # scratchpads - "special:btop, decorate:false" - "special:pipewire, decorate:false" - "special:nixos, decorate:false" - (mkIf config.services.asusd.enable - "special:rog, decorate:false") - "special:keepassxc, decorate:false" - ]; - - input = { - kb_layout = "de"; - kb_variant = ""; - kb_model = ""; - kb_options = ""; - kb_rules = ""; - - follow_mouse = true; - touchpad = { - disable_while_typing = false; - }; - - repeat_rate = 50; - repeat_delay = 250; - touchdevice = { - output = "eDP-1"; - }; - - tablet = { - output = "HDMI-A-1"; - }; - }; - - general = { - sensitivity = 1.0; - - gaps_in = 5; - gaps_out = 5; - border_size = 2; - - apply_sens_to_raw = 0; - - #no_border_on_floating = true; - allow_tearing = mkIf cfg.tearing true; - - "col.active_border" = "0xFFF5C2E7"; - "col.inactive_border" = "0xFF45475A"; - #col.group_border_active = "0xFFA6E3A1"; - #col.group_border = "0xFF45475A"; - }; - - env = optionals cfg.tearing [ "WLR_DRM_NO_ATOMIC,1" ]; - - decoration = { - rounding = 10; - blur = { - enabled = true; - size = 3; - passes = 2; - }; - - drop_shadow = 1; - shadow_range = 15; - shadow_render_power = 2; - shadow_ignore_window = 1; - shadow_offset = "2 4"; - shadow_scale = 1; - - "col.shadow" = "0xAF1E1E2E"; - }; - - bezier = [ - "dupa, 0.1, 0.9, 0.1, 1.05" - ]; - - animations = { - enabled = true; - animation = [ - "windows, 1, 4, dupa, popin" - "windowsOut, 1, 7, dupa, slide" - "border, 1, 15, default" - "fade, 1, 10, default" - "workspaces, 1, 5, dupa, slidevert" - ]; - }; - - dwindle = { - no_gaps_when_only = true; - }; - - misc = { - enable_swallow = false; - swallow_regex = "foot"; - focus_on_activate = true; - vrr = 1; - vfr = true; - animate_manual_resizes = false; - animate_mouse_windowdragging = false; - force_default_wallpaper = 0; - }; - - windowrulev2 = [ - "float, class:^(Tor Browser)$" - "float, class:^(foot)$" - "float, class:^(mpv)$" - "float, class:^(imv)$" - "float, class:^(Vieb)$" - "float, title:^(Picture-in-Picture)$" - "float, title:^(.*)(Choose User Profile)(.*)$" - "float, title:^(blob:null/)(.*)$" - - "float, class:^(xdg-desktop-portal-gtk)$" - "float, class:^(code), title: ^(Open*)" - "size 70% 70%, class:^(code), title: ^(Open*)" - "center, class: ^(code), title: ^(Open*)" - "float, class:^(org.keepassxc.KeePassXC)$" - (mkIf config.services.asusd.enable - "size 960 670, title:^(ROG Control Center)$") - ]; - - bind = [ - "$mainMod, RETURN, exec, ${foot}/bin/${foot}" - "$mainMod SHIFT, Q, killactive" - "$mainMod, F, fullscreen, 0" - "$mainMod, M, fullscreen, 1" - "$mainMod, D, exec, ${pkgs.procps}/bin/pkill anyrun || ${anyrun}/bin/anyrun" - "$mainMod, SPACE, togglefloating, active" - "$mainMod SHIFT, C, centerwindow" - "$mainMod CONTROL, R, bringactivetotop" - "$mainMod, P, pin" - # workspaces - "$mainMod, 1, ${if smwPresent then "split-" else ""}workspace, 1" - "$mainMod, 2, ${if smwPresent then "split-" else ""}workspace, 2" - "$mainMod, 3, ${if smwPresent then "split-" else ""}workspace, 3" - "$mainMod, 4, ${if smwPresent then "split-" else ""}workspace, 4" - "$mainMod, 5, ${if smwPresent then "split-" else ""}workspace, 5" - "$mainMod, 6, ${if smwPresent then "split-" else ""}workspace, 6" - "$mainMod, 7, ${if smwPresent then "split-" else ""}workspace, 7" - "$mainMod, 8, ${if smwPresent then "split-" else ""}workspace, 8" - "$mainMod, 9, ${if smwPresent then "split-" else ""}workspace, 9" - "$mainMod, 0, ${if smwPresent then "split-" else ""}workspace, 10" - "$mainMod SHIFT, 1, ${if smwPresent then "split-" else ""}movetoworkspacesilent, 1" - "$mainMod SHIFT, 2, ${if smwPresent then "split-" else ""}movetoworkspacesilent, 2" - "$mainMod SHIFT, 3, ${if smwPresent then "split-" else ""}movetoworkspacesilent, 3" - "$mainMod SHIFT, 4, ${if smwPresent then "split-" else ""}movetoworkspacesilent, 4" - "$mainMod SHIFT, 5, ${if smwPresent then "split-" else ""}movetoworkspacesilent, 5" - "$mainMod SHIFT, 6, ${if smwPresent then "split-" else ""}movetoworkspacesilent, 6" - "$mainMod SHIFT, 7, ${if smwPresent then "split-" else ""}movetoworkspacesilent, 7" - "$mainMod SHIFT, 8, ${if smwPresent then "split-" else ""}movetoworkspacesilent, 8" - "$mainMod SHIFT, 9, ${if smwPresent then "split-" else ""}movetoworkspacesilent, 9" - "$mainMod SHIFT, 0, ${if smwPresent then "split-" else ""}movetoworkspacesilent, 10" - # screenshots - "$mainMod, S, exec, grimblast save area - | ${pkgs.coreutils-full}/bin/tee \"$(${pkgs.xdg-user-dirs}/bin/xdg-user-dir PICTURES)/Screenshots/$(date +'screenshot-%Y%m%d%H%M%S.png')\" | ${wl-clipboard}/bin/wl-copy && ${pkgs.libnotify}/bin/notify-send \"Screenshot taken\"" - "$mainMod CONTROL, S, exec, grimblast save area - | ${pkgs.swappy}/bin/swappy -f - -o - | ${pkgs.coreutils-full}/bin/tee \"$(${pkgs.xdg-user-dirs}/bin/xdg-user-dir PICTURES)/Screenshots/$(date +'screenshot-%Y%m%d%H%M%S.png')\" | ${wl-clipboard}/bin/wl-copy && ${pkgs.libnotify}/bin/notify-send \"Screenshot taken\"" - "$mainMod SHIFT, R, exec, ${hyprland}/bin/hyprctl reload" - - # TODO fix this maybe - "$mainMod, T, exec, grim -g \"$(slurp)\" -t ppm - | tesseract -l pol - - | wl-copy && notify-send \"Copied text: \" \"\\\"$(wl-paste)\\\"\"" - # TODO fix this - "$mainMod, SEMICOLON, exec, ~/.config/rofi/powermenu/type-2/powermenu.sh" - "$mainMod, G, togglegroup" - # this sometimes fixes the portal - "$mainMod CONTROL, X, exec, ${pkgs.systemd}/bin/systemctl --user restart xdg-desktop-portal-hyprland" - "$mainMod SHIFT, X, exec, ${hyprland}/bin/hyprctl kill" - # scratchpad binds - "$mainMod, B, togglespecialworkspace, btop" - "$mainMod, V, togglespecialworkspace, pipewire" - "$mainMod, N, togglespecialworkspace, nixos" - "$mainMod, X, togglespecialworkspace, keepassxc" - "$mainMod, C, exec, ${hyprlock}/bin/hyprlock" - # toggle waybar - "$mainMod CONTROL, B, exec, ${pkgs.procps}/bin/pkill waybar || waybar" - - #"$mainMod, mouse_up, exec, ${hyprland}/bin/hyprctl keyword misc:cursor_zoom_factor $(echo \"$(${hyprland}/bin/hyprctl getoption misc:cursor_zoom_factor -j | ${pkgs.jq}/bin/jq '.float') + 0.01\" | ${pkgs.bc}/bin/bc)" - #"$mainMod, mouse_down, exec, ${hyprland}/bin/hyprctl keyword misc:cursor_zoom_factor $(echo \"$(${hyprland}/bin/hyprctl getoption misc:cursor_zoom_factor -j | ${pkgs.jq}/bin/jq '.float') - 0.01\" | ${pkgs.bc}/bin/bc)" - - #"$mainMod, mouse_up, exec, ${pkgs.libnotify}/bin/notify-send 'mouse_up'" - #"$mainMod, mouse_down, exec, ${pkgs.libnotify}/bin/notify-send 'mouse_down'" - ]; - - # repeat - binde = [ - # window / monitor focus - "$mainMod, H, movefocus, l" - "$mainMod, J, movefocus, d" - "$mainMod, K, movefocus, u" - "$mainMod, L, movefocus, r" - "$mainMod CONTROL, J, focusmonitor, l" - "$mainMod CONTROL, K, focusmonitor, r" - - "$mainMod SHIFT, G, changegroupactive, f" - "$mainMod CONTROL, G, changegroupactive, b" - ]; - - # locked - bindl = [ - ", XF86AudioMedia, exec, ${pkgs.playerctl}/bin/playerctl play-pause" - ", XF86AudioPlay, exec, ${pkgs.playerctl}/bin/playerctl play-pause" - ", XF86AudioStop, exec, ${pkgs.playerctl}/bin/playerctl stop" - ", XF86AudioPrev, exec, ${pkgs.playerctl}/bin/playerctl previous" - ", XF86AudioNext, exec, ${pkgs.playerctl}/bin/playerctl next" - ", XF86AudioMute, exec, ~/Scripts/notif_volume.sh --toggle-mute" - ]; - - # locked + repeat - bindle = [ - ", XF86MonBrightnessUp, exec, ~/Scripts/notif_brightness.sh set +5%" - ", XF86MonBrightnessDown, exec, ~/Scripts/notif_brightness.sh set 5%-" - ", XF86AudioRaiseVolume, exec, ~/Scripts/notif_volume.sh -ui 5" - ", XF86AudioLowerVolume, exec, ~/Scripts/notif_volume.sh -ud 5" - ]; - - # mouse - bindm = [ - "$mainMod, mouse:272, movewindow" - "$mainMod, mouse:273, resizewindow" - ]; - - binds = { - pass_mouse_when_bound = false; - movefocus_cycles_fullscreen = false; - }; - - exec-once = let - # https://wiki.hyprland.org/IPC/#how-to-use-socket2-with-bash - handle_hyprland_events = pkgs.writeShellScriptBin "handle_hyprland_events" '' - #!/bin/sh - - handle() { - case $1 in - configreloaded*) - ${hyprland}/bin/hyprctl notify 1 2500 "" " Reloading Hyprland..." - ;; - esac - } - - ${pkgs.socat}/bin/socat -U - UNIX-CONNECT:/tmp/hypr/$HYPRLAND_INSTANCE_SIGNATURE/.socket2.sock | - while read -r line; do - handle "$line" - done - ''; - in [ - "waybar" - - # run persistent special workspace windows - "[workspace special:nixos silent;tile] cd ~/niksos; ${foot}/bin/foot" - (mkIf config.services.asusd.enable - "[workspace special:rog silent;tile] ${config.services.asusd.package}/bin/rog-control-center") - "[workspace special:keepassxc silent;tile] ${pkgs.keepassxc}/bin/keepassxc" - - (if config.modules.programs.foot.server then "sleep 0.5 && ${pkgs.systemd}/bin/systemctl --user restart foot.service" else ";") - - "${hyprland}/bin/hyprctl setcursor Bibata-Modern-Classic 24" - - # TODO do something with this - #"${wl-clipboard}/bin/wl-paste --watch cliphist store" - - "${swww}/bin/swww init" - "${wlsunset}/bin/wlsunset -S 06:00 -s 20:00" - # TODO fix fcitx5 - #"fcitx5" - # TODO do these do anything anymore - "${pkgs.systemd}/bin/systemctl --user import-environment WAYLAND_DISPLAY XDG_CURRENT_DESKTOP" - "${pkgs.dbus}/bin/dbus-update-activation-environment --systemd WAYLAND_DISPLAY XDG_CURRENT_DESKTOP=$XDG_CURRENT_DESKTOP" - "rot8 --threshold 0.75" - "${handle_hyprland_events}/bin/handle_hyprland_events" - "wvkbd-mobintl --hidden -L 500" - ]; - - exec = [ - # kill (almost) everything on special workspaces - "${pkgs.procps}/bin/pkill btop" - "${pkgs.procps}/bin/pkill helvum" - "${pkgs.procps}/bin/pkill pavucontrol" - # and run it all again - "[workspace special:btop silent;tile] ${foot}/bin/foot -e ${pkgs.btop}/bin/btop" - "[workspace special:pipewire silent;tile] ${pkgs.helvum}/bin/helvum" - "[workspace special:pipewire silent;tile] ${pkgs.pavucontrol}/bin/pavucontrol" - - # wait a bit then set the wallpapers -# "sleep 0.5 && ${swww}/bin/swww img -o eDP-1 ~/catppuccin-wall0.png" -# "sleep 0.5 && ${swww}/bin/swww img -o HDMI-A-1 ~/catppuccin-wall1.png" - - "${pkgs.networkmanagerapplet}/bin/nm-applet --indicator" - "${pkgs.blueman}/bin/blueman-applet" - ]; - - layerrule = [ - # no black border on grimblast screenshots - "noanim, ^(selection)$" - - "blur, ^(waybar)$" - "blur, ^(eww)$" - - # TODO maybe this isn't needed - # temporary fix to swaylock screenshoting rofi before locking - #"noanim, ^(rofi)$" - - "blur, ^(anyrun)$" - ]; - - plugin = { - split-monitor-workspaces = { - count = 10; - keep_focused = true; - }; - }; - } // cfg.extraSettings; - }; - }; - }; -} diff --git a/hosts/vali/mars/hypr/lock.nix b/hosts/vali/mars/hypr/lock.nix deleted file mode 100644 index 25c65ca..0000000 --- a/hosts/vali/mars/hypr/lock.nix +++ /dev/null @@ -1,81 +0,0 @@ -{ - config, - inputs, - lib, - pkgs, - ... -}: with lib; let - cfg = config.modules.programs.hypr.lock; - username = config.modules.other.system.username; - - text_color = "rgba(eae0e4FF)"; -in { - options.modules.programs.hypr.lock = { - enable = mkEnableOption "hiper zamek"; - extraSettings = mkOption { - type = types.attrs; - description = "extra per host hyprlock settings"; - default = {}; - }; - }; - - config = mkIf cfg.enable { - home-manager.users.${username} = { - imports = [ inputs.hyprlock.homeManagerModules.default ]; - - programs.hyprlock = { - enable = true; - package = inputs.hyprlock.packages.${pkgs.system}.hyprlock; - general = { - grace = 2; - }; - backgrounds = [ - { - color = "rgba(120f1177)"; - path = "screenshot"; - blur_size = 5; - blur_passes = 4; - } - ]; - - input-fields = [ - { - size = { - width = 600; - height = 50; - }; - outline_thickness = 3; - dots_size = 0.1; - dots_spacing = 0.3; - outer_color = "rgba(9a8d9555)"; - inner_color = "rgba(120f1111)"; - font_color = "rgba(d1c2cbff)"; - fade_on_empty = true; - position = { - x = 0; - y = 20; - }; - halign = "center"; - valign = "center"; - } - ]; - - labels = [ - { - # clock - text = "$TIME"; - color = text_color; - font_size = 65; - position = { - x = 0; - y = 300; - }; - halign = "center"; - valign = "center"; - } - - ]; - }; - }; - }; -} From 9a67c4009f726e40e84ee1c7d38353e4c2ca0994 Mon Sep 17 00:00:00 2001 From: LarsZauberer Date: Sat, 13 Apr 2024 21:08:08 +0200 Subject: [PATCH 18/27] Added wofi --- hosts/lars/hyprland.nix | 1 + hosts/lars/programs.nix | 1 + 2 files changed, 2 insertions(+) diff --git a/hosts/lars/hyprland.nix b/hosts/lars/hyprland.nix index dfbeee3..0b7f57e 100644 --- a/hosts/lars/hyprland.nix +++ b/hosts/lars/hyprland.nix @@ -83,6 +83,7 @@ in { "$mod SHIFT, m, exit" ", F11, exec, pamixer -d 2" ", F12, exec, pamixer -i 2" + "$mod, d, exec, wofi --show drun" # Application "$mod SHIFT, c, exec, code --enable-features=UseOzonePlatform --ozone-platform=wayland --disable-gpu" diff --git a/hosts/lars/programs.nix b/hosts/lars/programs.nix index 459545e..a9a55c3 100644 --- a/hosts/lars/programs.nix +++ b/hosts/lars/programs.nix @@ -53,6 +53,7 @@ in { slurp wl-clipboard pavucontrol + wofi ]; }; } From 26c8590a99c7d97df4b6877631227d75e1cbf2ba Mon Sep 17 00:00:00 2001 From: LarsZauberer Date: Sat, 13 Apr 2024 21:08:22 +0200 Subject: [PATCH 19/27] completely fixed firefox --- hosts/lars/default.nix | 12 ++++++++---- modules/gui/firefox.nix | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 4 deletions(-) diff --git a/hosts/lars/default.nix b/hosts/lars/default.nix index 71b892e..0cb39a8 100644 --- a/hosts/lars/default.nix +++ b/hosts/lars/default.nix @@ -20,7 +20,7 @@ vesktop.enable = true; btop.enable = true; mpv.enable = true; - schizofox.enable = true; + schizofox.enable = false; zsh = { enable = true; @@ -46,7 +46,11 @@ enable = true; extensions = { "support@lastpass.com" = { - install_url = "https://addons.mozilla.org/de/firefox/addon/lastpass-password-manager/"; + install_url = "https://addons.mozilla.org/firefox/downloads/file/4246455/lastpass_password_manager-4.127.0.1.xpi"; + installation_mode = "force_installed"; + }; + "newtaboverride@agenedia.com" = { + install_url = "https://addons.mozilla.org/firefox/downloads/file/4231522/new_tab_override-16.0.0.xpi"; installation_mode = "force_installed"; }; }; @@ -65,7 +69,7 @@ size = 24; }; gtk = { - enable = false; + enable = true; package = pkgs.catppuccin-gtk; name = "Catppuccin-Mocha-Standard-Green-Dark"; variant = "mocha"; @@ -76,7 +80,7 @@ }; }; qt = { - enable = false; + enable = true; package = pkgs.catppuccin-kde; name = "Catppuccin-Mocha-Dark"; variant = "mocha"; diff --git a/modules/gui/firefox.nix b/modules/gui/firefox.nix index 06125cd..07704ca 100644 --- a/modules/gui/firefox.nix +++ b/modules/gui/firefox.nix @@ -16,7 +16,41 @@ in { home-manager.users.${username} = { programs.firefox = { enable = true; + policies = { + DisableTelemetry = true; + DisableFirefoxStudies = true; + EnableTrackingProtection = { + Value= true; + Locked = true; + Cryptomining = true; + Fingerprinting = true; + }; + DisablePocket = true; + DisableFirefoxAccounts = true; + DisableAccounts = true; + DisableFirefoxScreenshots = true; + OverrideFirstRunPage = ""; + OverridePostUpdatePage = ""; + DontCheckDefaultBrowser = true; + DisplayBookmarksToolbar = "never"; # alternatives: "always" or "newtab" + DisplayMenuBar = "default-off"; # alternatives: "always", "never" or "default-on" + SearchBar = "unified"; # alternative: "separate" + FirefoxSuggest = { + WebSuggestions = true; + ImproveSuggest = true; + Locked = true; + }; + SearchSuggestEnabled = true; + theme = { + colors = { + background-darker = "181825"; + background = "1e1e2e"; + foreground = "cdd6f4"; + }; + }; + + font = "Lexend"; ExtensionSettings = lib.mkMerge [{ "uBlock0@raymondhill.net" = { install_url = "https://addons.mozilla.org/firefox/downloads/latest/ublock-origin/latest.xpi"; From 4ffc02a065ff35c81fede9c946bbec8d245f57d9 Mon Sep 17 00:00:00 2001 From: vali Date: Sat, 13 Apr 2024 21:22:44 +0200 Subject: [PATCH 20/27] added dwm --- hosts/vali/mars/configuration.nix | 2 +- hosts/vali/mars/dwm/dwm-6.5/LICENSE | 38 + hosts/vali/mars/dwm/dwm-6.5/Makefile | 45 + hosts/vali/mars/dwm/dwm-6.5/README | 48 + hosts/vali/mars/dwm/dwm-6.5/config.def.h | 116 ++ hosts/vali/mars/dwm/dwm-6.5/config.mk | 39 + hosts/vali/mars/dwm/dwm-6.5/drw.c | 450 +++++ hosts/vali/mars/dwm/dwm-6.5/drw.h | 58 + hosts/vali/mars/dwm/dwm-6.5/dwm.1 | 176 ++ hosts/vali/mars/dwm/dwm-6.5/dwm.c | 2165 ++++++++++++++++++++++ hosts/vali/mars/dwm/dwm-6.5/dwm.png | Bin 0 -> 373 bytes hosts/vali/mars/dwm/dwm-6.5/transient.c | 42 + hosts/vali/mars/dwm/dwm-6.5/util.c | 36 + hosts/vali/mars/dwm/dwm-6.5/util.h | 8 + hosts/vali/mars/dwm/dwm.nix | 22 + hosts/vali/mars/programs.nix | 2 + modules/gui/schizofox.nix | 1 - 17 files changed, 3246 insertions(+), 2 deletions(-) create mode 100644 hosts/vali/mars/dwm/dwm-6.5/LICENSE create mode 100644 hosts/vali/mars/dwm/dwm-6.5/Makefile create mode 100644 hosts/vali/mars/dwm/dwm-6.5/README create mode 100644 hosts/vali/mars/dwm/dwm-6.5/config.def.h create mode 100644 hosts/vali/mars/dwm/dwm-6.5/config.mk create mode 100644 hosts/vali/mars/dwm/dwm-6.5/drw.c create mode 100644 hosts/vali/mars/dwm/dwm-6.5/drw.h create mode 100644 hosts/vali/mars/dwm/dwm-6.5/dwm.1 create mode 100644 hosts/vali/mars/dwm/dwm-6.5/dwm.c create mode 100644 hosts/vali/mars/dwm/dwm-6.5/dwm.png create mode 100644 hosts/vali/mars/dwm/dwm-6.5/transient.c create mode 100644 hosts/vali/mars/dwm/dwm-6.5/util.c create mode 100644 hosts/vali/mars/dwm/dwm-6.5/util.h create mode 100644 hosts/vali/mars/dwm/dwm.nix diff --git a/hosts/vali/mars/configuration.nix b/hosts/vali/mars/configuration.nix index ada9ab0..05ade7b 100644 --- a/hosts/vali/mars/configuration.nix +++ b/hosts/vali/mars/configuration.nix @@ -52,7 +52,7 @@ ssh.enable = true; btop.enable = true; mpv.enable = true; - i3.enable = true; + dwm.enable = true; schizofox.enable = true; displaymanager.enable = true; #neovim.enable = true; diff --git a/hosts/vali/mars/dwm/dwm-6.5/LICENSE b/hosts/vali/mars/dwm/dwm-6.5/LICENSE new file mode 100644 index 0000000..995172f --- /dev/null +++ b/hosts/vali/mars/dwm/dwm-6.5/LICENSE @@ -0,0 +1,38 @@ +MIT/X Consortium License + +© 2006-2019 Anselm R Garbe +© 2006-2009 Jukka Salmi +© 2006-2007 Sander van Dijk +© 2007-2011 Peter Hartlich +© 2007-2009 Szabolcs Nagy +© 2007-2009 Christof Musik +© 2007-2009 Premysl Hruby +© 2007-2008 Enno Gottox Boland +© 2008 Martin Hurton +© 2008 Neale Pickett +© 2009 Mate Nagy +© 2010-2016 Hiltjo Posthuma +© 2010-2012 Connor Lane Smith +© 2011 Christoph Lohmann <20h@r-36.net> +© 2015-2016 Quentin Rameau +© 2015-2016 Eric Pruitt +© 2016-2017 Markus Teich +© 2020-2022 Chris Down + +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/hosts/vali/mars/dwm/dwm-6.5/Makefile b/hosts/vali/mars/dwm/dwm-6.5/Makefile new file mode 100644 index 0000000..ffa69b4 --- /dev/null +++ b/hosts/vali/mars/dwm/dwm-6.5/Makefile @@ -0,0 +1,45 @@ +# dwm - dynamic window manager +# See LICENSE file for copyright and license details. + +include config.mk + +SRC = drw.c dwm.c util.c +OBJ = ${SRC:.c=.o} + +all: dwm + +.c.o: + ${CC} -c ${CFLAGS} $< + +${OBJ}: config.h config.mk + +config.h: + cp config.def.h $@ + +dwm: ${OBJ} + ${CC} -o $@ ${OBJ} ${LDFLAGS} + +clean: + rm -f dwm ${OBJ} dwm-${VERSION}.tar.gz + +dist: clean + mkdir -p dwm-${VERSION} + cp -R LICENSE Makefile README config.def.h config.mk\ + dwm.1 drw.h util.h ${SRC} dwm.png transient.c dwm-${VERSION} + tar -cf dwm-${VERSION}.tar dwm-${VERSION} + gzip dwm-${VERSION}.tar + rm -rf dwm-${VERSION} + +install: all + mkdir -p ${DESTDIR}${PREFIX}/bin + cp -f dwm ${DESTDIR}${PREFIX}/bin + chmod 755 ${DESTDIR}${PREFIX}/bin/dwm + mkdir -p ${DESTDIR}${MANPREFIX}/man1 + sed "s/VERSION/${VERSION}/g" < dwm.1 > ${DESTDIR}${MANPREFIX}/man1/dwm.1 + chmod 644 ${DESTDIR}${MANPREFIX}/man1/dwm.1 + +uninstall: + rm -f ${DESTDIR}${PREFIX}/bin/dwm\ + ${DESTDIR}${MANPREFIX}/man1/dwm.1 + +.PHONY: all clean dist install uninstall diff --git a/hosts/vali/mars/dwm/dwm-6.5/README b/hosts/vali/mars/dwm/dwm-6.5/README new file mode 100644 index 0000000..95d4fd0 --- /dev/null +++ b/hosts/vali/mars/dwm/dwm-6.5/README @@ -0,0 +1,48 @@ +dwm - dynamic window manager +============================ +dwm is an extremely fast, small, and dynamic window manager for X. + + +Requirements +------------ +In order to build dwm you need the Xlib header files. + + +Installation +------------ +Edit config.mk to match your local setup (dwm is installed into +the /usr/local namespace by default). + +Afterwards enter the following command to build and install dwm (if +necessary as root): + + make clean install + + +Running dwm +----------- +Add the following line to your .xinitrc to start dwm using startx: + + exec dwm + +In order to connect dwm to a specific display, make sure that +the DISPLAY environment variable is set correctly, e.g.: + + DISPLAY=foo.bar:1 exec dwm + +(This will start dwm on display :1 of the host foo.bar.) + +In order to display status info in the bar, you can do something +like this in your .xinitrc: + + while xsetroot -name "`date` `uptime | sed 's/.*,//'`" + do + sleep 1 + done & + exec dwm + + +Configuration +------------- +The configuration of dwm is done by creating a custom config.h +and (re)compiling the source code. diff --git a/hosts/vali/mars/dwm/dwm-6.5/config.def.h b/hosts/vali/mars/dwm/dwm-6.5/config.def.h new file mode 100644 index 0000000..9efa774 --- /dev/null +++ b/hosts/vali/mars/dwm/dwm-6.5/config.def.h @@ -0,0 +1,116 @@ +/* See LICENSE file for copyright and license details. */ + +/* appearance */ +static const unsigned int borderpx = 1; /* border pixel of windows */ +static const unsigned int snap = 32; /* snap pixel */ +static const int showbar = 1; /* 0 means no bar */ +static const int topbar = 1; /* 0 means bottom bar */ +static const char *fonts[] = { "monospace:size=10" }; +static const char dmenufont[] = "monospace:size=10"; +static const char col_gray1[] = "#222222"; +static const char col_gray2[] = "#444444"; +static const char col_gray3[] = "#bbbbbb"; +static const char col_gray4[] = "#eeeeee"; +static const char col_cyan[] = "#005577"; +static const char *colors[][3] = { + /* fg bg border */ + [SchemeNorm] = { col_gray3, col_gray1, col_gray2 }, + [SchemeSel] = { col_gray4, col_cyan, col_cyan }, +}; + +/* tagging */ +static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" }; + +static const Rule rules[] = { + /* xprop(1): + * WM_CLASS(STRING) = instance, class + * WM_NAME(STRING) = title + */ + /* class instance title tags mask isfloating monitor */ + { "Gimp", NULL, NULL, 0, 1, -1 }, + { "Firefox", NULL, NULL, 1 << 8, 0, -1 }, +}; + +/* layout(s) */ +static const float mfact = 0.55; /* factor of master area size [0.05..0.95] */ +static const int nmaster = 1; /* number of clients in master area */ +static const int resizehints = 1; /* 1 means respect size hints in tiled resizals */ +static const int lockfullscreen = 1; /* 1 will force focus on the fullscreen window */ + +static const Layout layouts[] = { + /* symbol arrange function */ + { "[]=", tile }, /* first entry is default */ + { "><>", NULL }, /* no layout function means floating behavior */ + { "[M]", monocle }, +}; + +/* key definitions */ +#define MODKEY Mod1Mask +#define TAGKEYS(KEY,TAG) \ + { MODKEY, KEY, view, {.ui = 1 << TAG} }, \ + { MODKEY|ControlMask, KEY, toggleview, {.ui = 1 << TAG} }, \ + { MODKEY|ShiftMask, KEY, tag, {.ui = 1 << TAG} }, \ + { MODKEY|ControlMask|ShiftMask, KEY, toggletag, {.ui = 1 << TAG} }, + +/* helper for spawning shell commands in the pre dwm-5.0 fashion */ +#define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } } + +/* commands */ +static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() */ +static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", dmenufont, "-nb", col_gray1, "-nf", col_gray3, "-sb", col_cyan, "-sf", col_gray4, NULL }; +static const char *termcmd[] = { "st", NULL }; + +static const Key keys[] = { + /* modifier key function argument */ + { MODKEY, XK_p, spawn, {.v = dmenucmd } }, + { MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } }, + { MODKEY, XK_b, togglebar, {0} }, + { MODKEY, XK_j, focusstack, {.i = +1 } }, + { MODKEY, XK_k, focusstack, {.i = -1 } }, + { MODKEY, XK_i, incnmaster, {.i = +1 } }, + { MODKEY, XK_d, incnmaster, {.i = -1 } }, + { MODKEY, XK_h, setmfact, {.f = -0.05} }, + { MODKEY, XK_l, setmfact, {.f = +0.05} }, + { MODKEY, XK_Return, zoom, {0} }, + { MODKEY, XK_Tab, view, {0} }, + { MODKEY|ShiftMask, XK_c, killclient, {0} }, + { MODKEY, XK_t, setlayout, {.v = &layouts[0]} }, + { MODKEY, XK_f, setlayout, {.v = &layouts[1]} }, + { MODKEY, XK_m, setlayout, {.v = &layouts[2]} }, + { MODKEY, XK_space, setlayout, {0} }, + { MODKEY|ShiftMask, XK_space, togglefloating, {0} }, + { MODKEY, XK_0, view, {.ui = ~0 } }, + { MODKEY|ShiftMask, XK_0, tag, {.ui = ~0 } }, + { MODKEY, XK_comma, focusmon, {.i = -1 } }, + { MODKEY, XK_period, focusmon, {.i = +1 } }, + { MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } }, + { MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } }, + TAGKEYS( XK_1, 0) + TAGKEYS( XK_2, 1) + TAGKEYS( XK_3, 2) + TAGKEYS( XK_4, 3) + TAGKEYS( XK_5, 4) + TAGKEYS( XK_6, 5) + TAGKEYS( XK_7, 6) + TAGKEYS( XK_8, 7) + TAGKEYS( XK_9, 8) + { MODKEY|ShiftMask, XK_q, quit, {0} }, +}; + +/* button definitions */ +/* click can be ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */ +static const Button buttons[] = { + /* click event mask button function argument */ + { ClkLtSymbol, 0, Button1, setlayout, {0} }, + { ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} }, + { ClkWinTitle, 0, Button2, zoom, {0} }, + { ClkStatusText, 0, Button2, spawn, {.v = termcmd } }, + { ClkClientWin, MODKEY, Button1, movemouse, {0} }, + { ClkClientWin, MODKEY, Button2, togglefloating, {0} }, + { ClkClientWin, MODKEY, Button3, resizemouse, {0} }, + { ClkTagBar, 0, Button1, view, {0} }, + { ClkTagBar, 0, Button3, toggleview, {0} }, + { ClkTagBar, MODKEY, Button1, tag, {0} }, + { ClkTagBar, MODKEY, Button3, toggletag, {0} }, +}; + diff --git a/hosts/vali/mars/dwm/dwm-6.5/config.mk b/hosts/vali/mars/dwm/dwm-6.5/config.mk new file mode 100644 index 0000000..8efca9a --- /dev/null +++ b/hosts/vali/mars/dwm/dwm-6.5/config.mk @@ -0,0 +1,39 @@ +# dwm version +VERSION = 6.5 + +# Customize below to fit your system + +# 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=700L -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} +#CFLAGS = -g -std=c99 -pedantic -Wall -O0 ${INCS} ${CPPFLAGS} +CFLAGS = -std=c99 -pedantic -Wall -Wno-deprecated-declarations -Os ${INCS} ${CPPFLAGS} +LDFLAGS = ${LIBS} + +# Solaris +#CFLAGS = -fast ${INCS} -DVERSION=\"${VERSION}\" +#LDFLAGS = ${LIBS} + +# compiler and linker +CC = cc diff --git a/hosts/vali/mars/dwm/dwm-6.5/drw.c b/hosts/vali/mars/dwm/dwm-6.5/drw.c new file mode 100644 index 0000000..a58a2b4 --- /dev/null +++ b/hosts/vali/mars/dwm/dwm-6.5/drw.c @@ -0,0 +1,450 @@ +/* See LICENSE file for copyright and license details. */ +#include +#include +#include +#include +#include + +#include "drw.h" +#include "util.h" + +#define UTF_INVALID 0xFFFD +#define UTF_SIZ 4 + +static const unsigned char utfbyte[UTF_SIZ + 1] = {0x80, 0, 0xC0, 0xE0, 0xF0}; +static const unsigned char utfmask[UTF_SIZ + 1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8}; +static const long utfmin[UTF_SIZ + 1] = { 0, 0, 0x80, 0x800, 0x10000}; +static const long utfmax[UTF_SIZ + 1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF}; + +static long +utf8decodebyte(const char c, size_t *i) +{ + for (*i = 0; *i < (UTF_SIZ + 1); ++(*i)) + if (((unsigned char)c & utfmask[*i]) == utfbyte[*i]) + return (unsigned char)c & ~utfmask[*i]; + return 0; +} + +static size_t +utf8validate(long *u, size_t i) +{ + if (!BETWEEN(*u, utfmin[i], utfmax[i]) || BETWEEN(*u, 0xD800, 0xDFFF)) + *u = UTF_INVALID; + for (i = 1; *u > utfmax[i]; ++i) + ; + return i; +} + +static size_t +utf8decode(const char *c, long *u, size_t clen) +{ + size_t i, j, len, type; + long udecoded; + + *u = UTF_INVALID; + if (!clen) + return 0; + udecoded = utf8decodebyte(c[0], &len); + if (!BETWEEN(len, 1, UTF_SIZ)) + return 1; + for (i = 1, j = 1; i < clen && j < len; ++i, ++j) { + udecoded = (udecoded << 6) | utf8decodebyte(c[i], &type); + if (type) + return j; + } + if (j < len) + return 0; + *u = udecoded; + utf8validate(u, len); + + 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 i, ty, ellipsis_x = 0; + unsigned int tmpw, ew, ellipsis_w = 0, ellipsis_len; + XftDraw *d = NULL; + Fnt *usedfont, *curfont, *nextfont; + int utf8strlen, utf8charlen, 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. */ + enum { nomatches_len = 64 }; + static struct { long codepoint[nomatches_len]; unsigned int idx; } nomatches; + static unsigned int ellipsis_width = 0; + + 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); + 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, "..."); + while (1) { + ew = ellipsis_len = utf8strlen = 0; + utf8str = text; + nextfont = NULL; + while (*text) { + utf8charlen = utf8decode(text, &utf8codepoint, UTF_SIZ); + 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) { + utf8strlen += utf8charlen; + text += utf8charlen; + ew += tmpw; + } else { + nextfont = curfont; + } + break; + } + } + + if (overflow || !charexists || nextfont) + 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 (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; + + for (i = 0; i < nomatches_len; ++i) { + /* avoid calling XftFontMatch if we know we won't find a match */ + if (utf8codepoint == nomatches.codepoint[i]) + 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.codepoint[++nomatches.idx % nomatches_len] = 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/hosts/vali/mars/dwm/dwm-6.5/drw.h b/hosts/vali/mars/dwm/dwm-6.5/drw.h new file mode 100644 index 0000000..6471431 --- /dev/null +++ b/hosts/vali/mars/dwm/dwm-6.5/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, ColBorder }; /* 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/hosts/vali/mars/dwm/dwm-6.5/dwm.1 b/hosts/vali/mars/dwm/dwm-6.5/dwm.1 new file mode 100644 index 0000000..ddc8321 --- /dev/null +++ b/hosts/vali/mars/dwm/dwm-6.5/dwm.1 @@ -0,0 +1,176 @@ +.TH DWM 1 dwm\-VERSION +.SH NAME +dwm \- dynamic window manager +.SH SYNOPSIS +.B dwm +.RB [ \-v ] +.SH DESCRIPTION +dwm is a dynamic window manager for X. It manages windows in tiled, monocle +and floating layouts. Either layout can be applied dynamically, optimising the +environment for the application in use and the task performed. +.P +In tiled layouts windows are managed in a master and stacking area. The master +area on the left contains one window by default, and the stacking area on the +right contains all other windows. The number of master area windows can be +adjusted from zero to an arbitrary number. In monocle layout all windows are +maximised to the screen size. In floating layout windows can be resized and +moved freely. Dialog windows are always managed floating, regardless of the +layout applied. +.P +Windows are grouped by tags. Each window can be tagged with one or multiple +tags. Selecting certain tags displays all windows with these tags. +.P +Each screen contains a small status bar which displays all available tags, the +layout, the title of the focused window, and the text read from the root window +name property, if the screen is focused. A floating window is indicated with an +empty square and a maximised floating window is indicated with a filled square +before the windows title. The selected tags are indicated with a different +color. The tags of the focused window are indicated with a filled square in the +top left corner. The tags which are applied to one or more windows are +indicated with an empty square in the top left corner. +.P +dwm draws a small border around windows to indicate the focus state. +.SH OPTIONS +.TP +.B \-v +prints version information to stderr, then exits. +.SH USAGE +.SS Status bar +.TP +.B X root window name +is read and displayed in the status text area. It can be set with the +.BR xsetroot (1) +command. +.TP +.B Button1 +click on a tag label to display all windows with that tag, click on the layout +label toggles between tiled and floating layout. +.TP +.B Button3 +click on a tag label adds/removes all windows with that tag to/from the view. +.TP +.B Mod1\-Button1 +click on a tag label applies that tag to the focused window. +.TP +.B Mod1\-Button3 +click on a tag label adds/removes that tag to/from the focused window. +.SS Keyboard commands +.TP +.B Mod1\-Shift\-Return +Start +.BR st(1). +.TP +.B Mod1\-p +Spawn +.BR dmenu(1) +for launching other programs. +.TP +.B Mod1\-, +Focus previous screen, if any. +.TP +.B Mod1\-. +Focus next screen, if any. +.TP +.B Mod1\-Shift\-, +Send focused window to previous screen, if any. +.TP +.B Mod1\-Shift\-. +Send focused window to next screen, if any. +.TP +.B Mod1\-b +Toggles bar on and off. +.TP +.B Mod1\-t +Sets tiled layout. +.TP +.B Mod1\-f +Sets floating layout. +.TP +.B Mod1\-m +Sets monocle layout. +.TP +.B Mod1\-space +Toggles between current and previous layout. +.TP +.B Mod1\-j +Focus next window. +.TP +.B Mod1\-k +Focus previous window. +.TP +.B Mod1\-i +Increase number of windows in master area. +.TP +.B Mod1\-d +Decrease number of windows in master area. +.TP +.B Mod1\-l +Increase master area size. +.TP +.B Mod1\-h +Decrease master area size. +.TP +.B Mod1\-Return +Zooms/cycles focused window to/from master area (tiled layouts only). +.TP +.B Mod1\-Shift\-c +Close focused window. +.TP +.B Mod1\-Shift\-space +Toggle focused window between tiled and floating state. +.TP +.B Mod1\-Tab +Toggles to the previously selected tags. +.TP +.B Mod1\-Shift\-[1..n] +Apply nth tag to focused window. +.TP +.B Mod1\-Shift\-0 +Apply all tags to focused window. +.TP +.B Mod1\-Control\-Shift\-[1..n] +Add/remove nth tag to/from focused window. +.TP +.B Mod1\-[1..n] +View all windows with nth tag. +.TP +.B Mod1\-0 +View all windows with any tag. +.TP +.B Mod1\-Control\-[1..n] +Add/remove all windows with nth tag to/from the view. +.TP +.B Mod1\-Shift\-q +Quit dwm. +.SS Mouse commands +.TP +.B Mod1\-Button1 +Move focused window while dragging. Tiled windows will be toggled to the floating state. +.TP +.B Mod1\-Button2 +Toggles focused window between floating and tiled state. +.TP +.B Mod1\-Button3 +Resize focused window while dragging. Tiled windows will be toggled to the floating state. +.SH CUSTOMIZATION +dwm is customized by creating a custom config.h and (re)compiling the source +code. This keeps it fast, secure and simple. +.SH SEE ALSO +.BR dmenu (1), +.BR st (1) +.SH ISSUES +Java applications which use the XToolkit/XAWT backend may draw grey windows +only. The XToolkit/XAWT backend breaks ICCCM-compliance in recent JDK 1.5 and early +JDK 1.6 versions, because it assumes a reparenting window manager. Possible workarounds +are using JDK 1.4 (which doesn't contain the XToolkit/XAWT backend) or setting the +environment variable +.BR AWT_TOOLKIT=MToolkit +(to use the older Motif backend instead) or running +.B xprop -root -f _NET_WM_NAME 32a -set _NET_WM_NAME LG3D +or +.B wmname LG3D +(to pretend that a non-reparenting window manager is running that the +XToolkit/XAWT backend can recognize) or when using OpenJDK setting the environment variable +.BR _JAVA_AWT_WM_NONREPARENTING=1 . +.SH BUGS +Send all bug reports with a patch to hackers@suckless.org. diff --git a/hosts/vali/mars/dwm/dwm-6.5/dwm.c b/hosts/vali/mars/dwm/dwm-6.5/dwm.c new file mode 100644 index 0000000..f1d86b2 --- /dev/null +++ b/hosts/vali/mars/dwm/dwm-6.5/dwm.c @@ -0,0 +1,2165 @@ +/* See LICENSE file for copyright and license details. + * + * dynamic window manager is designed like any other X client as well. It is + * driven through handling X events. In contrast to other X clients, a window + * manager selects for SubstructureRedirectMask on the root window, to receive + * events about window (dis-)appearance. Only one X connection at a time is + * allowed to select for this event mask. + * + * The event handlers of dwm are organized in an array which is accessed + * whenever a new event has been fetched. This allows event dispatching + * in O(1) time. + * + * Each child of the root window is called a client, except windows which have + * set the override_redirect flag. Clients are organized in a linked client + * list on each monitor, the focus history is remembered through a stack list + * on each monitor. Each client contains a bit array to indicate the tags of a + * client. + * + * Keys and tagging rules are organized as arrays and defined in config.h. + * + * To understand everything else, start reading main(). + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef XINERAMA +#include +#endif /* XINERAMA */ +#include + +#include "drw.h" +#include "util.h" + +/* macros */ +#define BUTTONMASK (ButtonPressMask|ButtonReleaseMask) +#define CLEANMASK(mask) (mask & ~(numlockmask|LockMask) & (ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask)) +#define INTERSECT(x,y,w,h,m) (MAX(0, MIN((x)+(w),(m)->wx+(m)->ww) - MAX((x),(m)->wx)) \ + * MAX(0, MIN((y)+(h),(m)->wy+(m)->wh) - MAX((y),(m)->wy))) +#define ISVISIBLE(C) ((C->tags & C->mon->tagset[C->mon->seltags])) +#define LENGTH(X) (sizeof X / sizeof X[0]) +#define MOUSEMASK (BUTTONMASK|PointerMotionMask) +#define WIDTH(X) ((X)->w + 2 * (X)->bw) +#define HEIGHT(X) ((X)->h + 2 * (X)->bw) +#define TAGMASK ((1 << LENGTH(tags)) - 1) +#define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad) + +/* enums */ +enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ +enum { SchemeNorm, SchemeSel }; /* color schemes */ +enum { NetSupported, NetWMName, NetWMState, NetWMCheck, + NetWMFullscreen, NetActiveWindow, NetWMWindowType, + NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */ +enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */ +enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, + ClkClientWin, ClkRootWin, ClkLast }; /* clicks */ + +typedef union { + int i; + unsigned int ui; + float f; + const void *v; +} Arg; + +typedef struct { + unsigned int click; + unsigned int mask; + unsigned int button; + void (*func)(const Arg *arg); + const Arg arg; +} Button; + +typedef struct Monitor Monitor; +typedef struct Client Client; +struct Client { + char name[256]; + float mina, maxa; + int x, y, w, h; + int oldx, oldy, oldw, oldh; + int basew, baseh, incw, inch, maxw, maxh, minw, minh, hintsvalid; + int bw, oldbw; + unsigned int tags; + int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen; + Client *next; + Client *snext; + Monitor *mon; + Window win; +}; + +typedef struct { + unsigned int mod; + KeySym keysym; + void (*func)(const Arg *); + const Arg arg; +} Key; + +typedef struct { + const char *symbol; + void (*arrange)(Monitor *); +} Layout; + +struct Monitor { + char ltsymbol[16]; + float mfact; + int nmaster; + int num; + int by; /* bar geometry */ + int mx, my, mw, mh; /* screen size */ + int wx, wy, ww, wh; /* window area */ + unsigned int seltags; + unsigned int sellt; + unsigned int tagset[2]; + int showbar; + int topbar; + Client *clients; + Client *sel; + Client *stack; + Monitor *next; + Window barwin; + const Layout *lt[2]; +}; + +typedef struct { + const char *class; + const char *instance; + const char *title; + unsigned int tags; + int isfloating; + int monitor; +} Rule; + +/* function declarations */ +static void applyrules(Client *c); +static int applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact); +static void arrange(Monitor *m); +static void arrangemon(Monitor *m); +static void attach(Client *c); +static void attachstack(Client *c); +static void buttonpress(XEvent *e); +static void checkotherwm(void); +static void cleanup(void); +static void cleanupmon(Monitor *mon); +static void clientmessage(XEvent *e); +static void configure(Client *c); +static void configurenotify(XEvent *e); +static void configurerequest(XEvent *e); +static Monitor *createmon(void); +static void destroynotify(XEvent *e); +static void detach(Client *c); +static void detachstack(Client *c); +static Monitor *dirtomon(int dir); +static void drawbar(Monitor *m); +static void drawbars(void); +static void enternotify(XEvent *e); +static void expose(XEvent *e); +static void focus(Client *c); +static void focusin(XEvent *e); +static void focusmon(const Arg *arg); +static void focusstack(const Arg *arg); +static Atom getatomprop(Client *c, Atom prop); +static int getrootptr(int *x, int *y); +static long getstate(Window w); +static int gettextprop(Window w, Atom atom, char *text, unsigned int size); +static void grabbuttons(Client *c, int focused); +static void grabkeys(void); +static void incnmaster(const Arg *arg); +static void keypress(XEvent *e); +static void killclient(const Arg *arg); +static void manage(Window w, XWindowAttributes *wa); +static void mappingnotify(XEvent *e); +static void maprequest(XEvent *e); +static void monocle(Monitor *m); +static void motionnotify(XEvent *e); +static void movemouse(const Arg *arg); +static Client *nexttiled(Client *c); +static void pop(Client *c); +static void propertynotify(XEvent *e); +static void quit(const Arg *arg); +static Monitor *recttomon(int x, int y, int w, int h); +static void resize(Client *c, int x, int y, int w, int h, int interact); +static void resizeclient(Client *c, int x, int y, int w, int h); +static void resizemouse(const Arg *arg); +static void restack(Monitor *m); +static void run(void); +static void scan(void); +static int sendevent(Client *c, Atom proto); +static void sendmon(Client *c, Monitor *m); +static void setclientstate(Client *c, long state); +static void setfocus(Client *c); +static void setfullscreen(Client *c, int fullscreen); +static void setlayout(const Arg *arg); +static void setmfact(const Arg *arg); +static void setup(void); +static void seturgent(Client *c, int urg); +static void showhide(Client *c); +static void spawn(const Arg *arg); +static void tag(const Arg *arg); +static void tagmon(const Arg *arg); +static void tile(Monitor *m); +static void togglebar(const Arg *arg); +static void togglefloating(const Arg *arg); +static void toggletag(const Arg *arg); +static void toggleview(const Arg *arg); +static void unfocus(Client *c, int setfocus); +static void unmanage(Client *c, int destroyed); +static void unmapnotify(XEvent *e); +static void updatebarpos(Monitor *m); +static void updatebars(void); +static void updateclientlist(void); +static int updategeom(void); +static void updatenumlockmask(void); +static void updatesizehints(Client *c); +static void updatestatus(void); +static void updatetitle(Client *c); +static void updatewindowtype(Client *c); +static void updatewmhints(Client *c); +static void view(const Arg *arg); +static Client *wintoclient(Window w); +static Monitor *wintomon(Window w); +static int xerror(Display *dpy, XErrorEvent *ee); +static int xerrordummy(Display *dpy, XErrorEvent *ee); +static int xerrorstart(Display *dpy, XErrorEvent *ee); +static void zoom(const Arg *arg); + +/* variables */ +static const char broken[] = "broken"; +static char stext[256]; +static int screen; +static int sw, sh; /* X display screen geometry width, height */ +static int bh; /* bar height */ +static int lrpad; /* sum of left and right padding for text */ +static int (*xerrorxlib)(Display *, XErrorEvent *); +static unsigned int numlockmask = 0; +static void (*handler[LASTEvent]) (XEvent *) = { + [ButtonPress] = buttonpress, + [ClientMessage] = clientmessage, + [ConfigureRequest] = configurerequest, + [ConfigureNotify] = configurenotify, + [DestroyNotify] = destroynotify, + [EnterNotify] = enternotify, + [Expose] = expose, + [FocusIn] = focusin, + [KeyPress] = keypress, + [MappingNotify] = mappingnotify, + [MapRequest] = maprequest, + [MotionNotify] = motionnotify, + [PropertyNotify] = propertynotify, + [UnmapNotify] = unmapnotify +}; +static Atom wmatom[WMLast], netatom[NetLast]; +static int running = 1; +static Cur *cursor[CurLast]; +static Clr **scheme; +static Display *dpy; +static Drw *drw; +static Monitor *mons, *selmon; +static Window root, wmcheckwin; + +/* configuration, allows nested code to access above variables */ +#include "config.h" + +/* compile-time check if all tags fit into an unsigned int bit array. */ +struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; }; + +/* function implementations */ +void +applyrules(Client *c) +{ + const char *class, *instance; + unsigned int i; + const Rule *r; + Monitor *m; + XClassHint ch = { NULL, NULL }; + + /* rule matching */ + c->isfloating = 0; + c->tags = 0; + XGetClassHint(dpy, c->win, &ch); + class = ch.res_class ? ch.res_class : broken; + instance = ch.res_name ? ch.res_name : broken; + + for (i = 0; i < LENGTH(rules); i++) { + r = &rules[i]; + if ((!r->title || strstr(c->name, r->title)) + && (!r->class || strstr(class, r->class)) + && (!r->instance || strstr(instance, r->instance))) + { + c->isfloating = r->isfloating; + c->tags |= r->tags; + for (m = mons; m && m->num != r->monitor; m = m->next); + if (m) + c->mon = m; + } + } + if (ch.res_class) + XFree(ch.res_class); + if (ch.res_name) + XFree(ch.res_name); + c->tags = c->tags & TAGMASK ? c->tags & TAGMASK : c->mon->tagset[c->mon->seltags]; +} + +int +applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact) +{ + int baseismin; + Monitor *m = c->mon; + + /* set minimum possible */ + *w = MAX(1, *w); + *h = MAX(1, *h); + if (interact) { + if (*x > sw) + *x = sw - WIDTH(c); + if (*y > sh) + *y = sh - HEIGHT(c); + if (*x + *w + 2 * c->bw < 0) + *x = 0; + if (*y + *h + 2 * c->bw < 0) + *y = 0; + } else { + if (*x >= m->wx + m->ww) + *x = m->wx + m->ww - WIDTH(c); + if (*y >= m->wy + m->wh) + *y = m->wy + m->wh - HEIGHT(c); + if (*x + *w + 2 * c->bw <= m->wx) + *x = m->wx; + if (*y + *h + 2 * c->bw <= m->wy) + *y = m->wy; + } + if (*h < bh) + *h = bh; + if (*w < bh) + *w = bh; + if (resizehints || c->isfloating || !c->mon->lt[c->mon->sellt]->arrange) { + if (!c->hintsvalid) + updatesizehints(c); + /* see last two sentences in ICCCM 4.1.2.3 */ + baseismin = c->basew == c->minw && c->baseh == c->minh; + if (!baseismin) { /* temporarily remove base dimensions */ + *w -= c->basew; + *h -= c->baseh; + } + /* adjust for aspect limits */ + if (c->mina > 0 && c->maxa > 0) { + if (c->maxa < (float)*w / *h) + *w = *h * c->maxa + 0.5; + else if (c->mina < (float)*h / *w) + *h = *w * c->mina + 0.5; + } + if (baseismin) { /* increment calculation requires this */ + *w -= c->basew; + *h -= c->baseh; + } + /* adjust for increment value */ + if (c->incw) + *w -= *w % c->incw; + if (c->inch) + *h -= *h % c->inch; + /* restore base dimensions */ + *w = MAX(*w + c->basew, c->minw); + *h = MAX(*h + c->baseh, c->minh); + if (c->maxw) + *w = MIN(*w, c->maxw); + if (c->maxh) + *h = MIN(*h, c->maxh); + } + return *x != c->x || *y != c->y || *w != c->w || *h != c->h; +} + +void +arrange(Monitor *m) +{ + if (m) + showhide(m->stack); + else for (m = mons; m; m = m->next) + showhide(m->stack); + if (m) { + arrangemon(m); + restack(m); + } else for (m = mons; m; m = m->next) + arrangemon(m); +} + +void +arrangemon(Monitor *m) +{ + strncpy(m->ltsymbol, m->lt[m->sellt]->symbol, sizeof m->ltsymbol); + if (m->lt[m->sellt]->arrange) + m->lt[m->sellt]->arrange(m); +} + +void +attach(Client *c) +{ + c->next = c->mon->clients; + c->mon->clients = c; +} + +void +attachstack(Client *c) +{ + c->snext = c->mon->stack; + c->mon->stack = c; +} + +void +buttonpress(XEvent *e) +{ + unsigned int i, x, click; + Arg arg = {0}; + Client *c; + Monitor *m; + XButtonPressedEvent *ev = &e->xbutton; + + click = ClkRootWin; + /* focus monitor if necessary */ + if ((m = wintomon(ev->window)) && m != selmon) { + unfocus(selmon->sel, 1); + selmon = m; + focus(NULL); + } + if (ev->window == selmon->barwin) { + i = x = 0; + do + x += TEXTW(tags[i]); + while (ev->x >= x && ++i < LENGTH(tags)); + if (i < LENGTH(tags)) { + click = ClkTagBar; + arg.ui = 1 << i; + } else if (ev->x < x + TEXTW(selmon->ltsymbol)) + click = ClkLtSymbol; + else if (ev->x > selmon->ww - (int)TEXTW(stext)) + click = ClkStatusText; + else + click = ClkWinTitle; + } else if ((c = wintoclient(ev->window))) { + focus(c); + restack(selmon); + XAllowEvents(dpy, ReplayPointer, CurrentTime); + click = ClkClientWin; + } + for (i = 0; i < LENGTH(buttons); i++) + if (click == buttons[i].click && buttons[i].func && buttons[i].button == ev->button + && CLEANMASK(buttons[i].mask) == CLEANMASK(ev->state)) + buttons[i].func(click == ClkTagBar && buttons[i].arg.i == 0 ? &arg : &buttons[i].arg); +} + +void +checkotherwm(void) +{ + xerrorxlib = XSetErrorHandler(xerrorstart); + /* this causes an error if some other window manager is running */ + XSelectInput(dpy, DefaultRootWindow(dpy), SubstructureRedirectMask); + XSync(dpy, False); + XSetErrorHandler(xerror); + XSync(dpy, False); +} + +void +cleanup(void) +{ + Arg a = {.ui = ~0}; + Layout foo = { "", NULL }; + Monitor *m; + size_t i; + + view(&a); + selmon->lt[selmon->sellt] = &foo; + for (m = mons; m; m = m->next) + while (m->stack) + unmanage(m->stack, 0); + XUngrabKey(dpy, AnyKey, AnyModifier, root); + while (mons) + cleanupmon(mons); + for (i = 0; i < CurLast; i++) + drw_cur_free(drw, cursor[i]); + for (i = 0; i < LENGTH(colors); i++) + free(scheme[i]); + free(scheme); + XDestroyWindow(dpy, wmcheckwin); + drw_free(drw); + XSync(dpy, False); + XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime); + XDeleteProperty(dpy, root, netatom[NetActiveWindow]); +} + +void +cleanupmon(Monitor *mon) +{ + Monitor *m; + + if (mon == mons) + mons = mons->next; + else { + for (m = mons; m && m->next != mon; m = m->next); + m->next = mon->next; + } + XUnmapWindow(dpy, mon->barwin); + XDestroyWindow(dpy, mon->barwin); + free(mon); +} + +void +clientmessage(XEvent *e) +{ + XClientMessageEvent *cme = &e->xclient; + Client *c = wintoclient(cme->window); + + if (!c) + return; + if (cme->message_type == netatom[NetWMState]) { + if (cme->data.l[1] == netatom[NetWMFullscreen] + || cme->data.l[2] == netatom[NetWMFullscreen]) + setfullscreen(c, (cme->data.l[0] == 1 /* _NET_WM_STATE_ADD */ + || (cme->data.l[0] == 2 /* _NET_WM_STATE_TOGGLE */ && !c->isfullscreen))); + } else if (cme->message_type == netatom[NetActiveWindow]) { + if (c != selmon->sel && !c->isurgent) + seturgent(c, 1); + } +} + +void +configure(Client *c) +{ + XConfigureEvent ce; + + ce.type = ConfigureNotify; + ce.display = dpy; + ce.event = c->win; + ce.window = c->win; + ce.x = c->x; + ce.y = c->y; + ce.width = c->w; + ce.height = c->h; + ce.border_width = c->bw; + ce.above = None; + ce.override_redirect = False; + XSendEvent(dpy, c->win, False, StructureNotifyMask, (XEvent *)&ce); +} + +void +configurenotify(XEvent *e) +{ + Monitor *m; + Client *c; + XConfigureEvent *ev = &e->xconfigure; + int dirty; + + /* TODO: updategeom handling sucks, needs to be simplified */ + if (ev->window == root) { + dirty = (sw != ev->width || sh != ev->height); + sw = ev->width; + sh = ev->height; + if (updategeom() || dirty) { + drw_resize(drw, sw, bh); + updatebars(); + for (m = mons; m; m = m->next) { + for (c = m->clients; c; c = c->next) + if (c->isfullscreen) + resizeclient(c, m->mx, m->my, m->mw, m->mh); + XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh); + } + focus(NULL); + arrange(NULL); + } + } +} + +void +configurerequest(XEvent *e) +{ + Client *c; + Monitor *m; + XConfigureRequestEvent *ev = &e->xconfigurerequest; + XWindowChanges wc; + + if ((c = wintoclient(ev->window))) { + if (ev->value_mask & CWBorderWidth) + c->bw = ev->border_width; + else if (c->isfloating || !selmon->lt[selmon->sellt]->arrange) { + m = c->mon; + if (ev->value_mask & CWX) { + c->oldx = c->x; + c->x = m->mx + ev->x; + } + if (ev->value_mask & CWY) { + c->oldy = c->y; + c->y = m->my + ev->y; + } + if (ev->value_mask & CWWidth) { + c->oldw = c->w; + c->w = ev->width; + } + if (ev->value_mask & CWHeight) { + c->oldh = c->h; + c->h = ev->height; + } + if ((c->x + c->w) > m->mx + m->mw && c->isfloating) + c->x = m->mx + (m->mw / 2 - WIDTH(c) / 2); /* center in x direction */ + if ((c->y + c->h) > m->my + m->mh && c->isfloating) + c->y = m->my + (m->mh / 2 - HEIGHT(c) / 2); /* center in y direction */ + if ((ev->value_mask & (CWX|CWY)) && !(ev->value_mask & (CWWidth|CWHeight))) + configure(c); + if (ISVISIBLE(c)) + XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h); + } else + configure(c); + } else { + wc.x = ev->x; + wc.y = ev->y; + wc.width = ev->width; + wc.height = ev->height; + wc.border_width = ev->border_width; + wc.sibling = ev->above; + wc.stack_mode = ev->detail; + XConfigureWindow(dpy, ev->window, ev->value_mask, &wc); + } + XSync(dpy, False); +} + +Monitor * +createmon(void) +{ + Monitor *m; + + m = ecalloc(1, sizeof(Monitor)); + m->tagset[0] = m->tagset[1] = 1; + m->mfact = mfact; + m->nmaster = nmaster; + m->showbar = showbar; + m->topbar = topbar; + m->lt[0] = &layouts[0]; + m->lt[1] = &layouts[1 % LENGTH(layouts)]; + strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol); + return m; +} + +void +destroynotify(XEvent *e) +{ + Client *c; + XDestroyWindowEvent *ev = &e->xdestroywindow; + + if ((c = wintoclient(ev->window))) + unmanage(c, 1); +} + +void +detach(Client *c) +{ + Client **tc; + + for (tc = &c->mon->clients; *tc && *tc != c; tc = &(*tc)->next); + *tc = c->next; +} + +void +detachstack(Client *c) +{ + Client **tc, *t; + + for (tc = &c->mon->stack; *tc && *tc != c; tc = &(*tc)->snext); + *tc = c->snext; + + if (c == c->mon->sel) { + for (t = c->mon->stack; t && !ISVISIBLE(t); t = t->snext); + c->mon->sel = t; + } +} + +Monitor * +dirtomon(int dir) +{ + Monitor *m = NULL; + + if (dir > 0) { + if (!(m = selmon->next)) + m = mons; + } else if (selmon == mons) + for (m = mons; m->next; m = m->next); + else + for (m = mons; m->next != selmon; m = m->next); + return m; +} + +void +drawbar(Monitor *m) +{ + int x, w, tw = 0; + int boxs = drw->fonts->h / 9; + int boxw = drw->fonts->h / 6 + 2; + unsigned int i, occ = 0, urg = 0; + Client *c; + + if (!m->showbar) + return; + + /* draw status first so it can be overdrawn by tags later */ + if (m == selmon) { /* status is only drawn on selected monitor */ + drw_setscheme(drw, scheme[SchemeNorm]); + tw = TEXTW(stext) - lrpad + 2; /* 2px right padding */ + drw_text(drw, m->ww - tw, 0, tw, bh, 0, stext, 0); + } + + for (c = m->clients; c; c = c->next) { + occ |= c->tags; + if (c->isurgent) + urg |= c->tags; + } + x = 0; + for (i = 0; i < LENGTH(tags); i++) { + w = TEXTW(tags[i]); + drw_setscheme(drw, scheme[m->tagset[m->seltags] & 1 << i ? SchemeSel : SchemeNorm]); + drw_text(drw, x, 0, w, bh, lrpad / 2, tags[i], urg & 1 << i); + if (occ & 1 << i) + drw_rect(drw, x + boxs, boxs, boxw, boxw, + m == selmon && selmon->sel && selmon->sel->tags & 1 << i, + urg & 1 << i); + x += w; + } + w = TEXTW(m->ltsymbol); + drw_setscheme(drw, scheme[SchemeNorm]); + x = drw_text(drw, x, 0, w, bh, lrpad / 2, m->ltsymbol, 0); + + if ((w = m->ww - tw - x) > bh) { + if (m->sel) { + drw_setscheme(drw, scheme[m == selmon ? SchemeSel : SchemeNorm]); + drw_text(drw, x, 0, w, bh, lrpad / 2, m->sel->name, 0); + if (m->sel->isfloating) + drw_rect(drw, x + boxs, boxs, boxw, boxw, m->sel->isfixed, 0); + } else { + drw_setscheme(drw, scheme[SchemeNorm]); + drw_rect(drw, x, 0, w, bh, 1, 1); + } + } + drw_map(drw, m->barwin, 0, 0, m->ww, bh); +} + +void +drawbars(void) +{ + Monitor *m; + + for (m = mons; m; m = m->next) + drawbar(m); +} + +void +enternotify(XEvent *e) +{ + Client *c; + Monitor *m; + XCrossingEvent *ev = &e->xcrossing; + + if ((ev->mode != NotifyNormal || ev->detail == NotifyInferior) && ev->window != root) + return; + c = wintoclient(ev->window); + m = c ? c->mon : wintomon(ev->window); + if (m != selmon) { + unfocus(selmon->sel, 1); + selmon = m; + } else if (!c || c == selmon->sel) + return; + focus(c); +} + +void +expose(XEvent *e) +{ + Monitor *m; + XExposeEvent *ev = &e->xexpose; + + if (ev->count == 0 && (m = wintomon(ev->window))) + drawbar(m); +} + +void +focus(Client *c) +{ + if (!c || !ISVISIBLE(c)) + for (c = selmon->stack; c && !ISVISIBLE(c); c = c->snext); + if (selmon->sel && selmon->sel != c) + unfocus(selmon->sel, 0); + if (c) { + if (c->mon != selmon) + selmon = c->mon; + if (c->isurgent) + seturgent(c, 0); + detachstack(c); + attachstack(c); + grabbuttons(c, 1); + XSetWindowBorder(dpy, c->win, scheme[SchemeSel][ColBorder].pixel); + setfocus(c); + } else { + XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime); + XDeleteProperty(dpy, root, netatom[NetActiveWindow]); + } + selmon->sel = c; + drawbars(); +} + +/* there are some broken focus acquiring clients needing extra handling */ +void +focusin(XEvent *e) +{ + XFocusChangeEvent *ev = &e->xfocus; + + if (selmon->sel && ev->window != selmon->sel->win) + setfocus(selmon->sel); +} + +void +focusmon(const Arg *arg) +{ + Monitor *m; + + if (!mons->next) + return; + if ((m = dirtomon(arg->i)) == selmon) + return; + unfocus(selmon->sel, 0); + selmon = m; + focus(NULL); +} + +void +focusstack(const Arg *arg) +{ + Client *c = NULL, *i; + + if (!selmon->sel || (selmon->sel->isfullscreen && lockfullscreen)) + return; + if (arg->i > 0) { + for (c = selmon->sel->next; c && !ISVISIBLE(c); c = c->next); + if (!c) + for (c = selmon->clients; c && !ISVISIBLE(c); c = c->next); + } else { + for (i = selmon->clients; i != selmon->sel; i = i->next) + if (ISVISIBLE(i)) + c = i; + if (!c) + for (; i; i = i->next) + if (ISVISIBLE(i)) + c = i; + } + if (c) { + focus(c); + restack(selmon); + } +} + +Atom +getatomprop(Client *c, Atom prop) +{ + int di; + unsigned long dl; + unsigned char *p = NULL; + Atom da, atom = None; + + if (XGetWindowProperty(dpy, c->win, prop, 0L, sizeof atom, False, XA_ATOM, + &da, &di, &dl, &dl, &p) == Success && p) { + atom = *(Atom *)p; + XFree(p); + } + return atom; +} + +int +getrootptr(int *x, int *y) +{ + int di; + unsigned int dui; + Window dummy; + + return XQueryPointer(dpy, root, &dummy, &dummy, x, y, &di, &di, &dui); +} + +long +getstate(Window w) +{ + int format; + long result = -1; + unsigned char *p = NULL; + unsigned long n, extra; + Atom real; + + if (XGetWindowProperty(dpy, w, wmatom[WMState], 0L, 2L, False, wmatom[WMState], + &real, &format, &n, &extra, (unsigned char **)&p) != Success) + return -1; + if (n != 0) + result = *p; + XFree(p); + return result; +} + +int +gettextprop(Window w, Atom atom, char *text, unsigned int size) +{ + char **list = NULL; + int n; + XTextProperty name; + + if (!text || size == 0) + return 0; + text[0] = '\0'; + if (!XGetTextProperty(dpy, w, &name, atom) || !name.nitems) + return 0; + if (name.encoding == XA_STRING) { + strncpy(text, (char *)name.value, size - 1); + } else if (XmbTextPropertyToTextList(dpy, &name, &list, &n) >= Success && n > 0 && *list) { + strncpy(text, *list, size - 1); + XFreeStringList(list); + } + text[size - 1] = '\0'; + XFree(name.value); + return 1; +} + +void +grabbuttons(Client *c, int focused) +{ + updatenumlockmask(); + { + unsigned int i, j; + unsigned int modifiers[] = { 0, LockMask, numlockmask, numlockmask|LockMask }; + XUngrabButton(dpy, AnyButton, AnyModifier, c->win); + if (!focused) + XGrabButton(dpy, AnyButton, AnyModifier, c->win, False, + BUTTONMASK, GrabModeSync, GrabModeSync, None, None); + for (i = 0; i < LENGTH(buttons); i++) + if (buttons[i].click == ClkClientWin) + for (j = 0; j < LENGTH(modifiers); j++) + XGrabButton(dpy, buttons[i].button, + buttons[i].mask | modifiers[j], + c->win, False, BUTTONMASK, + GrabModeAsync, GrabModeSync, None, None); + } +} + +void +grabkeys(void) +{ + updatenumlockmask(); + { + unsigned int i, j, k; + unsigned int modifiers[] = { 0, LockMask, numlockmask, numlockmask|LockMask }; + int start, end, skip; + KeySym *syms; + + XUngrabKey(dpy, AnyKey, AnyModifier, root); + XDisplayKeycodes(dpy, &start, &end); + syms = XGetKeyboardMapping(dpy, start, end - start + 1, &skip); + if (!syms) + return; + for (k = start; k <= end; k++) + for (i = 0; i < LENGTH(keys); i++) + /* skip modifier codes, we do that ourselves */ + if (keys[i].keysym == syms[(k - start) * skip]) + for (j = 0; j < LENGTH(modifiers); j++) + XGrabKey(dpy, k, + keys[i].mod | modifiers[j], + root, True, + GrabModeAsync, GrabModeAsync); + XFree(syms); + } +} + +void +incnmaster(const Arg *arg) +{ + selmon->nmaster = MAX(selmon->nmaster + arg->i, 0); + arrange(selmon); +} + +#ifdef XINERAMA +static int +isuniquegeom(XineramaScreenInfo *unique, size_t n, XineramaScreenInfo *info) +{ + while (n--) + if (unique[n].x_org == info->x_org && unique[n].y_org == info->y_org + && unique[n].width == info->width && unique[n].height == info->height) + return 0; + return 1; +} +#endif /* XINERAMA */ + +void +keypress(XEvent *e) +{ + unsigned int i; + KeySym keysym; + XKeyEvent *ev; + + ev = &e->xkey; + keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0); + for (i = 0; i < LENGTH(keys); i++) + if (keysym == keys[i].keysym + && CLEANMASK(keys[i].mod) == CLEANMASK(ev->state) + && keys[i].func) + keys[i].func(&(keys[i].arg)); +} + +void +killclient(const Arg *arg) +{ + if (!selmon->sel) + return; + if (!sendevent(selmon->sel, wmatom[WMDelete])) { + XGrabServer(dpy); + XSetErrorHandler(xerrordummy); + XSetCloseDownMode(dpy, DestroyAll); + XKillClient(dpy, selmon->sel->win); + XSync(dpy, False); + XSetErrorHandler(xerror); + XUngrabServer(dpy); + } +} + +void +manage(Window w, XWindowAttributes *wa) +{ + Client *c, *t = NULL; + Window trans = None; + XWindowChanges wc; + + c = ecalloc(1, sizeof(Client)); + c->win = w; + /* geometry */ + c->x = c->oldx = wa->x; + c->y = c->oldy = wa->y; + c->w = c->oldw = wa->width; + c->h = c->oldh = wa->height; + c->oldbw = wa->border_width; + + updatetitle(c); + if (XGetTransientForHint(dpy, w, &trans) && (t = wintoclient(trans))) { + c->mon = t->mon; + c->tags = t->tags; + } else { + c->mon = selmon; + applyrules(c); + } + + if (c->x + WIDTH(c) > c->mon->wx + c->mon->ww) + c->x = c->mon->wx + c->mon->ww - WIDTH(c); + if (c->y + HEIGHT(c) > c->mon->wy + c->mon->wh) + c->y = c->mon->wy + c->mon->wh - HEIGHT(c); + c->x = MAX(c->x, c->mon->wx); + c->y = MAX(c->y, c->mon->wy); + c->bw = borderpx; + + wc.border_width = c->bw; + XConfigureWindow(dpy, w, CWBorderWidth, &wc); + XSetWindowBorder(dpy, w, scheme[SchemeNorm][ColBorder].pixel); + configure(c); /* propagates border_width, if size doesn't change */ + updatewindowtype(c); + updatesizehints(c); + updatewmhints(c); + XSelectInput(dpy, w, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask); + grabbuttons(c, 0); + if (!c->isfloating) + c->isfloating = c->oldstate = trans != None || c->isfixed; + if (c->isfloating) + XRaiseWindow(dpy, c->win); + attach(c); + attachstack(c); + XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 32, PropModeAppend, + (unsigned char *) &(c->win), 1); + XMoveResizeWindow(dpy, c->win, c->x + 2 * sw, c->y, c->w, c->h); /* some windows require this */ + setclientstate(c, NormalState); + if (c->mon == selmon) + unfocus(selmon->sel, 0); + c->mon->sel = c; + arrange(c->mon); + XMapWindow(dpy, c->win); + focus(NULL); +} + +void +mappingnotify(XEvent *e) +{ + XMappingEvent *ev = &e->xmapping; + + XRefreshKeyboardMapping(ev); + if (ev->request == MappingKeyboard) + grabkeys(); +} + +void +maprequest(XEvent *e) +{ + static XWindowAttributes wa; + XMapRequestEvent *ev = &e->xmaprequest; + + if (!XGetWindowAttributes(dpy, ev->window, &wa) || wa.override_redirect) + return; + if (!wintoclient(ev->window)) + manage(ev->window, &wa); +} + +void +monocle(Monitor *m) +{ + unsigned int n = 0; + Client *c; + + for (c = m->clients; c; c = c->next) + if (ISVISIBLE(c)) + n++; + if (n > 0) /* override layout symbol */ + snprintf(m->ltsymbol, sizeof m->ltsymbol, "[%d]", n); + for (c = nexttiled(m->clients); c; c = nexttiled(c->next)) + resize(c, m->wx, m->wy, m->ww - 2 * c->bw, m->wh - 2 * c->bw, 0); +} + +void +motionnotify(XEvent *e) +{ + static Monitor *mon = NULL; + Monitor *m; + XMotionEvent *ev = &e->xmotion; + + if (ev->window != root) + return; + if ((m = recttomon(ev->x_root, ev->y_root, 1, 1)) != mon && mon) { + unfocus(selmon->sel, 1); + selmon = m; + focus(NULL); + } + mon = m; +} + +void +movemouse(const Arg *arg) +{ + int x, y, ocx, ocy, nx, ny; + Client *c; + Monitor *m; + XEvent ev; + Time lasttime = 0; + + if (!(c = selmon->sel)) + return; + if (c->isfullscreen) /* no support moving fullscreen windows by mouse */ + return; + restack(selmon); + ocx = c->x; + ocy = c->y; + if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, + None, cursor[CurMove]->cursor, CurrentTime) != GrabSuccess) + return; + if (!getrootptr(&x, &y)) + return; + do { + XMaskEvent(dpy, MOUSEMASK|ExposureMask|SubstructureRedirectMask, &ev); + switch(ev.type) { + case ConfigureRequest: + case Expose: + case MapRequest: + handler[ev.type](&ev); + break; + case MotionNotify: + if ((ev.xmotion.time - lasttime) <= (1000 / 60)) + continue; + lasttime = ev.xmotion.time; + + nx = ocx + (ev.xmotion.x - x); + ny = ocy + (ev.xmotion.y - y); + if (abs(selmon->wx - nx) < snap) + nx = selmon->wx; + else if (abs((selmon->wx + selmon->ww) - (nx + WIDTH(c))) < snap) + nx = selmon->wx + selmon->ww - WIDTH(c); + if (abs(selmon->wy - ny) < snap) + ny = selmon->wy; + else if (abs((selmon->wy + selmon->wh) - (ny + HEIGHT(c))) < snap) + ny = selmon->wy + selmon->wh - HEIGHT(c); + if (!c->isfloating && selmon->lt[selmon->sellt]->arrange + && (abs(nx - c->x) > snap || abs(ny - c->y) > snap)) + togglefloating(NULL); + if (!selmon->lt[selmon->sellt]->arrange || c->isfloating) + resize(c, nx, ny, c->w, c->h, 1); + break; + } + } while (ev.type != ButtonRelease); + XUngrabPointer(dpy, CurrentTime); + if ((m = recttomon(c->x, c->y, c->w, c->h)) != selmon) { + sendmon(c, m); + selmon = m; + focus(NULL); + } +} + +Client * +nexttiled(Client *c) +{ + for (; c && (c->isfloating || !ISVISIBLE(c)); c = c->next); + return c; +} + +void +pop(Client *c) +{ + detach(c); + attach(c); + focus(c); + arrange(c->mon); +} + +void +propertynotify(XEvent *e) +{ + Client *c; + Window trans; + XPropertyEvent *ev = &e->xproperty; + + if ((ev->window == root) && (ev->atom == XA_WM_NAME)) + updatestatus(); + else if (ev->state == PropertyDelete) + return; /* ignore */ + else if ((c = wintoclient(ev->window))) { + switch(ev->atom) { + default: break; + case XA_WM_TRANSIENT_FOR: + if (!c->isfloating && (XGetTransientForHint(dpy, c->win, &trans)) && + (c->isfloating = (wintoclient(trans)) != NULL)) + arrange(c->mon); + break; + case XA_WM_NORMAL_HINTS: + c->hintsvalid = 0; + break; + case XA_WM_HINTS: + updatewmhints(c); + drawbars(); + break; + } + if (ev->atom == XA_WM_NAME || ev->atom == netatom[NetWMName]) { + updatetitle(c); + if (c == c->mon->sel) + drawbar(c->mon); + } + if (ev->atom == netatom[NetWMWindowType]) + updatewindowtype(c); + } +} + +void +quit(const Arg *arg) +{ + running = 0; +} + +Monitor * +recttomon(int x, int y, int w, int h) +{ + Monitor *m, *r = selmon; + int a, area = 0; + + for (m = mons; m; m = m->next) + if ((a = INTERSECT(x, y, w, h, m)) > area) { + area = a; + r = m; + } + return r; +} + +void +resize(Client *c, int x, int y, int w, int h, int interact) +{ + if (applysizehints(c, &x, &y, &w, &h, interact)) + resizeclient(c, x, y, w, h); +} + +void +resizeclient(Client *c, int x, int y, int w, int h) +{ + XWindowChanges wc; + + c->oldx = c->x; c->x = wc.x = x; + c->oldy = c->y; c->y = wc.y = y; + c->oldw = c->w; c->w = wc.width = w; + c->oldh = c->h; c->h = wc.height = h; + wc.border_width = c->bw; + XConfigureWindow(dpy, c->win, CWX|CWY|CWWidth|CWHeight|CWBorderWidth, &wc); + configure(c); + XSync(dpy, False); +} + +void +resizemouse(const Arg *arg) +{ + int ocx, ocy, nw, nh; + Client *c; + Monitor *m; + XEvent ev; + Time lasttime = 0; + + if (!(c = selmon->sel)) + return; + if (c->isfullscreen) /* no support resizing fullscreen windows by mouse */ + return; + restack(selmon); + ocx = c->x; + ocy = c->y; + if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, + None, cursor[CurResize]->cursor, CurrentTime) != GrabSuccess) + return; + XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->bw - 1, c->h + c->bw - 1); + do { + XMaskEvent(dpy, MOUSEMASK|ExposureMask|SubstructureRedirectMask, &ev); + switch(ev.type) { + case ConfigureRequest: + case Expose: + case MapRequest: + handler[ev.type](&ev); + break; + case MotionNotify: + if ((ev.xmotion.time - lasttime) <= (1000 / 60)) + continue; + lasttime = ev.xmotion.time; + + nw = MAX(ev.xmotion.x - ocx - 2 * c->bw + 1, 1); + nh = MAX(ev.xmotion.y - ocy - 2 * c->bw + 1, 1); + if (c->mon->wx + nw >= selmon->wx && c->mon->wx + nw <= selmon->wx + selmon->ww + && c->mon->wy + nh >= selmon->wy && c->mon->wy + nh <= selmon->wy + selmon->wh) + { + if (!c->isfloating && selmon->lt[selmon->sellt]->arrange + && (abs(nw - c->w) > snap || abs(nh - c->h) > snap)) + togglefloating(NULL); + } + if (!selmon->lt[selmon->sellt]->arrange || c->isfloating) + resize(c, c->x, c->y, nw, nh, 1); + break; + } + } while (ev.type != ButtonRelease); + XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->bw - 1, c->h + c->bw - 1); + XUngrabPointer(dpy, CurrentTime); + while (XCheckMaskEvent(dpy, EnterWindowMask, &ev)); + if ((m = recttomon(c->x, c->y, c->w, c->h)) != selmon) { + sendmon(c, m); + selmon = m; + focus(NULL); + } +} + +void +restack(Monitor *m) +{ + Client *c; + XEvent ev; + XWindowChanges wc; + + drawbar(m); + if (!m->sel) + return; + if (m->sel->isfloating || !m->lt[m->sellt]->arrange) + XRaiseWindow(dpy, m->sel->win); + if (m->lt[m->sellt]->arrange) { + wc.stack_mode = Below; + wc.sibling = m->barwin; + for (c = m->stack; c; c = c->snext) + if (!c->isfloating && ISVISIBLE(c)) { + XConfigureWindow(dpy, c->win, CWSibling|CWStackMode, &wc); + wc.sibling = c->win; + } + } + XSync(dpy, False); + while (XCheckMaskEvent(dpy, EnterWindowMask, &ev)); +} + +void +run(void) +{ + XEvent ev; + /* main event loop */ + XSync(dpy, False); + while (running && !XNextEvent(dpy, &ev)) + if (handler[ev.type]) + handler[ev.type](&ev); /* call handler */ +} + +void +scan(void) +{ + unsigned int i, num; + Window d1, d2, *wins = NULL; + XWindowAttributes wa; + + if (XQueryTree(dpy, root, &d1, &d2, &wins, &num)) { + for (i = 0; i < num; i++) { + if (!XGetWindowAttributes(dpy, wins[i], &wa) + || wa.override_redirect || XGetTransientForHint(dpy, wins[i], &d1)) + continue; + if (wa.map_state == IsViewable || getstate(wins[i]) == IconicState) + manage(wins[i], &wa); + } + for (i = 0; i < num; i++) { /* now the transients */ + if (!XGetWindowAttributes(dpy, wins[i], &wa)) + continue; + if (XGetTransientForHint(dpy, wins[i], &d1) + && (wa.map_state == IsViewable || getstate(wins[i]) == IconicState)) + manage(wins[i], &wa); + } + if (wins) + XFree(wins); + } +} + +void +sendmon(Client *c, Monitor *m) +{ + if (c->mon == m) + return; + unfocus(c, 1); + detach(c); + detachstack(c); + c->mon = m; + c->tags = m->tagset[m->seltags]; /* assign tags of target monitor */ + attach(c); + attachstack(c); + focus(NULL); + arrange(NULL); +} + +void +setclientstate(Client *c, long state) +{ + long data[] = { state, None }; + + XChangeProperty(dpy, c->win, wmatom[WMState], wmatom[WMState], 32, + PropModeReplace, (unsigned char *)data, 2); +} + +int +sendevent(Client *c, Atom proto) +{ + int n; + Atom *protocols; + int exists = 0; + XEvent ev; + + if (XGetWMProtocols(dpy, c->win, &protocols, &n)) { + while (!exists && n--) + exists = protocols[n] == proto; + XFree(protocols); + } + if (exists) { + ev.type = ClientMessage; + ev.xclient.window = c->win; + ev.xclient.message_type = wmatom[WMProtocols]; + ev.xclient.format = 32; + ev.xclient.data.l[0] = proto; + ev.xclient.data.l[1] = CurrentTime; + XSendEvent(dpy, c->win, False, NoEventMask, &ev); + } + return exists; +} + +void +setfocus(Client *c) +{ + if (!c->neverfocus) { + XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime); + XChangeProperty(dpy, root, netatom[NetActiveWindow], + XA_WINDOW, 32, PropModeReplace, + (unsigned char *) &(c->win), 1); + } + sendevent(c, wmatom[WMTakeFocus]); +} + +void +setfullscreen(Client *c, int fullscreen) +{ + if (fullscreen && !c->isfullscreen) { + XChangeProperty(dpy, c->win, netatom[NetWMState], XA_ATOM, 32, + PropModeReplace, (unsigned char*)&netatom[NetWMFullscreen], 1); + c->isfullscreen = 1; + c->oldstate = c->isfloating; + c->oldbw = c->bw; + c->bw = 0; + c->isfloating = 1; + resizeclient(c, c->mon->mx, c->mon->my, c->mon->mw, c->mon->mh); + XRaiseWindow(dpy, c->win); + } else if (!fullscreen && c->isfullscreen){ + XChangeProperty(dpy, c->win, netatom[NetWMState], XA_ATOM, 32, + PropModeReplace, (unsigned char*)0, 0); + c->isfullscreen = 0; + c->isfloating = c->oldstate; + c->bw = c->oldbw; + c->x = c->oldx; + c->y = c->oldy; + c->w = c->oldw; + c->h = c->oldh; + resizeclient(c, c->x, c->y, c->w, c->h); + arrange(c->mon); + } +} + +void +setlayout(const Arg *arg) +{ + if (!arg || !arg->v || arg->v != selmon->lt[selmon->sellt]) + selmon->sellt ^= 1; + if (arg && arg->v) + selmon->lt[selmon->sellt] = (Layout *)arg->v; + strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, sizeof selmon->ltsymbol); + if (selmon->sel) + arrange(selmon); + else + drawbar(selmon); +} + +/* arg > 1.0 will set mfact absolutely */ +void +setmfact(const Arg *arg) +{ + float f; + + if (!arg || !selmon->lt[selmon->sellt]->arrange) + return; + f = arg->f < 1.0 ? arg->f + selmon->mfact : arg->f - 1.0; + if (f < 0.05 || f > 0.95) + return; + selmon->mfact = f; + arrange(selmon); +} + +void +setup(void) +{ + int i; + XSetWindowAttributes wa; + Atom utf8string; + struct sigaction sa; + + /* do not transform children into zombies when they terminate */ + sigemptyset(&sa.sa_mask); + sa.sa_flags = SA_NOCLDSTOP | SA_NOCLDWAIT | SA_RESTART; + sa.sa_handler = SIG_IGN; + sigaction(SIGCHLD, &sa, NULL); + + /* clean up any zombies (inherited from .xinitrc etc) immediately */ + while (waitpid(-1, NULL, WNOHANG) > 0); + + /* init screen */ + screen = DefaultScreen(dpy); + sw = DisplayWidth(dpy, screen); + sh = DisplayHeight(dpy, screen); + root = RootWindow(dpy, screen); + drw = drw_create(dpy, screen, root, sw, sh); + if (!drw_fontset_create(drw, fonts, LENGTH(fonts))) + die("no fonts could be loaded."); + lrpad = drw->fonts->h; + bh = drw->fonts->h + 2; + updategeom(); + /* init atoms */ + utf8string = XInternAtom(dpy, "UTF8_STRING", False); + wmatom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False); + wmatom[WMDelete] = XInternAtom(dpy, "WM_DELETE_WINDOW", False); + wmatom[WMState] = XInternAtom(dpy, "WM_STATE", False); + wmatom[WMTakeFocus] = XInternAtom(dpy, "WM_TAKE_FOCUS", False); + netatom[NetActiveWindow] = XInternAtom(dpy, "_NET_ACTIVE_WINDOW", False); + netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False); + netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False); + netatom[NetWMState] = XInternAtom(dpy, "_NET_WM_STATE", False); + netatom[NetWMCheck] = XInternAtom(dpy, "_NET_SUPPORTING_WM_CHECK", False); + netatom[NetWMFullscreen] = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False); + netatom[NetWMWindowType] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False); + netatom[NetWMWindowTypeDialog] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DIALOG", False); + netatom[NetClientList] = XInternAtom(dpy, "_NET_CLIENT_LIST", False); + /* init cursors */ + cursor[CurNormal] = drw_cur_create(drw, XC_left_ptr); + cursor[CurResize] = drw_cur_create(drw, XC_sizing); + cursor[CurMove] = drw_cur_create(drw, XC_fleur); + /* init appearance */ + scheme = ecalloc(LENGTH(colors), sizeof(Clr *)); + for (i = 0; i < LENGTH(colors); i++) + scheme[i] = drw_scm_create(drw, colors[i], 3); + /* init bars */ + updatebars(); + updatestatus(); + /* supporting window for NetWMCheck */ + wmcheckwin = XCreateSimpleWindow(dpy, root, 0, 0, 1, 1, 0, 0, 0); + XChangeProperty(dpy, wmcheckwin, netatom[NetWMCheck], XA_WINDOW, 32, + PropModeReplace, (unsigned char *) &wmcheckwin, 1); + XChangeProperty(dpy, wmcheckwin, netatom[NetWMName], utf8string, 8, + PropModeReplace, (unsigned char *) "dwm", 3); + XChangeProperty(dpy, root, netatom[NetWMCheck], XA_WINDOW, 32, + PropModeReplace, (unsigned char *) &wmcheckwin, 1); + /* EWMH support per view */ + XChangeProperty(dpy, root, netatom[NetSupported], XA_ATOM, 32, + PropModeReplace, (unsigned char *) netatom, NetLast); + XDeleteProperty(dpy, root, netatom[NetClientList]); + /* select events */ + wa.cursor = cursor[CurNormal]->cursor; + wa.event_mask = SubstructureRedirectMask|SubstructureNotifyMask + |ButtonPressMask|PointerMotionMask|EnterWindowMask + |LeaveWindowMask|StructureNotifyMask|PropertyChangeMask; + XChangeWindowAttributes(dpy, root, CWEventMask|CWCursor, &wa); + XSelectInput(dpy, root, wa.event_mask); + grabkeys(); + focus(NULL); +} + +void +seturgent(Client *c, int urg) +{ + XWMHints *wmh; + + c->isurgent = urg; + if (!(wmh = XGetWMHints(dpy, c->win))) + return; + wmh->flags = urg ? (wmh->flags | XUrgencyHint) : (wmh->flags & ~XUrgencyHint); + XSetWMHints(dpy, c->win, wmh); + XFree(wmh); +} + +void +showhide(Client *c) +{ + if (!c) + return; + if (ISVISIBLE(c)) { + /* show clients top down */ + XMoveWindow(dpy, c->win, c->x, c->y); + if ((!c->mon->lt[c->mon->sellt]->arrange || c->isfloating) && !c->isfullscreen) + resize(c, c->x, c->y, c->w, c->h, 0); + showhide(c->snext); + } else { + /* hide clients bottom up */ + showhide(c->snext); + XMoveWindow(dpy, c->win, WIDTH(c) * -2, c->y); + } +} + +void +spawn(const Arg *arg) +{ + struct sigaction sa; + + if (arg->v == dmenucmd) + dmenumon[0] = '0' + selmon->num; + if (fork() == 0) { + if (dpy) + close(ConnectionNumber(dpy)); + setsid(); + + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; + sa.sa_handler = SIG_DFL; + sigaction(SIGCHLD, &sa, NULL); + + execvp(((char **)arg->v)[0], (char **)arg->v); + die("dwm: execvp '%s' failed:", ((char **)arg->v)[0]); + } +} + +void +tag(const Arg *arg) +{ + if (selmon->sel && arg->ui & TAGMASK) { + selmon->sel->tags = arg->ui & TAGMASK; + focus(NULL); + arrange(selmon); + } +} + +void +tagmon(const Arg *arg) +{ + if (!selmon->sel || !mons->next) + return; + sendmon(selmon->sel, dirtomon(arg->i)); +} + +void +tile(Monitor *m) +{ + unsigned int i, n, h, mw, my, ty; + Client *c; + + for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); + if (n == 0) + return; + + if (n > m->nmaster) + mw = m->nmaster ? m->ww * m->mfact : 0; + else + mw = m->ww; + for (i = my = ty = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) + if (i < m->nmaster) { + h = (m->wh - my) / (MIN(n, m->nmaster) - i); + resize(c, m->wx, m->wy + my, mw - (2*c->bw), h - (2*c->bw), 0); + if (my + HEIGHT(c) < m->wh) + my += HEIGHT(c); + } else { + h = (m->wh - ty) / (n - i); + resize(c, m->wx + mw, m->wy + ty, m->ww - mw - (2*c->bw), h - (2*c->bw), 0); + if (ty + HEIGHT(c) < m->wh) + ty += HEIGHT(c); + } +} + +void +togglebar(const Arg *arg) +{ + selmon->showbar = !selmon->showbar; + updatebarpos(selmon); + XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, bh); + arrange(selmon); +} + +void +togglefloating(const Arg *arg) +{ + if (!selmon->sel) + return; + if (selmon->sel->isfullscreen) /* no support for fullscreen windows */ + return; + selmon->sel->isfloating = !selmon->sel->isfloating || selmon->sel->isfixed; + if (selmon->sel->isfloating) + resize(selmon->sel, selmon->sel->x, selmon->sel->y, + selmon->sel->w, selmon->sel->h, 0); + arrange(selmon); +} + +void +toggletag(const Arg *arg) +{ + unsigned int newtags; + + if (!selmon->sel) + return; + newtags = selmon->sel->tags ^ (arg->ui & TAGMASK); + if (newtags) { + selmon->sel->tags = newtags; + focus(NULL); + arrange(selmon); + } +} + +void +toggleview(const Arg *arg) +{ + unsigned int newtagset = selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK); + + if (newtagset) { + selmon->tagset[selmon->seltags] = newtagset; + focus(NULL); + arrange(selmon); + } +} + +void +unfocus(Client *c, int setfocus) +{ + if (!c) + return; + grabbuttons(c, 0); + XSetWindowBorder(dpy, c->win, scheme[SchemeNorm][ColBorder].pixel); + if (setfocus) { + XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime); + XDeleteProperty(dpy, root, netatom[NetActiveWindow]); + } +} + +void +unmanage(Client *c, int destroyed) +{ + Monitor *m = c->mon; + XWindowChanges wc; + + detach(c); + detachstack(c); + if (!destroyed) { + wc.border_width = c->oldbw; + XGrabServer(dpy); /* avoid race conditions */ + XSetErrorHandler(xerrordummy); + XSelectInput(dpy, c->win, NoEventMask); + XConfigureWindow(dpy, c->win, CWBorderWidth, &wc); /* restore border */ + XUngrabButton(dpy, AnyButton, AnyModifier, c->win); + setclientstate(c, WithdrawnState); + XSync(dpy, False); + XSetErrorHandler(xerror); + XUngrabServer(dpy); + } + free(c); + focus(NULL); + updateclientlist(); + arrange(m); +} + +void +unmapnotify(XEvent *e) +{ + Client *c; + XUnmapEvent *ev = &e->xunmap; + + if ((c = wintoclient(ev->window))) { + if (ev->send_event) + setclientstate(c, WithdrawnState); + else + unmanage(c, 0); + } +} + +void +updatebars(void) +{ + Monitor *m; + XSetWindowAttributes wa = { + .override_redirect = True, + .background_pixmap = ParentRelative, + .event_mask = ButtonPressMask|ExposureMask + }; + XClassHint ch = {"dwm", "dwm"}; + for (m = mons; m; m = m->next) { + if (m->barwin) + continue; + m->barwin = XCreateWindow(dpy, root, m->wx, m->by, m->ww, bh, 0, DefaultDepth(dpy, screen), + CopyFromParent, DefaultVisual(dpy, screen), + CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa); + XDefineCursor(dpy, m->barwin, cursor[CurNormal]->cursor); + XMapRaised(dpy, m->barwin); + XSetClassHint(dpy, m->barwin, &ch); + } +} + +void +updatebarpos(Monitor *m) +{ + m->wy = m->my; + m->wh = m->mh; + if (m->showbar) { + m->wh -= bh; + m->by = m->topbar ? m->wy : m->wy + m->wh; + m->wy = m->topbar ? m->wy + bh : m->wy; + } else + m->by = -bh; +} + +void +updateclientlist() +{ + Client *c; + Monitor *m; + + XDeleteProperty(dpy, root, netatom[NetClientList]); + for (m = mons; m; m = m->next) + for (c = m->clients; c; c = c->next) + XChangeProperty(dpy, root, netatom[NetClientList], + XA_WINDOW, 32, PropModeAppend, + (unsigned char *) &(c->win), 1); +} + +int +updategeom(void) +{ + int dirty = 0; + +#ifdef XINERAMA + if (XineramaIsActive(dpy)) { + int i, j, n, nn; + Client *c; + Monitor *m; + XineramaScreenInfo *info = XineramaQueryScreens(dpy, &nn); + XineramaScreenInfo *unique = NULL; + + for (n = 0, m = mons; m; m = m->next, n++); + /* only consider unique geometries as separate screens */ + unique = ecalloc(nn, sizeof(XineramaScreenInfo)); + for (i = 0, j = 0; i < nn; i++) + if (isuniquegeom(unique, j, &info[i])) + memcpy(&unique[j++], &info[i], sizeof(XineramaScreenInfo)); + XFree(info); + nn = j; + + /* new monitors if nn > n */ + for (i = n; i < nn; i++) { + for (m = mons; m && m->next; m = m->next); + if (m) + m->next = createmon(); + else + mons = createmon(); + } + for (i = 0, m = mons; i < nn && m; m = m->next, i++) + if (i >= n + || unique[i].x_org != m->mx || unique[i].y_org != m->my + || unique[i].width != m->mw || unique[i].height != m->mh) + { + dirty = 1; + m->num = i; + m->mx = m->wx = unique[i].x_org; + m->my = m->wy = unique[i].y_org; + m->mw = m->ww = unique[i].width; + m->mh = m->wh = unique[i].height; + updatebarpos(m); + } + /* removed monitors if n > nn */ + for (i = nn; i < n; i++) { + for (m = mons; m && m->next; m = m->next); + while ((c = m->clients)) { + dirty = 1; + m->clients = c->next; + detachstack(c); + c->mon = mons; + attach(c); + attachstack(c); + } + if (m == selmon) + selmon = mons; + cleanupmon(m); + } + free(unique); + } else +#endif /* XINERAMA */ + { /* default monitor setup */ + if (!mons) + mons = createmon(); + if (mons->mw != sw || mons->mh != sh) { + dirty = 1; + mons->mw = mons->ww = sw; + mons->mh = mons->wh = sh; + updatebarpos(mons); + } + } + if (dirty) { + selmon = mons; + selmon = wintomon(root); + } + return dirty; +} + +void +updatenumlockmask(void) +{ + unsigned int i, j; + XModifierKeymap *modmap; + + numlockmask = 0; + modmap = XGetModifierMapping(dpy); + for (i = 0; i < 8; i++) + for (j = 0; j < modmap->max_keypermod; j++) + if (modmap->modifiermap[i * modmap->max_keypermod + j] + == XKeysymToKeycode(dpy, XK_Num_Lock)) + numlockmask = (1 << i); + XFreeModifiermap(modmap); +} + +void +updatesizehints(Client *c) +{ + long msize; + XSizeHints size; + + if (!XGetWMNormalHints(dpy, c->win, &size, &msize)) + /* size is uninitialized, ensure that size.flags aren't used */ + size.flags = PSize; + if (size.flags & PBaseSize) { + c->basew = size.base_width; + c->baseh = size.base_height; + } else if (size.flags & PMinSize) { + c->basew = size.min_width; + c->baseh = size.min_height; + } else + c->basew = c->baseh = 0; + if (size.flags & PResizeInc) { + c->incw = size.width_inc; + c->inch = size.height_inc; + } else + c->incw = c->inch = 0; + if (size.flags & PMaxSize) { + c->maxw = size.max_width; + c->maxh = size.max_height; + } else + c->maxw = c->maxh = 0; + if (size.flags & PMinSize) { + c->minw = size.min_width; + c->minh = size.min_height; + } else if (size.flags & PBaseSize) { + c->minw = size.base_width; + c->minh = size.base_height; + } else + c->minw = c->minh = 0; + if (size.flags & PAspect) { + c->mina = (float)size.min_aspect.y / size.min_aspect.x; + c->maxa = (float)size.max_aspect.x / size.max_aspect.y; + } else + c->maxa = c->mina = 0.0; + c->isfixed = (c->maxw && c->maxh && c->maxw == c->minw && c->maxh == c->minh); + c->hintsvalid = 1; +} + +void +updatestatus(void) +{ + if (!gettextprop(root, XA_WM_NAME, stext, sizeof(stext))) + strcpy(stext, "dwm-"VERSION); + drawbar(selmon); +} + +void +updatetitle(Client *c) +{ + if (!gettextprop(c->win, netatom[NetWMName], c->name, sizeof c->name)) + gettextprop(c->win, XA_WM_NAME, c->name, sizeof c->name); + if (c->name[0] == '\0') /* hack to mark broken clients */ + strcpy(c->name, broken); +} + +void +updatewindowtype(Client *c) +{ + Atom state = getatomprop(c, netatom[NetWMState]); + Atom wtype = getatomprop(c, netatom[NetWMWindowType]); + + if (state == netatom[NetWMFullscreen]) + setfullscreen(c, 1); + if (wtype == netatom[NetWMWindowTypeDialog]) + c->isfloating = 1; +} + +void +updatewmhints(Client *c) +{ + XWMHints *wmh; + + if ((wmh = XGetWMHints(dpy, c->win))) { + if (c == selmon->sel && wmh->flags & XUrgencyHint) { + wmh->flags &= ~XUrgencyHint; + XSetWMHints(dpy, c->win, wmh); + } else + c->isurgent = (wmh->flags & XUrgencyHint) ? 1 : 0; + if (wmh->flags & InputHint) + c->neverfocus = !wmh->input; + else + c->neverfocus = 0; + XFree(wmh); + } +} + +void +view(const Arg *arg) +{ + if ((arg->ui & TAGMASK) == selmon->tagset[selmon->seltags]) + return; + selmon->seltags ^= 1; /* toggle sel tagset */ + if (arg->ui & TAGMASK) + selmon->tagset[selmon->seltags] = arg->ui & TAGMASK; + focus(NULL); + arrange(selmon); +} + +Client * +wintoclient(Window w) +{ + Client *c; + Monitor *m; + + for (m = mons; m; m = m->next) + for (c = m->clients; c; c = c->next) + if (c->win == w) + return c; + return NULL; +} + +Monitor * +wintomon(Window w) +{ + int x, y; + Client *c; + Monitor *m; + + if (w == root && getrootptr(&x, &y)) + return recttomon(x, y, 1, 1); + for (m = mons; m; m = m->next) + if (w == m->barwin) + return m; + if ((c = wintoclient(w))) + return c->mon; + return selmon; +} + +/* There's no way to check accesses to destroyed windows, thus those cases are + * ignored (especially on UnmapNotify's). Other types of errors call Xlibs + * default error handler, which may call exit. */ +int +xerror(Display *dpy, XErrorEvent *ee) +{ + if (ee->error_code == BadWindow + || (ee->request_code == X_SetInputFocus && ee->error_code == BadMatch) + || (ee->request_code == X_PolyText8 && ee->error_code == BadDrawable) + || (ee->request_code == X_PolyFillRectangle && ee->error_code == BadDrawable) + || (ee->request_code == X_PolySegment && ee->error_code == BadDrawable) + || (ee->request_code == X_ConfigureWindow && ee->error_code == BadMatch) + || (ee->request_code == X_GrabButton && ee->error_code == BadAccess) + || (ee->request_code == X_GrabKey && ee->error_code == BadAccess) + || (ee->request_code == X_CopyArea && ee->error_code == BadDrawable)) + return 0; + fprintf(stderr, "dwm: fatal error: request code=%d, error code=%d\n", + ee->request_code, ee->error_code); + return xerrorxlib(dpy, ee); /* may call exit */ +} + +int +xerrordummy(Display *dpy, XErrorEvent *ee) +{ + return 0; +} + +/* Startup Error handler to check if another window manager + * is already running. */ +int +xerrorstart(Display *dpy, XErrorEvent *ee) +{ + die("dwm: another window manager is already running"); + return -1; +} + +void +zoom(const Arg *arg) +{ + Client *c = selmon->sel; + + if (!selmon->lt[selmon->sellt]->arrange || !c || c->isfloating) + return; + if (c == nexttiled(selmon->clients) && !(c = nexttiled(c->next))) + return; + pop(c); +} + +int +main(int argc, char *argv[]) +{ + if (argc == 2 && !strcmp("-v", argv[1])) + die("dwm-"VERSION); + else if (argc != 1) + die("usage: dwm [-v]"); + if (!setlocale(LC_CTYPE, "") || !XSupportsLocale()) + fputs("warning: no locale support\n", stderr); + if (!(dpy = XOpenDisplay(NULL))) + die("dwm: cannot open display"); + checkotherwm(); + setup(); +#ifdef __OpenBSD__ + if (pledge("stdio rpath proc exec", NULL) == -1) + die("pledge"); +#endif /* __OpenBSD__ */ + scan(); + run(); + cleanup(); + XCloseDisplay(dpy); + return EXIT_SUCCESS; +} diff --git a/hosts/vali/mars/dwm/dwm-6.5/dwm.png b/hosts/vali/mars/dwm/dwm-6.5/dwm.png new file mode 100644 index 0000000000000000000000000000000000000000..b1f9ba7e5f4cc7350ee2392ebcea5fcbe00fb49b GIT binary patch literal 373 zcmeAS@N?(olHy`uVBq!ia0y~yU^u|Qz!1Q}1Y+HIE6l*az?S6g?!xdN1Q+aGKAC}m zfwRCPvY3H^TNs2H8D`CqU|?WiFY)wsWxvKQ%wx!QPg+ZWfq_A`#5JPCIX^cyHLrxh zxhOTUBsE2$JhLQ2AtWPJ!QIn0;C+f}9s>izO-~ockcwMx?>cfd81OJSD*yX``Xg^6 zTaZz4SYYHW?+Yi+q)+P5khOpNZ+qolCYF{40Rbi^MnwgdmIen04h}{|1pxsjCkGA= zh?J9q0!T_g04&AA!nDZw&Oe5$@0m;M>sM6OY71;LKv54jO6E(b|BHY2*SA&9y8V3S z8iyN)!0OOUb8_ejn#VrNZ2je0``gbZufgI1u!%>m)^#5eUAZ~`sxkuu1B0ilpUXO@ GgeCxv)opSB literal 0 HcmV?d00001 diff --git a/hosts/vali/mars/dwm/dwm-6.5/transient.c b/hosts/vali/mars/dwm/dwm-6.5/transient.c new file mode 100644 index 0000000..040adb5 --- /dev/null +++ b/hosts/vali/mars/dwm/dwm-6.5/transient.c @@ -0,0 +1,42 @@ +/* cc transient.c -o transient -lX11 */ + +#include +#include +#include +#include + +int main(void) { + Display *d; + Window r, f, t = None; + XSizeHints h; + XEvent e; + + d = XOpenDisplay(NULL); + if (!d) + exit(1); + r = DefaultRootWindow(d); + + f = XCreateSimpleWindow(d, r, 100, 100, 400, 400, 0, 0, 0); + h.min_width = h.max_width = h.min_height = h.max_height = 400; + h.flags = PMinSize | PMaxSize; + XSetWMNormalHints(d, f, &h); + XStoreName(d, f, "floating"); + XMapWindow(d, f); + + XSelectInput(d, f, ExposureMask); + while (1) { + XNextEvent(d, &e); + + if (t == None) { + sleep(5); + t = XCreateSimpleWindow(d, r, 50, 50, 100, 100, 0, 0, 0); + XSetTransientForHint(d, t, f); + XStoreName(d, t, "transient"); + XMapWindow(d, t); + XSelectInput(d, t, ExposureMask); + } + } + + XCloseDisplay(d); + exit(0); +} diff --git a/hosts/vali/mars/dwm/dwm-6.5/util.c b/hosts/vali/mars/dwm/dwm-6.5/util.c new file mode 100644 index 0000000..96b82c9 --- /dev/null +++ b/hosts/vali/mars/dwm/dwm-6.5/util.c @@ -0,0 +1,36 @@ +/* See LICENSE file for copyright and license details. */ +#include +#include +#include +#include + +#include "util.h" + +void +die(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + + if (fmt[0] && fmt[strlen(fmt)-1] == ':') { + fputc(' ', stderr); + perror(NULL); + } else { + fputc('\n', stderr); + } + + exit(1); +} + +void * +ecalloc(size_t nmemb, size_t size) +{ + void *p; + + if (!(p = calloc(nmemb, size))) + die("calloc:"); + return p; +} diff --git a/hosts/vali/mars/dwm/dwm-6.5/util.h b/hosts/vali/mars/dwm/dwm-6.5/util.h new file mode 100644 index 0000000..f633b51 --- /dev/null +++ b/hosts/vali/mars/dwm/dwm-6.5/util.h @@ -0,0 +1,8 @@ +/* See LICENSE file for copyright and license details. */ + +#define MAX(A, B) ((A) > (B) ? (A) : (B)) +#define MIN(A, B) ((A) < (B) ? (A) : (B)) +#define BETWEEN(X, A, B) ((A) <= (X) && (X) <= (B)) + +void die(const char *fmt, ...); +void *ecalloc(size_t nmemb, size_t size); diff --git a/hosts/vali/mars/dwm/dwm.nix b/hosts/vali/mars/dwm/dwm.nix new file mode 100644 index 0000000..8fec3cb --- /dev/null +++ b/hosts/vali/mars/dwm/dwm.nix @@ -0,0 +1,22 @@ +{ pkgs, lib, config, callPackage, ... }: +with lib; let + username = config.modules.other.system.username; + cfg = config.modules.programs.dwm; +in { + options.modules.programs.dwm.enable = mkEnableOption "dwm"; + + config = mkIf cfg.enable { + services.xserver = { + enable = true; + xkb.layout = "de"; + windowManager.dwm = { + enable = true; + package = pkgs.dwm.overrideAttrs.src = ./dwm-6.5 + }; + displayManager = { + gdm.enable = true; + defaultSession = "none+dwm"; + }; + }; + }; +} diff --git a/hosts/vali/mars/programs.nix b/hosts/vali/mars/programs.nix index 9c9fb41..ece2570 100644 --- a/hosts/vali/mars/programs.nix +++ b/hosts/vali/mars/programs.nix @@ -34,6 +34,7 @@ in { krita lazygit libreoffice-fresh + librewolf moc ncmpcpp neofetch @@ -69,6 +70,7 @@ in { ventoy-full vesktop vlc + wget xclip yt-dlp zathura diff --git a/modules/gui/schizofox.nix b/modules/gui/schizofox.nix index 63cb67d..07cdc5b 100644 --- a/modules/gui/schizofox.nix +++ b/modules/gui/schizofox.nix @@ -69,7 +69,6 @@ in { darkreader.enable = true; extraExtensions = { - "webextension@metamask.io".install_url = "https://addons.mozilla.org/firefox/downloads/latest/ether-metamask/latest.xpi"; }; }; From cea755e932c1512cfefd5324eb34a7d4a385d2b4 Mon Sep 17 00:00:00 2001 From: LarsZauberer Date: Sat, 13 Apr 2024 21:31:55 +0200 Subject: [PATCH 21/27] Alacritty configured --- flake.lock | 472 ++++++++++++++++++++++++++-- hosts/lars/default.nix | 34 +- hosts/lars/kronos/configuration.nix | 8 + hosts/lars/programs.nix | 25 +- modules/gui/alacritty.nix | 42 +++ modules/gui/default.nix | 3 +- 6 files changed, 536 insertions(+), 48 deletions(-) create mode 100644 modules/gui/alacritty.nix diff --git a/flake.lock b/flake.lock index 319d786..bd07fb4 100644 --- a/flake.lock +++ b/flake.lock @@ -86,6 +86,28 @@ "type": "github" } }, + "devshell": { + "inputs": { + "flake-utils": "flake-utils_3", + "nixpkgs": [ + "nixvim", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1711099426, + "narHash": "sha256-HzpgM/wc3aqpnHJJ2oDqPBkNsqWbW0WfWUO8lKu8nGk=", + "owner": "numtide", + "repo": "devshell", + "rev": "2d45b54ca4a183f2fdcf4b19c895b64fbf620ee8", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "devshell", + "type": "github" + } + }, "fenix": { "inputs": { "nixpkgs": [ @@ -108,6 +130,22 @@ } }, "flake-compat": { + "flake": false, + "locked": { + "lastModified": 1696426674, + "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "flake-compat_2": { "locked": { "lastModified": 1688025799, "narHash": "sha256-ktpB4dRtnksm9F5WawoIkEneh1nrEvuxb5lJFt1iOyw=", @@ -122,7 +160,37 @@ "type": "github" } }, - "flake-compat_2": { + "flake-compat_3": { + "locked": { + "lastModified": 1696426674, + "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", + "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", + "revCount": 57, + "type": "tarball", + "url": "https://api.flakehub.com/f/pinned/edolstra/flake-compat/1.0.1/018afb31-abd1-7bff-a5e4-cff7e18efb7a/source.tar.gz" + }, + "original": { + "type": "tarball", + "url": "https://flakehub.com/f/edolstra/flake-compat/1.tar.gz" + } + }, + "flake-compat_4": { + "flake": false, + "locked": { + "lastModified": 1696426674, + "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "flake-compat_5": { "flake": false, "locked": { "lastModified": 1696426674, @@ -160,6 +228,48 @@ } }, "flake-parts_2": { + "inputs": { + "nixpkgs-lib": [ + "neovim-nightly-overlay", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1712014858, + "narHash": "sha256-sB4SWl2lX95bExY2gMFG5HIzvva5AVMJd4Igm+GpZNw=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "9126214d0a59633752a136528f5f3b9aa8565b7d", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, + "flake-parts_3": { + "inputs": { + "nixpkgs-lib": [ + "neovim-nightly-overlay", + "hercules-ci-effects", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1709336216, + "narHash": "sha256-Dt/wOWeW6Sqm11Yh+2+t0dfEWxoMxGBvv3JpIocFl9E=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "f7b3c975cf067e56e7cda6cb098ebe3fb4d74ca2", + "type": "github" + }, + "original": { + "id": "flake-parts", + "type": "indirect" + } + }, + "flake-parts_4": { "inputs": { "nixpkgs-lib": [ "nixpkgs-wayland", @@ -181,7 +291,28 @@ "type": "github" } }, - "flake-parts_3": { + "flake-parts_5": { + "inputs": { + "nixpkgs-lib": [ + "nixvim", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1712014858, + "narHash": "sha256-sB4SWl2lX95bExY2gMFG5HIzvva5AVMJd4Igm+GpZNw=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "9126214d0a59633752a136528f5f3b9aa8565b7d", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, + "flake-parts_6": { "inputs": { "nixpkgs-lib": [ "schizofox", @@ -202,7 +333,7 @@ "type": "github" } }, - "flake-parts_4": { + "flake-parts_7": { "inputs": { "nixpkgs-lib": "nixpkgs-lib_2" }, @@ -224,6 +355,24 @@ "inputs": { "systems": "systems_2" }, + "locked": { + "lastModified": 1701680307, + "narHash": "sha256-kAuep2h5ajznlPMD9rnQyffWG8EM/C73lejGofXvdM8=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "4022d587cbbfd70fe950c1e2083a02621806a725", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_2": { + "inputs": { + "systems": "systems_3" + }, "locked": { "lastModified": 1710146030, "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", @@ -238,7 +387,87 @@ "type": "github" } }, + "flake-utils_3": { + "inputs": { + "systems": "systems_4" + }, + "locked": { + "lastModified": 1701680307, + "narHash": "sha256-kAuep2h5ajznlPMD9rnQyffWG8EM/C73lejGofXvdM8=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "4022d587cbbfd70fe950c1e2083a02621806a725", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_4": { + "inputs": { + "systems": "systems_5" + }, + "locked": { + "lastModified": 1710146030, + "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "gitignore": { + "inputs": { + "nixpkgs": [ + "nixvim", + "pre-commit-hooks", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1709087332, + "narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=", + "owner": "hercules-ci", + "repo": "gitignore.nix", + "rev": "637db329424fd7e46cf4185293b9cc8c88c95394", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "gitignore.nix", + "type": "github" + } + }, "hercules-ci-effects": { + "inputs": { + "flake-parts": "flake-parts_3", + "nixpkgs": [ + "neovim-nightly-overlay", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1710478346, + "narHash": "sha256-Xjf8BdnQG0tLhPMlqQdwCIjOp7Teox0DP3N/jjyiGM4=", + "owner": "hercules-ci", + "repo": "hercules-ci-effects", + "rev": "64e7763d72c1e4c1e5e6472640615b6ae2d40fbf", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "hercules-ci-effects", + "type": "github" + } + }, + "hercules-ci-effects_2": { "inputs": { "flake-parts": [ "schizofox", @@ -307,6 +536,27 @@ } }, "home-manager_3": { + "inputs": { + "nixpkgs": [ + "nixvim", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1712759992, + "narHash": "sha256-2APpO3ZW4idlgtlb8hB04u/rmIcKA8O7pYqxF66xbNY=", + "owner": "nix-community", + "repo": "home-manager", + "rev": "31357486b0ef6f4e161e002b6893eeb4fafc3ca9", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "home-manager", + "type": "github" + } + }, + "home-manager_4": { "inputs": { "nixpkgs": [ "schizofox", @@ -364,8 +614,8 @@ "hyprcursor": "hyprcursor", "hyprland-protocols": "hyprland-protocols", "hyprlang": "hyprlang", - "nixpkgs": "nixpkgs_5", - "systems": "systems_3", + "nixpkgs": "nixpkgs_6", + "systems": "systems_6", "wlroots": "wlroots", "xdph": "xdph" }, @@ -439,7 +689,7 @@ }, "lib-aggregate": { "inputs": { - "flake-utils": "flake-utils", + "flake-utils": "flake-utils_2", "nixpkgs-lib": "nixpkgs-lib" }, "locked": { @@ -456,11 +706,78 @@ "type": "github" } }, + "neovim-flake": { + "inputs": { + "flake-utils": "flake-utils", + "nixpkgs": [ + "neovim-nightly-overlay", + "nixpkgs" + ] + }, + "locked": { + "dir": "contrib", + "lastModified": 1712963920, + "narHash": "sha256-5Rh+bUrpeQLYtvnFlMFmUFkV/H6b+I22Bei8oNa+dBw=", + "owner": "neovim", + "repo": "neovim", + "rev": "66220d164a40791a5131d4660e6ffbee431070d5", + "type": "github" + }, + "original": { + "dir": "contrib", + "owner": "neovim", + "repo": "neovim", + "type": "github" + } + }, + "neovim-nightly-overlay": { + "inputs": { + "flake-compat": "flake-compat", + "flake-parts": "flake-parts_2", + "hercules-ci-effects": "hercules-ci-effects", + "neovim-flake": "neovim-flake", + "nixpkgs": "nixpkgs_2" + }, + "locked": { + "lastModified": 1712966609, + "narHash": "sha256-XkNBbh8x1niHtVILUiNlGJHN9N2JkY+a8MR8w0/mhrI=", + "owner": "nix-community", + "repo": "neovim-nightly-overlay", + "rev": "c83e531b908c1fe71a95830bbad6db8a1e5b5b6b", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "neovim-nightly-overlay", + "type": "github" + } + }, + "nix-darwin": { + "inputs": { + "nixpkgs": [ + "nixvim", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1711763326, + "narHash": "sha256-sXcesZWKXFlEQ8oyGHnfk4xc9f2Ip0X/+YZOq3sKviI=", + "owner": "lnl7", + "repo": "nix-darwin", + "rev": "36524adc31566655f2f4d55ad6b875fb5c1a4083", + "type": "github" + }, + "original": { + "owner": "lnl7", + "repo": "nix-darwin", + "type": "github" + } + }, "nix-eval-jobs": { "inputs": { - "flake-parts": "flake-parts_2", + "flake-parts": "flake-parts_4", "nix-github-actions": "nix-github-actions", - "nixpkgs": "nixpkgs_3", + "nixpkgs": "nixpkgs_4", "treefmt-nix": "treefmt-nix" }, "locked": { @@ -520,7 +837,7 @@ "schizofox", "flake-parts" ], - "hercules-ci-effects": "hercules-ci-effects", + "hercules-ci-effects": "hercules-ci-effects_2", "nixpkgs": [ "schizofox", "nixpkgs" @@ -591,10 +908,10 @@ }, "nixpkgs-wayland": { "inputs": { - "flake-compat": "flake-compat", + "flake-compat": "flake-compat_2", "lib-aggregate": "lib-aggregate", "nix-eval-jobs": "nix-eval-jobs", - "nixpkgs": "nixpkgs_4" + "nixpkgs": "nixpkgs_5" }, "locked": { "lastModified": 1712942143, @@ -611,6 +928,22 @@ } }, "nixpkgs_2": { + "locked": { + "lastModified": 1712849433, + "narHash": "sha256-flQtf/ZPJgkLY/So3Fd+dGilw2DKIsiwgMEn7BbBHL0=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "f173d0881eff3b21ebb29a2ef8bedbc106c86ea5", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_3": { "locked": { "lastModified": 1712791164, "narHash": "sha256-3sbWO1mbpWsLepZGbWaMovSO7ndZeFqDSdX0hZ9nVyw=", @@ -626,7 +959,7 @@ "type": "github" } }, - "nixpkgs_3": { + "nixpkgs_4": { "locked": { "lastModified": 1703134684, "narHash": "sha256-SQmng1EnBFLzS7WSRyPM9HgmZP2kLJcPAz+Ug/nug6o=", @@ -642,7 +975,7 @@ "type": "github" } }, - "nixpkgs_4": { + "nixpkgs_5": { "locked": { "lastModified": 1712791164, "narHash": "sha256-3sbWO1mbpWsLepZGbWaMovSO7ndZeFqDSdX0hZ9nVyw=", @@ -658,7 +991,7 @@ "type": "github" } }, - "nixpkgs_5": { + "nixpkgs_6": { "locked": { "lastModified": 1712439257, "narHash": "sha256-aSpiNepFOMk9932HOax0XwNxbA38GOUVOiXfUVPOrck=", @@ -674,6 +1007,32 @@ "type": "github" } }, + "nixvim": { + "inputs": { + "devshell": "devshell", + "flake-compat": "flake-compat_3", + "flake-parts": "flake-parts_5", + "home-manager": "home-manager_3", + "nix-darwin": "nix-darwin", + "nixpkgs": [ + "nixpkgs" + ], + "pre-commit-hooks": "pre-commit-hooks" + }, + "locked": { + "lastModified": 1713008785, + "narHash": "sha256-fblaj6/83OQYrD1UHBjLapxjGQaC4edouX4g2X8CVhk=", + "owner": "nix-community", + "repo": "nixvim", + "rev": "21c233919d747d3375e3a173b65f7f26ccf01256", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nixvim", + "type": "github" + } + }, "nur": { "locked": { "lastModified": 1712918680, @@ -689,14 +1048,44 @@ "type": "github" } }, + "pre-commit-hooks": { + "inputs": { + "flake-compat": "flake-compat_4", + "flake-utils": "flake-utils_4", + "gitignore": "gitignore", + "nixpkgs": [ + "nixvim", + "nixpkgs" + ], + "nixpkgs-stable": [ + "nixvim", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1712897695, + "narHash": "sha256-nMirxrGteNAl9sWiOhoN5tIHyjBbVi5e2tgZUgZlK3Y=", + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "rev": "40e6053ecb65fcbf12863338a6dcefb3f55f1bf8", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "type": "github" + } + }, "root": { "inputs": { "agenix": "agenix", "anyrun": "anyrun", "fenix": "fenix", "home-manager": "home-manager_2", - "nixpkgs": "nixpkgs_2", + "neovim-nightly-overlay": "neovim-nightly-overlay", + "nixpkgs": "nixpkgs_3", "nixpkgs-wayland": "nixpkgs-wayland", + "nixvim": "nixvim", "nur": "nur", "schizofox": "schizofox", "split-monitor-workspaces": "split-monitor-workspaces" @@ -721,9 +1110,9 @@ }, "schizofox": { "inputs": { - "flake-compat": "flake-compat_2", - "flake-parts": "flake-parts_3", - "home-manager": "home-manager_3", + "flake-compat": "flake-compat_5", + "flake-parts": "flake-parts_6", + "home-manager": "home-manager_4", "nixpak": "nixpak", "nixpkgs": [ "nixpkgs" @@ -747,7 +1136,7 @@ "searx-randomizer": { "inputs": { "crane": "crane", - "flake-parts": "flake-parts_4", + "flake-parts": "flake-parts_7", "nixpkgs": [ "schizofox", "nixpkgs" @@ -817,6 +1206,51 @@ } }, "systems_3": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_4": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_5": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_6": { "locked": { "lastModified": 1689347949, "narHash": "sha256-12tWmuL2zgBgZkdoB6qXZsgJEH9LR3oUgpaQq2RbI80=", diff --git a/hosts/lars/default.nix b/hosts/lars/default.nix index 0cb39a8..d7176b6 100644 --- a/hosts/lars/default.nix +++ b/hosts/lars/default.nix @@ -20,7 +20,6 @@ vesktop.enable = true; btop.enable = true; mpv.enable = true; - schizofox.enable = false; zsh = { enable = true; @@ -31,9 +30,9 @@ }; ohmyzsh = { enable = true; - theme = "fino-time"; - }; - }; + theme = "fino-time"; + }; + }; git = { enable = true; @@ -43,17 +42,22 @@ }; firefox = { - enable = true; - extensions = { - "support@lastpass.com" = { - install_url = "https://addons.mozilla.org/firefox/downloads/file/4246455/lastpass_password_manager-4.127.0.1.xpi"; - installation_mode = "force_installed"; - }; - "newtaboverride@agenedia.com" = { - install_url = "https://addons.mozilla.org/firefox/downloads/file/4231522/new_tab_override-16.0.0.xpi"; - installation_mode = "force_installed"; - }; - }; + enable = true; + extensions = { + "support@lastpass.com" = { + install_url = "https://addons.mozilla.org/firefox/downloads/file/4246455/lastpass_password_manager-4.127.0.1.xpi"; + installation_mode = "force_installed"; + }; + "newtaboverride@agenedia.com" = { + install_url = "https://addons.mozilla.org/firefox/downloads/file/4231522/new_tab_override-16.0.0.xpi"; + installation_mode = "force_installed"; + }; + }; + }; + + alacritty = { + enable = true; + catppuccin = true; }; }; diff --git a/hosts/lars/kronos/configuration.nix b/hosts/lars/kronos/configuration.nix index 70ef21c..0d0af04 100644 --- a/hosts/lars/kronos/configuration.nix +++ b/hosts/lars/kronos/configuration.nix @@ -7,6 +7,14 @@ username = "lars"; }; }; + + programs = { + alacritty = { + opacity = 0.8; + blur = true; + }; + }; + hyprland = { enable = true; nvidia.enable = true; diff --git a/hosts/lars/programs.nix b/hosts/lars/programs.nix index a9a55c3..8997cfc 100644 --- a/hosts/lars/programs.nix +++ b/hosts/lars/programs.nix @@ -7,20 +7,19 @@ in { fenix = inputs.fenix.packages.${pkgs.system}; in with pkgs; [ - neofetch + neofetch git - trash-cli + trash-cli element-desktop steam libreoffice-fresh ventoy-full lazygit - obsidian + obsidian neofetch zip vlc zathura - alacritty unzip gcc bibata-cursors @@ -45,15 +44,15 @@ in { python3 rustdesk neovim - tmux - kitty - nextcloud-client - vscode - grim - slurp - wl-clipboard - pavucontrol - wofi + tmux + kitty + nextcloud-client + vscode + grim + slurp + wl-clipboard + pavucontrol + wofi ]; }; } diff --git a/modules/gui/alacritty.nix b/modules/gui/alacritty.nix new file mode 100644 index 0000000..fcafa8b --- /dev/null +++ b/modules/gui/alacritty.nix @@ -0,0 +1,42 @@ +{ config, lib, inputs, pkgs, ... }: +with lib; let + username = config.modules.other.system.username; + cfg = config.modules.programs.alacritty; +in { + options.modules.programs.alacritty = { + enable = mkEnableOption "alacritty"; + catppuccin = mkEnableOption "catppuccin"; + opacity = mkOption { + description = "opacity of alacritty"; + type = types.number; + default = 1.0; + }; + blur = mkOption { + description = "blur of alacritty"; + type = types.bool; + default = false; + }; + }; + + config = mkIf cfg.enable { + home-manager.users.${username} = { + programs.alacritty.enable = true; + + programs.alacritty.settings = { + window = { + blur = cfg.blur; + opacity = cfg.opacity; + }; + + colors = mkIf cfg.catppuccin { + primary = { + background = "#1e1e2e"; + foreground = "#cdd6f4"; + dim_foreground = "#7f849c"; + bright_foreground = "#cdd6f4"; + }; + }; + }; + }; + }; +} diff --git a/modules/gui/default.nix b/modules/gui/default.nix index 70631a4..95868e4 100644 --- a/modules/gui/default.nix +++ b/modules/gui/default.nix @@ -11,6 +11,7 @@ _: { ./foot.nix # ./vivado.nix ./WM - ./firefox.nix + ./alacritty.nix + ./firefox.nix ]; } From 2028a6669c35d7d3c71a6f26ce25852547a175d3 Mon Sep 17 00:00:00 2001 From: LarsZauberer Date: Sat, 13 Apr 2024 21:32:11 +0200 Subject: [PATCH 22/27] Alacritty configured for vali --- hosts/vali/mars/configuration.nix | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/hosts/vali/mars/configuration.nix b/hosts/vali/mars/configuration.nix index ada9ab0..bab54fc 100644 --- a/hosts/vali/mars/configuration.nix +++ b/hosts/vali/mars/configuration.nix @@ -67,6 +67,13 @@ enable = true; profiling = false; }; + alacritty = { + enable = true; + catppuccin = true; + opacity = 0.8; + blur = true; + # Grüsse + }; }; services = { pipewire.enable = true; From a9deb84530b2d49df39d48fa8c87b099da553370 Mon Sep 17 00:00:00 2001 From: vali Date: Sat, 13 Apr 2024 22:44:39 +0200 Subject: [PATCH 23/27] added dwm --- hosts/vali/mars/configuration.nix | 1 + hosts/vali/mars/default.nix | 1 + hosts/vali/mars/dwm/dwm-6.5/config.h | 116 ++++++++++++++++++++++++++ hosts/vali/mars/dwm/dwm-6.5/drw.o | Bin 0 -> 11144 bytes hosts/vali/mars/dwm/dwm-6.5/dwm | Bin 0 -> 62616 bytes hosts/vali/mars/dwm/dwm-6.5/dwm.o | Bin 0 -> 57728 bytes hosts/vali/mars/dwm/dwm-6.5/shell.nix | 9 ++ hosts/vali/mars/dwm/dwm-6.5/util.o | Bin 0 -> 2248 bytes hosts/vali/mars/dwm/dwm.nix | 11 +-- hosts/vali/mars/programs.nix | 4 + 10 files changed, 137 insertions(+), 5 deletions(-) create mode 100644 hosts/vali/mars/dwm/dwm-6.5/config.h create mode 100644 hosts/vali/mars/dwm/dwm-6.5/drw.o create mode 100755 hosts/vali/mars/dwm/dwm-6.5/dwm create mode 100644 hosts/vali/mars/dwm/dwm-6.5/dwm.o create mode 100644 hosts/vali/mars/dwm/dwm-6.5/shell.nix create mode 100644 hosts/vali/mars/dwm/dwm-6.5/util.o diff --git a/hosts/vali/mars/configuration.nix b/hosts/vali/mars/configuration.nix index 05ade7b..54f82fe 100644 --- a/hosts/vali/mars/configuration.nix +++ b/hosts/vali/mars/configuration.nix @@ -52,6 +52,7 @@ ssh.enable = true; btop.enable = true; mpv.enable = true; + i3.enable = true; dwm.enable = true; schizofox.enable = true; displaymanager.enable = true; diff --git a/hosts/vali/mars/default.nix b/hosts/vali/mars/default.nix index 360094d..2a9abad 100644 --- a/hosts/vali/mars/default.nix +++ b/hosts/vali/mars/default.nix @@ -5,5 +5,6 @@ _: { ./hardware-configuration.nix ./profile.nix ./i3 + ./dwm/dwm.nix ]; } diff --git a/hosts/vali/mars/dwm/dwm-6.5/config.h b/hosts/vali/mars/dwm/dwm-6.5/config.h new file mode 100644 index 0000000..9efa774 --- /dev/null +++ b/hosts/vali/mars/dwm/dwm-6.5/config.h @@ -0,0 +1,116 @@ +/* See LICENSE file for copyright and license details. */ + +/* appearance */ +static const unsigned int borderpx = 1; /* border pixel of windows */ +static const unsigned int snap = 32; /* snap pixel */ +static const int showbar = 1; /* 0 means no bar */ +static const int topbar = 1; /* 0 means bottom bar */ +static const char *fonts[] = { "monospace:size=10" }; +static const char dmenufont[] = "monospace:size=10"; +static const char col_gray1[] = "#222222"; +static const char col_gray2[] = "#444444"; +static const char col_gray3[] = "#bbbbbb"; +static const char col_gray4[] = "#eeeeee"; +static const char col_cyan[] = "#005577"; +static const char *colors[][3] = { + /* fg bg border */ + [SchemeNorm] = { col_gray3, col_gray1, col_gray2 }, + [SchemeSel] = { col_gray4, col_cyan, col_cyan }, +}; + +/* tagging */ +static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" }; + +static const Rule rules[] = { + /* xprop(1): + * WM_CLASS(STRING) = instance, class + * WM_NAME(STRING) = title + */ + /* class instance title tags mask isfloating monitor */ + { "Gimp", NULL, NULL, 0, 1, -1 }, + { "Firefox", NULL, NULL, 1 << 8, 0, -1 }, +}; + +/* layout(s) */ +static const float mfact = 0.55; /* factor of master area size [0.05..0.95] */ +static const int nmaster = 1; /* number of clients in master area */ +static const int resizehints = 1; /* 1 means respect size hints in tiled resizals */ +static const int lockfullscreen = 1; /* 1 will force focus on the fullscreen window */ + +static const Layout layouts[] = { + /* symbol arrange function */ + { "[]=", tile }, /* first entry is default */ + { "><>", NULL }, /* no layout function means floating behavior */ + { "[M]", monocle }, +}; + +/* key definitions */ +#define MODKEY Mod1Mask +#define TAGKEYS(KEY,TAG) \ + { MODKEY, KEY, view, {.ui = 1 << TAG} }, \ + { MODKEY|ControlMask, KEY, toggleview, {.ui = 1 << TAG} }, \ + { MODKEY|ShiftMask, KEY, tag, {.ui = 1 << TAG} }, \ + { MODKEY|ControlMask|ShiftMask, KEY, toggletag, {.ui = 1 << TAG} }, + +/* helper for spawning shell commands in the pre dwm-5.0 fashion */ +#define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } } + +/* commands */ +static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() */ +static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", dmenufont, "-nb", col_gray1, "-nf", col_gray3, "-sb", col_cyan, "-sf", col_gray4, NULL }; +static const char *termcmd[] = { "st", NULL }; + +static const Key keys[] = { + /* modifier key function argument */ + { MODKEY, XK_p, spawn, {.v = dmenucmd } }, + { MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } }, + { MODKEY, XK_b, togglebar, {0} }, + { MODKEY, XK_j, focusstack, {.i = +1 } }, + { MODKEY, XK_k, focusstack, {.i = -1 } }, + { MODKEY, XK_i, incnmaster, {.i = +1 } }, + { MODKEY, XK_d, incnmaster, {.i = -1 } }, + { MODKEY, XK_h, setmfact, {.f = -0.05} }, + { MODKEY, XK_l, setmfact, {.f = +0.05} }, + { MODKEY, XK_Return, zoom, {0} }, + { MODKEY, XK_Tab, view, {0} }, + { MODKEY|ShiftMask, XK_c, killclient, {0} }, + { MODKEY, XK_t, setlayout, {.v = &layouts[0]} }, + { MODKEY, XK_f, setlayout, {.v = &layouts[1]} }, + { MODKEY, XK_m, setlayout, {.v = &layouts[2]} }, + { MODKEY, XK_space, setlayout, {0} }, + { MODKEY|ShiftMask, XK_space, togglefloating, {0} }, + { MODKEY, XK_0, view, {.ui = ~0 } }, + { MODKEY|ShiftMask, XK_0, tag, {.ui = ~0 } }, + { MODKEY, XK_comma, focusmon, {.i = -1 } }, + { MODKEY, XK_period, focusmon, {.i = +1 } }, + { MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } }, + { MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } }, + TAGKEYS( XK_1, 0) + TAGKEYS( XK_2, 1) + TAGKEYS( XK_3, 2) + TAGKEYS( XK_4, 3) + TAGKEYS( XK_5, 4) + TAGKEYS( XK_6, 5) + TAGKEYS( XK_7, 6) + TAGKEYS( XK_8, 7) + TAGKEYS( XK_9, 8) + { MODKEY|ShiftMask, XK_q, quit, {0} }, +}; + +/* button definitions */ +/* click can be ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */ +static const Button buttons[] = { + /* click event mask button function argument */ + { ClkLtSymbol, 0, Button1, setlayout, {0} }, + { ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} }, + { ClkWinTitle, 0, Button2, zoom, {0} }, + { ClkStatusText, 0, Button2, spawn, {.v = termcmd } }, + { ClkClientWin, MODKEY, Button1, movemouse, {0} }, + { ClkClientWin, MODKEY, Button2, togglefloating, {0} }, + { ClkClientWin, MODKEY, Button3, resizemouse, {0} }, + { ClkTagBar, 0, Button1, view, {0} }, + { ClkTagBar, 0, Button3, toggleview, {0} }, + { ClkTagBar, MODKEY, Button1, tag, {0} }, + { ClkTagBar, MODKEY, Button3, toggletag, {0} }, +}; + diff --git a/hosts/vali/mars/dwm/dwm-6.5/drw.o b/hosts/vali/mars/dwm/dwm-6.5/drw.o new file mode 100644 index 0000000000000000000000000000000000000000..05c8f4bcf9b50e8bbf99e044134728ba7fba5051 GIT binary patch literal 11144 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 z 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 literal 0 HcmV?d00001 diff --git a/hosts/vali/mars/dwm/dwm-6.5/dwm.o b/hosts/vali/mars/dwm/dwm-6.5/dwm.o new file mode 100644 index 0000000000000000000000000000000000000000..171c5aa11aa3dea0c38629fca09642fd5c865b51 GIT binary patch literal 57728 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 {} }: + pkgs.mkShell { + nativeBuildInputs = with pkgs; [ + gnumake + xorg.libX11.dev + xorg.libXft + xorg.libXinerama + ]; +} diff --git a/hosts/vali/mars/dwm/dwm-6.5/util.o b/hosts/vali/mars/dwm/dwm-6.5/util.o new file mode 100644 index 0000000000000000000000000000000000000000..4b569ab3cf3d20cbdf0c56dd2448b4cd6d4ad19a GIT binary patch literal 2248 zcmb<-^>JfjWMqH=Mg}_u1P><4z~I4(U^{@B4h(z@ybPhi9-Y5E8sFStU|{g*EK$+$ z=nPRY@aXhWvGD11QE~9;^ilC>IZ$HGuj!%^z_00}lEAMSqEf)GIY*^|fq{WvbBW3X zFug`)0hr#RvH?u*Q8~cCz>wn6&7!ISHrz!;!tj7cw=T$bkIsi4owq!CTU0(UFfi<6 zVqjo6&Z5ErQrBI};L+)#!r{^DqM~rzMTNxxB--hsBJcvFv%#97M9rh~K7>=l{NJin z+@rgcVZQj1q)av7)*L}9`wk2qCElyODu`L6Cug zK>$@Ln5T|ITn~phD9o{$?7I4BLV zBZ==q5(mW*O#OKzaZnnAiC;q!2PJu!_%kGNWc8qI2a*EW%Z+63H;^C$12~<7(g4gH zR#3uXU|;~{RAwagJWz3vIUo#E56UATqd@9G7{mr)NZA812P6)Q9|pbR%G{E~BnG|W zk|GG50b>=V<|OKsq*jzL=%plbdHE%& zdhULqy2T}l$=OhTdS0nsK~a7|YEelggC5wx)QtGFqQu-(kgF)iApe4b0u;B%rosFx z3X(*UK;tqB7p03~4d!)TDdL2OWA4^;xDVnKoo3=G0x z9)f@hgZ&H=^@Q3FVk6@Mm_lShENUYe7#KkL50oa6mBRF+y9?bvg-|om^)G Date: Sun, 14 Apr 2024 10:59:57 +0200 Subject: [PATCH 24/27] added working dwm --- hosts/vali/mars/dwm/dwm-6.5/config.h | 12 ++++++------ hosts/vali/mars/dwm/dwm-6.5/dwm | Bin 62616 -> 62616 bytes hosts/vali/mars/dwm/dwm-6.5/dwm.o | Bin 57728 -> 57728 bytes 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/hosts/vali/mars/dwm/dwm-6.5/config.h b/hosts/vali/mars/dwm/dwm-6.5/config.h index 9efa774..0709852 100644 --- a/hosts/vali/mars/dwm/dwm-6.5/config.h +++ b/hosts/vali/mars/dwm/dwm-6.5/config.h @@ -45,7 +45,7 @@ static const Layout layouts[] = { }; /* key definitions */ -#define MODKEY Mod1Mask +#define MODKEY Mod4Mask #define TAGKEYS(KEY,TAG) \ { MODKEY, KEY, view, {.ui = 1 << TAG} }, \ { MODKEY|ControlMask, KEY, toggleview, {.ui = 1 << TAG} }, \ @@ -62,8 +62,8 @@ static const char *termcmd[] = { "st", NULL }; static const Key keys[] = { /* modifier key function argument */ - { MODKEY, XK_p, spawn, {.v = dmenucmd } }, - { MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } }, + { MODKEY, XK_d, spawn, {.v = dmenucmd } }, + { MODKEY, XK_Return, spawn, {.v = termcmd } }, { MODKEY, XK_b, togglebar, {0} }, { MODKEY, XK_j, focusstack, {.i = +1 } }, { MODKEY, XK_k, focusstack, {.i = -1 } }, @@ -71,9 +71,9 @@ static const Key keys[] = { { MODKEY, XK_d, incnmaster, {.i = -1 } }, { MODKEY, XK_h, setmfact, {.f = -0.05} }, { MODKEY, XK_l, setmfact, {.f = +0.05} }, - { MODKEY, XK_Return, zoom, {0} }, + { MODKEY|ShiftMask, XK_Return, zoom, {0} }, { MODKEY, XK_Tab, view, {0} }, - { MODKEY|ShiftMask, XK_c, killclient, {0} }, + { MODKEY|ShiftMask, XK_q, killclient, {0} }, { MODKEY, XK_t, setlayout, {.v = &layouts[0]} }, { MODKEY, XK_f, setlayout, {.v = &layouts[1]} }, { MODKEY, XK_m, setlayout, {.v = &layouts[2]} }, @@ -94,7 +94,7 @@ static const Key keys[] = { TAGKEYS( XK_7, 6) TAGKEYS( XK_8, 7) TAGKEYS( XK_9, 8) - { MODKEY|ShiftMask, XK_q, quit, {0} }, + { MODKEY|ShiftMask, XK_e, quit, {0} }, }; /* button definitions */ diff --git a/hosts/vali/mars/dwm/dwm-6.5/dwm b/hosts/vali/mars/dwm/dwm-6.5/dwm index 5e45246b831547ce4527139ccc5d7724832c2e03..ada53af8858f284682206aef4d9936bdcd919065 100755 GIT binary patch delta 482 zcmbR7l6l5U<_#(986764u9s(YnA{2`m#&XzbePP#LEhGZfq{XU0RlM6Ks*Q=M8bF} zAPxfq!>cTah{FXaJvng$$jnACxe!bq1d|WJB;!VqtRk3n1e1wivT>ulq9fGILMR;# zH5~N56GS>#F$qoluESVV~fTPR-!hn(- zP`Ut0zsiEhJ6wR!oRbqbfJ|)!lMBJ*K`{9cOfqf+$tr?LM=+TPCL1@(D{?~3Oor0Y zP_v<229C)G!D=6ZNybfJlQzjSa!z&xvlGGWMlgFJm^=s;c?c#MH-pu0mS^Od?6?`E zD{-?tBk$x!u=ql-_(8DvL$EmG7O?s)VD($T>bHQ^gT)tu#SenTAA-dhw}RDg1*_i* zR=*Xj9xT2PEPfCy{tztAxDBj+8(94|u=;Ia^#_eGB+rjF$gVk>b StKTlq2@AQx%`3ORw*deOu7nN% diff --git a/hosts/vali/mars/dwm/dwm-6.5/dwm.o b/hosts/vali/mars/dwm/dwm-6.5/dwm.o index 171c5aa11aa3dea0c38629fca09642fd5c865b51..3ced421d5a5a19c4e752356261f1930e66f7151c 100644 GIT binary patch delta 494 zcmZoT%-nF8d4q}vqr>Eb_r)hSc(6=X@L&P)9w74=ABs zZ}1SA+;Ep=@{#)@lN&rZz-*R>AT|q_eZ&*QhKQ?p%7DdOpmd6-45P#3Mo)Q0hsg`U z#9z}1EIf-Dh z(OVv53YY}39VS2YmY-Y_A~5-bw*aFfnCEbpW%3hmkjoN%)l;VaMR3KE%oA(>_J6JHrdm&p&oG9c0w%yyWZ=m*x}2iD;S z*5L delta 477 zcmZoT%-nF8d4q}vBgf=}_r)hSc(6=X@L&P)9>95%kK7TN+z=oz`NMqyF#W)tWAX+M zk;w-4StcL3FEY8og9FSyaYq2k=3p$CT<9Ur$T?ZjQ+~3+eU8Z!&8EhV{)UX zJR`^Cg<$d^n0yE(8NEQ_a6MiUoSY00kPI>pY(j?@#H1Ba`UI4I;U&SyIr*U%#6Asg z5Kqw?WL_eeZ1k3Aixm$!Qv0W;vkZDGKl1yoaiOLxFKL70MAU6p8x;= From e5fdc3585eb1e6f4b9a5e51592d5e06f0ec26ff3 Mon Sep 17 00:00:00 2001 From: vali Date: Sun, 14 Apr 2024 11:39:54 +0200 Subject: [PATCH 25/27] added st --- hosts/vali/mars/dwm/default.nix | 0 hosts/vali/mars/dwm/dmenu-5.3/LICENSE | 30 + hosts/vali/mars/dwm/dmenu-5.3/Makefile | 58 + hosts/vali/mars/dwm/dmenu-5.3/README | 24 + hosts/vali/mars/dwm/dmenu-5.3/arg.h | 49 + hosts/vali/mars/dwm/dmenu-5.3/config.def.h | 23 + hosts/vali/mars/dwm/dmenu-5.3/config.mk | 32 + hosts/vali/mars/dwm/dmenu-5.3/dmenu.1 | 194 ++ hosts/vali/mars/dwm/dmenu-5.3/dmenu.c | 796 ++++++ hosts/vali/mars/dwm/dmenu-5.3/dmenu_path | 13 + hosts/vali/mars/dwm/dmenu-5.3/dmenu_run | 2 + hosts/vali/mars/dwm/dmenu-5.3/drw.c | 451 ++++ hosts/vali/mars/dwm/dmenu-5.3/drw.h | 58 + hosts/vali/mars/dwm/dmenu-5.3/stest.1 | 90 + hosts/vali/mars/dwm/dmenu-5.3/stest.c | 109 + hosts/vali/mars/dwm/dmenu-5.3/util.c | 36 + hosts/vali/mars/dwm/dmenu-5.3/util.h | 9 + hosts/vali/mars/dwm/dmenu.nix | 0 hosts/vali/mars/dwm/dwm-6.5/config.h | 2 +- hosts/vali/mars/dwm/dwm.nix | 10 +- hosts/vali/mars/dwm/st-0.9.2/FAQ | 253 ++ hosts/vali/mars/dwm/st-0.9.2/LEGACY | 17 + hosts/vali/mars/dwm/st-0.9.2/LICENSE | 34 + hosts/vali/mars/dwm/st-0.9.2/Makefile | 51 + hosts/vali/mars/dwm/st-0.9.2/README | 34 + hosts/vali/mars/dwm/st-0.9.2/TODO | 28 + hosts/vali/mars/dwm/st-0.9.2/arg.h | 50 + hosts/vali/mars/dwm/st-0.9.2/config.def.h | 474 ++++ hosts/vali/mars/dwm/st-0.9.2/config.h | 474 ++++ hosts/vali/mars/dwm/st-0.9.2/config.mk | 36 + hosts/vali/mars/dwm/st-0.9.2/shell.nix | 10 + hosts/vali/mars/dwm/st-0.9.2/st | Bin 0 -> 96616 bytes hosts/vali/mars/dwm/st-0.9.2/st.1 | 177 ++ hosts/vali/mars/dwm/st-0.9.2/st.c | 2675 ++++++++++++++++++++ hosts/vali/mars/dwm/st-0.9.2/st.h | 126 + hosts/vali/mars/dwm/st-0.9.2/st.info | 243 ++ hosts/vali/mars/dwm/st-0.9.2/st.o | Bin 0 -> 79120 bytes hosts/vali/mars/dwm/st-0.9.2/win.h | 41 + hosts/vali/mars/dwm/st-0.9.2/x.c | 2105 +++++++++++++++ hosts/vali/mars/dwm/st-0.9.2/x.o | Bin 0 -> 75240 bytes hosts/vali/mars/dwm/st.nix | 5 + 41 files changed, 8815 insertions(+), 4 deletions(-) create mode 100644 hosts/vali/mars/dwm/default.nix create mode 100644 hosts/vali/mars/dwm/dmenu-5.3/LICENSE create mode 100644 hosts/vali/mars/dwm/dmenu-5.3/Makefile create mode 100644 hosts/vali/mars/dwm/dmenu-5.3/README create mode 100644 hosts/vali/mars/dwm/dmenu-5.3/arg.h create mode 100644 hosts/vali/mars/dwm/dmenu-5.3/config.def.h create mode 100644 hosts/vali/mars/dwm/dmenu-5.3/config.mk create mode 100644 hosts/vali/mars/dwm/dmenu-5.3/dmenu.1 create mode 100644 hosts/vali/mars/dwm/dmenu-5.3/dmenu.c create mode 100755 hosts/vali/mars/dwm/dmenu-5.3/dmenu_path create mode 100755 hosts/vali/mars/dwm/dmenu-5.3/dmenu_run create mode 100644 hosts/vali/mars/dwm/dmenu-5.3/drw.c create mode 100644 hosts/vali/mars/dwm/dmenu-5.3/drw.h create mode 100644 hosts/vali/mars/dwm/dmenu-5.3/stest.1 create mode 100644 hosts/vali/mars/dwm/dmenu-5.3/stest.c create mode 100644 hosts/vali/mars/dwm/dmenu-5.3/util.c create mode 100644 hosts/vali/mars/dwm/dmenu-5.3/util.h create mode 100644 hosts/vali/mars/dwm/dmenu.nix create mode 100644 hosts/vali/mars/dwm/st-0.9.2/FAQ create mode 100644 hosts/vali/mars/dwm/st-0.9.2/LEGACY create mode 100644 hosts/vali/mars/dwm/st-0.9.2/LICENSE create mode 100644 hosts/vali/mars/dwm/st-0.9.2/Makefile create mode 100644 hosts/vali/mars/dwm/st-0.9.2/README create mode 100644 hosts/vali/mars/dwm/st-0.9.2/TODO create mode 100644 hosts/vali/mars/dwm/st-0.9.2/arg.h create mode 100644 hosts/vali/mars/dwm/st-0.9.2/config.def.h create mode 100644 hosts/vali/mars/dwm/st-0.9.2/config.h create mode 100644 hosts/vali/mars/dwm/st-0.9.2/config.mk create mode 100644 hosts/vali/mars/dwm/st-0.9.2/shell.nix create mode 100755 hosts/vali/mars/dwm/st-0.9.2/st create mode 100644 hosts/vali/mars/dwm/st-0.9.2/st.1 create mode 100644 hosts/vali/mars/dwm/st-0.9.2/st.c create mode 100644 hosts/vali/mars/dwm/st-0.9.2/st.h create mode 100644 hosts/vali/mars/dwm/st-0.9.2/st.info create mode 100644 hosts/vali/mars/dwm/st-0.9.2/st.o create mode 100644 hosts/vali/mars/dwm/st-0.9.2/win.h create mode 100644 hosts/vali/mars/dwm/st-0.9.2/x.c create mode 100644 hosts/vali/mars/dwm/st-0.9.2/x.o create mode 100644 hosts/vali/mars/dwm/st.nix diff --git a/hosts/vali/mars/dwm/default.nix b/hosts/vali/mars/dwm/default.nix new file mode 100644 index 0000000..e69de29 diff --git a/hosts/vali/mars/dwm/dmenu-5.3/LICENSE b/hosts/vali/mars/dwm/dmenu-5.3/LICENSE new file mode 100644 index 0000000..2a64b28 --- /dev/null +++ b/hosts/vali/mars/dwm/dmenu-5.3/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/hosts/vali/mars/dwm/dmenu-5.3/Makefile b/hosts/vali/mars/dwm/dmenu-5.3/Makefile new file mode 100644 index 0000000..458c524 --- /dev/null +++ b/hosts/vali/mars/dwm/dmenu-5.3/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/hosts/vali/mars/dwm/dmenu-5.3/README b/hosts/vali/mars/dwm/dmenu-5.3/README new file mode 100644 index 0000000..a8fcdfe --- /dev/null +++ b/hosts/vali/mars/dwm/dmenu-5.3/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/hosts/vali/mars/dwm/dmenu-5.3/arg.h b/hosts/vali/mars/dwm/dmenu-5.3/arg.h new file mode 100644 index 0000000..e94e02b --- /dev/null +++ b/hosts/vali/mars/dwm/dmenu-5.3/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/hosts/vali/mars/dwm/dmenu-5.3/config.def.h b/hosts/vali/mars/dwm/dmenu-5.3/config.def.h new file mode 100644 index 0000000..1edb647 --- /dev/null +++ b/hosts/vali/mars/dwm/dmenu-5.3/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/hosts/vali/mars/dwm/dmenu-5.3/config.mk b/hosts/vali/mars/dwm/dmenu-5.3/config.mk new file mode 100644 index 0000000..137f7c8 --- /dev/null +++ b/hosts/vali/mars/dwm/dmenu-5.3/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/hosts/vali/mars/dwm/dmenu-5.3/dmenu.1 b/hosts/vali/mars/dwm/dmenu-5.3/dmenu.1 new file mode 100644 index 0000000..323f93c --- /dev/null +++ b/hosts/vali/mars/dwm/dmenu-5.3/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/hosts/vali/mars/dwm/dmenu-5.3/dmenu.c b/hosts/vali/mars/dwm/dmenu-5.3/dmenu.c new file mode 100644 index 0000000..40f93e0 --- /dev/null +++ b/hosts/vali/mars/dwm/dmenu-5.3/dmenu.c @@ -0,0 +1,796 @@ +/* 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; + + XUngrabKey(dpy, AnyKey, AnyModifier, root); + 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/hosts/vali/mars/dwm/dmenu-5.3/dmenu_path b/hosts/vali/mars/dwm/dmenu-5.3/dmenu_path new file mode 100755 index 0000000..3a7cda7 --- /dev/null +++ b/hosts/vali/mars/dwm/dmenu-5.3/dmenu_path @@ -0,0 +1,13 @@ +#!/bin/sh + +cachedir="${XDG_CACHE_HOME:-"$HOME/.cache"}" +cache="$cachedir/dmenu_run" + +[ ! -e "$cachedir" ] && mkdir -p "$cachedir" + +IFS=: +if stest -dqr -n "$cache" $PATH; then + stest -flx $PATH | sort -u | tee "$cache" +else + cat "$cache" +fi diff --git a/hosts/vali/mars/dwm/dmenu-5.3/dmenu_run b/hosts/vali/mars/dwm/dmenu-5.3/dmenu_run new file mode 100755 index 0000000..834ede5 --- /dev/null +++ b/hosts/vali/mars/dwm/dmenu-5.3/dmenu_run @@ -0,0 +1,2 @@ +#!/bin/sh +dmenu_path | dmenu "$@" | ${SHELL:-"/bin/sh"} & diff --git a/hosts/vali/mars/dwm/dmenu-5.3/drw.c b/hosts/vali/mars/dwm/dmenu-5.3/drw.c new file mode 100644 index 0000000..78a2b27 --- /dev/null +++ b/hosts/vali/mars/dwm/dmenu-5.3/drw.c @@ -0,0 +1,451 @@ +/* See LICENSE file for copyright and license details. */ +#include +#include +#include +#include +#include + +#include "drw.h" +#include "util.h" + +#define UTF_INVALID 0xFFFD +#define UTF_SIZ 4 + +static const unsigned char utfbyte[UTF_SIZ + 1] = {0x80, 0, 0xC0, 0xE0, 0xF0}; +static const unsigned char utfmask[UTF_SIZ + 1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8}; +static const long utfmin[UTF_SIZ + 1] = { 0, 0, 0x80, 0x800, 0x10000}; +static const long utfmax[UTF_SIZ + 1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF}; + +static long +utf8decodebyte(const char c, size_t *i) +{ + for (*i = 0; *i < (UTF_SIZ + 1); ++(*i)) + if (((unsigned char)c & utfmask[*i]) == utfbyte[*i]) + return (unsigned char)c & ~utfmask[*i]; + return 0; +} + +static size_t +utf8validate(long *u, size_t i) +{ + if (!BETWEEN(*u, utfmin[i], utfmax[i]) || BETWEEN(*u, 0xD800, 0xDFFF)) + *u = UTF_INVALID; + for (i = 1; *u > utfmax[i]; ++i) + ; + return i; +} + +static size_t +utf8decode(const char *c, long *u, size_t clen) +{ + size_t i, j, len, type; + long udecoded; + + *u = UTF_INVALID; + if (!clen) + return 0; + udecoded = utf8decodebyte(c[0], &len); + if (!BETWEEN(len, 1, UTF_SIZ)) + return 1; + for (i = 1, j = 1; i < clen && j < len; ++i, ++j) { + udecoded = (udecoded << 6) | utf8decodebyte(c[i], &type); + if (type) + return j; + } + if (j < len) + return 0; + *u = udecoded; + utf8validate(u, len); + + 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, 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; + + 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); + 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, "..."); + while (1) { + ew = ellipsis_len = utf8strlen = 0; + utf8str = text; + nextfont = NULL; + while (*text) { + utf8charlen = utf8decode(text, &utf8codepoint, UTF_SIZ); + 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) { + utf8strlen += utf8charlen; + text += utf8charlen; + ew += tmpw; + } else { + nextfont = curfont; + } + break; + } + } + + if (overflow || !charexists || nextfont) + 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 (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/hosts/vali/mars/dwm/dmenu-5.3/drw.h b/hosts/vali/mars/dwm/dmenu-5.3/drw.h new file mode 100644 index 0000000..fd7631b --- /dev/null +++ b/hosts/vali/mars/dwm/dmenu-5.3/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/hosts/vali/mars/dwm/dmenu-5.3/stest.1 b/hosts/vali/mars/dwm/dmenu-5.3/stest.1 new file mode 100644 index 0000000..2667d8a --- /dev/null +++ b/hosts/vali/mars/dwm/dmenu-5.3/stest.1 @@ -0,0 +1,90 @@ +.TH STEST 1 dmenu\-VERSION +.SH NAME +stest \- filter a list of files by properties +.SH SYNOPSIS +.B stest +.RB [ -abcdefghlpqrsuwx ] +.RB [ -n +.IR file ] +.RB [ -o +.IR file ] +.RI [ file ...] +.SH DESCRIPTION +.B stest +takes a list of files and filters by the files' properties, analogous to +.IR test (1). +Files which pass all tests are printed to stdout. If no files are given, stest +reads files from stdin. +.SH OPTIONS +.TP +.B \-a +Test hidden files. +.TP +.B \-b +Test that files are block specials. +.TP +.B \-c +Test that files are character specials. +.TP +.B \-d +Test that files are directories. +.TP +.B \-e +Test that files exist. +.TP +.B \-f +Test that files are regular files. +.TP +.B \-g +Test that files have their set-group-ID flag set. +.TP +.B \-h +Test that files are symbolic links. +.TP +.B \-l +Test the contents of a directory given as an argument. +.TP +.BI \-n " file" +Test that files are newer than +.IR file . +.TP +.BI \-o " file" +Test that files are older than +.IR file . +.TP +.B \-p +Test that files are named pipes. +.TP +.B \-q +No files are printed, only the exit status is returned. +.TP +.B \-r +Test that files are readable. +.TP +.B \-s +Test that files are not empty. +.TP +.B \-u +Test that files have their set-user-ID flag set. +.TP +.B \-v +Invert the sense of tests, only failing files pass. +.TP +.B \-w +Test that files are writable. +.TP +.B \-x +Test that files are executable. +.SH EXIT STATUS +.TP +.B 0 +At least one file passed all tests. +.TP +.B 1 +No files passed all tests. +.TP +.B 2 +An error occurred. +.SH SEE ALSO +.IR dmenu (1), +.IR test (1) diff --git a/hosts/vali/mars/dwm/dmenu-5.3/stest.c b/hosts/vali/mars/dwm/dmenu-5.3/stest.c new file mode 100644 index 0000000..e27d3a5 --- /dev/null +++ b/hosts/vali/mars/dwm/dmenu-5.3/stest.c @@ -0,0 +1,109 @@ +/* See LICENSE file for copyright and license details. */ +#include + +#include +#include +#include +#include +#include +#include + +#include "arg.h" +char *argv0; + +#define FLAG(x) (flag[(x)-'a']) + +static void test(const char *, const char *); +static void usage(void); + +static int match = 0; +static int flag[26]; +static struct stat old, new; + +static void +test(const char *path, const char *name) +{ + struct stat st, ln; + + if ((!stat(path, &st) && (FLAG('a') || name[0] != '.') /* hidden files */ + && (!FLAG('b') || S_ISBLK(st.st_mode)) /* block special */ + && (!FLAG('c') || S_ISCHR(st.st_mode)) /* character special */ + && (!FLAG('d') || S_ISDIR(st.st_mode)) /* directory */ + && (!FLAG('e') || access(path, F_OK) == 0) /* exists */ + && (!FLAG('f') || S_ISREG(st.st_mode)) /* regular file */ + && (!FLAG('g') || st.st_mode & S_ISGID) /* set-group-id flag */ + && (!FLAG('h') || (!lstat(path, &ln) && S_ISLNK(ln.st_mode))) /* symbolic link */ + && (!FLAG('n') || st.st_mtime > new.st_mtime) /* newer than file */ + && (!FLAG('o') || st.st_mtime < old.st_mtime) /* older than file */ + && (!FLAG('p') || S_ISFIFO(st.st_mode)) /* named pipe */ + && (!FLAG('r') || access(path, R_OK) == 0) /* readable */ + && (!FLAG('s') || st.st_size > 0) /* not empty */ + && (!FLAG('u') || st.st_mode & S_ISUID) /* set-user-id flag */ + && (!FLAG('w') || access(path, W_OK) == 0) /* writable */ + && (!FLAG('x') || access(path, X_OK) == 0)) != FLAG('v')) { /* executable */ + if (FLAG('q')) + exit(0); + match = 1; + puts(name); + } +} + +static void +usage(void) +{ + fprintf(stderr, "usage: %s [-abcdefghlpqrsuvwx] " + "[-n file] [-o file] [file...]\n", argv0); + exit(2); /* like test(1) return > 1 on error */ +} + +int +main(int argc, char *argv[]) +{ + struct dirent *d; + char path[PATH_MAX], *line = NULL, *file; + size_t linesiz = 0; + ssize_t n; + DIR *dir; + int r; + + ARGBEGIN { + case 'n': /* newer than file */ + case 'o': /* older than file */ + file = EARGF(usage()); + if (!(FLAG(ARGC()) = !stat(file, (ARGC() == 'n' ? &new : &old)))) + perror(file); + break; + default: + /* miscellaneous operators */ + if (strchr("abcdefghlpqrsuvwx", ARGC())) + FLAG(ARGC()) = 1; + else + usage(); /* unknown flag */ + } ARGEND; + + if (!argc) { + /* read list from stdin */ + while ((n = getline(&line, &linesiz, stdin)) > 0) { + if (line[n - 1] == '\n') + line[n - 1] = '\0'; + test(line, line); + } + free(line); + } else { + for (; argc; argc--, argv++) { + if (FLAG('l') && (dir = opendir(*argv))) { + /* test directory contents */ + while ((d = readdir(dir))) { + r = snprintf(path, sizeof path, "%s/%s", + *argv, d->d_name); + if (r >= 0 && (size_t)r < sizeof path) + test(path, d->d_name); + } + closedir(dir); + } else { + test(*argv, *argv); + } + } + } + return match ? 0 : 1; +} diff --git a/hosts/vali/mars/dwm/dmenu-5.3/util.c b/hosts/vali/mars/dwm/dmenu-5.3/util.c new file mode 100644 index 0000000..96b82c9 --- /dev/null +++ b/hosts/vali/mars/dwm/dmenu-5.3/util.c @@ -0,0 +1,36 @@ +/* See LICENSE file for copyright and license details. */ +#include +#include +#include +#include + +#include "util.h" + +void +die(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + + if (fmt[0] && fmt[strlen(fmt)-1] == ':') { + fputc(' ', stderr); + perror(NULL); + } else { + fputc('\n', stderr); + } + + exit(1); +} + +void * +ecalloc(size_t nmemb, size_t size) +{ + void *p; + + if (!(p = calloc(nmemb, size))) + die("calloc:"); + return p; +} diff --git a/hosts/vali/mars/dwm/dmenu-5.3/util.h b/hosts/vali/mars/dwm/dmenu-5.3/util.h new file mode 100644 index 0000000..c0a50d4 --- /dev/null +++ b/hosts/vali/mars/dwm/dmenu-5.3/util.h @@ -0,0 +1,9 @@ +/* See LICENSE file for copyright and license details. */ + +#define MAX(A, B) ((A) > (B) ? (A) : (B)) +#define MIN(A, B) ((A) < (B) ? (A) : (B)) +#define BETWEEN(X, A, B) ((A) <= (X) && (X) <= (B)) +#define LENGTH(X) (sizeof (X) / sizeof (X)[0]) + +void die(const char *fmt, ...); +void *ecalloc(size_t nmemb, size_t size); diff --git a/hosts/vali/mars/dwm/dmenu.nix b/hosts/vali/mars/dwm/dmenu.nix new file mode 100644 index 0000000..e69de29 diff --git a/hosts/vali/mars/dwm/dwm-6.5/config.h b/hosts/vali/mars/dwm/dwm-6.5/config.h index 0709852..c6c72bc 100644 --- a/hosts/vali/mars/dwm/dwm-6.5/config.h +++ b/hosts/vali/mars/dwm/dwm-6.5/config.h @@ -72,12 +72,12 @@ static const Key keys[] = { { MODKEY, XK_h, setmfact, {.f = -0.05} }, { MODKEY, XK_l, setmfact, {.f = +0.05} }, { MODKEY|ShiftMask, XK_Return, zoom, {0} }, + { MODKEY, XK_space, zoom, {0} }, { MODKEY, XK_Tab, view, {0} }, { MODKEY|ShiftMask, XK_q, killclient, {0} }, { MODKEY, XK_t, setlayout, {.v = &layouts[0]} }, { MODKEY, XK_f, setlayout, {.v = &layouts[1]} }, { MODKEY, XK_m, setlayout, {.v = &layouts[2]} }, - { MODKEY, XK_space, setlayout, {0} }, { MODKEY|ShiftMask, XK_space, togglefloating, {0} }, { MODKEY, XK_0, view, {.ui = ~0 } }, { MODKEY|ShiftMask, XK_0, tag, {.ui = ~0 } }, diff --git a/hosts/vali/mars/dwm/dwm.nix b/hosts/vali/mars/dwm/dwm.nix index e7cea0d..a2104c0 100644 --- a/hosts/vali/mars/dwm/dwm.nix +++ b/hosts/vali/mars/dwm/dwm.nix @@ -6,18 +6,22 @@ in { options.modules.programs.dwm.enable = mkEnableOption "dwm"; config = mkIf cfg.enable { - services.xserver = { + services.xserver = { enable = true; xkb.layout = "de"; windowManager.dwm = { enable = true; - # package = pkgs.dwm.overrideAttrs { src = ./dwm-6.5/dwm; }; }; }; nixpkgs.overlays = [ (final: prev: { - dwm = prev.dwm.overrideAttrs (old: {src = ./dwm-6.5;}); #FIX ME: Update with path to your dwm folder + dwm = prev.dwm.overrideAttrs (old: {src = ./dwm-6.5;}); + dmenu = prev.dmenu.overrideAttrs (old: {src = ./dmenu-5.3;}); }) ]; + environment.systemPackages = with pkgs; [ + (st.overrideAttrs (oldAttrs: rec { src = ./st-0.9.2; })) + ]; + }; } diff --git a/hosts/vali/mars/dwm/st-0.9.2/FAQ b/hosts/vali/mars/dwm/st-0.9.2/FAQ new file mode 100644 index 0000000..6287a27 --- /dev/null +++ b/hosts/vali/mars/dwm/st-0.9.2/FAQ @@ -0,0 +1,253 @@ +## Why does st not handle utmp entries? + +Use the excellent tool of [utmp](https://git.suckless.org/utmp/) for this task. + + +## Some _random program_ complains that st is unknown/not recognised/unsupported/whatever! + +It means that st doesn’t have any terminfo entry on your system. Chances are +you did not `make install`. If you just want to test it without installing it, +you can manually run `tic -sx st.info`. + + +## Nothing works, and nothing is said about an unknown terminal! + +* Some programs just assume they’re running in xterm i.e. they don’t rely on + terminfo. What you see is the current state of the “xterm compliance”. +* Some programs don’t complain about the lacking st description and default to + another terminal. In that case see the question about terminfo. + + +## How do I scroll back up? + +* Using a terminal multiplexer. + * `st -e tmux` using C-b [ + * `st -e screen` using C-a ESC +* Using the excellent tool of [scroll](https://git.suckless.org/scroll/). +* Using the scrollback [patch](https://st.suckless.org/patches/scrollback/). + + +## I would like to have utmp and/or scroll functionality by default + +You can add the absolute path of both programs in your config.h file. You only +have to modify the value of utmp and scroll variables. + + +## Why doesn't the Del key work in some programs? + +Taken from the terminfo manpage: + + If the terminal has a keypad that transmits codes when the keys + are pressed, this information can be given. Note that it is not + possible to handle terminals where the keypad only works in + local (this applies, for example, to the unshifted HP 2621 keys). + If the keypad can be set to transmit or not transmit, give these + codes as smkx and rmkx. Otherwise the keypad is assumed to + always transmit. + +In the st case smkx=E[?1hE= and rmkx=E[?1lE>, so it is mandatory that +applications which want to test against keypad keys send these +sequences. + +But buggy applications (like bash and irssi, for example) don't do this. A fast +solution for them is to use the following command: + + $ printf '\033[?1h\033=' >/dev/tty + +or + $ tput smkx + +In the case of bash, readline is used. Readline has a different note in its +manpage about this issue: + + enable-keypad (Off) + When set to On, readline will try to enable the + application keypad when it is called. Some systems + need this to enable arrow keys. + +Adding this option to your .inputrc will fix the keypad problem for all +applications using readline. + +If you are using zsh, then read the zsh FAQ +: + + It should be noted that the O / [ confusion can occur with other keys + such as Home and End. Some systems let you query the key sequences + sent by these keys from the system's terminal database, terminfo. + Unfortunately, the key sequences given there typically apply to the + mode that is not the one zsh uses by default (it's the "application" + mode rather than the "raw" mode). Explaining the use of terminfo is + outside of the scope of this FAQ, but if you wish to use the key + sequences given there you can tell the line editor to turn on + "application" mode when it starts and turn it off when it stops: + + function zle-line-init () { echoti smkx } + function zle-line-finish () { echoti rmkx } + zle -N zle-line-init + zle -N zle-line-finish + +Putting these lines into your .zshrc will fix the problems. + + +## How can I use meta in 8bit mode? + +St supports meta in 8bit mode, but the default terminfo entry doesn't +use this capability. If you want it, you have to use the 'st-meta' value +in TERM. + + +## I cannot compile st in OpenBSD + +OpenBSD lacks librt, despite it being mandatory in POSIX +. +If you want to compile st for OpenBSD you have to remove -lrt from config.mk, and +st will compile without any loss of functionality, because all the functions are +included in libc on this platform. + + +## The Backspace Case + +St is emulating the Linux way of handling backspace being delete and delete being +backspace. + +This is an issue that was discussed in suckless mailing list +. Here is why some old grumpy +terminal users wants its backspace to be how he feels it: + + Well, I am going to comment why I want to change the behaviour + of this key. When ASCII was defined in 1968, communication + with computers was done using punched cards, or hardcopy + terminals (basically a typewriter machine connected with the + computer using a serial port). ASCII defines DELETE as 7F, + because, in punched-card terms, it means all the holes of the + card punched; it is thus a kind of 'physical delete'. In the + same way, the BACKSPACE key was a non-destructive backspace, + as on a typewriter. So, if you wanted to delete a character, + you had to BACKSPACE and then DELETE. Another use of BACKSPACE + was to type accented characters, for example 'a BACKSPACE `'. + The VT100 had no BACKSPACE key; it was generated using the + CONTROL key as another control character (CONTROL key sets to + 0 b7 b6 b5, so it converts H (code 0x48) into BACKSPACE (code + 0x08)), but it had a DELETE key in a similar position where + the BACKSPACE key is located today on common PC keyboards. + All the terminal emulators emulated the difference between + these keys correctly: the backspace key generated a BACKSPACE + (^H) and delete key generated a DELETE (^?). + + But a problem arose when Linus Torvalds wrote Linux. Unlike + earlier terminals, the Linux virtual terminal (the terminal + emulator integrated in the kernel) returned a DELETE when + backspace was pressed, due to the VT100 having a DELETE key in + the same position. This created a lot of problems (see [1] + and [2]). Since Linux has become the king, a lot of terminal + emulators today generate a DELETE when the backspace key is + pressed in order to avoid problems with Linux. The result is + that the only way of generating a BACKSPACE on these systems + is by using CONTROL + H. (I also think that emacs had an + important point here because the CONTROL + H prefix is used + in emacs in some commands (help commands).) + + From point of view of the kernel, you can change the key + for deleting a previous character with stty erase. When you + connect a real terminal into a machine you describe the type + of terminal, so getty configures the correct value of stty + erase for this terminal. In the case of terminal emulators, + however, you don't have any getty that can set the correct + value of stty erase, so you always get the default value. + For this reason, it is necessary to add 'stty erase ^H' to your + profile if you have changed the value of the backspace key. + Of course, another solution is for st itself to modify the + value of stty erase. I usually have the inverse problem: + when I connect to non-Unix machines, I have to press CONTROL + + h to get a BACKSPACE. The inverse problem occurs when a user + connects to my Unix machines from a different system with a + correct backspace key. + + [1] http://www.ibb.net/~anne/keyboard.html + [2] http://www.tldp.org/HOWTO/Keyboard-and-Console-HOWTO-5.html + + +## But I really want the old grumpy behaviour of my terminal + +Apply [1]. + +[1] https://st.suckless.org/patches/delkey + + +## Why do images not work in st using the w3m image hack? + +w3mimg uses a hack that draws an image on top of the terminal emulator Drawable +window. The hack relies on the terminal to use a single buffer to draw its +contents directly. + +st uses double-buffered drawing so the image is quickly replaced and may show a +short flicker effect. + +Below is a patch example to change st double-buffering to a single Drawable +buffer. + +diff --git a/x.c b/x.c +--- a/x.c ++++ b/x.c +@@ -732,10 +732,6 @@ xresize(int col, int row) + win.tw = col * win.cw; + win.th = row * win.ch; + +- XFreePixmap(xw.dpy, xw.buf); +- xw.buf = XCreatePixmap(xw.dpy, xw.win, win.w, win.h, +- DefaultDepth(xw.dpy, xw.scr)); +- XftDrawChange(xw.draw, xw.buf); + xclear(0, 0, win.w, win.h); + + /* resize to new width */ +@@ -1148,8 +1144,7 @@ xinit(int cols, int rows) + gcvalues.graphics_exposures = False; + dc.gc = XCreateGC(xw.dpy, parent, GCGraphicsExposures, + &gcvalues); +- xw.buf = XCreatePixmap(xw.dpy, xw.win, win.w, win.h, +- DefaultDepth(xw.dpy, xw.scr)); ++ xw.buf = xw.win; + XSetForeground(xw.dpy, dc.gc, dc.col[defaultbg].pixel); + XFillRectangle(xw.dpy, xw.buf, dc.gc, 0, 0, win.w, win.h); + +@@ -1632,8 +1627,6 @@ xdrawline(Line line, int x1, int y1, int x2) + void + xfinishdraw(void) + { +- XCopyArea(xw.dpy, xw.buf, xw.win, dc.gc, 0, 0, win.w, +- win.h, 0, 0); + XSetForeground(xw.dpy, dc.gc, + dc.col[IS_SET(MODE_REVERSE)? + defaultfg : defaultbg].pixel); + + +## BadLength X error in Xft when trying to render emoji + +Xft makes st crash when rendering color emojis with the following error: + +"X Error of failed request: BadLength (poly request too large or internal Xlib length error)" + Major opcode of failed request: 139 (RENDER) + Minor opcode of failed request: 20 (RenderAddGlyphs) + Serial number of failed request: 1595 + Current serial number in output stream: 1818" + +This is a known bug in Xft (not st) which happens on some platforms and +combination of particular fonts and fontconfig settings. + +See also: +https://gitlab.freedesktop.org/xorg/lib/libxft/issues/6 +https://bugs.freedesktop.org/show_bug.cgi?id=107534 +https://bugzilla.redhat.com/show_bug.cgi?id=1498269 + +The solution is to remove color emoji fonts or disable this in the fontconfig +XML configuration. As an ugly workaround (which may work only on newer +fontconfig versions (FC_COLOR)), the following code can be used to mask color +fonts: + + FcPatternAddBool(fcpattern, FC_COLOR, FcFalse); + +Please don't bother reporting this bug to st, but notify the upstream Xft +developers about fixing this bug. + +As of 2022-09-05 this now seems to be finally fixed in libXft 2.3.5: +https://gitlab.freedesktop.org/xorg/lib/libxft/-/blob/libXft-2.3.5/NEWS diff --git a/hosts/vali/mars/dwm/st-0.9.2/LEGACY b/hosts/vali/mars/dwm/st-0.9.2/LEGACY new file mode 100644 index 0000000..bf28b1e --- /dev/null +++ b/hosts/vali/mars/dwm/st-0.9.2/LEGACY @@ -0,0 +1,17 @@ +A STATEMENT ON LEGACY SUPPORT + +In the terminal world there is much cruft that comes from old and unsup‐ +ported terminals that inherit incompatible modes and escape sequences +which noone is able to know, except when he/she comes from that time and +developed a graphical vt100 emulator at that time. + +One goal of st is to only support what is really needed. When you en‐ +counter a sequence which you really need, implement it. But while you +are at it, do not add the other cruft you might encounter while sneek‐ +ing at other terminal emulators. History has bloated them and there is +no real evidence that most of the sequences are used today. + + +Christoph Lohmann <20h@r-36.net> +2012-09-13T07:00:36.081271045+02:00 + diff --git a/hosts/vali/mars/dwm/st-0.9.2/LICENSE b/hosts/vali/mars/dwm/st-0.9.2/LICENSE new file mode 100644 index 0000000..3cbf420 --- /dev/null +++ b/hosts/vali/mars/dwm/st-0.9.2/LICENSE @@ -0,0 +1,34 @@ +MIT/X Consortium License + +© 2014-2022 Hiltjo Posthuma +© 2018 Devin J. Pohly +© 2014-2017 Quentin Rameau +© 2009-2012 Aurélien APTEL +© 2008-2017 Anselm R Garbe +© 2012-2017 Roberto E. Vargas Caballero +© 2012-2016 Christoph Lohmann <20h at r-36 dot net> +© 2013 Eon S. Jeon +© 2013 Alexander Sedov +© 2013 Mark Edgar +© 2013-2014 Eric Pruitt +© 2013 Michael Forney +© 2013-2014 Markus Teich +© 2014-2015 Laslo Hunhold + +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/hosts/vali/mars/dwm/st-0.9.2/Makefile b/hosts/vali/mars/dwm/st-0.9.2/Makefile new file mode 100644 index 0000000..15db421 --- /dev/null +++ b/hosts/vali/mars/dwm/st-0.9.2/Makefile @@ -0,0 +1,51 @@ +# st - simple terminal +# See LICENSE file for copyright and license details. +.POSIX: + +include config.mk + +SRC = st.c x.c +OBJ = $(SRC:.c=.o) + +all: st + +config.h: + cp config.def.h config.h + +.c.o: + $(CC) $(STCFLAGS) -c $< + +st.o: config.h st.h win.h +x.o: arg.h config.h st.h win.h + +$(OBJ): config.h config.mk + +st: $(OBJ) + $(CC) -o $@ $(OBJ) $(STLDFLAGS) + +clean: + rm -f st $(OBJ) st-$(VERSION).tar.gz + +dist: clean + mkdir -p st-$(VERSION) + cp -R FAQ LEGACY TODO LICENSE Makefile README config.mk\ + config.def.h st.info st.1 arg.h st.h win.h $(SRC)\ + st-$(VERSION) + tar -cf - st-$(VERSION) | gzip > st-$(VERSION).tar.gz + rm -rf st-$(VERSION) + +install: st + mkdir -p $(DESTDIR)$(PREFIX)/bin + cp -f st $(DESTDIR)$(PREFIX)/bin + chmod 755 $(DESTDIR)$(PREFIX)/bin/st + mkdir -p $(DESTDIR)$(MANPREFIX)/man1 + sed "s/VERSION/$(VERSION)/g" < st.1 > $(DESTDIR)$(MANPREFIX)/man1/st.1 + chmod 644 $(DESTDIR)$(MANPREFIX)/man1/st.1 + tic -sx st.info + @echo Please see the README file regarding the terminfo entry of st. + +uninstall: + rm -f $(DESTDIR)$(PREFIX)/bin/st + rm -f $(DESTDIR)$(MANPREFIX)/man1/st.1 + +.PHONY: all clean dist install uninstall diff --git a/hosts/vali/mars/dwm/st-0.9.2/README b/hosts/vali/mars/dwm/st-0.9.2/README new file mode 100644 index 0000000..6a846ed --- /dev/null +++ b/hosts/vali/mars/dwm/st-0.9.2/README @@ -0,0 +1,34 @@ +st - simple terminal +-------------------- +st is a simple terminal emulator for X which sucks less. + + +Requirements +------------ +In order to build st you need the Xlib header files. + + +Installation +------------ +Edit config.mk to match your local setup (st is installed into +the /usr/local namespace by default). + +Afterwards enter the following command to build and install st (if +necessary as root): + + make clean install + + +Running st +---------- +If you did not install st with make clean install, you must compile +the st terminfo entry with the following command: + + tic -sx st.info + +See the man page for additional details. + +Credits +------- +Based on Aurélien APTEL bt source code. + diff --git a/hosts/vali/mars/dwm/st-0.9.2/TODO b/hosts/vali/mars/dwm/st-0.9.2/TODO new file mode 100644 index 0000000..5f74cd5 --- /dev/null +++ b/hosts/vali/mars/dwm/st-0.9.2/TODO @@ -0,0 +1,28 @@ +vt emulation +------------ + +* double-height support + +code & interface +---------------- + +* add a simple way to do multiplexing + +drawing +------- +* add diacritics support to xdraws() + * switch to a suckless font drawing library +* make the font cache simpler +* add better support for brightening of the upper colors + +bugs +---- + +* fix shift up/down (shift selection in emacs) +* remove DEC test sequence when appropriate + +misc +---- + + $ grep -nE 'XXX|TODO' st.c + diff --git a/hosts/vali/mars/dwm/st-0.9.2/arg.h b/hosts/vali/mars/dwm/st-0.9.2/arg.h new file mode 100644 index 0000000..a22e019 --- /dev/null +++ b/hosts/vali/mars/dwm/st-0.9.2/arg.h @@ -0,0 +1,50 @@ +/* + * 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;\ + }\ + int i_;\ + for (i_ = 1, brk_ = 0, argv_ = argv;\ + argv[0][i_] && !brk_;\ + i_++) {\ + if (argv_ != argv)\ + break;\ + argc_ = argv[0][i_];\ + switch (argc_) + +#define ARGEND }\ + } + +#define ARGC() argc_ + +#define EARGF(x) ((argv[0][i_+1] == '\0' && argv[1] == NULL)?\ + ((x), abort(), (char *)0) :\ + (brk_ = 1, (argv[0][i_+1] != '\0')?\ + (&argv[0][i_+1]) :\ + (argc--, argv++, argv[0]))) + +#define ARGF() ((argv[0][i_+1] == '\0' && argv[1] == NULL)?\ + (char *)0 :\ + (brk_ = 1, (argv[0][i_+1] != '\0')?\ + (&argv[0][i_+1]) :\ + (argc--, argv++, argv[0]))) + +#endif diff --git a/hosts/vali/mars/dwm/st-0.9.2/config.def.h b/hosts/vali/mars/dwm/st-0.9.2/config.def.h new file mode 100644 index 0000000..2cd740a --- /dev/null +++ b/hosts/vali/mars/dwm/st-0.9.2/config.def.h @@ -0,0 +1,474 @@ +/* See LICENSE file for copyright and license details. */ + +/* + * appearance + * + * font: see http://freedesktop.org/software/fontconfig/fontconfig-user.html + */ +static char *font = "Liberation Mono:pixelsize=12:antialias=true:autohint=true"; +static int borderpx = 2; + +/* + * What program is execed by st depends of these precedence rules: + * 1: program passed with -e + * 2: scroll and/or utmp + * 3: SHELL environment variable + * 4: value of shell in /etc/passwd + * 5: value of shell in config.h + */ +static char *shell = "/bin/sh"; +char *utmp = NULL; +/* scroll program: to enable use a string like "scroll" */ +char *scroll = NULL; +char *stty_args = "stty raw pass8 nl -echo -iexten -cstopb 38400"; + +/* identification sequence returned in DA and DECID */ +char *vtiden = "\033[?6c"; + +/* Kerning / character bounding-box multipliers */ +static float cwscale = 1.0; +static float chscale = 1.0; + +/* + * word delimiter string + * + * More advanced example: L" `'\"()[]{}" + */ +wchar_t *worddelimiters = L" "; + +/* selection timeouts (in milliseconds) */ +static unsigned int doubleclicktimeout = 300; +static unsigned int tripleclicktimeout = 600; + +/* alt screens */ +int allowaltscreen = 1; + +/* allow certain non-interactive (insecure) window operations such as: + setting the clipboard text */ +int allowwindowops = 0; + +/* + * draw latency range in ms - from new content/keypress/etc until drawing. + * within this range, st draws when content stops arriving (idle). mostly it's + * near minlatency, but it waits longer for slow updates to avoid partial draw. + * low minlatency will tear/flicker more, as it can "detect" idle too early. + */ +static double minlatency = 2; +static double maxlatency = 33; + +/* + * blinking timeout (set to 0 to disable blinking) for the terminal blinking + * attribute. + */ +static unsigned int blinktimeout = 800; + +/* + * thickness of underline and bar cursors + */ +static unsigned int cursorthickness = 2; + +/* + * bell volume. It must be a value between -100 and 100. Use 0 for disabling + * it + */ +static int bellvolume = 0; + +/* default TERM value */ +char *termname = "st-256color"; + +/* + * spaces per tab + * + * When you are changing this value, don't forget to adapt the »it« value in + * the st.info and appropriately install the st.info in the environment where + * you use this st version. + * + * it#$tabspaces, + * + * Secondly make sure your kernel is not expanding tabs. When running `stty + * -a` »tab0« should appear. You can tell the terminal to not expand tabs by + * running following command: + * + * stty tabs + */ +unsigned int tabspaces = 8; + +/* Terminal colors (16 first used in escape sequence) */ +static const char *colorname[] = { + /* 8 normal colors */ + "black", + "red3", + "green3", + "yellow3", + "blue2", + "magenta3", + "cyan3", + "gray90", + + /* 8 bright colors */ + "gray50", + "red", + "green", + "yellow", + "#5c5cff", + "magenta", + "cyan", + "white", + + [255] = 0, + + /* more colors can be added after 255 to use with DefaultXX */ + "#cccccc", + "#555555", + "gray90", /* default foreground colour */ + "black", /* default background colour */ +}; + + +/* + * Default colors (colorname index) + * foreground, background, cursor, reverse cursor + */ +unsigned int defaultfg = 258; +unsigned int defaultbg = 259; +unsigned int defaultcs = 256; +static unsigned int defaultrcs = 257; + +/* + * Default shape of cursor + * 2: Block ("█") + * 4: Underline ("_") + * 6: Bar ("|") + * 7: Snowman ("☃") + */ +static unsigned int cursorshape = 2; + +/* + * Default columns and rows numbers + */ + +static unsigned int cols = 80; +static unsigned int rows = 24; + +/* + * Default colour and shape of the mouse cursor + */ +static unsigned int mouseshape = XC_xterm; +static unsigned int mousefg = 7; +static unsigned int mousebg = 0; + +/* + * Color used to display font attributes when fontconfig selected a font which + * doesn't match the ones requested. + */ +static unsigned int defaultattr = 11; + +/* + * Force mouse select/shortcuts while mask is active (when MODE_MOUSE is set). + * Note that if you want to use ShiftMask with selmasks, set this to an other + * modifier, set to 0 to not use it. + */ +static uint forcemousemod = ShiftMask; + +/* + * Internal mouse shortcuts. + * Beware that overloading Button1 will disable the selection. + */ +static MouseShortcut mshortcuts[] = { + /* mask button function argument release */ + { XK_ANY_MOD, Button2, selpaste, {.i = 0}, 1 }, + { ShiftMask, Button4, ttysend, {.s = "\033[5;2~"} }, + { XK_ANY_MOD, Button4, ttysend, {.s = "\031"} }, + { ShiftMask, Button5, ttysend, {.s = "\033[6;2~"} }, + { XK_ANY_MOD, Button5, ttysend, {.s = "\005"} }, +}; + +/* Internal keyboard shortcuts. */ +#define MODKEY Mod1Mask +#define TERMMOD (ControlMask|ShiftMask) + +static Shortcut shortcuts[] = { + /* mask keysym function argument */ + { XK_ANY_MOD, XK_Break, sendbreak, {.i = 0} }, + { ControlMask, XK_Print, toggleprinter, {.i = 0} }, + { ShiftMask, XK_Print, printscreen, {.i = 0} }, + { XK_ANY_MOD, XK_Print, printsel, {.i = 0} }, + { TERMMOD, XK_Prior, zoom, {.f = +1} }, + { TERMMOD, XK_Next, zoom, {.f = -1} }, + { TERMMOD, XK_Home, zoomreset, {.f = 0} }, + { TERMMOD, XK_C, clipcopy, {.i = 0} }, + { TERMMOD, XK_V, clippaste, {.i = 0} }, + { TERMMOD, XK_Y, selpaste, {.i = 0} }, + { ShiftMask, XK_Insert, selpaste, {.i = 0} }, + { TERMMOD, XK_Num_Lock, numlock, {.i = 0} }, +}; + +/* + * Special keys (change & recompile st.info accordingly) + * + * Mask value: + * * Use XK_ANY_MOD to match the key no matter modifiers state + * * Use XK_NO_MOD to match the key alone (no modifiers) + * appkey value: + * * 0: no value + * * > 0: keypad application mode enabled + * * = 2: term.numlock = 1 + * * < 0: keypad application mode disabled + * appcursor value: + * * 0: no value + * * > 0: cursor application mode enabled + * * < 0: cursor application mode disabled + * + * Be careful with the order of the definitions because st searches in + * this table sequentially, so any XK_ANY_MOD must be in the last + * position for a key. + */ + +/* + * If you want keys other than the X11 function keys (0xFD00 - 0xFFFF) + * to be mapped below, add them to this array. + */ +static KeySym mappedkeys[] = { -1 }; + +/* + * State bits to ignore when matching key or button events. By default, + * numlock (Mod2Mask) and keyboard layout (XK_SWITCH_MOD) are ignored. + */ +static uint ignoremod = Mod2Mask|XK_SWITCH_MOD; + +/* + * This is the huge key array which defines all compatibility to the Linux + * world. Please decide about changes wisely. + */ +static Key key[] = { + /* keysym mask string appkey appcursor */ + { XK_KP_Home, ShiftMask, "\033[2J", 0, -1}, + { XK_KP_Home, ShiftMask, "\033[1;2H", 0, +1}, + { XK_KP_Home, XK_ANY_MOD, "\033[H", 0, -1}, + { XK_KP_Home, XK_ANY_MOD, "\033[1~", 0, +1}, + { XK_KP_Up, XK_ANY_MOD, "\033Ox", +1, 0}, + { XK_KP_Up, XK_ANY_MOD, "\033[A", 0, -1}, + { XK_KP_Up, XK_ANY_MOD, "\033OA", 0, +1}, + { XK_KP_Down, XK_ANY_MOD, "\033Or", +1, 0}, + { XK_KP_Down, XK_ANY_MOD, "\033[B", 0, -1}, + { XK_KP_Down, XK_ANY_MOD, "\033OB", 0, +1}, + { XK_KP_Left, XK_ANY_MOD, "\033Ot", +1, 0}, + { XK_KP_Left, XK_ANY_MOD, "\033[D", 0, -1}, + { XK_KP_Left, XK_ANY_MOD, "\033OD", 0, +1}, + { XK_KP_Right, XK_ANY_MOD, "\033Ov", +1, 0}, + { XK_KP_Right, XK_ANY_MOD, "\033[C", 0, -1}, + { XK_KP_Right, XK_ANY_MOD, "\033OC", 0, +1}, + { XK_KP_Prior, ShiftMask, "\033[5;2~", 0, 0}, + { XK_KP_Prior, XK_ANY_MOD, "\033[5~", 0, 0}, + { XK_KP_Begin, XK_ANY_MOD, "\033[E", 0, 0}, + { XK_KP_End, ControlMask, "\033[J", -1, 0}, + { XK_KP_End, ControlMask, "\033[1;5F", +1, 0}, + { XK_KP_End, ShiftMask, "\033[K", -1, 0}, + { XK_KP_End, ShiftMask, "\033[1;2F", +1, 0}, + { XK_KP_End, XK_ANY_MOD, "\033[4~", 0, 0}, + { XK_KP_Next, ShiftMask, "\033[6;2~", 0, 0}, + { XK_KP_Next, XK_ANY_MOD, "\033[6~", 0, 0}, + { XK_KP_Insert, ShiftMask, "\033[2;2~", +1, 0}, + { XK_KP_Insert, ShiftMask, "\033[4l", -1, 0}, + { XK_KP_Insert, ControlMask, "\033[L", -1, 0}, + { XK_KP_Insert, ControlMask, "\033[2;5~", +1, 0}, + { XK_KP_Insert, XK_ANY_MOD, "\033[4h", -1, 0}, + { XK_KP_Insert, XK_ANY_MOD, "\033[2~", +1, 0}, + { XK_KP_Delete, ControlMask, "\033[M", -1, 0}, + { XK_KP_Delete, ControlMask, "\033[3;5~", +1, 0}, + { XK_KP_Delete, ShiftMask, "\033[2K", -1, 0}, + { XK_KP_Delete, ShiftMask, "\033[3;2~", +1, 0}, + { XK_KP_Delete, XK_ANY_MOD, "\033[P", -1, 0}, + { XK_KP_Delete, XK_ANY_MOD, "\033[3~", +1, 0}, + { XK_KP_Multiply, XK_ANY_MOD, "\033Oj", +2, 0}, + { XK_KP_Add, XK_ANY_MOD, "\033Ok", +2, 0}, + { XK_KP_Enter, XK_ANY_MOD, "\033OM", +2, 0}, + { XK_KP_Enter, XK_ANY_MOD, "\r", -1, 0}, + { XK_KP_Subtract, XK_ANY_MOD, "\033Om", +2, 0}, + { XK_KP_Decimal, XK_ANY_MOD, "\033On", +2, 0}, + { XK_KP_Divide, XK_ANY_MOD, "\033Oo", +2, 0}, + { XK_KP_0, XK_ANY_MOD, "\033Op", +2, 0}, + { XK_KP_1, XK_ANY_MOD, "\033Oq", +2, 0}, + { XK_KP_2, XK_ANY_MOD, "\033Or", +2, 0}, + { XK_KP_3, XK_ANY_MOD, "\033Os", +2, 0}, + { XK_KP_4, XK_ANY_MOD, "\033Ot", +2, 0}, + { XK_KP_5, XK_ANY_MOD, "\033Ou", +2, 0}, + { XK_KP_6, XK_ANY_MOD, "\033Ov", +2, 0}, + { XK_KP_7, XK_ANY_MOD, "\033Ow", +2, 0}, + { XK_KP_8, XK_ANY_MOD, "\033Ox", +2, 0}, + { XK_KP_9, XK_ANY_MOD, "\033Oy", +2, 0}, + { XK_Up, ShiftMask, "\033[1;2A", 0, 0}, + { XK_Up, Mod1Mask, "\033[1;3A", 0, 0}, + { XK_Up, ShiftMask|Mod1Mask,"\033[1;4A", 0, 0}, + { XK_Up, ControlMask, "\033[1;5A", 0, 0}, + { XK_Up, ShiftMask|ControlMask,"\033[1;6A", 0, 0}, + { XK_Up, ControlMask|Mod1Mask,"\033[1;7A", 0, 0}, + { XK_Up,ShiftMask|ControlMask|Mod1Mask,"\033[1;8A", 0, 0}, + { XK_Up, XK_ANY_MOD, "\033[A", 0, -1}, + { XK_Up, XK_ANY_MOD, "\033OA", 0, +1}, + { XK_Down, ShiftMask, "\033[1;2B", 0, 0}, + { XK_Down, Mod1Mask, "\033[1;3B", 0, 0}, + { XK_Down, ShiftMask|Mod1Mask,"\033[1;4B", 0, 0}, + { XK_Down, ControlMask, "\033[1;5B", 0, 0}, + { XK_Down, ShiftMask|ControlMask,"\033[1;6B", 0, 0}, + { XK_Down, ControlMask|Mod1Mask,"\033[1;7B", 0, 0}, + { XK_Down,ShiftMask|ControlMask|Mod1Mask,"\033[1;8B",0, 0}, + { XK_Down, XK_ANY_MOD, "\033[B", 0, -1}, + { XK_Down, XK_ANY_MOD, "\033OB", 0, +1}, + { XK_Left, ShiftMask, "\033[1;2D", 0, 0}, + { XK_Left, Mod1Mask, "\033[1;3D", 0, 0}, + { XK_Left, ShiftMask|Mod1Mask,"\033[1;4D", 0, 0}, + { XK_Left, ControlMask, "\033[1;5D", 0, 0}, + { XK_Left, ShiftMask|ControlMask,"\033[1;6D", 0, 0}, + { XK_Left, ControlMask|Mod1Mask,"\033[1;7D", 0, 0}, + { XK_Left,ShiftMask|ControlMask|Mod1Mask,"\033[1;8D",0, 0}, + { XK_Left, XK_ANY_MOD, "\033[D", 0, -1}, + { XK_Left, XK_ANY_MOD, "\033OD", 0, +1}, + { XK_Right, ShiftMask, "\033[1;2C", 0, 0}, + { XK_Right, Mod1Mask, "\033[1;3C", 0, 0}, + { XK_Right, ShiftMask|Mod1Mask,"\033[1;4C", 0, 0}, + { XK_Right, ControlMask, "\033[1;5C", 0, 0}, + { XK_Right, ShiftMask|ControlMask,"\033[1;6C", 0, 0}, + { XK_Right, ControlMask|Mod1Mask,"\033[1;7C", 0, 0}, + { XK_Right,ShiftMask|ControlMask|Mod1Mask,"\033[1;8C",0, 0}, + { XK_Right, XK_ANY_MOD, "\033[C", 0, -1}, + { XK_Right, XK_ANY_MOD, "\033OC", 0, +1}, + { XK_ISO_Left_Tab, ShiftMask, "\033[Z", 0, 0}, + { XK_Return, Mod1Mask, "\033\r", 0, 0}, + { XK_Return, XK_ANY_MOD, "\r", 0, 0}, + { XK_Insert, ShiftMask, "\033[4l", -1, 0}, + { XK_Insert, ShiftMask, "\033[2;2~", +1, 0}, + { XK_Insert, ControlMask, "\033[L", -1, 0}, + { XK_Insert, ControlMask, "\033[2;5~", +1, 0}, + { XK_Insert, XK_ANY_MOD, "\033[4h", -1, 0}, + { XK_Insert, XK_ANY_MOD, "\033[2~", +1, 0}, + { XK_Delete, ControlMask, "\033[M", -1, 0}, + { XK_Delete, ControlMask, "\033[3;5~", +1, 0}, + { XK_Delete, ShiftMask, "\033[2K", -1, 0}, + { XK_Delete, ShiftMask, "\033[3;2~", +1, 0}, + { XK_Delete, XK_ANY_MOD, "\033[P", -1, 0}, + { XK_Delete, XK_ANY_MOD, "\033[3~", +1, 0}, + { XK_BackSpace, XK_NO_MOD, "\177", 0, 0}, + { XK_BackSpace, Mod1Mask, "\033\177", 0, 0}, + { XK_Home, ShiftMask, "\033[2J", 0, -1}, + { XK_Home, ShiftMask, "\033[1;2H", 0, +1}, + { XK_Home, XK_ANY_MOD, "\033[H", 0, -1}, + { XK_Home, XK_ANY_MOD, "\033[1~", 0, +1}, + { XK_End, ControlMask, "\033[J", -1, 0}, + { XK_End, ControlMask, "\033[1;5F", +1, 0}, + { XK_End, ShiftMask, "\033[K", -1, 0}, + { XK_End, ShiftMask, "\033[1;2F", +1, 0}, + { XK_End, XK_ANY_MOD, "\033[4~", 0, 0}, + { XK_Prior, ControlMask, "\033[5;5~", 0, 0}, + { XK_Prior, ShiftMask, "\033[5;2~", 0, 0}, + { XK_Prior, XK_ANY_MOD, "\033[5~", 0, 0}, + { XK_Next, ControlMask, "\033[6;5~", 0, 0}, + { XK_Next, ShiftMask, "\033[6;2~", 0, 0}, + { XK_Next, XK_ANY_MOD, "\033[6~", 0, 0}, + { XK_F1, XK_NO_MOD, "\033OP" , 0, 0}, + { XK_F1, /* F13 */ ShiftMask, "\033[1;2P", 0, 0}, + { XK_F1, /* F25 */ ControlMask, "\033[1;5P", 0, 0}, + { XK_F1, /* F37 */ Mod4Mask, "\033[1;6P", 0, 0}, + { XK_F1, /* F49 */ Mod1Mask, "\033[1;3P", 0, 0}, + { XK_F1, /* F61 */ Mod3Mask, "\033[1;4P", 0, 0}, + { XK_F2, XK_NO_MOD, "\033OQ" , 0, 0}, + { XK_F2, /* F14 */ ShiftMask, "\033[1;2Q", 0, 0}, + { XK_F2, /* F26 */ ControlMask, "\033[1;5Q", 0, 0}, + { XK_F2, /* F38 */ Mod4Mask, "\033[1;6Q", 0, 0}, + { XK_F2, /* F50 */ Mod1Mask, "\033[1;3Q", 0, 0}, + { XK_F2, /* F62 */ Mod3Mask, "\033[1;4Q", 0, 0}, + { XK_F3, XK_NO_MOD, "\033OR" , 0, 0}, + { XK_F3, /* F15 */ ShiftMask, "\033[1;2R", 0, 0}, + { XK_F3, /* F27 */ ControlMask, "\033[1;5R", 0, 0}, + { XK_F3, /* F39 */ Mod4Mask, "\033[1;6R", 0, 0}, + { XK_F3, /* F51 */ Mod1Mask, "\033[1;3R", 0, 0}, + { XK_F3, /* F63 */ Mod3Mask, "\033[1;4R", 0, 0}, + { XK_F4, XK_NO_MOD, "\033OS" , 0, 0}, + { XK_F4, /* F16 */ ShiftMask, "\033[1;2S", 0, 0}, + { XK_F4, /* F28 */ ControlMask, "\033[1;5S", 0, 0}, + { XK_F4, /* F40 */ Mod4Mask, "\033[1;6S", 0, 0}, + { XK_F4, /* F52 */ Mod1Mask, "\033[1;3S", 0, 0}, + { XK_F5, XK_NO_MOD, "\033[15~", 0, 0}, + { XK_F5, /* F17 */ ShiftMask, "\033[15;2~", 0, 0}, + { XK_F5, /* F29 */ ControlMask, "\033[15;5~", 0, 0}, + { XK_F5, /* F41 */ Mod4Mask, "\033[15;6~", 0, 0}, + { XK_F5, /* F53 */ Mod1Mask, "\033[15;3~", 0, 0}, + { XK_F6, XK_NO_MOD, "\033[17~", 0, 0}, + { XK_F6, /* F18 */ ShiftMask, "\033[17;2~", 0, 0}, + { XK_F6, /* F30 */ ControlMask, "\033[17;5~", 0, 0}, + { XK_F6, /* F42 */ Mod4Mask, "\033[17;6~", 0, 0}, + { XK_F6, /* F54 */ Mod1Mask, "\033[17;3~", 0, 0}, + { XK_F7, XK_NO_MOD, "\033[18~", 0, 0}, + { XK_F7, /* F19 */ ShiftMask, "\033[18;2~", 0, 0}, + { XK_F7, /* F31 */ ControlMask, "\033[18;5~", 0, 0}, + { XK_F7, /* F43 */ Mod4Mask, "\033[18;6~", 0, 0}, + { XK_F7, /* F55 */ Mod1Mask, "\033[18;3~", 0, 0}, + { XK_F8, XK_NO_MOD, "\033[19~", 0, 0}, + { XK_F8, /* F20 */ ShiftMask, "\033[19;2~", 0, 0}, + { XK_F8, /* F32 */ ControlMask, "\033[19;5~", 0, 0}, + { XK_F8, /* F44 */ Mod4Mask, "\033[19;6~", 0, 0}, + { XK_F8, /* F56 */ Mod1Mask, "\033[19;3~", 0, 0}, + { XK_F9, XK_NO_MOD, "\033[20~", 0, 0}, + { XK_F9, /* F21 */ ShiftMask, "\033[20;2~", 0, 0}, + { XK_F9, /* F33 */ ControlMask, "\033[20;5~", 0, 0}, + { XK_F9, /* F45 */ Mod4Mask, "\033[20;6~", 0, 0}, + { XK_F9, /* F57 */ Mod1Mask, "\033[20;3~", 0, 0}, + { XK_F10, XK_NO_MOD, "\033[21~", 0, 0}, + { XK_F10, /* F22 */ ShiftMask, "\033[21;2~", 0, 0}, + { XK_F10, /* F34 */ ControlMask, "\033[21;5~", 0, 0}, + { XK_F10, /* F46 */ Mod4Mask, "\033[21;6~", 0, 0}, + { XK_F10, /* F58 */ Mod1Mask, "\033[21;3~", 0, 0}, + { XK_F11, XK_NO_MOD, "\033[23~", 0, 0}, + { XK_F11, /* F23 */ ShiftMask, "\033[23;2~", 0, 0}, + { XK_F11, /* F35 */ ControlMask, "\033[23;5~", 0, 0}, + { XK_F11, /* F47 */ Mod4Mask, "\033[23;6~", 0, 0}, + { XK_F11, /* F59 */ Mod1Mask, "\033[23;3~", 0, 0}, + { XK_F12, XK_NO_MOD, "\033[24~", 0, 0}, + { XK_F12, /* F24 */ ShiftMask, "\033[24;2~", 0, 0}, + { XK_F12, /* F36 */ ControlMask, "\033[24;5~", 0, 0}, + { XK_F12, /* F48 */ Mod4Mask, "\033[24;6~", 0, 0}, + { XK_F12, /* F60 */ Mod1Mask, "\033[24;3~", 0, 0}, + { XK_F13, XK_NO_MOD, "\033[1;2P", 0, 0}, + { XK_F14, XK_NO_MOD, "\033[1;2Q", 0, 0}, + { XK_F15, XK_NO_MOD, "\033[1;2R", 0, 0}, + { XK_F16, XK_NO_MOD, "\033[1;2S", 0, 0}, + { XK_F17, XK_NO_MOD, "\033[15;2~", 0, 0}, + { XK_F18, XK_NO_MOD, "\033[17;2~", 0, 0}, + { XK_F19, XK_NO_MOD, "\033[18;2~", 0, 0}, + { XK_F20, XK_NO_MOD, "\033[19;2~", 0, 0}, + { XK_F21, XK_NO_MOD, "\033[20;2~", 0, 0}, + { XK_F22, XK_NO_MOD, "\033[21;2~", 0, 0}, + { XK_F23, XK_NO_MOD, "\033[23;2~", 0, 0}, + { XK_F24, XK_NO_MOD, "\033[24;2~", 0, 0}, + { XK_F25, XK_NO_MOD, "\033[1;5P", 0, 0}, + { XK_F26, XK_NO_MOD, "\033[1;5Q", 0, 0}, + { XK_F27, XK_NO_MOD, "\033[1;5R", 0, 0}, + { XK_F28, XK_NO_MOD, "\033[1;5S", 0, 0}, + { XK_F29, XK_NO_MOD, "\033[15;5~", 0, 0}, + { XK_F30, XK_NO_MOD, "\033[17;5~", 0, 0}, + { XK_F31, XK_NO_MOD, "\033[18;5~", 0, 0}, + { XK_F32, XK_NO_MOD, "\033[19;5~", 0, 0}, + { XK_F33, XK_NO_MOD, "\033[20;5~", 0, 0}, + { XK_F34, XK_NO_MOD, "\033[21;5~", 0, 0}, + { XK_F35, XK_NO_MOD, "\033[23;5~", 0, 0}, +}; + +/* + * Selection types' masks. + * Use the same masks as usual. + * Button1Mask is always unset, to make masks match between ButtonPress. + * ButtonRelease and MotionNotify. + * If no match is found, regular selection is used. + */ +static uint selmasks[] = { + [SEL_RECTANGULAR] = Mod1Mask, +}; + +/* + * Printable characters in ASCII, used to estimate the advance width + * of single wide characters. + */ +static char ascii_printable[] = + " !\"#$%&'()*+,-./0123456789:;<=>?" + "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_" + "`abcdefghijklmnopqrstuvwxyz{|}~"; diff --git a/hosts/vali/mars/dwm/st-0.9.2/config.h b/hosts/vali/mars/dwm/st-0.9.2/config.h new file mode 100644 index 0000000..8efb49a --- /dev/null +++ b/hosts/vali/mars/dwm/st-0.9.2/config.h @@ -0,0 +1,474 @@ +/* See LICENSE file for copyright and license details. */ + +/* + * appearance + * + * font: see http://freedesktop.org/software/fontconfig/fontconfig-user.html + */ +static char *font = "Liberation Mono:pixelsize=16:antialias=true:autohint=true"; +static int borderpx = 2; + +/* + * What program is execed by st depends of these precedence rules: + * 1: program passed with -e + * 2: scroll and/or utmp + * 3: SHELL environment variable + * 4: value of shell in /etc/passwd + * 5: value of shell in config.h + */ +static char *shell = "/bin/sh"; +char *utmp = NULL; +/* scroll program: to enable use a string like "scroll" */ +char *scroll = NULL; +char *stty_args = "stty raw pass8 nl -echo -iexten -cstopb 38400"; + +/* identification sequence returned in DA and DECID */ +char *vtiden = "\033[?6c"; + +/* Kerning / character bounding-box multipliers */ +static float cwscale = 1.0; +static float chscale = 1.0; + +/* + * word delimiter string + * + * More advanced example: L" `'\"()[]{}" + */ +wchar_t *worddelimiters = L" "; + +/* selection timeouts (in milliseconds) */ +static unsigned int doubleclicktimeout = 300; +static unsigned int tripleclicktimeout = 600; + +/* alt screens */ +int allowaltscreen = 1; + +/* allow certain non-interactive (insecure) window operations such as: + setting the clipboard text */ +int allowwindowops = 0; + +/* + * draw latency range in ms - from new content/keypress/etc until drawing. + * within this range, st draws when content stops arriving (idle). mostly it's + * near minlatency, but it waits longer for slow updates to avoid partial draw. + * low minlatency will tear/flicker more, as it can "detect" idle too early. + */ +static double minlatency = 2; +static double maxlatency = 33; + +/* + * blinking timeout (set to 0 to disable blinking) for the terminal blinking + * attribute. + */ +static unsigned int blinktimeout = 800; + +/* + * thickness of underline and bar cursors + */ +static unsigned int cursorthickness = 2; + +/* + * bell volume. It must be a value between -100 and 100. Use 0 for disabling + * it + */ +static int bellvolume = 0; + +/* default TERM value */ +char *termname = "st-256color"; + +/* + * spaces per tab + * + * When you are changing this value, don't forget to adapt the »it« value in + * the st.info and appropriately install the st.info in the environment where + * you use this st version. + * + * it#$tabspaces, + * + * Secondly make sure your kernel is not expanding tabs. When running `stty + * -a` »tab0« should appear. You can tell the terminal to not expand tabs by + * running following command: + * + * stty tabs + */ +unsigned int tabspaces = 8; + +/* Terminal colors (16 first used in escape sequence) */ +static const char *colorname[] = { + /* 8 normal colors */ + "black", + "red3", + "green3", + "yellow3", + "blue2", + "magenta3", + "cyan3", + "gray90", + + /* 8 bright colors */ + "gray50", + "red", + "green", + "yellow", + "#5c5cff", + "magenta", + "cyan", + "white", + + [255] = 0, + + /* more colors can be added after 255 to use with DefaultXX */ + "#cccccc", + "#555555", + "gray90", /* default foreground colour */ + "black", /* default background colour */ +}; + + +/* + * Default colors (colorname index) + * foreground, background, cursor, reverse cursor + */ +unsigned int defaultfg = 258; +unsigned int defaultbg = 259; +unsigned int defaultcs = 256; +static unsigned int defaultrcs = 257; + +/* + * Default shape of cursor + * 2: Block ("█") + * 4: Underline ("_") + * 6: Bar ("|") + * 7: Snowman ("☃") + */ +static unsigned int cursorshape = 2; + +/* + * Default columns and rows numbers + */ + +static unsigned int cols = 80; +static unsigned int rows = 24; + +/* + * Default colour and shape of the mouse cursor + */ +static unsigned int mouseshape = XC_xterm; +static unsigned int mousefg = 7; +static unsigned int mousebg = 0; + +/* + * Color used to display font attributes when fontconfig selected a font which + * doesn't match the ones requested. + */ +static unsigned int defaultattr = 11; + +/* + * Force mouse select/shortcuts while mask is active (when MODE_MOUSE is set). + * Note that if you want to use ShiftMask with selmasks, set this to an other + * modifier, set to 0 to not use it. + */ +static uint forcemousemod = ShiftMask; + +/* + * Internal mouse shortcuts. + * Beware that overloading Button1 will disable the selection. + */ +static MouseShortcut mshortcuts[] = { + /* mask button function argument release */ + { XK_ANY_MOD, Button2, selpaste, {.i = 0}, 1 }, + { ShiftMask, Button4, ttysend, {.s = "\033[5;2~"} }, + { XK_ANY_MOD, Button4, ttysend, {.s = "\031"} }, + { ShiftMask, Button5, ttysend, {.s = "\033[6;2~"} }, + { XK_ANY_MOD, Button5, ttysend, {.s = "\005"} }, +}; + +/* Internal keyboard shortcuts. */ +#define MODKEY Mod1Mask +#define TERMMOD (ControlMask|ShiftMask) + +static Shortcut shortcuts[] = { + /* mask keysym function argument */ + { XK_ANY_MOD, XK_Break, sendbreak, {.i = 0} }, + { ControlMask, XK_Print, toggleprinter, {.i = 0} }, + { ShiftMask, XK_Print, printscreen, {.i = 0} }, + { XK_ANY_MOD, XK_Print, printsel, {.i = 0} }, + { TERMMOD, XK_Prior, zoom, {.f = +1} }, + { TERMMOD, XK_Next, zoom, {.f = -1} }, + { TERMMOD, XK_Home, zoomreset, {.f = 0} }, + { TERMMOD, XK_C, clipcopy, {.i = 0} }, + { TERMMOD, XK_V, clippaste, {.i = 0} }, + { TERMMOD, XK_Y, selpaste, {.i = 0} }, + { ShiftMask, XK_Insert, selpaste, {.i = 0} }, + { TERMMOD, XK_Num_Lock, numlock, {.i = 0} }, +}; + +/* + * Special keys (change & recompile st.info accordingly) + * + * Mask value: + * * Use XK_ANY_MOD to match the key no matter modifiers state + * * Use XK_NO_MOD to match the key alone (no modifiers) + * appkey value: + * * 0: no value + * * > 0: keypad application mode enabled + * * = 2: term.numlock = 1 + * * < 0: keypad application mode disabled + * appcursor value: + * * 0: no value + * * > 0: cursor application mode enabled + * * < 0: cursor application mode disabled + * + * Be careful with the order of the definitions because st searches in + * this table sequentially, so any XK_ANY_MOD must be in the last + * position for a key. + */ + +/* + * If you want keys other than the X11 function keys (0xFD00 - 0xFFFF) + * to be mapped below, add them to this array. + */ +static KeySym mappedkeys[] = { -1 }; + +/* + * State bits to ignore when matching key or button events. By default, + * numlock (Mod2Mask) and keyboard layout (XK_SWITCH_MOD) are ignored. + */ +static uint ignoremod = Mod2Mask|XK_SWITCH_MOD; + +/* + * This is the huge key array which defines all compatibility to the Linux + * world. Please decide about changes wisely. + */ +static Key key[] = { + /* keysym mask string appkey appcursor */ + { XK_KP_Home, ShiftMask, "\033[2J", 0, -1}, + { XK_KP_Home, ShiftMask, "\033[1;2H", 0, +1}, + { XK_KP_Home, XK_ANY_MOD, "\033[H", 0, -1}, + { XK_KP_Home, XK_ANY_MOD, "\033[1~", 0, +1}, + { XK_KP_Up, XK_ANY_MOD, "\033Ox", +1, 0}, + { XK_KP_Up, XK_ANY_MOD, "\033[A", 0, -1}, + { XK_KP_Up, XK_ANY_MOD, "\033OA", 0, +1}, + { XK_KP_Down, XK_ANY_MOD, "\033Or", +1, 0}, + { XK_KP_Down, XK_ANY_MOD, "\033[B", 0, -1}, + { XK_KP_Down, XK_ANY_MOD, "\033OB", 0, +1}, + { XK_KP_Left, XK_ANY_MOD, "\033Ot", +1, 0}, + { XK_KP_Left, XK_ANY_MOD, "\033[D", 0, -1}, + { XK_KP_Left, XK_ANY_MOD, "\033OD", 0, +1}, + { XK_KP_Right, XK_ANY_MOD, "\033Ov", +1, 0}, + { XK_KP_Right, XK_ANY_MOD, "\033[C", 0, -1}, + { XK_KP_Right, XK_ANY_MOD, "\033OC", 0, +1}, + { XK_KP_Prior, ShiftMask, "\033[5;2~", 0, 0}, + { XK_KP_Prior, XK_ANY_MOD, "\033[5~", 0, 0}, + { XK_KP_Begin, XK_ANY_MOD, "\033[E", 0, 0}, + { XK_KP_End, ControlMask, "\033[J", -1, 0}, + { XK_KP_End, ControlMask, "\033[1;5F", +1, 0}, + { XK_KP_End, ShiftMask, "\033[K", -1, 0}, + { XK_KP_End, ShiftMask, "\033[1;2F", +1, 0}, + { XK_KP_End, XK_ANY_MOD, "\033[4~", 0, 0}, + { XK_KP_Next, ShiftMask, "\033[6;2~", 0, 0}, + { XK_KP_Next, XK_ANY_MOD, "\033[6~", 0, 0}, + { XK_KP_Insert, ShiftMask, "\033[2;2~", +1, 0}, + { XK_KP_Insert, ShiftMask, "\033[4l", -1, 0}, + { XK_KP_Insert, ControlMask, "\033[L", -1, 0}, + { XK_KP_Insert, ControlMask, "\033[2;5~", +1, 0}, + { XK_KP_Insert, XK_ANY_MOD, "\033[4h", -1, 0}, + { XK_KP_Insert, XK_ANY_MOD, "\033[2~", +1, 0}, + { XK_KP_Delete, ControlMask, "\033[M", -1, 0}, + { XK_KP_Delete, ControlMask, "\033[3;5~", +1, 0}, + { XK_KP_Delete, ShiftMask, "\033[2K", -1, 0}, + { XK_KP_Delete, ShiftMask, "\033[3;2~", +1, 0}, + { XK_KP_Delete, XK_ANY_MOD, "\033[P", -1, 0}, + { XK_KP_Delete, XK_ANY_MOD, "\033[3~", +1, 0}, + { XK_KP_Multiply, XK_ANY_MOD, "\033Oj", +2, 0}, + { XK_KP_Add, XK_ANY_MOD, "\033Ok", +2, 0}, + { XK_KP_Enter, XK_ANY_MOD, "\033OM", +2, 0}, + { XK_KP_Enter, XK_ANY_MOD, "\r", -1, 0}, + { XK_KP_Subtract, XK_ANY_MOD, "\033Om", +2, 0}, + { XK_KP_Decimal, XK_ANY_MOD, "\033On", +2, 0}, + { XK_KP_Divide, XK_ANY_MOD, "\033Oo", +2, 0}, + { XK_KP_0, XK_ANY_MOD, "\033Op", +2, 0}, + { XK_KP_1, XK_ANY_MOD, "\033Oq", +2, 0}, + { XK_KP_2, XK_ANY_MOD, "\033Or", +2, 0}, + { XK_KP_3, XK_ANY_MOD, "\033Os", +2, 0}, + { XK_KP_4, XK_ANY_MOD, "\033Ot", +2, 0}, + { XK_KP_5, XK_ANY_MOD, "\033Ou", +2, 0}, + { XK_KP_6, XK_ANY_MOD, "\033Ov", +2, 0}, + { XK_KP_7, XK_ANY_MOD, "\033Ow", +2, 0}, + { XK_KP_8, XK_ANY_MOD, "\033Ox", +2, 0}, + { XK_KP_9, XK_ANY_MOD, "\033Oy", +2, 0}, + { XK_Up, ShiftMask, "\033[1;2A", 0, 0}, + { XK_Up, Mod1Mask, "\033[1;3A", 0, 0}, + { XK_Up, ShiftMask|Mod1Mask,"\033[1;4A", 0, 0}, + { XK_Up, ControlMask, "\033[1;5A", 0, 0}, + { XK_Up, ShiftMask|ControlMask,"\033[1;6A", 0, 0}, + { XK_Up, ControlMask|Mod1Mask,"\033[1;7A", 0, 0}, + { XK_Up,ShiftMask|ControlMask|Mod1Mask,"\033[1;8A", 0, 0}, + { XK_Up, XK_ANY_MOD, "\033[A", 0, -1}, + { XK_Up, XK_ANY_MOD, "\033OA", 0, +1}, + { XK_Down, ShiftMask, "\033[1;2B", 0, 0}, + { XK_Down, Mod1Mask, "\033[1;3B", 0, 0}, + { XK_Down, ShiftMask|Mod1Mask,"\033[1;4B", 0, 0}, + { XK_Down, ControlMask, "\033[1;5B", 0, 0}, + { XK_Down, ShiftMask|ControlMask,"\033[1;6B", 0, 0}, + { XK_Down, ControlMask|Mod1Mask,"\033[1;7B", 0, 0}, + { XK_Down,ShiftMask|ControlMask|Mod1Mask,"\033[1;8B",0, 0}, + { XK_Down, XK_ANY_MOD, "\033[B", 0, -1}, + { XK_Down, XK_ANY_MOD, "\033OB", 0, +1}, + { XK_Left, ShiftMask, "\033[1;2D", 0, 0}, + { XK_Left, Mod1Mask, "\033[1;3D", 0, 0}, + { XK_Left, ShiftMask|Mod1Mask,"\033[1;4D", 0, 0}, + { XK_Left, ControlMask, "\033[1;5D", 0, 0}, + { XK_Left, ShiftMask|ControlMask,"\033[1;6D", 0, 0}, + { XK_Left, ControlMask|Mod1Mask,"\033[1;7D", 0, 0}, + { XK_Left,ShiftMask|ControlMask|Mod1Mask,"\033[1;8D",0, 0}, + { XK_Left, XK_ANY_MOD, "\033[D", 0, -1}, + { XK_Left, XK_ANY_MOD, "\033OD", 0, +1}, + { XK_Right, ShiftMask, "\033[1;2C", 0, 0}, + { XK_Right, Mod1Mask, "\033[1;3C", 0, 0}, + { XK_Right, ShiftMask|Mod1Mask,"\033[1;4C", 0, 0}, + { XK_Right, ControlMask, "\033[1;5C", 0, 0}, + { XK_Right, ShiftMask|ControlMask,"\033[1;6C", 0, 0}, + { XK_Right, ControlMask|Mod1Mask,"\033[1;7C", 0, 0}, + { XK_Right,ShiftMask|ControlMask|Mod1Mask,"\033[1;8C",0, 0}, + { XK_Right, XK_ANY_MOD, "\033[C", 0, -1}, + { XK_Right, XK_ANY_MOD, "\033OC", 0, +1}, + { XK_ISO_Left_Tab, ShiftMask, "\033[Z", 0, 0}, + { XK_Return, Mod1Mask, "\033\r", 0, 0}, + { XK_Return, XK_ANY_MOD, "\r", 0, 0}, + { XK_Insert, ShiftMask, "\033[4l", -1, 0}, + { XK_Insert, ShiftMask, "\033[2;2~", +1, 0}, + { XK_Insert, ControlMask, "\033[L", -1, 0}, + { XK_Insert, ControlMask, "\033[2;5~", +1, 0}, + { XK_Insert, XK_ANY_MOD, "\033[4h", -1, 0}, + { XK_Insert, XK_ANY_MOD, "\033[2~", +1, 0}, + { XK_Delete, ControlMask, "\033[M", -1, 0}, + { XK_Delete, ControlMask, "\033[3;5~", +1, 0}, + { XK_Delete, ShiftMask, "\033[2K", -1, 0}, + { XK_Delete, ShiftMask, "\033[3;2~", +1, 0}, + { XK_Delete, XK_ANY_MOD, "\033[P", -1, 0}, + { XK_Delete, XK_ANY_MOD, "\033[3~", +1, 0}, + { XK_BackSpace, XK_NO_MOD, "\177", 0, 0}, + { XK_BackSpace, Mod1Mask, "\033\177", 0, 0}, + { XK_Home, ShiftMask, "\033[2J", 0, -1}, + { XK_Home, ShiftMask, "\033[1;2H", 0, +1}, + { XK_Home, XK_ANY_MOD, "\033[H", 0, -1}, + { XK_Home, XK_ANY_MOD, "\033[1~", 0, +1}, + { XK_End, ControlMask, "\033[J", -1, 0}, + { XK_End, ControlMask, "\033[1;5F", +1, 0}, + { XK_End, ShiftMask, "\033[K", -1, 0}, + { XK_End, ShiftMask, "\033[1;2F", +1, 0}, + { XK_End, XK_ANY_MOD, "\033[4~", 0, 0}, + { XK_Prior, ControlMask, "\033[5;5~", 0, 0}, + { XK_Prior, ShiftMask, "\033[5;2~", 0, 0}, + { XK_Prior, XK_ANY_MOD, "\033[5~", 0, 0}, + { XK_Next, ControlMask, "\033[6;5~", 0, 0}, + { XK_Next, ShiftMask, "\033[6;2~", 0, 0}, + { XK_Next, XK_ANY_MOD, "\033[6~", 0, 0}, + { XK_F1, XK_NO_MOD, "\033OP" , 0, 0}, + { XK_F1, /* F13 */ ShiftMask, "\033[1;2P", 0, 0}, + { XK_F1, /* F25 */ ControlMask, "\033[1;5P", 0, 0}, + { XK_F1, /* F37 */ Mod4Mask, "\033[1;6P", 0, 0}, + { XK_F1, /* F49 */ Mod1Mask, "\033[1;3P", 0, 0}, + { XK_F1, /* F61 */ Mod3Mask, "\033[1;4P", 0, 0}, + { XK_F2, XK_NO_MOD, "\033OQ" , 0, 0}, + { XK_F2, /* F14 */ ShiftMask, "\033[1;2Q", 0, 0}, + { XK_F2, /* F26 */ ControlMask, "\033[1;5Q", 0, 0}, + { XK_F2, /* F38 */ Mod4Mask, "\033[1;6Q", 0, 0}, + { XK_F2, /* F50 */ Mod1Mask, "\033[1;3Q", 0, 0}, + { XK_F2, /* F62 */ Mod3Mask, "\033[1;4Q", 0, 0}, + { XK_F3, XK_NO_MOD, "\033OR" , 0, 0}, + { XK_F3, /* F15 */ ShiftMask, "\033[1;2R", 0, 0}, + { XK_F3, /* F27 */ ControlMask, "\033[1;5R", 0, 0}, + { XK_F3, /* F39 */ Mod4Mask, "\033[1;6R", 0, 0}, + { XK_F3, /* F51 */ Mod1Mask, "\033[1;3R", 0, 0}, + { XK_F3, /* F63 */ Mod3Mask, "\033[1;4R", 0, 0}, + { XK_F4, XK_NO_MOD, "\033OS" , 0, 0}, + { XK_F4, /* F16 */ ShiftMask, "\033[1;2S", 0, 0}, + { XK_F4, /* F28 */ ControlMask, "\033[1;5S", 0, 0}, + { XK_F4, /* F40 */ Mod4Mask, "\033[1;6S", 0, 0}, + { XK_F4, /* F52 */ Mod1Mask, "\033[1;3S", 0, 0}, + { XK_F5, XK_NO_MOD, "\033[15~", 0, 0}, + { XK_F5, /* F17 */ ShiftMask, "\033[15;2~", 0, 0}, + { XK_F5, /* F29 */ ControlMask, "\033[15;5~", 0, 0}, + { XK_F5, /* F41 */ Mod4Mask, "\033[15;6~", 0, 0}, + { XK_F5, /* F53 */ Mod1Mask, "\033[15;3~", 0, 0}, + { XK_F6, XK_NO_MOD, "\033[17~", 0, 0}, + { XK_F6, /* F18 */ ShiftMask, "\033[17;2~", 0, 0}, + { XK_F6, /* F30 */ ControlMask, "\033[17;5~", 0, 0}, + { XK_F6, /* F42 */ Mod4Mask, "\033[17;6~", 0, 0}, + { XK_F6, /* F54 */ Mod1Mask, "\033[17;3~", 0, 0}, + { XK_F7, XK_NO_MOD, "\033[18~", 0, 0}, + { XK_F7, /* F19 */ ShiftMask, "\033[18;2~", 0, 0}, + { XK_F7, /* F31 */ ControlMask, "\033[18;5~", 0, 0}, + { XK_F7, /* F43 */ Mod4Mask, "\033[18;6~", 0, 0}, + { XK_F7, /* F55 */ Mod1Mask, "\033[18;3~", 0, 0}, + { XK_F8, XK_NO_MOD, "\033[19~", 0, 0}, + { XK_F8, /* F20 */ ShiftMask, "\033[19;2~", 0, 0}, + { XK_F8, /* F32 */ ControlMask, "\033[19;5~", 0, 0}, + { XK_F8, /* F44 */ Mod4Mask, "\033[19;6~", 0, 0}, + { XK_F8, /* F56 */ Mod1Mask, "\033[19;3~", 0, 0}, + { XK_F9, XK_NO_MOD, "\033[20~", 0, 0}, + { XK_F9, /* F21 */ ShiftMask, "\033[20;2~", 0, 0}, + { XK_F9, /* F33 */ ControlMask, "\033[20;5~", 0, 0}, + { XK_F9, /* F45 */ Mod4Mask, "\033[20;6~", 0, 0}, + { XK_F9, /* F57 */ Mod1Mask, "\033[20;3~", 0, 0}, + { XK_F10, XK_NO_MOD, "\033[21~", 0, 0}, + { XK_F10, /* F22 */ ShiftMask, "\033[21;2~", 0, 0}, + { XK_F10, /* F34 */ ControlMask, "\033[21;5~", 0, 0}, + { XK_F10, /* F46 */ Mod4Mask, "\033[21;6~", 0, 0}, + { XK_F10, /* F58 */ Mod1Mask, "\033[21;3~", 0, 0}, + { XK_F11, XK_NO_MOD, "\033[23~", 0, 0}, + { XK_F11, /* F23 */ ShiftMask, "\033[23;2~", 0, 0}, + { XK_F11, /* F35 */ ControlMask, "\033[23;5~", 0, 0}, + { XK_F11, /* F47 */ Mod4Mask, "\033[23;6~", 0, 0}, + { XK_F11, /* F59 */ Mod1Mask, "\033[23;3~", 0, 0}, + { XK_F12, XK_NO_MOD, "\033[24~", 0, 0}, + { XK_F12, /* F24 */ ShiftMask, "\033[24;2~", 0, 0}, + { XK_F12, /* F36 */ ControlMask, "\033[24;5~", 0, 0}, + { XK_F12, /* F48 */ Mod4Mask, "\033[24;6~", 0, 0}, + { XK_F12, /* F60 */ Mod1Mask, "\033[24;3~", 0, 0}, + { XK_F13, XK_NO_MOD, "\033[1;2P", 0, 0}, + { XK_F14, XK_NO_MOD, "\033[1;2Q", 0, 0}, + { XK_F15, XK_NO_MOD, "\033[1;2R", 0, 0}, + { XK_F16, XK_NO_MOD, "\033[1;2S", 0, 0}, + { XK_F17, XK_NO_MOD, "\033[15;2~", 0, 0}, + { XK_F18, XK_NO_MOD, "\033[17;2~", 0, 0}, + { XK_F19, XK_NO_MOD, "\033[18;2~", 0, 0}, + { XK_F20, XK_NO_MOD, "\033[19;2~", 0, 0}, + { XK_F21, XK_NO_MOD, "\033[20;2~", 0, 0}, + { XK_F22, XK_NO_MOD, "\033[21;2~", 0, 0}, + { XK_F23, XK_NO_MOD, "\033[23;2~", 0, 0}, + { XK_F24, XK_NO_MOD, "\033[24;2~", 0, 0}, + { XK_F25, XK_NO_MOD, "\033[1;5P", 0, 0}, + { XK_F26, XK_NO_MOD, "\033[1;5Q", 0, 0}, + { XK_F27, XK_NO_MOD, "\033[1;5R", 0, 0}, + { XK_F28, XK_NO_MOD, "\033[1;5S", 0, 0}, + { XK_F29, XK_NO_MOD, "\033[15;5~", 0, 0}, + { XK_F30, XK_NO_MOD, "\033[17;5~", 0, 0}, + { XK_F31, XK_NO_MOD, "\033[18;5~", 0, 0}, + { XK_F32, XK_NO_MOD, "\033[19;5~", 0, 0}, + { XK_F33, XK_NO_MOD, "\033[20;5~", 0, 0}, + { XK_F34, XK_NO_MOD, "\033[21;5~", 0, 0}, + { XK_F35, XK_NO_MOD, "\033[23;5~", 0, 0}, +}; + +/* + * Selection types' masks. + * Use the same masks as usual. + * Button1Mask is always unset, to make masks match between ButtonPress. + * ButtonRelease and MotionNotify. + * If no match is found, regular selection is used. + */ +static uint selmasks[] = { + [SEL_RECTANGULAR] = Mod1Mask, +}; + +/* + * Printable characters in ASCII, used to estimate the advance width + * of single wide characters. + */ +static char ascii_printable[] = + " !\"#$%&'()*+,-./0123456789:;<=>?" + "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_" + "`abcdefghijklmnopqrstuvwxyz{|}~"; diff --git a/hosts/vali/mars/dwm/st-0.9.2/config.mk b/hosts/vali/mars/dwm/st-0.9.2/config.mk new file mode 100644 index 0000000..fdc29a7 --- /dev/null +++ b/hosts/vali/mars/dwm/st-0.9.2/config.mk @@ -0,0 +1,36 @@ +# st version +VERSION = 0.9.2 + +# Customize below to fit your system + +# paths +PREFIX = /usr/local +MANPREFIX = $(PREFIX)/share/man + +X11INC = /usr/X11R6/include +X11LIB = /usr/X11R6/lib + +PKG_CONFIG = pkg-config + +# includes and libs +INCS = -I$(X11INC) \ + `$(PKG_CONFIG) --cflags fontconfig` \ + `$(PKG_CONFIG) --cflags freetype2` +LIBS = -L$(X11LIB) -lm -lrt -lX11 -lutil -lXft \ + `$(PKG_CONFIG) --libs fontconfig` \ + `$(PKG_CONFIG) --libs freetype2` + +# flags +STCPPFLAGS = -DVERSION=\"$(VERSION)\" -D_XOPEN_SOURCE=600 +STCFLAGS = $(INCS) $(STCPPFLAGS) $(CPPFLAGS) $(CFLAGS) +STLDFLAGS = $(LIBS) $(LDFLAGS) + +# OpenBSD: +#CPPFLAGS = -DVERSION=\"$(VERSION)\" -D_XOPEN_SOURCE=600 -D_BSD_SOURCE +#LIBS = -L$(X11LIB) -lm -lX11 -lutil -lXft \ +# `$(PKG_CONFIG) --libs fontconfig` \ +# `$(PKG_CONFIG) --libs freetype2` +#MANPREFIX = ${PREFIX}/man + +# compiler and linker +# CC = c99 diff --git a/hosts/vali/mars/dwm/st-0.9.2/shell.nix b/hosts/vali/mars/dwm/st-0.9.2/shell.nix new file mode 100644 index 0000000..ef1ce69 --- /dev/null +++ b/hosts/vali/mars/dwm/st-0.9.2/shell.nix @@ -0,0 +1,10 @@ +{ pkgs ? import {} }: + pkgs.mkShell { + nativeBuildInputs = with pkgs; [ + gnumake + xorg.libX11.dev + xorg.libXft + xorg.libXinerama + pkg-config + ]; +} diff --git a/hosts/vali/mars/dwm/st-0.9.2/st b/hosts/vali/mars/dwm/st-0.9.2/st new file mode 100755 index 0000000000000000000000000000000000000000..c6ea80e0ab9acec5eea0b98b018d105036233ce8 GIT binary patch literal 96616 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 v==wo%f*$uE{T$GPMx;TB1|$H*Ap4+9Fa +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +char *argv0; +#include "arg.h" +#include "st.h" +#include "win.h" + +/* types used in config.h */ +typedef struct { + uint mod; + KeySym keysym; + void (*func)(const Arg *); + const Arg arg; +} Shortcut; + +typedef struct { + uint mod; + uint button; + void (*func)(const Arg *); + const Arg arg; + uint release; +} MouseShortcut; + +typedef struct { + KeySym k; + uint mask; + char *s; + /* three-valued logic variables: 0 indifferent, 1 on, -1 off */ + signed char appkey; /* application keypad */ + signed char appcursor; /* application cursor */ +} Key; + +/* X modifiers */ +#define XK_ANY_MOD UINT_MAX +#define XK_NO_MOD 0 +#define XK_SWITCH_MOD (1<<13|1<<14) + +/* function definitions used in config.h */ +static void clipcopy(const Arg *); +static void clippaste(const Arg *); +static void numlock(const Arg *); +static void selpaste(const Arg *); +static void zoom(const Arg *); +static void zoomabs(const Arg *); +static void zoomreset(const Arg *); +static void ttysend(const Arg *); + +/* config.h for applying patches and the configuration. */ +#include "config.h" + +/* XEMBED messages */ +#define XEMBED_FOCUS_IN 4 +#define XEMBED_FOCUS_OUT 5 + +/* macros */ +#define IS_SET(flag) ((win.mode & (flag)) != 0) +#define TRUERED(x) (((x) & 0xff0000) >> 8) +#define TRUEGREEN(x) (((x) & 0xff00)) +#define TRUEBLUE(x) (((x) & 0xff) << 8) + +typedef XftDraw *Draw; +typedef XftColor Color; +typedef XftGlyphFontSpec GlyphFontSpec; + +/* Purely graphic info */ +typedef struct { + int tw, th; /* tty width and height */ + int w, h; /* window width and height */ + int ch; /* char height */ + int cw; /* char width */ + int mode; /* window state/mode flags */ + int cursor; /* cursor style */ +} TermWindow; + +typedef struct { + Display *dpy; + Colormap cmap; + Window win; + Drawable buf; + GlyphFontSpec *specbuf; /* font spec buffer used for rendering */ + Atom xembed, wmdeletewin, netwmname, netwmiconname, netwmpid; + struct { + XIM xim; + XIC xic; + XPoint spot; + XVaNestedList spotlist; + } ime; + Draw draw; + Visual *vis; + XSetWindowAttributes attrs; + int scr; + int isfixed; /* is fixed geometry? */ + int l, t; /* left and top offset */ + int gm; /* geometry mask */ +} XWindow; + +typedef struct { + Atom xtarget; + char *primary, *clipboard; + struct timespec tclick1; + struct timespec tclick2; +} XSelection; + +/* Font structure */ +#define Font Font_ +typedef struct { + int height; + int width; + int ascent; + int descent; + int badslant; + int badweight; + short lbearing; + short rbearing; + XftFont *match; + FcFontSet *set; + FcPattern *pattern; +} Font; + +/* Drawing Context */ +typedef struct { + Color *col; + size_t collen; + Font font, bfont, ifont, ibfont; + GC gc; +} DC; + +static inline ushort sixd_to_16bit(int); +static int xmakeglyphfontspecs(XftGlyphFontSpec *, const Glyph *, int, int, int); +static void xdrawglyphfontspecs(const XftGlyphFontSpec *, Glyph, int, int, int); +static void xdrawglyph(Glyph, int, int); +static void xclear(int, int, int, int); +static int xgeommasktogravity(int); +static int ximopen(Display *); +static void ximinstantiate(Display *, XPointer, XPointer); +static void ximdestroy(XIM, XPointer, XPointer); +static int xicdestroy(XIC, XPointer, XPointer); +static void xinit(int, int); +static void cresize(int, int); +static void xresize(int, int); +static void xhints(void); +static int xloadcolor(int, const char *, Color *); +static int xloadfont(Font *, FcPattern *); +static void xloadfonts(const char *, double); +static void xunloadfont(Font *); +static void xunloadfonts(void); +static void xsetenv(void); +static void xseturgency(int); +static int evcol(XEvent *); +static int evrow(XEvent *); + +static void expose(XEvent *); +static void visibility(XEvent *); +static void unmap(XEvent *); +static void kpress(XEvent *); +static void cmessage(XEvent *); +static void resize(XEvent *); +static void focus(XEvent *); +static uint buttonmask(uint); +static int mouseaction(XEvent *, uint); +static void brelease(XEvent *); +static void bpress(XEvent *); +static void bmotion(XEvent *); +static void propnotify(XEvent *); +static void selnotify(XEvent *); +static void selclear_(XEvent *); +static void selrequest(XEvent *); +static void setsel(char *, Time); +static void mousesel(XEvent *, int); +static void mousereport(XEvent *); +static char *kmap(KeySym, uint); +static int match(uint, uint); + +static void run(void); +static void usage(void); + +static void (*handler[LASTEvent])(XEvent *) = { + [KeyPress] = kpress, + [ClientMessage] = cmessage, + [ConfigureNotify] = resize, + [VisibilityNotify] = visibility, + [UnmapNotify] = unmap, + [Expose] = expose, + [FocusIn] = focus, + [FocusOut] = focus, + [MotionNotify] = bmotion, + [ButtonPress] = bpress, + [ButtonRelease] = brelease, +/* + * Uncomment if you want the selection to disappear when you select something + * different in another window. + */ +/* [SelectionClear] = selclear_, */ + [SelectionNotify] = selnotify, +/* + * PropertyNotify is only turned on when there is some INCR transfer happening + * for the selection retrieval. + */ + [PropertyNotify] = propnotify, + [SelectionRequest] = selrequest, +}; + +/* Globals */ +static DC dc; +static XWindow xw; +static XSelection xsel; +static TermWindow win; + +/* Font Ring Cache */ +enum { + FRC_NORMAL, + FRC_ITALIC, + FRC_BOLD, + FRC_ITALICBOLD +}; + +typedef struct { + XftFont *font; + int flags; + Rune unicodep; +} Fontcache; + +/* Fontcache is an array now. A new font will be appended to the array. */ +static Fontcache *frc = NULL; +static int frclen = 0; +static int frccap = 0; +static char *usedfont = NULL; +static double usedfontsize = 0; +static double defaultfontsize = 0; + +static char *opt_class = NULL; +static char **opt_cmd = NULL; +static char *opt_embed = NULL; +static char *opt_font = NULL; +static char *opt_io = NULL; +static char *opt_line = NULL; +static char *opt_name = NULL; +static char *opt_title = NULL; + +static uint buttons; /* bit field of pressed buttons */ + +void +clipcopy(const Arg *dummy) +{ + Atom clipboard; + + free(xsel.clipboard); + xsel.clipboard = NULL; + + if (xsel.primary != NULL) { + xsel.clipboard = xstrdup(xsel.primary); + clipboard = XInternAtom(xw.dpy, "CLIPBOARD", 0); + XSetSelectionOwner(xw.dpy, clipboard, xw.win, CurrentTime); + } +} + +void +clippaste(const Arg *dummy) +{ + Atom clipboard; + + clipboard = XInternAtom(xw.dpy, "CLIPBOARD", 0); + XConvertSelection(xw.dpy, clipboard, xsel.xtarget, clipboard, + xw.win, CurrentTime); +} + +void +selpaste(const Arg *dummy) +{ + XConvertSelection(xw.dpy, XA_PRIMARY, xsel.xtarget, XA_PRIMARY, + xw.win, CurrentTime); +} + +void +numlock(const Arg *dummy) +{ + win.mode ^= MODE_NUMLOCK; +} + +void +zoom(const Arg *arg) +{ + Arg larg; + + larg.f = usedfontsize + arg->f; + zoomabs(&larg); +} + +void +zoomabs(const Arg *arg) +{ + xunloadfonts(); + xloadfonts(usedfont, arg->f); + cresize(0, 0); + redraw(); + xhints(); +} + +void +zoomreset(const Arg *arg) +{ + Arg larg; + + if (defaultfontsize > 0) { + larg.f = defaultfontsize; + zoomabs(&larg); + } +} + +void +ttysend(const Arg *arg) +{ + ttywrite(arg->s, strlen(arg->s), 1); +} + +int +evcol(XEvent *e) +{ + int x = e->xbutton.x - borderpx; + LIMIT(x, 0, win.tw - 1); + return x / win.cw; +} + +int +evrow(XEvent *e) +{ + int y = e->xbutton.y - borderpx; + LIMIT(y, 0, win.th - 1); + return y / win.ch; +} + +void +mousesel(XEvent *e, int done) +{ + int type, seltype = SEL_REGULAR; + uint state = e->xbutton.state & ~(Button1Mask | forcemousemod); + + for (type = 1; type < LEN(selmasks); ++type) { + if (match(selmasks[type], state)) { + seltype = type; + break; + } + } + selextend(evcol(e), evrow(e), seltype, done); + if (done) + setsel(getsel(), e->xbutton.time); +} + +void +mousereport(XEvent *e) +{ + int len, btn, code; + int x = evcol(e), y = evrow(e); + int state = e->xbutton.state; + char buf[40]; + static int ox, oy; + + if (e->type == MotionNotify) { + if (x == ox && y == oy) + return; + if (!IS_SET(MODE_MOUSEMOTION) && !IS_SET(MODE_MOUSEMANY)) + return; + /* MODE_MOUSEMOTION: no reporting if no button is pressed */ + if (IS_SET(MODE_MOUSEMOTION) && buttons == 0) + return; + /* Set btn to lowest-numbered pressed button, or 12 if no + * buttons are pressed. */ + for (btn = 1; btn <= 11 && !(buttons & (1<<(btn-1))); btn++) + ; + code = 32; + } else { + btn = e->xbutton.button; + /* Only buttons 1 through 11 can be encoded */ + if (btn < 1 || btn > 11) + return; + if (e->type == ButtonRelease) { + /* MODE_MOUSEX10: no button release reporting */ + if (IS_SET(MODE_MOUSEX10)) + return; + /* Don't send release events for the scroll wheel */ + if (btn == 4 || btn == 5) + return; + } + code = 0; + } + + ox = x; + oy = y; + + /* Encode btn into code. If no button is pressed for a motion event in + * MODE_MOUSEMANY, then encode it as a release. */ + if ((!IS_SET(MODE_MOUSESGR) && e->type == ButtonRelease) || btn == 12) + code += 3; + else if (btn >= 8) + code += 128 + btn - 8; + else if (btn >= 4) + code += 64 + btn - 4; + else + code += btn - 1; + + if (!IS_SET(MODE_MOUSEX10)) { + code += ((state & ShiftMask ) ? 4 : 0) + + ((state & Mod1Mask ) ? 8 : 0) /* meta key: alt */ + + ((state & ControlMask) ? 16 : 0); + } + + if (IS_SET(MODE_MOUSESGR)) { + len = snprintf(buf, sizeof(buf), "\033[<%d;%d;%d%c", + code, x+1, y+1, + e->type == ButtonRelease ? 'm' : 'M'); + } else if (x < 223 && y < 223) { + len = snprintf(buf, sizeof(buf), "\033[M%c%c%c", + 32+code, 32+x+1, 32+y+1); + } else { + return; + } + + ttywrite(buf, len, 0); +} + +uint +buttonmask(uint button) +{ + return button == Button1 ? Button1Mask + : button == Button2 ? Button2Mask + : button == Button3 ? Button3Mask + : button == Button4 ? Button4Mask + : button == Button5 ? Button5Mask + : 0; +} + +int +mouseaction(XEvent *e, uint release) +{ + MouseShortcut *ms; + + /* ignore Buttonmask for Button - it's set on release */ + uint state = e->xbutton.state & ~buttonmask(e->xbutton.button); + + for (ms = mshortcuts; ms < mshortcuts + LEN(mshortcuts); ms++) { + if (ms->release == release && + ms->button == e->xbutton.button && + (match(ms->mod, state) || /* exact or forced */ + match(ms->mod, state & ~forcemousemod))) { + ms->func(&(ms->arg)); + return 1; + } + } + + return 0; +} + +void +bpress(XEvent *e) +{ + int btn = e->xbutton.button; + struct timespec now; + int snap; + + if (1 <= btn && btn <= 11) + buttons |= 1 << (btn-1); + + if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forcemousemod)) { + mousereport(e); + return; + } + + if (mouseaction(e, 0)) + return; + + if (btn == Button1) { + /* + * If the user clicks below predefined timeouts specific + * snapping behaviour is exposed. + */ + clock_gettime(CLOCK_MONOTONIC, &now); + if (TIMEDIFF(now, xsel.tclick2) <= tripleclicktimeout) { + snap = SNAP_LINE; + } else if (TIMEDIFF(now, xsel.tclick1) <= doubleclicktimeout) { + snap = SNAP_WORD; + } else { + snap = 0; + } + xsel.tclick2 = xsel.tclick1; + xsel.tclick1 = now; + + selstart(evcol(e), evrow(e), snap); + } +} + +void +propnotify(XEvent *e) +{ + XPropertyEvent *xpev; + Atom clipboard = XInternAtom(xw.dpy, "CLIPBOARD", 0); + + xpev = &e->xproperty; + if (xpev->state == PropertyNewValue && + (xpev->atom == XA_PRIMARY || + xpev->atom == clipboard)) { + selnotify(e); + } +} + +void +selnotify(XEvent *e) +{ + ulong nitems, ofs, rem; + int format; + uchar *data, *last, *repl; + Atom type, incratom, property = None; + + incratom = XInternAtom(xw.dpy, "INCR", 0); + + ofs = 0; + if (e->type == SelectionNotify) + property = e->xselection.property; + else if (e->type == PropertyNotify) + property = e->xproperty.atom; + + if (property == None) + return; + + do { + if (XGetWindowProperty(xw.dpy, xw.win, property, ofs, + BUFSIZ/4, False, AnyPropertyType, + &type, &format, &nitems, &rem, + &data)) { + fprintf(stderr, "Clipboard allocation failed\n"); + return; + } + + if (e->type == PropertyNotify && nitems == 0 && rem == 0) { + /* + * If there is some PropertyNotify with no data, then + * this is the signal of the selection owner that all + * data has been transferred. We won't need to receive + * PropertyNotify events anymore. + */ + MODBIT(xw.attrs.event_mask, 0, PropertyChangeMask); + XChangeWindowAttributes(xw.dpy, xw.win, CWEventMask, + &xw.attrs); + } + + if (type == incratom) { + /* + * Activate the PropertyNotify events so we receive + * when the selection owner does send us the next + * chunk of data. + */ + MODBIT(xw.attrs.event_mask, 1, PropertyChangeMask); + XChangeWindowAttributes(xw.dpy, xw.win, CWEventMask, + &xw.attrs); + + /* + * Deleting the property is the transfer start signal. + */ + XDeleteProperty(xw.dpy, xw.win, (int)property); + continue; + } + + /* + * As seen in getsel: + * Line endings are inconsistent in the terminal and GUI world + * copy and pasting. When receiving some selection data, + * replace all '\n' with '\r'. + * FIXME: Fix the computer world. + */ + repl = data; + last = data + nitems * format / 8; + while ((repl = memchr(repl, '\n', last - repl))) { + *repl++ = '\r'; + } + + if (IS_SET(MODE_BRCKTPASTE) && ofs == 0) + ttywrite("\033[200~", 6, 0); + ttywrite((char *)data, nitems * format / 8, 1); + if (IS_SET(MODE_BRCKTPASTE) && rem == 0) + ttywrite("\033[201~", 6, 0); + XFree(data); + /* number of 32-bit chunks returned */ + ofs += nitems * format / 32; + } while (rem > 0); + + /* + * Deleting the property again tells the selection owner to send the + * next data chunk in the property. + */ + XDeleteProperty(xw.dpy, xw.win, (int)property); +} + +void +xclipcopy(void) +{ + clipcopy(NULL); +} + +void +selclear_(XEvent *e) +{ + selclear(); +} + +void +selrequest(XEvent *e) +{ + XSelectionRequestEvent *xsre; + XSelectionEvent xev; + Atom xa_targets, string, clipboard; + char *seltext; + + xsre = (XSelectionRequestEvent *) e; + xev.type = SelectionNotify; + xev.requestor = xsre->requestor; + xev.selection = xsre->selection; + xev.target = xsre->target; + xev.time = xsre->time; + if (xsre->property == None) + xsre->property = xsre->target; + + /* reject */ + xev.property = None; + + xa_targets = XInternAtom(xw.dpy, "TARGETS", 0); + if (xsre->target == xa_targets) { + /* respond with the supported type */ + string = xsel.xtarget; + XChangeProperty(xsre->display, xsre->requestor, xsre->property, + XA_ATOM, 32, PropModeReplace, + (uchar *) &string, 1); + xev.property = xsre->property; + } else if (xsre->target == xsel.xtarget || xsre->target == XA_STRING) { + /* + * xith XA_STRING non ascii characters may be incorrect in the + * requestor. It is not our problem, use utf8. + */ + clipboard = XInternAtom(xw.dpy, "CLIPBOARD", 0); + if (xsre->selection == XA_PRIMARY) { + seltext = xsel.primary; + } else if (xsre->selection == clipboard) { + seltext = xsel.clipboard; + } else { + fprintf(stderr, + "Unhandled clipboard selection 0x%lx\n", + xsre->selection); + return; + } + if (seltext != NULL) { + XChangeProperty(xsre->display, xsre->requestor, + xsre->property, xsre->target, + 8, PropModeReplace, + (uchar *)seltext, strlen(seltext)); + xev.property = xsre->property; + } + } + + /* all done, send a notification to the listener */ + if (!XSendEvent(xsre->display, xsre->requestor, 1, 0, (XEvent *) &xev)) + fprintf(stderr, "Error sending SelectionNotify event\n"); +} + +void +setsel(char *str, Time t) +{ + if (!str) + return; + + free(xsel.primary); + xsel.primary = str; + + XSetSelectionOwner(xw.dpy, XA_PRIMARY, xw.win, t); + if (XGetSelectionOwner(xw.dpy, XA_PRIMARY) != xw.win) + selclear(); +} + +void +xsetsel(char *str) +{ + setsel(str, CurrentTime); +} + +void +brelease(XEvent *e) +{ + int btn = e->xbutton.button; + + if (1 <= btn && btn <= 11) + buttons &= ~(1 << (btn-1)); + + if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forcemousemod)) { + mousereport(e); + return; + } + + if (mouseaction(e, 1)) + return; + if (btn == Button1) + mousesel(e, 1); +} + +void +bmotion(XEvent *e) +{ + if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forcemousemod)) { + mousereport(e); + return; + } + + mousesel(e, 0); +} + +void +cresize(int width, int height) +{ + int col, row; + + if (width != 0) + win.w = width; + if (height != 0) + win.h = height; + + col = (win.w - 2 * borderpx) / win.cw; + row = (win.h - 2 * borderpx) / win.ch; + col = MAX(1, col); + row = MAX(1, row); + + tresize(col, row); + xresize(col, row); + ttyresize(win.tw, win.th); +} + +void +xresize(int col, int row) +{ + win.tw = col * win.cw; + win.th = row * win.ch; + + XFreePixmap(xw.dpy, xw.buf); + xw.buf = XCreatePixmap(xw.dpy, xw.win, win.w, win.h, + DefaultDepth(xw.dpy, xw.scr)); + XftDrawChange(xw.draw, xw.buf); + xclear(0, 0, win.w, win.h); + + /* resize to new width */ + xw.specbuf = xrealloc(xw.specbuf, col * sizeof(GlyphFontSpec)); +} + +ushort +sixd_to_16bit(int x) +{ + return x == 0 ? 0 : 0x3737 + 0x2828 * x; +} + +int +xloadcolor(int i, const char *name, Color *ncolor) +{ + XRenderColor color = { .alpha = 0xffff }; + + if (!name) { + if (BETWEEN(i, 16, 255)) { /* 256 color */ + if (i < 6*6*6+16) { /* same colors as xterm */ + color.red = sixd_to_16bit( ((i-16)/36)%6 ); + color.green = sixd_to_16bit( ((i-16)/6) %6 ); + color.blue = sixd_to_16bit( ((i-16)/1) %6 ); + } else { /* greyscale */ + color.red = 0x0808 + 0x0a0a * (i - (6*6*6+16)); + color.green = color.blue = color.red; + } + return XftColorAllocValue(xw.dpy, xw.vis, + xw.cmap, &color, ncolor); + } else + name = colorname[i]; + } + + return XftColorAllocName(xw.dpy, xw.vis, xw.cmap, name, ncolor); +} + +void +xloadcols(void) +{ + int i; + static int loaded; + Color *cp; + + if (loaded) { + for (cp = dc.col; cp < &dc.col[dc.collen]; ++cp) + XftColorFree(xw.dpy, xw.vis, xw.cmap, cp); + } else { + dc.collen = MAX(LEN(colorname), 256); + dc.col = xmalloc(dc.collen * sizeof(Color)); + } + + for (i = 0; i < dc.collen; i++) + if (!xloadcolor(i, NULL, &dc.col[i])) { + if (colorname[i]) + die("could not allocate color '%s'\n", colorname[i]); + else + die("could not allocate color %d\n", i); + } + loaded = 1; +} + +int +xgetcolor(int x, unsigned char *r, unsigned char *g, unsigned char *b) +{ + if (!BETWEEN(x, 0, dc.collen - 1)) + return 1; + + *r = dc.col[x].color.red >> 8; + *g = dc.col[x].color.green >> 8; + *b = dc.col[x].color.blue >> 8; + + return 0; +} + +int +xsetcolorname(int x, const char *name) +{ + Color ncolor; + + if (!BETWEEN(x, 0, dc.collen - 1)) + return 1; + + if (!xloadcolor(x, name, &ncolor)) + return 1; + + XftColorFree(xw.dpy, xw.vis, xw.cmap, &dc.col[x]); + dc.col[x] = ncolor; + + return 0; +} + +/* + * Absolute coordinates. + */ +void +xclear(int x1, int y1, int x2, int y2) +{ + XftDrawRect(xw.draw, + &dc.col[IS_SET(MODE_REVERSE)? defaultfg : defaultbg], + x1, y1, x2-x1, y2-y1); +} + +void +xhints(void) +{ + XClassHint class = {opt_name ? opt_name : termname, + opt_class ? opt_class : termname}; + XWMHints wm = {.flags = InputHint, .input = 1}; + XSizeHints *sizeh; + + sizeh = XAllocSizeHints(); + + sizeh->flags = PSize | PResizeInc | PBaseSize | PMinSize; + sizeh->height = win.h; + sizeh->width = win.w; + sizeh->height_inc = win.ch; + sizeh->width_inc = win.cw; + sizeh->base_height = 2 * borderpx; + sizeh->base_width = 2 * borderpx; + sizeh->min_height = win.ch + 2 * borderpx; + sizeh->min_width = win.cw + 2 * borderpx; + if (xw.isfixed) { + sizeh->flags |= PMaxSize; + sizeh->min_width = sizeh->max_width = win.w; + sizeh->min_height = sizeh->max_height = win.h; + } + if (xw.gm & (XValue|YValue)) { + sizeh->flags |= USPosition | PWinGravity; + sizeh->x = xw.l; + sizeh->y = xw.t; + sizeh->win_gravity = xgeommasktogravity(xw.gm); + } + + XSetWMProperties(xw.dpy, xw.win, NULL, NULL, NULL, 0, sizeh, &wm, + &class); + XFree(sizeh); +} + +int +xgeommasktogravity(int mask) +{ + switch (mask & (XNegative|YNegative)) { + case 0: + return NorthWestGravity; + case XNegative: + return NorthEastGravity; + case YNegative: + return SouthWestGravity; + } + + return SouthEastGravity; +} + +int +xloadfont(Font *f, FcPattern *pattern) +{ + FcPattern *configured; + FcPattern *match; + FcResult result; + XGlyphInfo extents; + int wantattr, haveattr; + + /* + * Manually configure instead of calling XftMatchFont + * so that we can use the configured pattern for + * "missing glyph" lookups. + */ + configured = FcPatternDuplicate(pattern); + if (!configured) + return 1; + + FcConfigSubstitute(NULL, configured, FcMatchPattern); + XftDefaultSubstitute(xw.dpy, xw.scr, configured); + + match = FcFontMatch(NULL, configured, &result); + if (!match) { + FcPatternDestroy(configured); + return 1; + } + + if (!(f->match = XftFontOpenPattern(xw.dpy, match))) { + FcPatternDestroy(configured); + FcPatternDestroy(match); + return 1; + } + + if ((XftPatternGetInteger(pattern, "slant", 0, &wantattr) == + XftResultMatch)) { + /* + * Check if xft was unable to find a font with the appropriate + * slant but gave us one anyway. Try to mitigate. + */ + if ((XftPatternGetInteger(f->match->pattern, "slant", 0, + &haveattr) != XftResultMatch) || haveattr < wantattr) { + f->badslant = 1; + fputs("font slant does not match\n", stderr); + } + } + + if ((XftPatternGetInteger(pattern, "weight", 0, &wantattr) == + XftResultMatch)) { + if ((XftPatternGetInteger(f->match->pattern, "weight", 0, + &haveattr) != XftResultMatch) || haveattr != wantattr) { + f->badweight = 1; + fputs("font weight does not match\n", stderr); + } + } + + XftTextExtentsUtf8(xw.dpy, f->match, + (const FcChar8 *) ascii_printable, + strlen(ascii_printable), &extents); + + f->set = NULL; + f->pattern = configured; + + f->ascent = f->match->ascent; + f->descent = f->match->descent; + f->lbearing = 0; + f->rbearing = f->match->max_advance_width; + + f->height = f->ascent + f->descent; + f->width = DIVCEIL(extents.xOff, strlen(ascii_printable)); + + return 0; +} + +void +xloadfonts(const char *fontstr, double fontsize) +{ + FcPattern *pattern; + double fontval; + + if (fontstr[0] == '-') + pattern = XftXlfdParse(fontstr, False, False); + else + pattern = FcNameParse((const FcChar8 *)fontstr); + + if (!pattern) + die("can't open font %s\n", fontstr); + + if (fontsize > 1) { + FcPatternDel(pattern, FC_PIXEL_SIZE); + FcPatternDel(pattern, FC_SIZE); + FcPatternAddDouble(pattern, FC_PIXEL_SIZE, (double)fontsize); + usedfontsize = fontsize; + } else { + if (FcPatternGetDouble(pattern, FC_PIXEL_SIZE, 0, &fontval) == + FcResultMatch) { + usedfontsize = fontval; + } else if (FcPatternGetDouble(pattern, FC_SIZE, 0, &fontval) == + FcResultMatch) { + usedfontsize = -1; + } else { + /* + * Default font size is 12, if none given. This is to + * have a known usedfontsize value. + */ + FcPatternAddDouble(pattern, FC_PIXEL_SIZE, 12); + usedfontsize = 12; + } + defaultfontsize = usedfontsize; + } + + if (xloadfont(&dc.font, pattern)) + die("can't open font %s\n", fontstr); + + if (usedfontsize < 0) { + FcPatternGetDouble(dc.font.match->pattern, + FC_PIXEL_SIZE, 0, &fontval); + usedfontsize = fontval; + if (fontsize == 0) + defaultfontsize = fontval; + } + + /* Setting character width and height. */ + win.cw = ceilf(dc.font.width * cwscale); + win.ch = ceilf(dc.font.height * chscale); + + FcPatternDel(pattern, FC_SLANT); + FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ITALIC); + if (xloadfont(&dc.ifont, pattern)) + die("can't open font %s\n", fontstr); + + FcPatternDel(pattern, FC_WEIGHT); + FcPatternAddInteger(pattern, FC_WEIGHT, FC_WEIGHT_BOLD); + if (xloadfont(&dc.ibfont, pattern)) + die("can't open font %s\n", fontstr); + + FcPatternDel(pattern, FC_SLANT); + FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ROMAN); + if (xloadfont(&dc.bfont, pattern)) + die("can't open font %s\n", fontstr); + + FcPatternDestroy(pattern); +} + +void +xunloadfont(Font *f) +{ + XftFontClose(xw.dpy, f->match); + FcPatternDestroy(f->pattern); + if (f->set) + FcFontSetDestroy(f->set); +} + +void +xunloadfonts(void) +{ + /* Free the loaded fonts in the font cache. */ + while (frclen > 0) + XftFontClose(xw.dpy, frc[--frclen].font); + + xunloadfont(&dc.font); + xunloadfont(&dc.bfont); + xunloadfont(&dc.ifont); + xunloadfont(&dc.ibfont); +} + +int +ximopen(Display *dpy) +{ + XIMCallback imdestroy = { .client_data = NULL, .callback = ximdestroy }; + XICCallback icdestroy = { .client_data = NULL, .callback = xicdestroy }; + + xw.ime.xim = XOpenIM(xw.dpy, NULL, NULL, NULL); + if (xw.ime.xim == NULL) + return 0; + + if (XSetIMValues(xw.ime.xim, XNDestroyCallback, &imdestroy, NULL)) + fprintf(stderr, "XSetIMValues: " + "Could not set XNDestroyCallback.\n"); + + xw.ime.spotlist = XVaCreateNestedList(0, XNSpotLocation, &xw.ime.spot, + NULL); + + if (xw.ime.xic == NULL) { + xw.ime.xic = XCreateIC(xw.ime.xim, XNInputStyle, + XIMPreeditNothing | XIMStatusNothing, + XNClientWindow, xw.win, + XNDestroyCallback, &icdestroy, + NULL); + } + if (xw.ime.xic == NULL) + fprintf(stderr, "XCreateIC: Could not create input context.\n"); + + return 1; +} + +void +ximinstantiate(Display *dpy, XPointer client, XPointer call) +{ + if (ximopen(dpy)) + XUnregisterIMInstantiateCallback(xw.dpy, NULL, NULL, NULL, + ximinstantiate, NULL); +} + +void +ximdestroy(XIM xim, XPointer client, XPointer call) +{ + xw.ime.xim = NULL; + XRegisterIMInstantiateCallback(xw.dpy, NULL, NULL, NULL, + ximinstantiate, NULL); + XFree(xw.ime.spotlist); +} + +int +xicdestroy(XIC xim, XPointer client, XPointer call) +{ + xw.ime.xic = NULL; + return 1; +} + +void +xinit(int cols, int rows) +{ + XGCValues gcvalues; + Cursor cursor; + Window parent; + pid_t thispid = getpid(); + XColor xmousefg, xmousebg; + + if (!(xw.dpy = XOpenDisplay(NULL))) + die("can't open display\n"); + xw.scr = XDefaultScreen(xw.dpy); + xw.vis = XDefaultVisual(xw.dpy, xw.scr); + + /* font */ + if (!FcInit()) + die("could not init fontconfig.\n"); + + usedfont = (opt_font == NULL)? font : opt_font; + xloadfonts(usedfont, 0); + + /* colors */ + xw.cmap = XDefaultColormap(xw.dpy, xw.scr); + xloadcols(); + + /* adjust fixed window geometry */ + win.w = 2 * borderpx + cols * win.cw; + win.h = 2 * borderpx + rows * win.ch; + if (xw.gm & XNegative) + xw.l += DisplayWidth(xw.dpy, xw.scr) - win.w - 2; + if (xw.gm & YNegative) + xw.t += DisplayHeight(xw.dpy, xw.scr) - win.h - 2; + + /* Events */ + xw.attrs.background_pixel = dc.col[defaultbg].pixel; + xw.attrs.border_pixel = dc.col[defaultbg].pixel; + xw.attrs.bit_gravity = NorthWestGravity; + xw.attrs.event_mask = FocusChangeMask | KeyPressMask | KeyReleaseMask + | ExposureMask | VisibilityChangeMask | StructureNotifyMask + | ButtonMotionMask | ButtonPressMask | ButtonReleaseMask; + xw.attrs.colormap = xw.cmap; + + if (!(opt_embed && (parent = strtol(opt_embed, NULL, 0)))) + parent = XRootWindow(xw.dpy, xw.scr); + xw.win = XCreateWindow(xw.dpy, parent, xw.l, xw.t, + win.w, win.h, 0, XDefaultDepth(xw.dpy, xw.scr), InputOutput, + xw.vis, CWBackPixel | CWBorderPixel | CWBitGravity + | CWEventMask | CWColormap, &xw.attrs); + + memset(&gcvalues, 0, sizeof(gcvalues)); + gcvalues.graphics_exposures = False; + dc.gc = XCreateGC(xw.dpy, parent, GCGraphicsExposures, + &gcvalues); + xw.buf = XCreatePixmap(xw.dpy, xw.win, win.w, win.h, + DefaultDepth(xw.dpy, xw.scr)); + XSetForeground(xw.dpy, dc.gc, dc.col[defaultbg].pixel); + XFillRectangle(xw.dpy, xw.buf, dc.gc, 0, 0, win.w, win.h); + + /* font spec buffer */ + xw.specbuf = xmalloc(cols * sizeof(GlyphFontSpec)); + + /* Xft rendering context */ + xw.draw = XftDrawCreate(xw.dpy, xw.buf, xw.vis, xw.cmap); + + /* input methods */ + if (!ximopen(xw.dpy)) { + XRegisterIMInstantiateCallback(xw.dpy, NULL, NULL, NULL, + ximinstantiate, NULL); + } + + /* white cursor, black outline */ + cursor = XCreateFontCursor(xw.dpy, mouseshape); + XDefineCursor(xw.dpy, xw.win, cursor); + + if (XParseColor(xw.dpy, xw.cmap, colorname[mousefg], &xmousefg) == 0) { + xmousefg.red = 0xffff; + xmousefg.green = 0xffff; + xmousefg.blue = 0xffff; + } + + if (XParseColor(xw.dpy, xw.cmap, colorname[mousebg], &xmousebg) == 0) { + xmousebg.red = 0x0000; + xmousebg.green = 0x0000; + xmousebg.blue = 0x0000; + } + + XRecolorCursor(xw.dpy, cursor, &xmousefg, &xmousebg); + + xw.xembed = XInternAtom(xw.dpy, "_XEMBED", False); + xw.wmdeletewin = XInternAtom(xw.dpy, "WM_DELETE_WINDOW", False); + xw.netwmname = XInternAtom(xw.dpy, "_NET_WM_NAME", False); + xw.netwmiconname = XInternAtom(xw.dpy, "_NET_WM_ICON_NAME", False); + XSetWMProtocols(xw.dpy, xw.win, &xw.wmdeletewin, 1); + + xw.netwmpid = XInternAtom(xw.dpy, "_NET_WM_PID", False); + XChangeProperty(xw.dpy, xw.win, xw.netwmpid, XA_CARDINAL, 32, + PropModeReplace, (uchar *)&thispid, 1); + + win.mode = MODE_NUMLOCK; + resettitle(); + xhints(); + XMapWindow(xw.dpy, xw.win); + XSync(xw.dpy, False); + + clock_gettime(CLOCK_MONOTONIC, &xsel.tclick1); + clock_gettime(CLOCK_MONOTONIC, &xsel.tclick2); + xsel.primary = NULL; + xsel.clipboard = NULL; + xsel.xtarget = XInternAtom(xw.dpy, "UTF8_STRING", 0); + if (xsel.xtarget == None) + xsel.xtarget = XA_STRING; +} + +int +xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x, int y) +{ + float winx = borderpx + x * win.cw, winy = borderpx + y * win.ch, xp, yp; + ushort mode, prevmode = USHRT_MAX; + Font *font = &dc.font; + int frcflags = FRC_NORMAL; + float runewidth = win.cw; + Rune rune; + FT_UInt glyphidx; + FcResult fcres; + FcPattern *fcpattern, *fontpattern; + FcFontSet *fcsets[] = { NULL }; + FcCharSet *fccharset; + int i, f, numspecs = 0; + + for (i = 0, xp = winx, yp = winy + font->ascent; i < len; ++i) { + /* Fetch rune and mode for current glyph. */ + rune = glyphs[i].u; + mode = glyphs[i].mode; + + /* Skip dummy wide-character spacing. */ + if (mode == ATTR_WDUMMY) + continue; + + /* Determine font for glyph if different from previous glyph. */ + if (prevmode != mode) { + prevmode = mode; + font = &dc.font; + frcflags = FRC_NORMAL; + runewidth = win.cw * ((mode & ATTR_WIDE) ? 2.0f : 1.0f); + if ((mode & ATTR_ITALIC) && (mode & ATTR_BOLD)) { + font = &dc.ibfont; + frcflags = FRC_ITALICBOLD; + } else if (mode & ATTR_ITALIC) { + font = &dc.ifont; + frcflags = FRC_ITALIC; + } else if (mode & ATTR_BOLD) { + font = &dc.bfont; + frcflags = FRC_BOLD; + } + yp = winy + font->ascent; + } + + /* Lookup character index with default font. */ + glyphidx = XftCharIndex(xw.dpy, font->match, rune); + if (glyphidx) { + specs[numspecs].font = font->match; + specs[numspecs].glyph = glyphidx; + specs[numspecs].x = (short)xp; + specs[numspecs].y = (short)yp; + xp += runewidth; + numspecs++; + continue; + } + + /* Fallback on font cache, search the font cache for match. */ + for (f = 0; f < frclen; f++) { + glyphidx = XftCharIndex(xw.dpy, frc[f].font, rune); + /* Everything correct. */ + if (glyphidx && frc[f].flags == frcflags) + break; + /* We got a default font for a not found glyph. */ + if (!glyphidx && frc[f].flags == frcflags + && frc[f].unicodep == rune) { + break; + } + } + + /* Nothing was found. Use fontconfig to find matching font. */ + if (f >= frclen) { + if (!font->set) + font->set = FcFontSort(0, font->pattern, + 1, 0, &fcres); + fcsets[0] = font->set; + + /* + * Nothing was found in the cache. Now use + * some dozen of Fontconfig calls to get the + * font for one single character. + * + * Xft and fontconfig are design failures. + */ + fcpattern = FcPatternDuplicate(font->pattern); + fccharset = FcCharSetCreate(); + + FcCharSetAddChar(fccharset, rune); + FcPatternAddCharSet(fcpattern, FC_CHARSET, + fccharset); + FcPatternAddBool(fcpattern, FC_SCALABLE, 1); + + FcConfigSubstitute(0, fcpattern, + FcMatchPattern); + FcDefaultSubstitute(fcpattern); + + fontpattern = FcFontSetMatch(0, fcsets, 1, + fcpattern, &fcres); + + /* Allocate memory for the new cache entry. */ + if (frclen >= frccap) { + frccap += 16; + frc = xrealloc(frc, frccap * sizeof(Fontcache)); + } + + frc[frclen].font = XftFontOpenPattern(xw.dpy, + fontpattern); + if (!frc[frclen].font) + die("XftFontOpenPattern failed seeking fallback font: %s\n", + strerror(errno)); + frc[frclen].flags = frcflags; + frc[frclen].unicodep = rune; + + glyphidx = XftCharIndex(xw.dpy, frc[frclen].font, rune); + + f = frclen; + frclen++; + + FcPatternDestroy(fcpattern); + FcCharSetDestroy(fccharset); + } + + specs[numspecs].font = frc[f].font; + specs[numspecs].glyph = glyphidx; + specs[numspecs].x = (short)xp; + specs[numspecs].y = (short)yp; + xp += runewidth; + numspecs++; + } + + return numspecs; +} + +void +xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, int y) +{ + int charlen = len * ((base.mode & ATTR_WIDE) ? 2 : 1); + int winx = borderpx + x * win.cw, winy = borderpx + y * win.ch, + width = charlen * win.cw; + Color *fg, *bg, *temp, revfg, revbg, truefg, truebg; + XRenderColor colfg, colbg; + XRectangle r; + + /* Fallback on color display for attributes not supported by the font */ + if (base.mode & ATTR_ITALIC && base.mode & ATTR_BOLD) { + if (dc.ibfont.badslant || dc.ibfont.badweight) + base.fg = defaultattr; + } else if ((base.mode & ATTR_ITALIC && dc.ifont.badslant) || + (base.mode & ATTR_BOLD && dc.bfont.badweight)) { + base.fg = defaultattr; + } + + if (IS_TRUECOL(base.fg)) { + colfg.alpha = 0xffff; + colfg.red = TRUERED(base.fg); + colfg.green = TRUEGREEN(base.fg); + colfg.blue = TRUEBLUE(base.fg); + XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colfg, &truefg); + fg = &truefg; + } else { + fg = &dc.col[base.fg]; + } + + if (IS_TRUECOL(base.bg)) { + colbg.alpha = 0xffff; + colbg.green = TRUEGREEN(base.bg); + colbg.red = TRUERED(base.bg); + colbg.blue = TRUEBLUE(base.bg); + XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colbg, &truebg); + bg = &truebg; + } else { + bg = &dc.col[base.bg]; + } + + /* Change basic system colors [0-7] to bright system colors [8-15] */ + if ((base.mode & ATTR_BOLD_FAINT) == ATTR_BOLD && BETWEEN(base.fg, 0, 7)) + fg = &dc.col[base.fg + 8]; + + if (IS_SET(MODE_REVERSE)) { + if (fg == &dc.col[defaultfg]) { + fg = &dc.col[defaultbg]; + } else { + colfg.red = ~fg->color.red; + colfg.green = ~fg->color.green; + colfg.blue = ~fg->color.blue; + colfg.alpha = fg->color.alpha; + XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colfg, + &revfg); + fg = &revfg; + } + + if (bg == &dc.col[defaultbg]) { + bg = &dc.col[defaultfg]; + } else { + colbg.red = ~bg->color.red; + colbg.green = ~bg->color.green; + colbg.blue = ~bg->color.blue; + colbg.alpha = bg->color.alpha; + XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colbg, + &revbg); + bg = &revbg; + } + } + + if ((base.mode & ATTR_BOLD_FAINT) == ATTR_FAINT) { + colfg.red = fg->color.red / 2; + colfg.green = fg->color.green / 2; + colfg.blue = fg->color.blue / 2; + colfg.alpha = fg->color.alpha; + XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colfg, &revfg); + fg = &revfg; + } + + if (base.mode & ATTR_REVERSE) { + temp = fg; + fg = bg; + bg = temp; + } + + if (base.mode & ATTR_BLINK && win.mode & MODE_BLINK) + fg = bg; + + if (base.mode & ATTR_INVISIBLE) + fg = bg; + + /* Intelligent cleaning up of the borders. */ + if (x == 0) { + xclear(0, (y == 0)? 0 : winy, borderpx, + winy + win.ch + + ((winy + win.ch >= borderpx + win.th)? win.h : 0)); + } + if (winx + width >= borderpx + win.tw) { + xclear(winx + width, (y == 0)? 0 : winy, win.w, + ((winy + win.ch >= borderpx + win.th)? win.h : (winy + win.ch))); + } + if (y == 0) + xclear(winx, 0, winx + width, borderpx); + if (winy + win.ch >= borderpx + win.th) + xclear(winx, winy + win.ch, winx + width, win.h); + + /* Clean up the region we want to draw to. */ + XftDrawRect(xw.draw, bg, winx, winy, width, win.ch); + + /* Set the clip region because Xft is sometimes dirty. */ + r.x = 0; + r.y = 0; + r.height = win.ch; + r.width = width; + XftDrawSetClipRectangles(xw.draw, winx, winy, &r, 1); + + /* Render the glyphs. */ + XftDrawGlyphFontSpec(xw.draw, fg, specs, len); + + /* Render underline and strikethrough. */ + if (base.mode & ATTR_UNDERLINE) { + XftDrawRect(xw.draw, fg, winx, winy + dc.font.ascent * chscale + 1, + width, 1); + } + + if (base.mode & ATTR_STRUCK) { + XftDrawRect(xw.draw, fg, winx, winy + 2 * dc.font.ascent * chscale / 3, + width, 1); + } + + /* Reset clip to none. */ + XftDrawSetClip(xw.draw, 0); +} + +void +xdrawglyph(Glyph g, int x, int y) +{ + int numspecs; + XftGlyphFontSpec spec; + + numspecs = xmakeglyphfontspecs(&spec, &g, 1, x, y); + xdrawglyphfontspecs(&spec, g, numspecs, x, y); +} + +void +xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og) +{ + Color drawcol; + + /* remove the old cursor */ + if (selected(ox, oy)) + og.mode ^= ATTR_REVERSE; + xdrawglyph(og, ox, oy); + + if (IS_SET(MODE_HIDE)) + return; + + /* + * Select the right color for the right mode. + */ + g.mode &= ATTR_BOLD|ATTR_ITALIC|ATTR_UNDERLINE|ATTR_STRUCK|ATTR_WIDE; + + if (IS_SET(MODE_REVERSE)) { + g.mode |= ATTR_REVERSE; + g.bg = defaultfg; + if (selected(cx, cy)) { + drawcol = dc.col[defaultcs]; + g.fg = defaultrcs; + } else { + drawcol = dc.col[defaultrcs]; + g.fg = defaultcs; + } + } else { + if (selected(cx, cy)) { + g.fg = defaultfg; + g.bg = defaultrcs; + } else { + g.fg = defaultbg; + g.bg = defaultcs; + } + drawcol = dc.col[g.bg]; + } + + /* draw the new one */ + if (IS_SET(MODE_FOCUSED)) { + switch (win.cursor) { + case 7: /* st extension */ + g.u = 0x2603; /* snowman (U+2603) */ + /* FALLTHROUGH */ + case 0: /* Blinking Block */ + case 1: /* Blinking Block (Default) */ + case 2: /* Steady Block */ + xdrawglyph(g, cx, cy); + break; + case 3: /* Blinking Underline */ + case 4: /* Steady Underline */ + XftDrawRect(xw.draw, &drawcol, + borderpx + cx * win.cw, + borderpx + (cy + 1) * win.ch - \ + cursorthickness, + win.cw, cursorthickness); + break; + case 5: /* Blinking bar */ + case 6: /* Steady bar */ + XftDrawRect(xw.draw, &drawcol, + borderpx + cx * win.cw, + borderpx + cy * win.ch, + cursorthickness, win.ch); + break; + } + } else { + XftDrawRect(xw.draw, &drawcol, + borderpx + cx * win.cw, + borderpx + cy * win.ch, + win.cw - 1, 1); + XftDrawRect(xw.draw, &drawcol, + borderpx + cx * win.cw, + borderpx + cy * win.ch, + 1, win.ch - 1); + XftDrawRect(xw.draw, &drawcol, + borderpx + (cx + 1) * win.cw - 1, + borderpx + cy * win.ch, + 1, win.ch - 1); + XftDrawRect(xw.draw, &drawcol, + borderpx + cx * win.cw, + borderpx + (cy + 1) * win.ch - 1, + win.cw, 1); + } +} + +void +xsetenv(void) +{ + char buf[sizeof(long) * 8 + 1]; + + snprintf(buf, sizeof(buf), "%lu", xw.win); + setenv("WINDOWID", buf, 1); +} + +void +xseticontitle(char *p) +{ + XTextProperty prop; + DEFAULT(p, opt_title); + + if (p[0] == '\0') + p = opt_title; + + if (Xutf8TextListToTextProperty(xw.dpy, &p, 1, XUTF8StringStyle, + &prop) != Success) + return; + XSetWMIconName(xw.dpy, xw.win, &prop); + XSetTextProperty(xw.dpy, xw.win, &prop, xw.netwmiconname); + XFree(prop.value); +} + +void +xsettitle(char *p) +{ + XTextProperty prop; + DEFAULT(p, opt_title); + + if (p[0] == '\0') + p = opt_title; + + if (Xutf8TextListToTextProperty(xw.dpy, &p, 1, XUTF8StringStyle, + &prop) != Success) + return; + XSetWMName(xw.dpy, xw.win, &prop); + XSetTextProperty(xw.dpy, xw.win, &prop, xw.netwmname); + XFree(prop.value); +} + +int +xstartdraw(void) +{ + return IS_SET(MODE_VISIBLE); +} + +void +xdrawline(Line line, int x1, int y1, int x2) +{ + int i, x, ox, numspecs; + Glyph base, new; + XftGlyphFontSpec *specs = xw.specbuf; + + numspecs = xmakeglyphfontspecs(specs, &line[x1], x2 - x1, x1, y1); + i = ox = 0; + for (x = x1; x < x2 && i < numspecs; x++) { + new = line[x]; + if (new.mode == ATTR_WDUMMY) + continue; + if (selected(x, y1)) + new.mode ^= ATTR_REVERSE; + if (i > 0 && ATTRCMP(base, new)) { + xdrawglyphfontspecs(specs, base, i, ox, y1); + specs += i; + numspecs -= i; + i = 0; + } + if (i == 0) { + ox = x; + base = new; + } + i++; + } + if (i > 0) + xdrawglyphfontspecs(specs, base, i, ox, y1); +} + +void +xfinishdraw(void) +{ + XCopyArea(xw.dpy, xw.buf, xw.win, dc.gc, 0, 0, win.w, + win.h, 0, 0); + XSetForeground(xw.dpy, dc.gc, + dc.col[IS_SET(MODE_REVERSE)? + defaultfg : defaultbg].pixel); +} + +void +xximspot(int x, int y) +{ + if (xw.ime.xic == NULL) + return; + + xw.ime.spot.x = borderpx + x * win.cw; + xw.ime.spot.y = borderpx + (y + 1) * win.ch; + + XSetICValues(xw.ime.xic, XNPreeditAttributes, xw.ime.spotlist, NULL); +} + +void +expose(XEvent *ev) +{ + redraw(); +} + +void +visibility(XEvent *ev) +{ + XVisibilityEvent *e = &ev->xvisibility; + + MODBIT(win.mode, e->state != VisibilityFullyObscured, MODE_VISIBLE); +} + +void +unmap(XEvent *ev) +{ + win.mode &= ~MODE_VISIBLE; +} + +void +xsetpointermotion(int set) +{ + MODBIT(xw.attrs.event_mask, set, PointerMotionMask); + XChangeWindowAttributes(xw.dpy, xw.win, CWEventMask, &xw.attrs); +} + +void +xsetmode(int set, unsigned int flags) +{ + int mode = win.mode; + MODBIT(win.mode, set, flags); + if ((win.mode & MODE_REVERSE) != (mode & MODE_REVERSE)) + redraw(); +} + +int +xsetcursor(int cursor) +{ + if (!BETWEEN(cursor, 0, 7)) /* 7: st extension */ + return 1; + win.cursor = cursor; + return 0; +} + +void +xseturgency(int add) +{ + XWMHints *h = XGetWMHints(xw.dpy, xw.win); + + MODBIT(h->flags, add, XUrgencyHint); + XSetWMHints(xw.dpy, xw.win, h); + XFree(h); +} + +void +xbell(void) +{ + if (!(IS_SET(MODE_FOCUSED))) + xseturgency(1); + if (bellvolume) + XkbBell(xw.dpy, xw.win, bellvolume, (Atom)NULL); +} + +void +focus(XEvent *ev) +{ + XFocusChangeEvent *e = &ev->xfocus; + + if (e->mode == NotifyGrab) + return; + + if (ev->type == FocusIn) { + if (xw.ime.xic) + XSetICFocus(xw.ime.xic); + win.mode |= MODE_FOCUSED; + xseturgency(0); + if (IS_SET(MODE_FOCUS)) + ttywrite("\033[I", 3, 0); + } else { + if (xw.ime.xic) + XUnsetICFocus(xw.ime.xic); + win.mode &= ~MODE_FOCUSED; + if (IS_SET(MODE_FOCUS)) + ttywrite("\033[O", 3, 0); + } +} + +int +match(uint mask, uint state) +{ + return mask == XK_ANY_MOD || mask == (state & ~ignoremod); +} + +char* +kmap(KeySym k, uint state) +{ + Key *kp; + int i; + + /* Check for mapped keys out of X11 function keys. */ + for (i = 0; i < LEN(mappedkeys); i++) { + if (mappedkeys[i] == k) + break; + } + if (i == LEN(mappedkeys)) { + if ((k & 0xFFFF) < 0xFD00) + return NULL; + } + + for (kp = key; kp < key + LEN(key); kp++) { + if (kp->k != k) + continue; + + if (!match(kp->mask, state)) + continue; + + if (IS_SET(MODE_APPKEYPAD) ? kp->appkey < 0 : kp->appkey > 0) + continue; + if (IS_SET(MODE_NUMLOCK) && kp->appkey == 2) + continue; + + if (IS_SET(MODE_APPCURSOR) ? kp->appcursor < 0 : kp->appcursor > 0) + continue; + + return kp->s; + } + + return NULL; +} + +void +kpress(XEvent *ev) +{ + XKeyEvent *e = &ev->xkey; + KeySym ksym = NoSymbol; + char buf[64], *customkey; + int len; + Rune c; + Status status; + Shortcut *bp; + + if (IS_SET(MODE_KBDLOCK)) + return; + + if (xw.ime.xic) { + len = XmbLookupString(xw.ime.xic, e, buf, sizeof buf, &ksym, &status); + if (status == XBufferOverflow) + return; + } else { + len = XLookupString(e, buf, sizeof buf, &ksym, NULL); + } + /* 1. shortcuts */ + for (bp = shortcuts; bp < shortcuts + LEN(shortcuts); bp++) { + if (ksym == bp->keysym && match(bp->mod, e->state)) { + bp->func(&(bp->arg)); + return; + } + } + + /* 2. custom keys from config.h */ + if ((customkey = kmap(ksym, e->state))) { + ttywrite(customkey, strlen(customkey), 1); + return; + } + + /* 3. composed string from input method */ + if (len == 0) + return; + if (len == 1 && e->state & Mod1Mask) { + if (IS_SET(MODE_8BIT)) { + if (*buf < 0177) { + c = *buf | 0x80; + len = utf8encode(c, buf); + } + } else { + buf[1] = buf[0]; + buf[0] = '\033'; + len = 2; + } + } + ttywrite(buf, len, 1); +} + +void +cmessage(XEvent *e) +{ + /* + * See xembed specs + * http://standards.freedesktop.org/xembed-spec/xembed-spec-latest.html + */ + if (e->xclient.message_type == xw.xembed && e->xclient.format == 32) { + if (e->xclient.data.l[1] == XEMBED_FOCUS_IN) { + win.mode |= MODE_FOCUSED; + xseturgency(0); + } else if (e->xclient.data.l[1] == XEMBED_FOCUS_OUT) { + win.mode &= ~MODE_FOCUSED; + } + } else if (e->xclient.data.l[0] == xw.wmdeletewin) { + ttyhangup(); + exit(0); + } +} + +void +resize(XEvent *e) +{ + if (e->xconfigure.width == win.w && e->xconfigure.height == win.h) + return; + + cresize(e->xconfigure.width, e->xconfigure.height); +} + +void +run(void) +{ + XEvent ev; + int w = win.w, h = win.h; + fd_set rfd; + int xfd = XConnectionNumber(xw.dpy), ttyfd, xev, drawing; + struct timespec seltv, *tv, now, lastblink, trigger; + double timeout; + + /* Waiting for window mapping */ + do { + XNextEvent(xw.dpy, &ev); + /* + * This XFilterEvent call is required because of XOpenIM. It + * does filter out the key event and some client message for + * the input method too. + */ + if (XFilterEvent(&ev, None)) + continue; + if (ev.type == ConfigureNotify) { + w = ev.xconfigure.width; + h = ev.xconfigure.height; + } + } while (ev.type != MapNotify); + + ttyfd = ttynew(opt_line, shell, opt_io, opt_cmd); + cresize(w, h); + + for (timeout = -1, drawing = 0, lastblink = (struct timespec){0};;) { + FD_ZERO(&rfd); + FD_SET(ttyfd, &rfd); + FD_SET(xfd, &rfd); + + if (XPending(xw.dpy)) + timeout = 0; /* existing events might not set xfd */ + + seltv.tv_sec = timeout / 1E3; + seltv.tv_nsec = 1E6 * (timeout - 1E3 * seltv.tv_sec); + tv = timeout >= 0 ? &seltv : NULL; + + if (pselect(MAX(xfd, ttyfd)+1, &rfd, NULL, NULL, tv, NULL) < 0) { + if (errno == EINTR) + continue; + die("select failed: %s\n", strerror(errno)); + } + clock_gettime(CLOCK_MONOTONIC, &now); + + if (FD_ISSET(ttyfd, &rfd)) + ttyread(); + + xev = 0; + while (XPending(xw.dpy)) { + xev = 1; + XNextEvent(xw.dpy, &ev); + if (XFilterEvent(&ev, None)) + continue; + if (handler[ev.type]) + (handler[ev.type])(&ev); + } + + /* + * To reduce flicker and tearing, when new content or event + * triggers drawing, we first wait a bit to ensure we got + * everything, and if nothing new arrives - we draw. + * We start with trying to wait minlatency ms. If more content + * arrives sooner, we retry with shorter and shorter periods, + * and eventually draw even without idle after maxlatency ms. + * Typically this results in low latency while interacting, + * maximum latency intervals during `cat huge.txt`, and perfect + * sync with periodic updates from animations/key-repeats/etc. + */ + if (FD_ISSET(ttyfd, &rfd) || xev) { + if (!drawing) { + trigger = now; + drawing = 1; + } + timeout = (maxlatency - TIMEDIFF(now, trigger)) \ + / maxlatency * minlatency; + if (timeout > 0) + continue; /* we have time, try to find idle */ + } + + /* idle detected or maxlatency exhausted -> draw */ + timeout = -1; + if (blinktimeout && tattrset(ATTR_BLINK)) { + timeout = blinktimeout - TIMEDIFF(now, lastblink); + if (timeout <= 0) { + if (-timeout > blinktimeout) /* start visible */ + win.mode |= MODE_BLINK; + win.mode ^= MODE_BLINK; + tsetdirtattr(ATTR_BLINK); + lastblink = now; + timeout = blinktimeout; + } + } + + draw(); + XFlush(xw.dpy); + drawing = 0; + } +} + +void +usage(void) +{ + die("usage: %s [-aiv] [-c class] [-f font] [-g geometry]" + " [-n name] [-o file]\n" + " [-T title] [-t title] [-w windowid]" + " [[-e] command [args ...]]\n" + " %s [-aiv] [-c class] [-f font] [-g geometry]" + " [-n name] [-o file]\n" + " [-T title] [-t title] [-w windowid] -l line" + " [stty_args ...]\n", argv0, argv0); +} + +int +main(int argc, char *argv[]) +{ + xw.l = xw.t = 0; + xw.isfixed = False; + xsetcursor(cursorshape); + + ARGBEGIN { + case 'a': + allowaltscreen = 0; + break; + case 'c': + opt_class = EARGF(usage()); + break; + case 'e': + if (argc > 0) + --argc, ++argv; + goto run; + case 'f': + opt_font = EARGF(usage()); + break; + case 'g': + xw.gm = XParseGeometry(EARGF(usage()), + &xw.l, &xw.t, &cols, &rows); + break; + case 'i': + xw.isfixed = 1; + break; + case 'o': + opt_io = EARGF(usage()); + break; + case 'l': + opt_line = EARGF(usage()); + break; + case 'n': + opt_name = EARGF(usage()); + break; + case 't': + case 'T': + opt_title = EARGF(usage()); + break; + case 'w': + opt_embed = EARGF(usage()); + break; + case 'v': + die("%s " VERSION "\n", argv0); + break; + default: + usage(); + } ARGEND; + +run: + if (argc > 0) /* eat all remaining arguments */ + opt_cmd = argv; + + if (!opt_title) + opt_title = (opt_line || !opt_cmd) ? "st" : opt_cmd[0]; + + setlocale(LC_CTYPE, ""); + XSetLocaleModifiers(""); + cols = MAX(cols, 1); + rows = MAX(rows, 1); + tnew(cols, rows); + xinit(cols, rows); + xsetenv(); + selinit(); + run(); + + return 0; +} diff --git a/hosts/vali/mars/dwm/st-0.9.2/x.o b/hosts/vali/mars/dwm/st-0.9.2/x.o new file mode 100644 index 0000000000000000000000000000000000000000..0304e60e65a8afb1f330537f39da69bae2c694a8 GIT binary patch literal 75240 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 literal 0 HcmV?d00001 diff --git a/hosts/vali/mars/dwm/st.nix b/hosts/vali/mars/dwm/st.nix new file mode 100644 index 0000000..2a15c65 --- /dev/null +++ b/hosts/vali/mars/dwm/st.nix @@ -0,0 +1,5 @@ +{ pkgs, lib, config, callPackage, ... }: +environment.systemPackages = with pkgs; [ + (st.overrideAttrs (oldAttrs: rec { src = ./st-0.9.2; })) +]; + From 2ea3474b1e103a1be1c515c1a8d493dbd5147f22 Mon Sep 17 00:00:00 2001 From: vali Date: Sun, 14 Apr 2024 13:27:24 +0200 Subject: [PATCH 26/27] dwm config --- hosts/vali/mars/dwm/dmenu-5.3/config.h | 23 +++++++++++++++++++++++ hosts/vali/mars/dwm/dmenu-5.3/dmenu | Bin 0 -> 42560 bytes hosts/vali/mars/dwm/dmenu-5.3/dmenu.o | Bin 0 -> 32384 bytes hosts/vali/mars/dwm/dmenu-5.3/drw.o | Bin 0 -> 11160 bytes hosts/vali/mars/dwm/dmenu-5.3/shell.nix | 9 +++++++++ hosts/vali/mars/dwm/dmenu-5.3/stest | Bin 0 -> 16576 bytes hosts/vali/mars/dwm/dmenu-5.3/stest.o | Bin 0 -> 5328 bytes hosts/vali/mars/dwm/dmenu-5.3/util.o | Bin 0 -> 2248 bytes hosts/vali/mars/dwm/dmenu.nix | 0 hosts/vali/mars/dwm/dwm-6.5/config.h | 6 +++--- hosts/vali/mars/dwm/dwm-6.5/dwm.1 | 3 +++ hosts/vali/mars/dwm/dwm-6.5/dwm.c | 8 ++++++++ hosts/vali/mars/dwm/dwm.nix | 2 +- hosts/vali/mars/dwm/st.nix | 5 ----- hosts/vali/mars/programs.nix | 1 + 15 files changed, 48 insertions(+), 9 deletions(-) create mode 100644 hosts/vali/mars/dwm/dmenu-5.3/config.h create mode 100755 hosts/vali/mars/dwm/dmenu-5.3/dmenu create mode 100644 hosts/vali/mars/dwm/dmenu-5.3/dmenu.o create mode 100644 hosts/vali/mars/dwm/dmenu-5.3/drw.o create mode 100644 hosts/vali/mars/dwm/dmenu-5.3/shell.nix create mode 100755 hosts/vali/mars/dwm/dmenu-5.3/stest create mode 100644 hosts/vali/mars/dwm/dmenu-5.3/stest.o create mode 100644 hosts/vali/mars/dwm/dmenu-5.3/util.o delete mode 100644 hosts/vali/mars/dwm/dmenu.nix delete mode 100644 hosts/vali/mars/dwm/st.nix diff --git a/hosts/vali/mars/dwm/dmenu-5.3/config.h b/hosts/vali/mars/dwm/dmenu-5.3/config.h new file mode 100644 index 0000000..687b07c --- /dev/null +++ b/hosts/vali/mars/dwm/dmenu-5.3/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 = 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=18" +}; +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/hosts/vali/mars/dwm/dmenu-5.3/dmenu b/hosts/vali/mars/dwm/dmenu-5.3/dmenu new file mode 100755 index 0000000000000000000000000000000000000000..e47d6461d622e7c3e46a853b9c513ee498f9f3f6 GIT binary patch literal 42560 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 literal 0 HcmV?d00001 diff --git a/hosts/vali/mars/dwm/dmenu-5.3/drw.o b/hosts/vali/mars/dwm/dmenu-5.3/drw.o new file mode 100644 index 0000000000000000000000000000000000000000..05bf8b656009a325422f7ddbb5b29a69d329acbc GIT binary patch literal 11160 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 literal 0 HcmV?d00001 diff --git a/hosts/vali/mars/dwm/dmenu-5.3/shell.nix b/hosts/vali/mars/dwm/dmenu-5.3/shell.nix new file mode 100644 index 0000000..883e00e --- /dev/null +++ b/hosts/vali/mars/dwm/dmenu-5.3/shell.nix @@ -0,0 +1,9 @@ +{ pkgs ? import {} }: + pkgs.mkShell { + nativeBuildInputs = with pkgs; [ + gnumake + xorg.libX11.dev + xorg.libXft + xorg.libXinerama + ]; +} diff --git a/hosts/vali/mars/dwm/dmenu-5.3/stest b/hosts/vali/mars/dwm/dmenu-5.3/stest new file mode 100755 index 0000000000000000000000000000000000000000..fe4502343d6b4550687dc5874e7330606ff82269 GIT binary patch literal 16576 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 ZLS@1GmC=-dr5ZpTa8SD$%tH|9`T_rqok#!x literal 0 HcmV?d00001 diff --git a/hosts/vali/mars/dwm/dmenu-5.3/stest.o b/hosts/vali/mars/dwm/dmenu-5.3/stest.o new file mode 100644 index 0000000000000000000000000000000000000000..27f2c5e6b523acec7972def72b6187b996e7bee2 GIT binary patch literal 5328 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 literal 0 HcmV?d00001 diff --git a/hosts/vali/mars/dwm/dmenu-5.3/util.o b/hosts/vali/mars/dwm/dmenu-5.3/util.o new file mode 100644 index 0000000000000000000000000000000000000000..4b569ab3cf3d20cbdf0c56dd2448b4cd6d4ad19a GIT binary patch literal 2248 zcmb<-^>JfjWMqH=Mg}_u1P><4z~I4(U^{@B4h(z@ybPhi9-Y5E8sFStU|{g*EK$+$ z=nPRY@aXhWvGD11QE~9;^ilC>IZ$HGuj!%^z_00}lEAMSqEf)GIY*^|fq{WvbBW3X zFug`)0hr#RvH?u*Q8~cCz>wn6&7!ISHrz!;!tj7cw=T$bkIsi4owq!CTU0(UFfi<6 zVqjo6&Z5ErQrBI};L+)#!r{^DqM~rzMTNxxB--hsBJcvFv%#97M9rh~K7>=l{NJin z+@rgcVZQj1q)av7)*L}9`wk2qCElyODu`L6Cug zK>$@Ln5T|ITn~phD9o{$?7I4BLV zBZ==q5(mW*O#OKzaZnnAiC;q!2PJu!_%kGNWc8qI2a*EW%Z+63H;^C$12~<7(g4gH zR#3uXU|;~{RAwagJWz3vIUo#E56UATqd@9G7{mr)NZA812P6)Q9|pbR%G{E~BnG|W zk|GG50b>=V<|OKsq*jzL=%plbdHE%& zdhULqy2T}l$=OhTdS0nsK~a7|YEelggC5wx)QtGFqQu-(kgF)iApe4b0u;B%rosFx z3X(*UK;tqB7p03~4d!)TDdL2OWA4^;xDVnKoo3=G0x z9)f@hgZ&H=^@Q3FVk6@Mm_lShENUYe7#KkL50oa6mBRF+y9?bvg-|om^)Gsel) + setfullscreen(selmon->sel, !selmon->sel>isfullscreen); +} + void toggletag(const Arg *arg) { diff --git a/hosts/vali/mars/dwm/dwm.nix b/hosts/vali/mars/dwm/dwm.nix index a2104c0..a90b77c 100644 --- a/hosts/vali/mars/dwm/dwm.nix +++ b/hosts/vali/mars/dwm/dwm.nix @@ -16,11 +16,11 @@ in { nixpkgs.overlays = [ (final: prev: { dwm = prev.dwm.overrideAttrs (old: {src = ./dwm-6.5;}); - dmenu = prev.dmenu.overrideAttrs (old: {src = ./dmenu-5.3;}); }) ]; environment.systemPackages = with pkgs; [ (st.overrideAttrs (oldAttrs: rec { src = ./st-0.9.2; })) + (dmenu.overrideAttrs (oldAttrs: rec { src = ./dmenu-5.3; })) ]; }; diff --git a/hosts/vali/mars/dwm/st.nix b/hosts/vali/mars/dwm/st.nix deleted file mode 100644 index 2a15c65..0000000 --- a/hosts/vali/mars/dwm/st.nix +++ /dev/null @@ -1,5 +0,0 @@ -{ pkgs, lib, config, callPackage, ... }: -environment.systemPackages = with pkgs; [ - (st.overrideAttrs (oldAttrs: rec { src = ./st-0.9.2; })) -]; - diff --git a/hosts/vali/mars/programs.nix b/hosts/vali/mars/programs.nix index b91e21d..d51ff68 100644 --- a/hosts/vali/mars/programs.nix +++ b/hosts/vali/mars/programs.nix @@ -10,6 +10,7 @@ in { # betterbird bibata-cursors dig + dmenu easyeffects element-desktop eza From 6b1b9e5b2eba6054a2497f2fcd4426246a1fe163 Mon Sep 17 00:00:00 2001 From: vali Date: Sun, 14 Apr 2024 14:35:10 +0200 Subject: [PATCH 27/27] fixed dwm --- hosts/vali/mars/configuration.nix | 3 --- hosts/vali/mars/default.nix | 1 + hosts/vali/mars/dwm/dwm-6.5/dwm | Bin 62616 -> 62656 bytes hosts/vali/mars/dwm/dwm-6.5/dwm.c | 2 +- hosts/vali/mars/dwm/dwm-6.5/dwm.o | Bin 57728 -> 57904 bytes hosts/vali/mars/dwm/dwm.nix | 5 +++++ hosts/vali/mars/profile.nix | 1 + hosts/vali/mars/programs.nix | 2 ++ modules/other/default.nix | 2 +- modules/other/xdg.nix | 1 - 10 files changed, 11 insertions(+), 6 deletions(-) diff --git a/hosts/vali/mars/configuration.nix b/hosts/vali/mars/configuration.nix index c41206e..1b7816a 100644 --- a/hosts/vali/mars/configuration.nix +++ b/hosts/vali/mars/configuration.nix @@ -52,11 +52,8 @@ ssh.enable = true; btop.enable = true; mpv.enable = true; - i3.enable = true; dwm.enable = true; schizofox.enable = true; - displaymanager.enable = true; - #neovim.enable = true; #git = { # enable = true; # userName = "vali"; diff --git a/hosts/vali/mars/default.nix b/hosts/vali/mars/default.nix index 2a9abad..acef5b9 100644 --- a/hosts/vali/mars/default.nix +++ b/hosts/vali/mars/default.nix @@ -6,5 +6,6 @@ _: { ./profile.nix ./i3 ./dwm/dwm.nix + ]; } diff --git a/hosts/vali/mars/dwm/dwm-6.5/dwm b/hosts/vali/mars/dwm/dwm-6.5/dwm index ada53af8858f284682206aef4d9936bdcd919065..5424031efddfa2f90be022e761ff0b34bb3996d2 100755 GIT binary patch delta 11008 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 delta 11019 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 diff --git a/hosts/vali/mars/dwm/dwm-6.5/dwm.c b/hosts/vali/mars/dwm/dwm-6.5/dwm.c index b801c2c..e940130 100644 --- a/hosts/vali/mars/dwm/dwm-6.5/dwm.c +++ b/hosts/vali/mars/dwm/dwm-6.5/dwm.c @@ -1740,7 +1740,7 @@ void togglefullscr(const Arg *arg) { if(selmon->sel) - setfullscreen(selmon->sel, !selmon->sel>isfullscreen); + setfullscreen(selmon->sel, !selmon->sel->isfullscreen); } void diff --git a/hosts/vali/mars/dwm/dwm-6.5/dwm.o b/hosts/vali/mars/dwm/dwm-6.5/dwm.o index 3ced421d5a5a19c4e752356261f1930e66f7151c..16a9fb0b210345759e64b77487522356433a3a0e 100644 GIT binary patch delta 13015 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 AdjJ3c delta 13070 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 z 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 diff --git a/hosts/vali/mars/dwm/dwm.nix b/hosts/vali/mars/dwm/dwm.nix index a90b77c..2cf92f3 100644 --- a/hosts/vali/mars/dwm/dwm.nix +++ b/hosts/vali/mars/dwm/dwm.nix @@ -12,6 +12,11 @@ in { windowManager.dwm = { enable = true; }; + displayManager.sddm = { + enable = true; + setupScript = "xrandr --output HDMI-1 --rotate normal --output DP-2 --rotate normal --left-of HDMI-1 --output HDMI-0 --right-of HDMI-1"; +# defaultSession = "dwm"; + }; }; nixpkgs.overlays = [ (final: prev: { diff --git a/hosts/vali/mars/profile.nix b/hosts/vali/mars/profile.nix index 26bce2e..bc3a40a 100644 --- a/hosts/vali/mars/profile.nix +++ b/hosts/vali/mars/profile.nix @@ -8,5 +8,6 @@ _: { ../../../options/common/pin-registry.nix ../../../options/common/preserve-system.nix #../../options/ + ../../../options/desktop/monitors.nix ]; } diff --git a/hosts/vali/mars/programs.nix b/hosts/vali/mars/programs.nix index d51ff68..5c068f8 100644 --- a/hosts/vali/mars/programs.nix +++ b/hosts/vali/mars/programs.nix @@ -15,6 +15,7 @@ in { element-desktop eza fastfetch + feh (fenix.complete.withComponents [ "cargo" "clippy" @@ -74,6 +75,7 @@ in { vlc wget xclip + xfce.thunar xorg.libX11.dev xorg.libXft xorg.libXinerama diff --git a/modules/other/default.nix b/modules/other/default.nix index 549359d..dc00064 100644 --- a/modules/other/default.nix +++ b/modules/other/default.nix @@ -2,7 +2,7 @@ _: { imports = [ ./home-manager.nix ./system.nix -# ./xdg.nix + ./xdg.nix ./displaymanager.nix ]; } diff --git a/modules/other/xdg.nix b/modules/other/xdg.nix index 36a32b8..09c8966 100644 --- a/modules/other/xdg.nix +++ b/modules/other/xdg.nix @@ -63,7 +63,6 @@ in { atexit.register(write_history) ''; - xdg = { cacheHome = "${hmCfg.home.homeDirectory}/.cache"; configHome = "${hmCfg.home.homeDirectory}/.config";

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 literal 0 HcmV?d00001 diff --git a/hosts/vali/mars/dwm/st-0.9.2/st.1 b/hosts/vali/mars/dwm/st-0.9.2/st.1 new file mode 100644 index 0000000..39120b4 --- /dev/null +++ b/hosts/vali/mars/dwm/st-0.9.2/st.1 @@ -0,0 +1,177 @@ +.TH ST 1 st\-VERSION +.SH NAME +st \- simple terminal +.SH SYNOPSIS +.B st +.RB [ \-aiv ] +.RB [ \-c +.IR class ] +.RB [ \-f +.IR font ] +.RB [ \-g +.IR geometry ] +.RB [ \-n +.IR name ] +.RB [ \-o +.IR iofile ] +.RB [ \-T +.IR title ] +.RB [ \-t +.IR title ] +.RB [ \-l +.IR line ] +.RB [ \-w +.IR windowid ] +.RB [[ \-e ] +.IR command +.RI [ arguments ...]] +.PP +.B st +.RB [ \-aiv ] +.RB [ \-c +.IR class ] +.RB [ \-f +.IR font ] +.RB [ \-g +.IR geometry ] +.RB [ \-n +.IR name ] +.RB [ \-o +.IR iofile ] +.RB [ \-T +.IR title ] +.RB [ \-t +.IR title ] +.RB [ \-w +.IR windowid ] +.RB \-l +.IR line +.RI [ stty_args ...] +.SH DESCRIPTION +.B st +is a simple terminal emulator. +.SH OPTIONS +.TP +.B \-a +disable alternate screens in terminal +.TP +.BI \-c " class" +defines the window class (default $TERM). +.TP +.BI \-f " font" +defines the +.I font +to use when st is run. +.TP +.BI \-g " geometry" +defines the X11 geometry string. +The form is [=][{xX}][{+-}{+-}]. See +.BR XParseGeometry (3) +for further details. +.TP +.B \-i +will fixate the position given with the -g option. +.TP +.BI \-n " name" +defines the window instance name (default $TERM). +.TP +.BI \-o " iofile" +writes all the I/O to +.I iofile. +This feature is useful when recording st sessions. A value of "-" means +standard output. +.TP +.BI \-T " title" +defines the window title (default 'st'). +.TP +.BI \-t " title" +defines the window title (default 'st'). +.TP +.BI \-w " windowid" +embeds st within the window identified by +.I windowid +.TP +.BI \-l " line" +use a tty +.I line +instead of a pseudo terminal. +.I line +should be a (pseudo-)serial device (e.g. /dev/ttyS0 on Linux for serial port +0). +When this flag is given +remaining arguments are used as flags for +.BR stty(1). +By default st initializes the serial line to 8 bits, no parity, 1 stop bit +and a 38400 baud rate. The speed is set by appending it as last argument +(e.g. 'st -l /dev/ttyS0 115200'). Arguments before the last one are +.BR stty(1) +flags. If you want to set odd parity on 115200 baud use for example 'st -l +/dev/ttyS0 parenb parodd 115200'. Set the number of bits by using for +example 'st -l /dev/ttyS0 cs7 115200'. See +.BR stty(1) +for more arguments and cases. +.TP +.B \-v +prints version information to stderr, then exits. +.TP +.BI \-e " command " [ " arguments " "... ]" +st executes +.I command +instead of the shell. If this is used it +.B must be the last option +on the command line, as in xterm / rxvt. +This option is only intended for compatibility, +and all the remaining arguments are used as a command +even without it. +.SH SHORTCUTS +.TP +.B Break +Send a break in the serial line. +Break key is obtained in PC keyboards +pressing at the same time control and pause. +.TP +.B Ctrl-Print Screen +Toggle if st should print to the +.I iofile. +.TP +.B Shift-Print Screen +Print the full screen to the +.I iofile. +.TP +.B Print Screen +Print the selection to the +.I iofile. +.TP +.B Ctrl-Shift-Page Up +Increase font size. +.TP +.B Ctrl-Shift-Page Down +Decrease font size. +.TP +.B Ctrl-Shift-Home +Reset to default font size. +.TP +.B Ctrl-Shift-y +Paste from primary selection (middle mouse button). +.TP +.B Ctrl-Shift-c +Copy the selected text to the clipboard selection. +.TP +.B Ctrl-Shift-v +Paste from the clipboard selection. +.SH CUSTOMIZATION +.B st +can be customized by creating a custom config.h and (re)compiling the source +code. This keeps it fast, secure and simple. +.SH AUTHORS +See the LICENSE file for the authors. +.SH LICENSE +See the LICENSE file for the terms of redistribution. +.SH SEE ALSO +.BR tabbed (1), +.BR utmp (1), +.BR stty (1), +.BR scroll (1) +.SH BUGS +See the TODO file in the distribution. + diff --git a/hosts/vali/mars/dwm/st-0.9.2/st.c b/hosts/vali/mars/dwm/st-0.9.2/st.c new file mode 100644 index 0000000..b9f66e7 --- /dev/null +++ b/hosts/vali/mars/dwm/st-0.9.2/st.c @@ -0,0 +1,2675 @@ +/* See LICENSE for license details. */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "st.h" +#include "win.h" + +#if defined(__linux) + #include +#elif defined(__OpenBSD__) || defined(__NetBSD__) || defined(__APPLE__) + #include +#elif defined(__FreeBSD__) || defined(__DragonFly__) + #include +#endif + +/* Arbitrary sizes */ +#define UTF_INVALID 0xFFFD +#define UTF_SIZ 4 +#define ESC_BUF_SIZ (128*UTF_SIZ) +#define ESC_ARG_SIZ 16 +#define STR_BUF_SIZ ESC_BUF_SIZ +#define STR_ARG_SIZ ESC_ARG_SIZ + +/* macros */ +#define IS_SET(flag) ((term.mode & (flag)) != 0) +#define ISCONTROLC0(c) (BETWEEN(c, 0, 0x1f) || (c) == 0x7f) +#define ISCONTROLC1(c) (BETWEEN(c, 0x80, 0x9f)) +#define ISCONTROL(c) (ISCONTROLC0(c) || ISCONTROLC1(c)) +#define ISDELIM(u) (u && wcschr(worddelimiters, u)) + +enum term_mode { + MODE_WRAP = 1 << 0, + MODE_INSERT = 1 << 1, + MODE_ALTSCREEN = 1 << 2, + MODE_CRLF = 1 << 3, + MODE_ECHO = 1 << 4, + MODE_PRINT = 1 << 5, + MODE_UTF8 = 1 << 6, +}; + +enum cursor_movement { + CURSOR_SAVE, + CURSOR_LOAD +}; + +enum cursor_state { + CURSOR_DEFAULT = 0, + CURSOR_WRAPNEXT = 1, + CURSOR_ORIGIN = 2 +}; + +enum charset { + CS_GRAPHIC0, + CS_GRAPHIC1, + CS_UK, + CS_USA, + CS_MULTI, + CS_GER, + CS_FIN +}; + +enum escape_state { + ESC_START = 1, + ESC_CSI = 2, + ESC_STR = 4, /* DCS, OSC, PM, APC */ + ESC_ALTCHARSET = 8, + ESC_STR_END = 16, /* a final string was encountered */ + ESC_TEST = 32, /* Enter in test mode */ + ESC_UTF8 = 64, +}; + +typedef struct { + Glyph attr; /* current char attributes */ + int x; + int y; + char state; +} TCursor; + +typedef struct { + int mode; + int type; + int snap; + /* + * Selection variables: + * nb – normalized coordinates of the beginning of the selection + * ne – normalized coordinates of the end of the selection + * ob – original coordinates of the beginning of the selection + * oe – original coordinates of the end of the selection + */ + struct { + int x, y; + } nb, ne, ob, oe; + + int alt; +} Selection; + +/* Internal representation of the screen */ +typedef struct { + int row; /* nb row */ + int col; /* nb col */ + Line *line; /* screen */ + Line *alt; /* alternate screen */ + int *dirty; /* dirtyness of lines */ + TCursor c; /* cursor */ + int ocx; /* old cursor col */ + int ocy; /* old cursor row */ + int top; /* top scroll limit */ + int bot; /* bottom scroll limit */ + int mode; /* terminal mode flags */ + int esc; /* escape state flags */ + char trantbl[4]; /* charset table translation */ + int charset; /* current charset */ + int icharset; /* selected charset for sequence */ + int *tabs; + Rune lastc; /* last printed char outside of sequence, 0 if control */ +} Term; + +/* CSI Escape sequence structs */ +/* ESC '[' [[ [] [;]] []] */ +typedef struct { + char buf[ESC_BUF_SIZ]; /* raw string */ + size_t len; /* raw string length */ + char priv; + int arg[ESC_ARG_SIZ]; + int narg; /* nb of args */ + char mode[2]; +} CSIEscape; + +/* STR Escape sequence structs */ +/* ESC type [[ [] [;]] ] ESC '\' */ +typedef struct { + char type; /* ESC type ... */ + char *buf; /* allocated raw string */ + size_t siz; /* allocation size */ + size_t len; /* raw string length */ + char *args[STR_ARG_SIZ]; + int narg; /* nb of args */ +} STREscape; + +static void execsh(char *, char **); +static void stty(char **); +static void sigchld(int); +static void ttywriteraw(const char *, size_t); + +static void csidump(void); +static void csihandle(void); +static void csiparse(void); +static void csireset(void); +static void osc_color_response(int, int, int); +static int eschandle(uchar); +static void strdump(void); +static void strhandle(void); +static void strparse(void); +static void strreset(void); + +static void tprinter(char *, size_t); +static void tdumpsel(void); +static void tdumpline(int); +static void tdump(void); +static void tclearregion(int, int, int, int); +static void tcursor(int); +static void tdeletechar(int); +static void tdeleteline(int); +static void tinsertblank(int); +static void tinsertblankline(int); +static int tlinelen(int); +static void tmoveto(int, int); +static void tmoveato(int, int); +static void tnewline(int); +static void tputtab(int); +static void tputc(Rune); +static void treset(void); +static void tscrollup(int, int); +static void tscrolldown(int, int); +static void tsetattr(const int *, int); +static void tsetchar(Rune, const Glyph *, int, int); +static void tsetdirt(int, int); +static void tsetscroll(int, int); +static void tswapscreen(void); +static void tsetmode(int, int, const int *, int); +static int twrite(const char *, int, int); +static void tfulldirt(void); +static void tcontrolcode(uchar ); +static void tdectest(char ); +static void tdefutf8(char); +static int32_t tdefcolor(const int *, int *, int); +static void tdeftran(char); +static void tstrsequence(uchar); + +static void drawregion(int, int, int, int); + +static void selnormalize(void); +static void selscroll(int, int); +static void selsnap(int *, int *, int); + +static size_t utf8decode(const char *, Rune *, size_t); +static Rune utf8decodebyte(char, size_t *); +static char utf8encodebyte(Rune, size_t); +static size_t utf8validate(Rune *, size_t); + +static char *base64dec(const char *); +static char base64dec_getc(const char **); + +static ssize_t xwrite(int, const char *, size_t); + +/* Globals */ +static Term term; +static Selection sel; +static CSIEscape csiescseq; +static STREscape strescseq; +static int iofd = 1; +static int cmdfd; +static pid_t pid; + +static const uchar utfbyte[UTF_SIZ + 1] = {0x80, 0, 0xC0, 0xE0, 0xF0}; +static const uchar utfmask[UTF_SIZ + 1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8}; +static const Rune utfmin[UTF_SIZ + 1] = { 0, 0, 0x80, 0x800, 0x10000}; +static const Rune utfmax[UTF_SIZ + 1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF}; + +ssize_t +xwrite(int fd, const char *s, size_t len) +{ + size_t aux = len; + ssize_t r; + + while (len > 0) { + r = write(fd, s, len); + if (r < 0) + return r; + len -= r; + s += r; + } + + return aux; +} + +void * +xmalloc(size_t len) +{ + void *p; + + if (!(p = malloc(len))) + die("malloc: %s\n", strerror(errno)); + + return p; +} + +void * +xrealloc(void *p, size_t len) +{ + if ((p = realloc(p, len)) == NULL) + die("realloc: %s\n", strerror(errno)); + + return p; +} + +char * +xstrdup(const char *s) +{ + char *p; + + if ((p = strdup(s)) == NULL) + die("strdup: %s\n", strerror(errno)); + + return p; +} + +size_t +utf8decode(const char *c, Rune *u, size_t clen) +{ + size_t i, j, len, type; + Rune udecoded; + + *u = UTF_INVALID; + if (!clen) + return 0; + udecoded = utf8decodebyte(c[0], &len); + if (!BETWEEN(len, 1, UTF_SIZ)) + return 1; + for (i = 1, j = 1; i < clen && j < len; ++i, ++j) { + udecoded = (udecoded << 6) | utf8decodebyte(c[i], &type); + if (type != 0) + return j; + } + if (j < len) + return 0; + *u = udecoded; + utf8validate(u, len); + + return len; +} + +Rune +utf8decodebyte(char c, size_t *i) +{ + for (*i = 0; *i < LEN(utfmask); ++(*i)) + if (((uchar)c & utfmask[*i]) == utfbyte[*i]) + return (uchar)c & ~utfmask[*i]; + + return 0; +} + +size_t +utf8encode(Rune u, char *c) +{ + size_t len, i; + + len = utf8validate(&u, 0); + if (len > UTF_SIZ) + return 0; + + for (i = len - 1; i != 0; --i) { + c[i] = utf8encodebyte(u, 0); + u >>= 6; + } + c[0] = utf8encodebyte(u, len); + + return len; +} + +char +utf8encodebyte(Rune u, size_t i) +{ + return utfbyte[i] | (u & ~utfmask[i]); +} + +size_t +utf8validate(Rune *u, size_t i) +{ + if (!BETWEEN(*u, utfmin[i], utfmax[i]) || BETWEEN(*u, 0xD800, 0xDFFF)) + *u = UTF_INVALID; + for (i = 1; *u > utfmax[i]; ++i) + ; + + return i; +} + +char +base64dec_getc(const char **src) +{ + while (**src && !isprint((unsigned char)**src)) + (*src)++; + return **src ? *((*src)++) : '='; /* emulate padding if string ends */ +} + +char * +base64dec(const char *src) +{ + size_t in_len = strlen(src); + char *result, *dst; + static const char base64_digits[256] = { + [43] = 62, 0, 0, 0, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, + 0, 0, 0, -1, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, + 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 0, 0, 0, + 0, 0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, + 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51 + }; + + if (in_len % 4) + in_len += 4 - (in_len % 4); + result = dst = xmalloc(in_len / 4 * 3 + 1); + while (*src) { + int a = base64_digits[(unsigned char) base64dec_getc(&src)]; + int b = base64_digits[(unsigned char) base64dec_getc(&src)]; + int c = base64_digits[(unsigned char) base64dec_getc(&src)]; + int d = base64_digits[(unsigned char) base64dec_getc(&src)]; + + /* invalid input. 'a' can be -1, e.g. if src is "\n" (c-str) */ + if (a == -1 || b == -1) + break; + + *dst++ = (a << 2) | ((b & 0x30) >> 4); + if (c == -1) + break; + *dst++ = ((b & 0x0f) << 4) | ((c & 0x3c) >> 2); + if (d == -1) + break; + *dst++ = ((c & 0x03) << 6) | d; + } + *dst = '\0'; + return result; +} + +void +selinit(void) +{ + sel.mode = SEL_IDLE; + sel.snap = 0; + sel.ob.x = -1; +} + +int +tlinelen(int y) +{ + int i = term.col; + + if (term.line[y][i - 1].mode & ATTR_WRAP) + return i; + + while (i > 0 && term.line[y][i - 1].u == ' ') + --i; + + return i; +} + +void +selstart(int col, int row, int snap) +{ + selclear(); + sel.mode = SEL_EMPTY; + sel.type = SEL_REGULAR; + sel.alt = IS_SET(MODE_ALTSCREEN); + sel.snap = snap; + sel.oe.x = sel.ob.x = col; + sel.oe.y = sel.ob.y = row; + selnormalize(); + + if (sel.snap != 0) + sel.mode = SEL_READY; + tsetdirt(sel.nb.y, sel.ne.y); +} + +void +selextend(int col, int row, int type, int done) +{ + int oldey, oldex, oldsby, oldsey, oldtype; + + if (sel.mode == SEL_IDLE) + return; + if (done && sel.mode == SEL_EMPTY) { + selclear(); + return; + } + + oldey = sel.oe.y; + oldex = sel.oe.x; + oldsby = sel.nb.y; + oldsey = sel.ne.y; + oldtype = sel.type; + + sel.oe.x = col; + sel.oe.y = row; + selnormalize(); + sel.type = type; + + if (oldey != sel.oe.y || oldex != sel.oe.x || oldtype != sel.type || sel.mode == SEL_EMPTY) + tsetdirt(MIN(sel.nb.y, oldsby), MAX(sel.ne.y, oldsey)); + + sel.mode = done ? SEL_IDLE : SEL_READY; +} + +void +selnormalize(void) +{ + int i; + + if (sel.type == SEL_REGULAR && sel.ob.y != sel.oe.y) { + sel.nb.x = sel.ob.y < sel.oe.y ? sel.ob.x : sel.oe.x; + sel.ne.x = sel.ob.y < sel.oe.y ? sel.oe.x : sel.ob.x; + } else { + sel.nb.x = MIN(sel.ob.x, sel.oe.x); + sel.ne.x = MAX(sel.ob.x, sel.oe.x); + } + sel.nb.y = MIN(sel.ob.y, sel.oe.y); + sel.ne.y = MAX(sel.ob.y, sel.oe.y); + + selsnap(&sel.nb.x, &sel.nb.y, -1); + selsnap(&sel.ne.x, &sel.ne.y, +1); + + /* expand selection over line breaks */ + if (sel.type == SEL_RECTANGULAR) + return; + i = tlinelen(sel.nb.y); + if (i < sel.nb.x) + sel.nb.x = i; + if (tlinelen(sel.ne.y) <= sel.ne.x) + sel.ne.x = term.col - 1; +} + +int +selected(int x, int y) +{ + if (sel.mode == SEL_EMPTY || sel.ob.x == -1 || + sel.alt != IS_SET(MODE_ALTSCREEN)) + return 0; + + if (sel.type == SEL_RECTANGULAR) + return BETWEEN(y, sel.nb.y, sel.ne.y) + && BETWEEN(x, sel.nb.x, sel.ne.x); + + return BETWEEN(y, sel.nb.y, sel.ne.y) + && (y != sel.nb.y || x >= sel.nb.x) + && (y != sel.ne.y || x <= sel.ne.x); +} + +void +selsnap(int *x, int *y, int direction) +{ + int newx, newy, xt, yt; + int delim, prevdelim; + const Glyph *gp, *prevgp; + + switch (sel.snap) { + case SNAP_WORD: + /* + * Snap around if the word wraps around at the end or + * beginning of a line. + */ + prevgp = &term.line[*y][*x]; + prevdelim = ISDELIM(prevgp->u); + for (;;) { + newx = *x + direction; + newy = *y; + if (!BETWEEN(newx, 0, term.col - 1)) { + newy += direction; + newx = (newx + term.col) % term.col; + if (!BETWEEN(newy, 0, term.row - 1)) + break; + + if (direction > 0) + yt = *y, xt = *x; + else + yt = newy, xt = newx; + if (!(term.line[yt][xt].mode & ATTR_WRAP)) + break; + } + + if (newx >= tlinelen(newy)) + break; + + gp = &term.line[newy][newx]; + delim = ISDELIM(gp->u); + if (!(gp->mode & ATTR_WDUMMY) && (delim != prevdelim + || (delim && gp->u != prevgp->u))) + break; + + *x = newx; + *y = newy; + prevgp = gp; + prevdelim = delim; + } + break; + case SNAP_LINE: + /* + * Snap around if the the previous line or the current one + * has set ATTR_WRAP at its end. Then the whole next or + * previous line will be selected. + */ + *x = (direction < 0) ? 0 : term.col - 1; + if (direction < 0) { + for (; *y > 0; *y += direction) { + if (!(term.line[*y-1][term.col-1].mode + & ATTR_WRAP)) { + break; + } + } + } else if (direction > 0) { + for (; *y < term.row-1; *y += direction) { + if (!(term.line[*y][term.col-1].mode + & ATTR_WRAP)) { + break; + } + } + } + break; + } +} + +char * +getsel(void) +{ + char *str, *ptr; + int y, bufsize, lastx, linelen; + const Glyph *gp, *last; + + if (sel.ob.x == -1) + return NULL; + + bufsize = (term.col+1) * (sel.ne.y-sel.nb.y+1) * UTF_SIZ; + ptr = str = xmalloc(bufsize); + + /* append every set & selected glyph to the selection */ + for (y = sel.nb.y; y <= sel.ne.y; y++) { + if ((linelen = tlinelen(y)) == 0) { + *ptr++ = '\n'; + continue; + } + + if (sel.type == SEL_RECTANGULAR) { + gp = &term.line[y][sel.nb.x]; + lastx = sel.ne.x; + } else { + gp = &term.line[y][sel.nb.y == y ? sel.nb.x : 0]; + lastx = (sel.ne.y == y) ? sel.ne.x : term.col-1; + } + last = &term.line[y][MIN(lastx, linelen-1)]; + while (last >= gp && last->u == ' ') + --last; + + for ( ; gp <= last; ++gp) { + if (gp->mode & ATTR_WDUMMY) + continue; + + ptr += utf8encode(gp->u, ptr); + } + + /* + * Copy and pasting of line endings is inconsistent + * in the inconsistent terminal and GUI world. + * The best solution seems like to produce '\n' when + * something is copied from st and convert '\n' to + * '\r', when something to be pasted is received by + * st. + * FIXME: Fix the computer world. + */ + if ((y < sel.ne.y || lastx >= linelen) && + (!(last->mode & ATTR_WRAP) || sel.type == SEL_RECTANGULAR)) + *ptr++ = '\n'; + } + *ptr = 0; + return str; +} + +void +selclear(void) +{ + if (sel.ob.x == -1) + return; + sel.mode = SEL_IDLE; + sel.ob.x = -1; + tsetdirt(sel.nb.y, sel.ne.y); +} + +void +die(const char *errstr, ...) +{ + va_list ap; + + va_start(ap, errstr); + vfprintf(stderr, errstr, ap); + va_end(ap); + exit(1); +} + +void +execsh(char *cmd, char **args) +{ + char *sh, *prog, *arg; + const struct passwd *pw; + + errno = 0; + if ((pw = getpwuid(getuid())) == NULL) { + if (errno) + die("getpwuid: %s\n", strerror(errno)); + else + die("who are you?\n"); + } + + if ((sh = getenv("SHELL")) == NULL) + sh = (pw->pw_shell[0]) ? pw->pw_shell : cmd; + + if (args) { + prog = args[0]; + arg = NULL; + } else if (scroll) { + prog = scroll; + arg = utmp ? utmp : sh; + } else if (utmp) { + prog = utmp; + arg = NULL; + } else { + prog = sh; + arg = NULL; + } + DEFAULT(args, ((char *[]) {prog, arg, NULL})); + + unsetenv("COLUMNS"); + unsetenv("LINES"); + unsetenv("TERMCAP"); + setenv("LOGNAME", pw->pw_name, 1); + setenv("USER", pw->pw_name, 1); + setenv("SHELL", sh, 1); + setenv("HOME", pw->pw_dir, 1); + setenv("TERM", termname, 1); + + signal(SIGCHLD, SIG_DFL); + signal(SIGHUP, SIG_DFL); + signal(SIGINT, SIG_DFL); + signal(SIGQUIT, SIG_DFL); + signal(SIGTERM, SIG_DFL); + signal(SIGALRM, SIG_DFL); + + execvp(prog, args); + _exit(1); +} + +void +sigchld(int a) +{ + int stat; + pid_t p; + + if ((p = waitpid(pid, &stat, WNOHANG)) < 0) + die("waiting for pid %hd failed: %s\n", pid, strerror(errno)); + + if (pid != p) + return; + + if (WIFEXITED(stat) && WEXITSTATUS(stat)) + die("child exited with status %d\n", WEXITSTATUS(stat)); + else if (WIFSIGNALED(stat)) + die("child terminated due to signal %d\n", WTERMSIG(stat)); + _exit(0); +} + +void +stty(char **args) +{ + char cmd[_POSIX_ARG_MAX], **p, *q, *s; + size_t n, siz; + + if ((n = strlen(stty_args)) > sizeof(cmd)-1) + die("incorrect stty parameters\n"); + memcpy(cmd, stty_args, n); + q = cmd + n; + siz = sizeof(cmd) - n; + for (p = args; p && (s = *p); ++p) { + if ((n = strlen(s)) > siz-1) + die("stty parameter length too long\n"); + *q++ = ' '; + memcpy(q, s, n); + q += n; + siz -= n + 1; + } + *q = '\0'; + if (system(cmd) != 0) + perror("Couldn't call stty"); +} + +int +ttynew(const char *line, char *cmd, const char *out, char **args) +{ + int m, s; + + if (out) { + term.mode |= MODE_PRINT; + iofd = (!strcmp(out, "-")) ? + 1 : open(out, O_WRONLY | O_CREAT, 0666); + if (iofd < 0) { + fprintf(stderr, "Error opening %s:%s\n", + out, strerror(errno)); + } + } + + if (line) { + if ((cmdfd = open(line, O_RDWR)) < 0) + die("open line '%s' failed: %s\n", + line, strerror(errno)); + dup2(cmdfd, 0); + stty(args); + return cmdfd; + } + + /* seems to work fine on linux, openbsd and freebsd */ + if (openpty(&m, &s, NULL, NULL, NULL) < 0) + die("openpty failed: %s\n", strerror(errno)); + + switch (pid = fork()) { + case -1: + die("fork failed: %s\n", strerror(errno)); + break; + case 0: + close(iofd); + close(m); + setsid(); /* create a new process group */ + dup2(s, 0); + dup2(s, 1); + dup2(s, 2); + if (ioctl(s, TIOCSCTTY, NULL) < 0) + die("ioctl TIOCSCTTY failed: %s\n", strerror(errno)); + if (s > 2) + close(s); +#ifdef __OpenBSD__ + if (pledge("stdio getpw proc exec", NULL) == -1) + die("pledge\n"); +#endif + execsh(cmd, args); + break; + default: +#ifdef __OpenBSD__ + if (pledge("stdio rpath tty proc", NULL) == -1) + die("pledge\n"); +#endif + close(s); + cmdfd = m; + signal(SIGCHLD, sigchld); + break; + } + return cmdfd; +} + +size_t +ttyread(void) +{ + static char buf[BUFSIZ]; + static int buflen = 0; + int ret, written; + + /* append read bytes to unprocessed bytes */ + ret = read(cmdfd, buf+buflen, LEN(buf)-buflen); + + switch (ret) { + case 0: + exit(0); + case -1: + die("couldn't read from shell: %s\n", strerror(errno)); + default: + buflen += ret; + written = twrite(buf, buflen, 0); + buflen -= written; + /* keep any incomplete UTF-8 byte sequence for the next call */ + if (buflen > 0) + memmove(buf, buf + written, buflen); + return ret; + } +} + +void +ttywrite(const char *s, size_t n, int may_echo) +{ + const char *next; + + if (may_echo && IS_SET(MODE_ECHO)) + twrite(s, n, 1); + + if (!IS_SET(MODE_CRLF)) { + ttywriteraw(s, n); + return; + } + + /* This is similar to how the kernel handles ONLCR for ttys */ + while (n > 0) { + if (*s == '\r') { + next = s + 1; + ttywriteraw("\r\n", 2); + } else { + next = memchr(s, '\r', n); + DEFAULT(next, s + n); + ttywriteraw(s, next - s); + } + n -= next - s; + s = next; + } +} + +void +ttywriteraw(const char *s, size_t n) +{ + fd_set wfd, rfd; + ssize_t r; + size_t lim = 256; + + /* + * Remember that we are using a pty, which might be a modem line. + * Writing too much will clog the line. That's why we are doing this + * dance. + * FIXME: Migrate the world to Plan 9. + */ + while (n > 0) { + FD_ZERO(&wfd); + FD_ZERO(&rfd); + FD_SET(cmdfd, &wfd); + FD_SET(cmdfd, &rfd); + + /* Check if we can write. */ + if (pselect(cmdfd+1, &rfd, &wfd, NULL, NULL, NULL) < 0) { + if (errno == EINTR) + continue; + die("select failed: %s\n", strerror(errno)); + } + if (FD_ISSET(cmdfd, &wfd)) { + /* + * Only write the bytes written by ttywrite() or the + * default of 256. This seems to be a reasonable value + * for a serial line. Bigger values might clog the I/O. + */ + if ((r = write(cmdfd, s, (n < lim)? n : lim)) < 0) + goto write_error; + if (r < n) { + /* + * We weren't able to write out everything. + * This means the buffer is getting full + * again. Empty it. + */ + if (n < lim) + lim = ttyread(); + n -= r; + s += r; + } else { + /* All bytes have been written. */ + break; + } + } + if (FD_ISSET(cmdfd, &rfd)) + lim = ttyread(); + } + return; + +write_error: + die("write error on tty: %s\n", strerror(errno)); +} + +void +ttyresize(int tw, int th) +{ + struct winsize w; + + w.ws_row = term.row; + w.ws_col = term.col; + w.ws_xpixel = tw; + w.ws_ypixel = th; + if (ioctl(cmdfd, TIOCSWINSZ, &w) < 0) + fprintf(stderr, "Couldn't set window size: %s\n", strerror(errno)); +} + +void +ttyhangup(void) +{ + /* Send SIGHUP to shell */ + kill(pid, SIGHUP); +} + +int +tattrset(int attr) +{ + int i, j; + + for (i = 0; i < term.row-1; i++) { + for (j = 0; j < term.col-1; j++) { + if (term.line[i][j].mode & attr) + return 1; + } + } + + return 0; +} + +void +tsetdirt(int top, int bot) +{ + int i; + + LIMIT(top, 0, term.row-1); + LIMIT(bot, 0, term.row-1); + + for (i = top; i <= bot; i++) + term.dirty[i] = 1; +} + +void +tsetdirtattr(int attr) +{ + int i, j; + + for (i = 0; i < term.row-1; i++) { + for (j = 0; j < term.col-1; j++) { + if (term.line[i][j].mode & attr) { + tsetdirt(i, i); + break; + } + } + } +} + +void +tfulldirt(void) +{ + tsetdirt(0, term.row-1); +} + +void +tcursor(int mode) +{ + static TCursor c[2]; + int alt = IS_SET(MODE_ALTSCREEN); + + if (mode == CURSOR_SAVE) { + c[alt] = term.c; + } else if (mode == CURSOR_LOAD) { + term.c = c[alt]; + tmoveto(c[alt].x, c[alt].y); + } +} + +void +treset(void) +{ + uint i; + + term.c = (TCursor){{ + .mode = ATTR_NULL, + .fg = defaultfg, + .bg = defaultbg + }, .x = 0, .y = 0, .state = CURSOR_DEFAULT}; + + memset(term.tabs, 0, term.col * sizeof(*term.tabs)); + for (i = tabspaces; i < term.col; i += tabspaces) + term.tabs[i] = 1; + term.top = 0; + term.bot = term.row - 1; + term.mode = MODE_WRAP|MODE_UTF8; + memset(term.trantbl, CS_USA, sizeof(term.trantbl)); + term.charset = 0; + + for (i = 0; i < 2; i++) { + tmoveto(0, 0); + tcursor(CURSOR_SAVE); + tclearregion(0, 0, term.col-1, term.row-1); + tswapscreen(); + } +} + +void +tnew(int col, int row) +{ + term = (Term){ .c = { .attr = { .fg = defaultfg, .bg = defaultbg } } }; + tresize(col, row); + treset(); +} + +void +tswapscreen(void) +{ + Line *tmp = term.line; + + term.line = term.alt; + term.alt = tmp; + term.mode ^= MODE_ALTSCREEN; + tfulldirt(); +} + +void +tscrolldown(int orig, int n) +{ + int i; + Line temp; + + LIMIT(n, 0, term.bot-orig+1); + + tsetdirt(orig, term.bot-n); + tclearregion(0, term.bot-n+1, term.col-1, term.bot); + + for (i = term.bot; i >= orig+n; i--) { + temp = term.line[i]; + term.line[i] = term.line[i-n]; + term.line[i-n] = temp; + } + + selscroll(orig, n); +} + +void +tscrollup(int orig, int n) +{ + int i; + Line temp; + + LIMIT(n, 0, term.bot-orig+1); + + tclearregion(0, orig, term.col-1, orig+n-1); + tsetdirt(orig+n, term.bot); + + for (i = orig; i <= term.bot-n; i++) { + temp = term.line[i]; + term.line[i] = term.line[i+n]; + term.line[i+n] = temp; + } + + selscroll(orig, -n); +} + +void +selscroll(int orig, int n) +{ + if (sel.ob.x == -1 || sel.alt != IS_SET(MODE_ALTSCREEN)) + return; + + if (BETWEEN(sel.nb.y, orig, term.bot) != BETWEEN(sel.ne.y, orig, term.bot)) { + selclear(); + } else if (BETWEEN(sel.nb.y, orig, term.bot)) { + sel.ob.y += n; + sel.oe.y += n; + if (sel.ob.y < term.top || sel.ob.y > term.bot || + sel.oe.y < term.top || sel.oe.y > term.bot) { + selclear(); + } else { + selnormalize(); + } + } +} + +void +tnewline(int first_col) +{ + int y = term.c.y; + + if (y == term.bot) { + tscrollup(term.top, 1); + } else { + y++; + } + tmoveto(first_col ? 0 : term.c.x, y); +} + +void +csiparse(void) +{ + char *p = csiescseq.buf, *np; + long int v; + + csiescseq.narg = 0; + if (*p == '?') { + csiescseq.priv = 1; + p++; + } + + csiescseq.buf[csiescseq.len] = '\0'; + while (p < csiescseq.buf+csiescseq.len) { + np = NULL; + v = strtol(p, &np, 10); + if (np == p) + v = 0; + if (v == LONG_MAX || v == LONG_MIN) + v = -1; + csiescseq.arg[csiescseq.narg++] = v; + p = np; + if (*p != ';' || csiescseq.narg == ESC_ARG_SIZ) + break; + p++; + } + csiescseq.mode[0] = *p++; + csiescseq.mode[1] = (p < csiescseq.buf+csiescseq.len) ? *p : '\0'; +} + +/* for absolute user moves, when decom is set */ +void +tmoveato(int x, int y) +{ + tmoveto(x, y + ((term.c.state & CURSOR_ORIGIN) ? term.top: 0)); +} + +void +tmoveto(int x, int y) +{ + int miny, maxy; + + if (term.c.state & CURSOR_ORIGIN) { + miny = term.top; + maxy = term.bot; + } else { + miny = 0; + maxy = term.row - 1; + } + term.c.state &= ~CURSOR_WRAPNEXT; + term.c.x = LIMIT(x, 0, term.col-1); + term.c.y = LIMIT(y, miny, maxy); +} + +void +tsetchar(Rune u, const Glyph *attr, int x, int y) +{ + static const char *vt100_0[62] = { /* 0x41 - 0x7e */ + "↑", "↓", "→", "←", "█", "▚", "☃", /* A - G */ + 0, 0, 0, 0, 0, 0, 0, 0, /* H - O */ + 0, 0, 0, 0, 0, 0, 0, 0, /* P - W */ + 0, 0, 0, 0, 0, 0, 0, " ", /* X - _ */ + "◆", "▒", "␉", "␌", "␍", "␊", "°", "±", /* ` - g */ + "␤", "␋", "┘", "┐", "┌", "└", "┼", "⎺", /* h - o */ + "⎻", "─", "⎼", "⎽", "├", "┤", "┴", "┬", /* p - w */ + "│", "≤", "≥", "π", "≠", "£", "·", /* x - ~ */ + }; + + /* + * The table is proudly stolen from rxvt. + */ + if (term.trantbl[term.charset] == CS_GRAPHIC0 && + BETWEEN(u, 0x41, 0x7e) && vt100_0[u - 0x41]) + utf8decode(vt100_0[u - 0x41], &u, UTF_SIZ); + + if (term.line[y][x].mode & ATTR_WIDE) { + if (x+1 < term.col) { + term.line[y][x+1].u = ' '; + term.line[y][x+1].mode &= ~ATTR_WDUMMY; + } + } else if (term.line[y][x].mode & ATTR_WDUMMY) { + term.line[y][x-1].u = ' '; + term.line[y][x-1].mode &= ~ATTR_WIDE; + } + + term.dirty[y] = 1; + term.line[y][x] = *attr; + term.line[y][x].u = u; +} + +void +tclearregion(int x1, int y1, int x2, int y2) +{ + int x, y, temp; + Glyph *gp; + + if (x1 > x2) + temp = x1, x1 = x2, x2 = temp; + if (y1 > y2) + temp = y1, y1 = y2, y2 = temp; + + LIMIT(x1, 0, term.col-1); + LIMIT(x2, 0, term.col-1); + LIMIT(y1, 0, term.row-1); + LIMIT(y2, 0, term.row-1); + + for (y = y1; y <= y2; y++) { + term.dirty[y] = 1; + for (x = x1; x <= x2; x++) { + gp = &term.line[y][x]; + if (selected(x, y)) + selclear(); + gp->fg = term.c.attr.fg; + gp->bg = term.c.attr.bg; + gp->mode = 0; + gp->u = ' '; + } + } +} + +void +tdeletechar(int n) +{ + int dst, src, size; + Glyph *line; + + LIMIT(n, 0, term.col - term.c.x); + + dst = term.c.x; + src = term.c.x + n; + size = term.col - src; + line = term.line[term.c.y]; + + memmove(&line[dst], &line[src], size * sizeof(Glyph)); + tclearregion(term.col-n, term.c.y, term.col-1, term.c.y); +} + +void +tinsertblank(int n) +{ + int dst, src, size; + Glyph *line; + + LIMIT(n, 0, term.col - term.c.x); + + dst = term.c.x + n; + src = term.c.x; + size = term.col - dst; + line = term.line[term.c.y]; + + memmove(&line[dst], &line[src], size * sizeof(Glyph)); + tclearregion(src, term.c.y, dst - 1, term.c.y); +} + +void +tinsertblankline(int n) +{ + if (BETWEEN(term.c.y, term.top, term.bot)) + tscrolldown(term.c.y, n); +} + +void +tdeleteline(int n) +{ + if (BETWEEN(term.c.y, term.top, term.bot)) + tscrollup(term.c.y, n); +} + +int32_t +tdefcolor(const int *attr, int *npar, int l) +{ + int32_t idx = -1; + uint r, g, b; + + switch (attr[*npar + 1]) { + case 2: /* direct color in RGB space */ + if (*npar + 4 >= l) { + fprintf(stderr, + "erresc(38): Incorrect number of parameters (%d)\n", + *npar); + break; + } + r = attr[*npar + 2]; + g = attr[*npar + 3]; + b = attr[*npar + 4]; + *npar += 4; + if (!BETWEEN(r, 0, 255) || !BETWEEN(g, 0, 255) || !BETWEEN(b, 0, 255)) + fprintf(stderr, "erresc: bad rgb color (%u,%u,%u)\n", + r, g, b); + else + idx = TRUECOLOR(r, g, b); + break; + case 5: /* indexed color */ + if (*npar + 2 >= l) { + fprintf(stderr, + "erresc(38): Incorrect number of parameters (%d)\n", + *npar); + break; + } + *npar += 2; + if (!BETWEEN(attr[*npar], 0, 255)) + fprintf(stderr, "erresc: bad fgcolor %d\n", attr[*npar]); + else + idx = attr[*npar]; + break; + case 0: /* implemented defined (only foreground) */ + case 1: /* transparent */ + case 3: /* direct color in CMY space */ + case 4: /* direct color in CMYK space */ + default: + fprintf(stderr, + "erresc(38): gfx attr %d unknown\n", attr[*npar]); + break; + } + + return idx; +} + +void +tsetattr(const int *attr, int l) +{ + int i; + int32_t idx; + + for (i = 0; i < l; i++) { + switch (attr[i]) { + case 0: + term.c.attr.mode &= ~( + ATTR_BOLD | + ATTR_FAINT | + ATTR_ITALIC | + ATTR_UNDERLINE | + ATTR_BLINK | + ATTR_REVERSE | + ATTR_INVISIBLE | + ATTR_STRUCK ); + term.c.attr.fg = defaultfg; + term.c.attr.bg = defaultbg; + break; + case 1: + term.c.attr.mode |= ATTR_BOLD; + break; + case 2: + term.c.attr.mode |= ATTR_FAINT; + break; + case 3: + term.c.attr.mode |= ATTR_ITALIC; + break; + case 4: + term.c.attr.mode |= ATTR_UNDERLINE; + break; + case 5: /* slow blink */ + /* FALLTHROUGH */ + case 6: /* rapid blink */ + term.c.attr.mode |= ATTR_BLINK; + break; + case 7: + term.c.attr.mode |= ATTR_REVERSE; + break; + case 8: + term.c.attr.mode |= ATTR_INVISIBLE; + break; + case 9: + term.c.attr.mode |= ATTR_STRUCK; + break; + case 22: + term.c.attr.mode &= ~(ATTR_BOLD | ATTR_FAINT); + break; + case 23: + term.c.attr.mode &= ~ATTR_ITALIC; + break; + case 24: + term.c.attr.mode &= ~ATTR_UNDERLINE; + break; + case 25: + term.c.attr.mode &= ~ATTR_BLINK; + break; + case 27: + term.c.attr.mode &= ~ATTR_REVERSE; + break; + case 28: + term.c.attr.mode &= ~ATTR_INVISIBLE; + break; + case 29: + term.c.attr.mode &= ~ATTR_STRUCK; + break; + case 38: + if ((idx = tdefcolor(attr, &i, l)) >= 0) + term.c.attr.fg = idx; + break; + case 39: + term.c.attr.fg = defaultfg; + break; + case 48: + if ((idx = tdefcolor(attr, &i, l)) >= 0) + term.c.attr.bg = idx; + break; + case 49: + term.c.attr.bg = defaultbg; + break; + default: + if (BETWEEN(attr[i], 30, 37)) { + term.c.attr.fg = attr[i] - 30; + } else if (BETWEEN(attr[i], 40, 47)) { + term.c.attr.bg = attr[i] - 40; + } else if (BETWEEN(attr[i], 90, 97)) { + term.c.attr.fg = attr[i] - 90 + 8; + } else if (BETWEEN(attr[i], 100, 107)) { + term.c.attr.bg = attr[i] - 100 + 8; + } else { + fprintf(stderr, + "erresc(default): gfx attr %d unknown\n", + attr[i]); + csidump(); + } + break; + } + } +} + +void +tsetscroll(int t, int b) +{ + int temp; + + LIMIT(t, 0, term.row-1); + LIMIT(b, 0, term.row-1); + if (t > b) { + temp = t; + t = b; + b = temp; + } + term.top = t; + term.bot = b; +} + +void +tsetmode(int priv, int set, const int *args, int narg) +{ + int alt; const int *lim; + + for (lim = args + narg; args < lim; ++args) { + if (priv) { + switch (*args) { + case 1: /* DECCKM -- Cursor key */ + xsetmode(set, MODE_APPCURSOR); + break; + case 5: /* DECSCNM -- Reverse video */ + xsetmode(set, MODE_REVERSE); + break; + case 6: /* DECOM -- Origin */ + MODBIT(term.c.state, set, CURSOR_ORIGIN); + tmoveato(0, 0); + break; + case 7: /* DECAWM -- Auto wrap */ + MODBIT(term.mode, set, MODE_WRAP); + break; + case 0: /* Error (IGNORED) */ + case 2: /* DECANM -- ANSI/VT52 (IGNORED) */ + case 3: /* DECCOLM -- Column (IGNORED) */ + case 4: /* DECSCLM -- Scroll (IGNORED) */ + case 8: /* DECARM -- Auto repeat (IGNORED) */ + case 18: /* DECPFF -- Printer feed (IGNORED) */ + case 19: /* DECPEX -- Printer extent (IGNORED) */ + case 42: /* DECNRCM -- National characters (IGNORED) */ + case 12: /* att610 -- Start blinking cursor (IGNORED) */ + break; + case 25: /* DECTCEM -- Text Cursor Enable Mode */ + xsetmode(!set, MODE_HIDE); + break; + case 9: /* X10 mouse compatibility mode */ + xsetpointermotion(0); + xsetmode(0, MODE_MOUSE); + xsetmode(set, MODE_MOUSEX10); + break; + case 1000: /* 1000: report button press */ + xsetpointermotion(0); + xsetmode(0, MODE_MOUSE); + xsetmode(set, MODE_MOUSEBTN); + break; + case 1002: /* 1002: report motion on button press */ + xsetpointermotion(0); + xsetmode(0, MODE_MOUSE); + xsetmode(set, MODE_MOUSEMOTION); + break; + case 1003: /* 1003: enable all mouse motions */ + xsetpointermotion(set); + xsetmode(0, MODE_MOUSE); + xsetmode(set, MODE_MOUSEMANY); + break; + case 1004: /* 1004: send focus events to tty */ + xsetmode(set, MODE_FOCUS); + break; + case 1006: /* 1006: extended reporting mode */ + xsetmode(set, MODE_MOUSESGR); + break; + case 1034: + xsetmode(set, MODE_8BIT); + break; + case 1049: /* swap screen & set/restore cursor as xterm */ + if (!allowaltscreen) + break; + tcursor((set) ? CURSOR_SAVE : CURSOR_LOAD); + /* FALLTHROUGH */ + case 47: /* swap screen */ + case 1047: + if (!allowaltscreen) + break; + alt = IS_SET(MODE_ALTSCREEN); + if (alt) { + tclearregion(0, 0, term.col-1, + term.row-1); + } + if (set ^ alt) /* set is always 1 or 0 */ + tswapscreen(); + if (*args != 1049) + break; + /* FALLTHROUGH */ + case 1048: + tcursor((set) ? CURSOR_SAVE : CURSOR_LOAD); + break; + case 2004: /* 2004: bracketed paste mode */ + xsetmode(set, MODE_BRCKTPASTE); + break; + /* Not implemented mouse modes. See comments there. */ + case 1001: /* mouse highlight mode; can hang the + terminal by design when implemented. */ + case 1005: /* UTF-8 mouse mode; will confuse + applications not supporting UTF-8 + and luit. */ + case 1015: /* urxvt mangled mouse mode; incompatible + and can be mistaken for other control + codes. */ + break; + default: + fprintf(stderr, + "erresc: unknown private set/reset mode %d\n", + *args); + break; + } + } else { + switch (*args) { + case 0: /* Error (IGNORED) */ + break; + case 2: + xsetmode(set, MODE_KBDLOCK); + break; + case 4: /* IRM -- Insertion-replacement */ + MODBIT(term.mode, set, MODE_INSERT); + break; + case 12: /* SRM -- Send/Receive */ + MODBIT(term.mode, !set, MODE_ECHO); + break; + case 20: /* LNM -- Linefeed/new line */ + MODBIT(term.mode, set, MODE_CRLF); + break; + default: + fprintf(stderr, + "erresc: unknown set/reset mode %d\n", + *args); + break; + } + } + } +} + +void +csihandle(void) +{ + char buf[40]; + int len; + + switch (csiescseq.mode[0]) { + default: + unknown: + fprintf(stderr, "erresc: unknown csi "); + csidump(); + /* die(""); */ + break; + case '@': /* ICH -- Insert blank char */ + DEFAULT(csiescseq.arg[0], 1); + tinsertblank(csiescseq.arg[0]); + break; + case 'A': /* CUU -- Cursor Up */ + DEFAULT(csiescseq.arg[0], 1); + tmoveto(term.c.x, term.c.y-csiescseq.arg[0]); + break; + case 'B': /* CUD -- Cursor Down */ + case 'e': /* VPR --Cursor Down */ + DEFAULT(csiescseq.arg[0], 1); + tmoveto(term.c.x, term.c.y+csiescseq.arg[0]); + break; + case 'i': /* MC -- Media Copy */ + switch (csiescseq.arg[0]) { + case 0: + tdump(); + break; + case 1: + tdumpline(term.c.y); + break; + case 2: + tdumpsel(); + break; + case 4: + term.mode &= ~MODE_PRINT; + break; + case 5: + term.mode |= MODE_PRINT; + break; + } + break; + case 'c': /* DA -- Device Attributes */ + if (csiescseq.arg[0] == 0) + ttywrite(vtiden, strlen(vtiden), 0); + break; + case 'b': /* REP -- if last char is printable print it more times */ + LIMIT(csiescseq.arg[0], 1, 65535); + if (term.lastc) + while (csiescseq.arg[0]-- > 0) + tputc(term.lastc); + break; + case 'C': /* CUF -- Cursor Forward */ + case 'a': /* HPR -- Cursor Forward */ + DEFAULT(csiescseq.arg[0], 1); + tmoveto(term.c.x+csiescseq.arg[0], term.c.y); + break; + case 'D': /* CUB -- Cursor Backward */ + DEFAULT(csiescseq.arg[0], 1); + tmoveto(term.c.x-csiescseq.arg[0], term.c.y); + break; + case 'E': /* CNL -- Cursor Down and first col */ + DEFAULT(csiescseq.arg[0], 1); + tmoveto(0, term.c.y+csiescseq.arg[0]); + break; + case 'F': /* CPL -- Cursor Up and first col */ + DEFAULT(csiescseq.arg[0], 1); + tmoveto(0, term.c.y-csiescseq.arg[0]); + break; + case 'g': /* TBC -- Tabulation clear */ + switch (csiescseq.arg[0]) { + case 0: /* clear current tab stop */ + term.tabs[term.c.x] = 0; + break; + case 3: /* clear all the tabs */ + memset(term.tabs, 0, term.col * sizeof(*term.tabs)); + break; + default: + goto unknown; + } + break; + case 'G': /* CHA -- Move to */ + case '`': /* HPA */ + DEFAULT(csiescseq.arg[0], 1); + tmoveto(csiescseq.arg[0]-1, term.c.y); + break; + case 'H': /* CUP -- Move to */ + case 'f': /* HVP */ + DEFAULT(csiescseq.arg[0], 1); + DEFAULT(csiescseq.arg[1], 1); + tmoveato(csiescseq.arg[1]-1, csiescseq.arg[0]-1); + break; + case 'I': /* CHT -- Cursor Forward Tabulation tab stops */ + DEFAULT(csiescseq.arg[0], 1); + tputtab(csiescseq.arg[0]); + break; + case 'J': /* ED -- Clear screen */ + switch (csiescseq.arg[0]) { + case 0: /* below */ + tclearregion(term.c.x, term.c.y, term.col-1, term.c.y); + if (term.c.y < term.row-1) { + tclearregion(0, term.c.y+1, term.col-1, + term.row-1); + } + break; + case 1: /* above */ + if (term.c.y > 1) + tclearregion(0, 0, term.col-1, term.c.y-1); + tclearregion(0, term.c.y, term.c.x, term.c.y); + break; + case 2: /* all */ + tclearregion(0, 0, term.col-1, term.row-1); + break; + default: + goto unknown; + } + break; + case 'K': /* EL -- Clear line */ + switch (csiescseq.arg[0]) { + case 0: /* right */ + tclearregion(term.c.x, term.c.y, term.col-1, + term.c.y); + break; + case 1: /* left */ + tclearregion(0, term.c.y, term.c.x, term.c.y); + break; + case 2: /* all */ + tclearregion(0, term.c.y, term.col-1, term.c.y); + break; + } + break; + case 'S': /* SU -- Scroll line up */ + if (csiescseq.priv) break; + DEFAULT(csiescseq.arg[0], 1); + tscrollup(term.top, csiescseq.arg[0]); + break; + case 'T': /* SD -- Scroll line down */ + DEFAULT(csiescseq.arg[0], 1); + tscrolldown(term.top, csiescseq.arg[0]); + break; + case 'L': /* IL -- Insert blank lines */ + DEFAULT(csiescseq.arg[0], 1); + tinsertblankline(csiescseq.arg[0]); + break; + case 'l': /* RM -- Reset Mode */ + tsetmode(csiescseq.priv, 0, csiescseq.arg, csiescseq.narg); + break; + case 'M': /* DL -- Delete lines */ + DEFAULT(csiescseq.arg[0], 1); + tdeleteline(csiescseq.arg[0]); + break; + case 'X': /* ECH -- Erase char */ + DEFAULT(csiescseq.arg[0], 1); + tclearregion(term.c.x, term.c.y, + term.c.x + csiescseq.arg[0] - 1, term.c.y); + break; + case 'P': /* DCH -- Delete char */ + DEFAULT(csiescseq.arg[0], 1); + tdeletechar(csiescseq.arg[0]); + break; + case 'Z': /* CBT -- Cursor Backward Tabulation tab stops */ + DEFAULT(csiescseq.arg[0], 1); + tputtab(-csiescseq.arg[0]); + break; + case 'd': /* VPA -- Move to */ + DEFAULT(csiescseq.arg[0], 1); + tmoveato(term.c.x, csiescseq.arg[0]-1); + break; + case 'h': /* SM -- Set terminal mode */ + tsetmode(csiescseq.priv, 1, csiescseq.arg, csiescseq.narg); + break; + case 'm': /* SGR -- Terminal attribute (color) */ + tsetattr(csiescseq.arg, csiescseq.narg); + break; + case 'n': /* DSR -- Device Status Report */ + switch (csiescseq.arg[0]) { + case 5: /* Status Report "OK" `0n` */ + ttywrite("\033[0n", sizeof("\033[0n") - 1, 0); + break; + case 6: /* Report Cursor Position (CPR) ";R" */ + len = snprintf(buf, sizeof(buf), "\033[%i;%iR", + term.c.y+1, term.c.x+1); + ttywrite(buf, len, 0); + break; + default: + goto unknown; + } + break; + case 'r': /* DECSTBM -- Set Scrolling Region */ + if (csiescseq.priv) { + goto unknown; + } else { + DEFAULT(csiescseq.arg[0], 1); + DEFAULT(csiescseq.arg[1], term.row); + tsetscroll(csiescseq.arg[0]-1, csiescseq.arg[1]-1); + tmoveato(0, 0); + } + break; + case 's': /* DECSC -- Save cursor position (ANSI.SYS) */ + tcursor(CURSOR_SAVE); + break; + case 'u': /* DECRC -- Restore cursor position (ANSI.SYS) */ + tcursor(CURSOR_LOAD); + break; + case ' ': + switch (csiescseq.mode[1]) { + case 'q': /* DECSCUSR -- Set Cursor Style */ + if (xsetcursor(csiescseq.arg[0])) + goto unknown; + break; + default: + goto unknown; + } + break; + } +} + +void +csidump(void) +{ + size_t i; + uint c; + + fprintf(stderr, "ESC["); + for (i = 0; i < csiescseq.len; i++) { + c = csiescseq.buf[i] & 0xff; + if (isprint(c)) { + putc(c, stderr); + } else if (c == '\n') { + fprintf(stderr, "(\\n)"); + } else if (c == '\r') { + fprintf(stderr, "(\\r)"); + } else if (c == 0x1b) { + fprintf(stderr, "(\\e)"); + } else { + fprintf(stderr, "(%02x)", c); + } + } + putc('\n', stderr); +} + +void +csireset(void) +{ + memset(&csiescseq, 0, sizeof(csiescseq)); +} + +void +osc_color_response(int num, int index, int is_osc4) +{ + int n; + char buf[32]; + unsigned char r, g, b; + + if (xgetcolor(is_osc4 ? num : index, &r, &g, &b)) { + fprintf(stderr, "erresc: failed to fetch %s color %d\n", + is_osc4 ? "osc4" : "osc", + is_osc4 ? num : index); + return; + } + + n = snprintf(buf, sizeof buf, "\033]%s%d;rgb:%02x%02x/%02x%02x/%02x%02x\007", + is_osc4 ? "4;" : "", num, r, r, g, g, b, b); + if (n < 0 || n >= sizeof(buf)) { + fprintf(stderr, "error: %s while printing %s response\n", + n < 0 ? "snprintf failed" : "truncation occurred", + is_osc4 ? "osc4" : "osc"); + } else { + ttywrite(buf, n, 1); + } +} + +void +strhandle(void) +{ + char *p = NULL, *dec; + int j, narg, par; + const struct { int idx; char *str; } osc_table[] = { + { defaultfg, "foreground" }, + { defaultbg, "background" }, + { defaultcs, "cursor" } + }; + + term.esc &= ~(ESC_STR_END|ESC_STR); + strparse(); + par = (narg = strescseq.narg) ? atoi(strescseq.args[0]) : 0; + + switch (strescseq.type) { + case ']': /* OSC -- Operating System Command */ + switch (par) { + case 0: + if (narg > 1) { + xsettitle(strescseq.args[1]); + xseticontitle(strescseq.args[1]); + } + return; + case 1: + if (narg > 1) + xseticontitle(strescseq.args[1]); + return; + case 2: + if (narg > 1) + xsettitle(strescseq.args[1]); + return; + case 52: + if (narg > 2 && allowwindowops) { + dec = base64dec(strescseq.args[2]); + if (dec) { + xsetsel(dec); + xclipcopy(); + } else { + fprintf(stderr, "erresc: invalid base64\n"); + } + } + return; + case 10: + case 11: + case 12: + if (narg < 2) + break; + p = strescseq.args[1]; + if ((j = par - 10) < 0 || j >= LEN(osc_table)) + break; /* shouldn't be possible */ + + if (!strcmp(p, "?")) { + osc_color_response(par, osc_table[j].idx, 0); + } else if (xsetcolorname(osc_table[j].idx, p)) { + fprintf(stderr, "erresc: invalid %s color: %s\n", + osc_table[j].str, p); + } else { + tfulldirt(); + } + return; + case 4: /* color set */ + if (narg < 3) + break; + p = strescseq.args[2]; + /* FALLTHROUGH */ + case 104: /* color reset */ + j = (narg > 1) ? atoi(strescseq.args[1]) : -1; + + if (p && !strcmp(p, "?")) { + osc_color_response(j, 0, 1); + } else if (xsetcolorname(j, p)) { + if (par == 104 && narg <= 1) { + xloadcols(); + return; /* color reset without parameter */ + } + fprintf(stderr, "erresc: invalid color j=%d, p=%s\n", + j, p ? p : "(null)"); + } else { + /* + * TODO if defaultbg color is changed, borders + * are dirty + */ + tfulldirt(); + } + return; + } + break; + case 'k': /* old title set compatibility */ + xsettitle(strescseq.args[0]); + return; + case 'P': /* DCS -- Device Control String */ + case '_': /* APC -- Application Program Command */ + case '^': /* PM -- Privacy Message */ + return; + } + + fprintf(stderr, "erresc: unknown str "); + strdump(); +} + +void +strparse(void) +{ + int c; + char *p = strescseq.buf; + + strescseq.narg = 0; + strescseq.buf[strescseq.len] = '\0'; + + if (*p == '\0') + return; + + while (strescseq.narg < STR_ARG_SIZ) { + strescseq.args[strescseq.narg++] = p; + while ((c = *p) != ';' && c != '\0') + ++p; + if (c == '\0') + return; + *p++ = '\0'; + } +} + +void +strdump(void) +{ + size_t i; + uint c; + + fprintf(stderr, "ESC%c", strescseq.type); + for (i = 0; i < strescseq.len; i++) { + c = strescseq.buf[i] & 0xff; + if (c == '\0') { + putc('\n', stderr); + return; + } else if (isprint(c)) { + putc(c, stderr); + } else if (c == '\n') { + fprintf(stderr, "(\\n)"); + } else if (c == '\r') { + fprintf(stderr, "(\\r)"); + } else if (c == 0x1b) { + fprintf(stderr, "(\\e)"); + } else { + fprintf(stderr, "(%02x)", c); + } + } + fprintf(stderr, "ESC\\\n"); +} + +void +strreset(void) +{ + strescseq = (STREscape){ + .buf = xrealloc(strescseq.buf, STR_BUF_SIZ), + .siz = STR_BUF_SIZ, + }; +} + +void +sendbreak(const Arg *arg) +{ + if (tcsendbreak(cmdfd, 0)) + perror("Error sending break"); +} + +void +tprinter(char *s, size_t len) +{ + if (iofd != -1 && xwrite(iofd, s, len) < 0) { + perror("Error writing to output file"); + close(iofd); + iofd = -1; + } +} + +void +toggleprinter(const Arg *arg) +{ + term.mode ^= MODE_PRINT; +} + +void +printscreen(const Arg *arg) +{ + tdump(); +} + +void +printsel(const Arg *arg) +{ + tdumpsel(); +} + +void +tdumpsel(void) +{ + char *ptr; + + if ((ptr = getsel())) { + tprinter(ptr, strlen(ptr)); + free(ptr); + } +} + +void +tdumpline(int n) +{ + char buf[UTF_SIZ]; + const Glyph *bp, *end; + + bp = &term.line[n][0]; + end = &bp[MIN(tlinelen(n), term.col) - 1]; + if (bp != end || bp->u != ' ') { + for ( ; bp <= end; ++bp) + tprinter(buf, utf8encode(bp->u, buf)); + } + tprinter("\n", 1); +} + +void +tdump(void) +{ + int i; + + for (i = 0; i < term.row; ++i) + tdumpline(i); +} + +void +tputtab(int n) +{ + uint x = term.c.x; + + if (n > 0) { + while (x < term.col && n--) + for (++x; x < term.col && !term.tabs[x]; ++x) + /* nothing */ ; + } else if (n < 0) { + while (x > 0 && n++) + for (--x; x > 0 && !term.tabs[x]; --x) + /* nothing */ ; + } + term.c.x = LIMIT(x, 0, term.col-1); +} + +void +tdefutf8(char ascii) +{ + if (ascii == 'G') + term.mode |= MODE_UTF8; + else if (ascii == '@') + term.mode &= ~MODE_UTF8; +} + +void +tdeftran(char ascii) +{ + static char cs[] = "0B"; + static int vcs[] = {CS_GRAPHIC0, CS_USA}; + char *p; + + if ((p = strchr(cs, ascii)) == NULL) { + fprintf(stderr, "esc unhandled charset: ESC ( %c\n", ascii); + } else { + term.trantbl[term.icharset] = vcs[p - cs]; + } +} + +void +tdectest(char c) +{ + int x, y; + + if (c == '8') { /* DEC screen alignment test. */ + for (x = 0; x < term.col; ++x) { + for (y = 0; y < term.row; ++y) + tsetchar('E', &term.c.attr, x, y); + } + } +} + +void +tstrsequence(uchar c) +{ + switch (c) { + case 0x90: /* DCS -- Device Control String */ + c = 'P'; + break; + case 0x9f: /* APC -- Application Program Command */ + c = '_'; + break; + case 0x9e: /* PM -- Privacy Message */ + c = '^'; + break; + case 0x9d: /* OSC -- Operating System Command */ + c = ']'; + break; + } + strreset(); + strescseq.type = c; + term.esc |= ESC_STR; +} + +void +tcontrolcode(uchar ascii) +{ + switch (ascii) { + case '\t': /* HT */ + tputtab(1); + return; + case '\b': /* BS */ + tmoveto(term.c.x-1, term.c.y); + return; + case '\r': /* CR */ + tmoveto(0, term.c.y); + return; + case '\f': /* LF */ + case '\v': /* VT */ + case '\n': /* LF */ + /* go to first col if the mode is set */ + tnewline(IS_SET(MODE_CRLF)); + return; + case '\a': /* BEL */ + if (term.esc & ESC_STR_END) { + /* backwards compatibility to xterm */ + strhandle(); + } else { + xbell(); + } + break; + case '\033': /* ESC */ + csireset(); + term.esc &= ~(ESC_CSI|ESC_ALTCHARSET|ESC_TEST); + term.esc |= ESC_START; + return; + case '\016': /* SO (LS1 -- Locking shift 1) */ + case '\017': /* SI (LS0 -- Locking shift 0) */ + term.charset = 1 - (ascii - '\016'); + return; + case '\032': /* SUB */ + tsetchar('?', &term.c.attr, term.c.x, term.c.y); + /* FALLTHROUGH */ + case '\030': /* CAN */ + csireset(); + break; + case '\005': /* ENQ (IGNORED) */ + case '\000': /* NUL (IGNORED) */ + case '\021': /* XON (IGNORED) */ + case '\023': /* XOFF (IGNORED) */ + case 0177: /* DEL (IGNORED) */ + return; + case 0x80: /* TODO: PAD */ + case 0x81: /* TODO: HOP */ + case 0x82: /* TODO: BPH */ + case 0x83: /* TODO: NBH */ + case 0x84: /* TODO: IND */ + break; + case 0x85: /* NEL -- Next line */ + tnewline(1); /* always go to first col */ + break; + case 0x86: /* TODO: SSA */ + case 0x87: /* TODO: ESA */ + break; + case 0x88: /* HTS -- Horizontal tab stop */ + term.tabs[term.c.x] = 1; + break; + case 0x89: /* TODO: HTJ */ + case 0x8a: /* TODO: VTS */ + case 0x8b: /* TODO: PLD */ + case 0x8c: /* TODO: PLU */ + case 0x8d: /* TODO: RI */ + case 0x8e: /* TODO: SS2 */ + case 0x8f: /* TODO: SS3 */ + case 0x91: /* TODO: PU1 */ + case 0x92: /* TODO: PU2 */ + case 0x93: /* TODO: STS */ + case 0x94: /* TODO: CCH */ + case 0x95: /* TODO: MW */ + case 0x96: /* TODO: SPA */ + case 0x97: /* TODO: EPA */ + case 0x98: /* TODO: SOS */ + case 0x99: /* TODO: SGCI */ + break; + case 0x9a: /* DECID -- Identify Terminal */ + ttywrite(vtiden, strlen(vtiden), 0); + break; + case 0x9b: /* TODO: CSI */ + case 0x9c: /* TODO: ST */ + break; + case 0x90: /* DCS -- Device Control String */ + case 0x9d: /* OSC -- Operating System Command */ + case 0x9e: /* PM -- Privacy Message */ + case 0x9f: /* APC -- Application Program Command */ + tstrsequence(ascii); + return; + } + /* only CAN, SUB, \a and C1 chars interrupt a sequence */ + term.esc &= ~(ESC_STR_END|ESC_STR); +} + +/* + * returns 1 when the sequence is finished and it hasn't to read + * more characters for this sequence, otherwise 0 + */ +int +eschandle(uchar ascii) +{ + switch (ascii) { + case '[': + term.esc |= ESC_CSI; + return 0; + case '#': + term.esc |= ESC_TEST; + return 0; + case '%': + term.esc |= ESC_UTF8; + return 0; + case 'P': /* DCS -- Device Control String */ + case '_': /* APC -- Application Program Command */ + case '^': /* PM -- Privacy Message */ + case ']': /* OSC -- Operating System Command */ + case 'k': /* old title set compatibility */ + tstrsequence(ascii); + return 0; + case 'n': /* LS2 -- Locking shift 2 */ + case 'o': /* LS3 -- Locking shift 3 */ + term.charset = 2 + (ascii - 'n'); + break; + case '(': /* GZD4 -- set primary charset G0 */ + case ')': /* G1D4 -- set secondary charset G1 */ + case '*': /* G2D4 -- set tertiary charset G2 */ + case '+': /* G3D4 -- set quaternary charset G3 */ + term.icharset = ascii - '('; + term.esc |= ESC_ALTCHARSET; + return 0; + case 'D': /* IND -- Linefeed */ + if (term.c.y == term.bot) { + tscrollup(term.top, 1); + } else { + tmoveto(term.c.x, term.c.y+1); + } + break; + case 'E': /* NEL -- Next line */ + tnewline(1); /* always go to first col */ + break; + case 'H': /* HTS -- Horizontal tab stop */ + term.tabs[term.c.x] = 1; + break; + case 'M': /* RI -- Reverse index */ + if (term.c.y == term.top) { + tscrolldown(term.top, 1); + } else { + tmoveto(term.c.x, term.c.y-1); + } + break; + case 'Z': /* DECID -- Identify Terminal */ + ttywrite(vtiden, strlen(vtiden), 0); + break; + case 'c': /* RIS -- Reset to initial state */ + treset(); + resettitle(); + xloadcols(); + xsetmode(0, MODE_HIDE); + break; + case '=': /* DECPAM -- Application keypad */ + xsetmode(1, MODE_APPKEYPAD); + break; + case '>': /* DECPNM -- Normal keypad */ + xsetmode(0, MODE_APPKEYPAD); + break; + case '7': /* DECSC -- Save Cursor */ + tcursor(CURSOR_SAVE); + break; + case '8': /* DECRC -- Restore Cursor */ + tcursor(CURSOR_LOAD); + break; + case '\\': /* ST -- String Terminator */ + if (term.esc & ESC_STR_END) + strhandle(); + break; + default: + fprintf(stderr, "erresc: unknown sequence ESC 0x%02X '%c'\n", + (uchar) ascii, isprint(ascii)? ascii:'.'); + break; + } + return 1; +} + +void +tputc(Rune u) +{ + char c[UTF_SIZ]; + int control; + int width, len; + Glyph *gp; + + control = ISCONTROL(u); + if (u < 127 || !IS_SET(MODE_UTF8)) { + c[0] = u; + width = len = 1; + } else { + len = utf8encode(u, c); + if (!control && (width = wcwidth(u)) == -1) + width = 1; + } + + if (IS_SET(MODE_PRINT)) + tprinter(c, len); + + /* + * STR sequence must be checked before anything else + * because it uses all following characters until it + * receives a ESC, a SUB, a ST or any other C1 control + * character. + */ + if (term.esc & ESC_STR) { + if (u == '\a' || u == 030 || u == 032 || u == 033 || + ISCONTROLC1(u)) { + term.esc &= ~(ESC_START|ESC_STR); + term.esc |= ESC_STR_END; + goto check_control_code; + } + + if (strescseq.len+len >= strescseq.siz) { + /* + * Here is a bug in terminals. If the user never sends + * some code to stop the str or esc command, then st + * will stop responding. But this is better than + * silently failing with unknown characters. At least + * then users will report back. + * + * In the case users ever get fixed, here is the code: + */ + /* + * term.esc = 0; + * strhandle(); + */ + if (strescseq.siz > (SIZE_MAX - UTF_SIZ) / 2) + return; + strescseq.siz *= 2; + strescseq.buf = xrealloc(strescseq.buf, strescseq.siz); + } + + memmove(&strescseq.buf[strescseq.len], c, len); + strescseq.len += len; + return; + } + +check_control_code: + /* + * Actions of control codes must be performed as soon they arrive + * because they can be embedded inside a control sequence, and + * they must not cause conflicts with sequences. + */ + if (control) { + /* in UTF-8 mode ignore handling C1 control characters */ + if (IS_SET(MODE_UTF8) && ISCONTROLC1(u)) + return; + tcontrolcode(u); + /* + * control codes are not shown ever + */ + if (!term.esc) + term.lastc = 0; + return; + } else if (term.esc & ESC_START) { + if (term.esc & ESC_CSI) { + csiescseq.buf[csiescseq.len++] = u; + if (BETWEEN(u, 0x40, 0x7E) + || csiescseq.len >= \ + sizeof(csiescseq.buf)-1) { + term.esc = 0; + csiparse(); + csihandle(); + } + return; + } else if (term.esc & ESC_UTF8) { + tdefutf8(u); + } else if (term.esc & ESC_ALTCHARSET) { + tdeftran(u); + } else if (term.esc & ESC_TEST) { + tdectest(u); + } else { + if (!eschandle(u)) + return; + /* sequence already finished */ + } + term.esc = 0; + /* + * All characters which form part of a sequence are not + * printed + */ + return; + } + if (selected(term.c.x, term.c.y)) + selclear(); + + gp = &term.line[term.c.y][term.c.x]; + if (IS_SET(MODE_WRAP) && (term.c.state & CURSOR_WRAPNEXT)) { + gp->mode |= ATTR_WRAP; + tnewline(1); + gp = &term.line[term.c.y][term.c.x]; + } + + if (IS_SET(MODE_INSERT) && term.c.x+width < term.col) { + memmove(gp+width, gp, (term.col - term.c.x - width) * sizeof(Glyph)); + gp->mode &= ~ATTR_WIDE; + } + + if (term.c.x+width > term.col) { + if (IS_SET(MODE_WRAP)) + tnewline(1); + else + tmoveto(term.col - width, term.c.y); + gp = &term.line[term.c.y][term.c.x]; + } + + tsetchar(u, &term.c.attr, term.c.x, term.c.y); + term.lastc = u; + + if (width == 2) { + gp->mode |= ATTR_WIDE; + if (term.c.x+1 < term.col) { + if (gp[1].mode == ATTR_WIDE && term.c.x+2 < term.col) { + gp[2].u = ' '; + gp[2].mode &= ~ATTR_WDUMMY; + } + gp[1].u = '\0'; + gp[1].mode = ATTR_WDUMMY; + } + } + if (term.c.x+width < term.col) { + tmoveto(term.c.x+width, term.c.y); + } else { + term.c.state |= CURSOR_WRAPNEXT; + } +} + +int +twrite(const char *buf, int buflen, int show_ctrl) +{ + int charsize; + Rune u; + int n; + + for (n = 0; n < buflen; n += charsize) { + if (IS_SET(MODE_UTF8)) { + /* process a complete utf8 char */ + charsize = utf8decode(buf + n, &u, buflen - n); + if (charsize == 0) + break; + } else { + u = buf[n] & 0xFF; + charsize = 1; + } + if (show_ctrl && ISCONTROL(u)) { + if (u & 0x80) { + u &= 0x7f; + tputc('^'); + tputc('['); + } else if (u != '\n' && u != '\r' && u != '\t') { + u ^= 0x40; + tputc('^'); + } + } + tputc(u); + } + return n; +} + +void +tresize(int col, int row) +{ + int i; + int minrow = MIN(row, term.row); + int mincol = MIN(col, term.col); + int *bp; + TCursor c; + + if (col < 1 || row < 1) { + fprintf(stderr, + "tresize: error resizing to %dx%d\n", col, row); + return; + } + + /* + * slide screen to keep cursor where we expect it - + * tscrollup would work here, but we can optimize to + * memmove because we're freeing the earlier lines + */ + for (i = 0; i <= term.c.y - row; i++) { + free(term.line[i]); + free(term.alt[i]); + } + /* ensure that both src and dst are not NULL */ + if (i > 0) { + memmove(term.line, term.line + i, row * sizeof(Line)); + memmove(term.alt, term.alt + i, row * sizeof(Line)); + } + for (i += row; i < term.row; i++) { + free(term.line[i]); + free(term.alt[i]); + } + + /* resize to new height */ + term.line = xrealloc(term.line, row * sizeof(Line)); + term.alt = xrealloc(term.alt, row * sizeof(Line)); + term.dirty = xrealloc(term.dirty, row * sizeof(*term.dirty)); + term.tabs = xrealloc(term.tabs, col * sizeof(*term.tabs)); + + /* resize each row to new width, zero-pad if needed */ + for (i = 0; i < minrow; i++) { + term.line[i] = xrealloc(term.line[i], col * sizeof(Glyph)); + term.alt[i] = xrealloc(term.alt[i], col * sizeof(Glyph)); + } + + /* allocate any new rows */ + for (/* i = minrow */; i < row; i++) { + term.line[i] = xmalloc(col * sizeof(Glyph)); + term.alt[i] = xmalloc(col * sizeof(Glyph)); + } + if (col > term.col) { + bp = term.tabs + term.col; + + memset(bp, 0, sizeof(*term.tabs) * (col - term.col)); + while (--bp > term.tabs && !*bp) + /* nothing */ ; + for (bp += tabspaces; bp < term.tabs + col; bp += tabspaces) + *bp = 1; + } + /* update terminal size */ + term.col = col; + term.row = row; + /* reset scrolling region */ + tsetscroll(0, row-1); + /* make use of the LIMIT in tmoveto */ + tmoveto(term.c.x, term.c.y); + /* Clearing both screens (it makes dirty all lines) */ + c = term.c; + for (i = 0; i < 2; i++) { + if (mincol < col && 0 < minrow) { + tclearregion(mincol, 0, col - 1, minrow - 1); + } + if (0 < col && minrow < row) { + tclearregion(0, minrow, col - 1, row - 1); + } + tswapscreen(); + tcursor(CURSOR_LOAD); + } + term.c = c; +} + +void +resettitle(void) +{ + xsettitle(NULL); +} + +void +drawregion(int x1, int y1, int x2, int y2) +{ + int y; + + for (y = y1; y < y2; y++) { + if (!term.dirty[y]) + continue; + + term.dirty[y] = 0; + xdrawline(term.line[y], x1, y, x2); + } +} + +void +draw(void) +{ + int cx = term.c.x, ocx = term.ocx, ocy = term.ocy; + + if (!xstartdraw()) + return; + + /* adjust cursor position */ + LIMIT(term.ocx, 0, term.col-1); + LIMIT(term.ocy, 0, term.row-1); + if (term.line[term.ocy][term.ocx].mode & ATTR_WDUMMY) + term.ocx--; + if (term.line[term.c.y][cx].mode & ATTR_WDUMMY) + cx--; + + drawregion(0, 0, term.col, term.row); + xdrawcursor(cx, term.c.y, term.line[term.c.y][cx], + term.ocx, term.ocy, term.line[term.ocy][term.ocx]); + term.ocx = cx; + term.ocy = term.c.y; + xfinishdraw(); + if (ocx != term.ocx || ocy != term.ocy) + xximspot(term.ocx, term.ocy); +} + +void +redraw(void) +{ + tfulldirt(); + draw(); +} diff --git a/hosts/vali/mars/dwm/st-0.9.2/st.h b/hosts/vali/mars/dwm/st-0.9.2/st.h new file mode 100644 index 0000000..fd3b0d8 --- /dev/null +++ b/hosts/vali/mars/dwm/st-0.9.2/st.h @@ -0,0 +1,126 @@ +/* See LICENSE for license details. */ + +#include +#include + +/* macros */ +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#define MAX(a, b) ((a) < (b) ? (b) : (a)) +#define LEN(a) (sizeof(a) / sizeof(a)[0]) +#define BETWEEN(x, a, b) ((a) <= (x) && (x) <= (b)) +#define DIVCEIL(n, d) (((n) + ((d) - 1)) / (d)) +#define DEFAULT(a, b) (a) = (a) ? (a) : (b) +#define LIMIT(x, a, b) (x) = (x) < (a) ? (a) : (x) > (b) ? (b) : (x) +#define ATTRCMP(a, b) ((a).mode != (b).mode || (a).fg != (b).fg || \ + (a).bg != (b).bg) +#define TIMEDIFF(t1, t2) ((t1.tv_sec-t2.tv_sec)*1000 + \ + (t1.tv_nsec-t2.tv_nsec)/1E6) +#define MODBIT(x, set, bit) ((set) ? ((x) |= (bit)) : ((x) &= ~(bit))) + +#define TRUECOLOR(r,g,b) (1 << 24 | (r) << 16 | (g) << 8 | (b)) +#define IS_TRUECOL(x) (1 << 24 & (x)) + +enum glyph_attribute { + ATTR_NULL = 0, + ATTR_BOLD = 1 << 0, + ATTR_FAINT = 1 << 1, + ATTR_ITALIC = 1 << 2, + ATTR_UNDERLINE = 1 << 3, + ATTR_BLINK = 1 << 4, + ATTR_REVERSE = 1 << 5, + ATTR_INVISIBLE = 1 << 6, + ATTR_STRUCK = 1 << 7, + ATTR_WRAP = 1 << 8, + ATTR_WIDE = 1 << 9, + ATTR_WDUMMY = 1 << 10, + ATTR_BOLD_FAINT = ATTR_BOLD | ATTR_FAINT, +}; + +enum selection_mode { + SEL_IDLE = 0, + SEL_EMPTY = 1, + SEL_READY = 2 +}; + +enum selection_type { + SEL_REGULAR = 1, + SEL_RECTANGULAR = 2 +}; + +enum selection_snap { + SNAP_WORD = 1, + SNAP_LINE = 2 +}; + +typedef unsigned char uchar; +typedef unsigned int uint; +typedef unsigned long ulong; +typedef unsigned short ushort; + +typedef uint_least32_t Rune; + +#define Glyph Glyph_ +typedef struct { + Rune u; /* character code */ + ushort mode; /* attribute flags */ + uint32_t fg; /* foreground */ + uint32_t bg; /* background */ +} Glyph; + +typedef Glyph *Line; + +typedef union { + int i; + uint ui; + float f; + const void *v; + const char *s; +} Arg; + +void die(const char *, ...); +void redraw(void); +void draw(void); + +void printscreen(const Arg *); +void printsel(const Arg *); +void sendbreak(const Arg *); +void toggleprinter(const Arg *); + +int tattrset(int); +void tnew(int, int); +void tresize(int, int); +void tsetdirtattr(int); +void ttyhangup(void); +int ttynew(const char *, char *, const char *, char **); +size_t ttyread(void); +void ttyresize(int, int); +void ttywrite(const char *, size_t, int); + +void resettitle(void); + +void selclear(void); +void selinit(void); +void selstart(int, int, int); +void selextend(int, int, int, int); +int selected(int, int); +char *getsel(void); + +size_t utf8encode(Rune, char *); + +void *xmalloc(size_t); +void *xrealloc(void *, size_t); +char *xstrdup(const char *); + +/* config.h globals */ +extern char *utmp; +extern char *scroll; +extern char *stty_args; +extern char *vtiden; +extern wchar_t *worddelimiters; +extern int allowaltscreen; +extern int allowwindowops; +extern char *termname; +extern unsigned int tabspaces; +extern unsigned int defaultfg; +extern unsigned int defaultbg; +extern unsigned int defaultcs; diff --git a/hosts/vali/mars/dwm/st-0.9.2/st.info b/hosts/vali/mars/dwm/st-0.9.2/st.info new file mode 100644 index 0000000..efab2cf --- /dev/null +++ b/hosts/vali/mars/dwm/st-0.9.2/st.info @@ -0,0 +1,243 @@ +st-mono| simpleterm monocolor, + acsc=+C\,D-A.B0E``aaffgghFiGjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~, + am, + bce, + bel=^G, + blink=\E[5m, + bold=\E[1m, + cbt=\E[Z, + cvvis=\E[?25h, + civis=\E[?25l, + clear=\E[H\E[2J, + cnorm=\E[?12l\E[?25h, + colors#2, + cols#80, + cr=^M, + csr=\E[%i%p1%d;%p2%dr, + cub=\E[%p1%dD, + cub1=^H, + cud1=^J, + cud=\E[%p1%dB, + cuf1=\E[C, + cuf=\E[%p1%dC, + cup=\E[%i%p1%d;%p2%dH, + cuu1=\E[A, + cuu=\E[%p1%dA, + dch=\E[%p1%dP, + dch1=\E[P, + dim=\E[2m, + dl=\E[%p1%dM, + dl1=\E[M, + ech=\E[%p1%dX, + ed=\E[J, + el=\E[K, + el1=\E[1K, + enacs=\E)0, + flash=\E[?5h$<80/>\E[?5l, + fsl=^G, + home=\E[H, + hpa=\E[%i%p1%dG, + hs, + ht=^I, + hts=\EH, + ich=\E[%p1%d@, + il1=\E[L, + il=\E[%p1%dL, + ind=^J, + indn=\E[%p1%dS, + invis=\E[8m, + is2=\E[4l\E>\E[?1034l, + it#8, + kel=\E[1;2F, + ked=\E[1;5F, + ka1=\E[1~, + ka3=\E[5~, + kc1=\E[4~, + kc3=\E[6~, + kbs=\177, + kcbt=\E[Z, + kb2=\EOu, + kcub1=\EOD, + kcud1=\EOB, + kcuf1=\EOC, + kcuu1=\EOA, + kDC=\E[3;2~, + kent=\EOM, + kEND=\E[1;2F, + kIC=\E[2;2~, + kNXT=\E[6;2~, + kPRV=\E[5;2~, + kHOM=\E[1;2H, + kLFT=\E[1;2D, + kRIT=\E[1;2C, + kind=\E[1;2B, + kri=\E[1;2A, + kclr=\E[3;5~, + kdl1=\E[3;2~, + kdch1=\E[3~, + kich1=\E[2~, + kend=\E[4~, + kf1=\EOP, + kf2=\EOQ, + kf3=\EOR, + kf4=\EOS, + kf5=\E[15~, + kf6=\E[17~, + kf7=\E[18~, + kf8=\E[19~, + kf9=\E[20~, + kf10=\E[21~, + kf11=\E[23~, + kf12=\E[24~, + kf13=\E[1;2P, + kf14=\E[1;2Q, + kf15=\E[1;2R, + kf16=\E[1;2S, + kf17=\E[15;2~, + kf18=\E[17;2~, + kf19=\E[18;2~, + kf20=\E[19;2~, + kf21=\E[20;2~, + kf22=\E[21;2~, + kf23=\E[23;2~, + kf24=\E[24;2~, + kf25=\E[1;5P, + kf26=\E[1;5Q, + kf27=\E[1;5R, + kf28=\E[1;5S, + kf29=\E[15;5~, + kf30=\E[17;5~, + kf31=\E[18;5~, + kf32=\E[19;5~, + kf33=\E[20;5~, + kf34=\E[21;5~, + kf35=\E[23;5~, + kf36=\E[24;5~, + kf37=\E[1;6P, + kf38=\E[1;6Q, + kf39=\E[1;6R, + kf40=\E[1;6S, + kf41=\E[15;6~, + kf42=\E[17;6~, + kf43=\E[18;6~, + kf44=\E[19;6~, + kf45=\E[20;6~, + kf46=\E[21;6~, + kf47=\E[23;6~, + kf48=\E[24;6~, + kf49=\E[1;3P, + kf50=\E[1;3Q, + kf51=\E[1;3R, + kf52=\E[1;3S, + kf53=\E[15;3~, + kf54=\E[17;3~, + kf55=\E[18;3~, + kf56=\E[19;3~, + kf57=\E[20;3~, + kf58=\E[21;3~, + kf59=\E[23;3~, + kf60=\E[24;3~, + kf61=\E[1;4P, + kf62=\E[1;4Q, + kf63=\E[1;4R, + khome=\E[1~, + kil1=\E[2;5~, + krmir=\E[2;2~, + knp=\E[6~, + kmous=\E[M, + kpp=\E[5~, + lines#24, + mir, + msgr, + npc, + op=\E[39;49m, + pairs#64, + mc0=\E[i, + mc4=\E[4i, + mc5=\E[5i, + rc=\E8, + rev=\E[7m, + ri=\EM, + rin=\E[%p1%dT, + ritm=\E[23m, + rmacs=\E(B, + rmcup=\E[?1049l, + rmir=\E[4l, + rmkx=\E[?1l\E>, + rmso=\E[27m, + rmul=\E[24m, + rs1=\Ec, + rs2=\E[4l\E>\E[?1034l, + sc=\E7, + sitm=\E[3m, + sgr0=\E[0m, + smacs=\E(0, + smcup=\E[?1049h, + smir=\E[4h, + smkx=\E[?1h\E=, + smso=\E[7m, + smul=\E[4m, + tbc=\E[3g, + tsl=\E]0;, + xenl, + vpa=\E[%i%p1%dd, +# XTerm extensions + rmxx=\E[29m, + smxx=\E[9m, + BE=\E[?2004h, + BD=\E[?2004l, + PS=\E[200~, + PE=\E[201~, +# disabled rep for now: causes some issues with older ncurses versions. +# rep=%p1%c\E[%p2%{1}%-%db, +# tmux extensions, see TERMINFO EXTENSIONS in tmux(1) + Tc, + Ms=\E]52;%p1%s;%p2%s\007, + Se=\E[2 q, + Ss=\E[%p1%d q, + +st| simpleterm, + use=st-mono, + colors#8, + setab=\E[4%p1%dm, + setaf=\E[3%p1%dm, + setb=\E[4%?%p1%{1}%=%t4%e%p1%{3}%=%t6%e%p1%{4}%=%t1%e%p1%{6}%=%t3%e%p1%d%;m, + setf=\E[3%?%p1%{1}%=%t4%e%p1%{3}%=%t6%e%p1%{4}%=%t1%e%p1%{6}%=%t3%e%p1%d%;m, + 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, + +st-256color| simpleterm with 256 colors, + use=st, + ccc, + colors#256, + oc=\E]104\007, + pairs#32767, +# Nicked from xterm-256color + initc=\E]4;%p1%d;rgb\:%p2%{255}%*%{1000}%/%2.2X/%p3%{255}%*%{1000}%/%2.2X/%p4%{255}%*%{1000}%/%2.2X\E\\, + setab=\E[%?%p1%{8}%<%t4%p1%d%e%p1%{16}%<%t10%p1%{8}%-%d%e48;5;%p1%d%;m, + setaf=\E[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;m, + +st-meta| simpleterm with meta key, + use=st, + km, + rmm=\E[?1034l, + smm=\E[?1034h, + rs2=\E[4l\E>\E[?1034h, + is2=\E[4l\E>\E[?1034h, + +st-meta-256color| simpleterm with meta key and 256 colors, + use=st-256color, + km, + rmm=\E[?1034l, + smm=\E[?1034h, + rs2=\E[4l\E>\E[?1034h, + is2=\E[4l\E>\E[?1034h, + +st-bs| simpleterm with backspace as backspace, + use=st, + kbs=\010, + kdch1=\177, + +st-bs-256color| simpleterm with backspace as backspace and 256colors, + use=st-256color, + kbs=\010, + kdch1=\177, diff --git a/hosts/vali/mars/dwm/st-0.9.2/st.o b/hosts/vali/mars/dwm/st-0.9.2/st.o new file mode 100644 index 0000000000000000000000000000000000000000..78397f5d4946e6914563b399b2700b61287fedb0 GIT binary patch literal 79120 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