Removing suckless tools in favour or openbsd defaults. - dotfiles - These are my dotfiles. There are many like it, but these are mine.
 (HTM) git clone git://jay.scot/dotfiles
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
       ---
 (DIR) commit 3344d07e0e3a34b3d66126d2c8958fca02d35caf
 (DIR) parent 880272711827b8fe9ee861faa1613f3829e0e640
 (HTM) Author: Jay Scott <me@jay.scot>
       Date:   Sat,  1 Feb 2025 12:47:52 +0000
       
       Removing suckless tools in favour or openbsd defaults.
       
       Diffstat:
         M README                              |       3 +--
         M Xdefaults                           |       2 --
         A bin/backup                          |      16 ++++++++++++++++
         M bin/link-handler                    |      15 ++++++---------
         M bootstrap.sh                        |       2 +-
         A castgetrc                           |      44 +++++++++++++++++++++++++++++++
         A cwmrc                               |      37 +++++++++++++++++++++++++++++++
         M lynx/bookmarks.html                 |      20 ++++++++++++--------
         A mutt/gruvbox                        |     121 +++++++++++++++++++++++++++++++
         M mutt/muttrc                         |      69 ++++---------------------------
         D mutt/theme                          |      94 -------------------------------
         A rss2email/rss2email.cfg             |     126 +++++++++++++++++++++++++++++++
         D suckless/dmenu/Makefile             |      39 -------------------------------
         D suckless/dmenu/config.h             |      16 ----------------
         D suckless/dmenu/patches/01-dmenu-bo… |      36 -------------------------------
         D suckless/dmenu/patches/02-dmenu-ce… |     120 -------------------------------
         D suckless/dwm/Makefile               |      41 -------------------------------
         D suckless/dwm/config.h               |     201 ------------------------------
         D suckless/dwm/patches/01-dwm-systra… |     746 -------------------------------
         D suckless/herbe/Makefile             |      40 -------------------------------
         D suckless/herbe/config.h             |      19 -------------------
         D suckless/slstatus/Makefile          |      35 -------------------------------
         D suckless/slstatus/config.h          |      71 -------------------------------
         M xsession                            |       3 ++-
       
       24 files changed, 373 insertions(+), 1543 deletions(-)
       ---
 (DIR) diff --git a/README b/README
       @@ -13,9 +13,8 @@ main desktop OS and are forever evolving.
        
        
          operating sys  : openbsd 7.6
       -  window manager : dwm
       +  window manager : cwm
          terminal       : xterm
       -  launcher       : dmenu
          email          : neomutt / isync / smtpd
          browser        : firefox / lynx
          media          : mpv
 (DIR) diff --git a/Xdefaults b/Xdefaults
       @@ -2,9 +2,7 @@ xterm*FaceName:                                Hack
        xterm*FaceSize:                                14
        xterm*toolBar:                                 false
        xterm*scrollBar:                         false
       -xterm*selectToClipboard:         false
        xterm*loginShell:                        true
       -xterm*scrollBar:                        false
        xterm*selectToClipboard:        true
        xterm.termName:                         xterm-256color
        
 (DIR) diff --git a/bin/backup b/bin/backup
       @@ -0,0 +1,16 @@
       +#!/bin/sh
       +
       +# Variables
       +USER_HOME="/home/jay"
       +BACKUP_DIR="$HOME/tmp"
       +BACKUP_FILE="backup_$(date +%Y%m%d).tar.gz"
       +REMOTE_HOST="192.168.1.100"    # Replace with your remote server address
       +REMOTE_PATH="backup/"      # Replace with the remote path to store backups
       +
       +mkdir -p "$BACKUP_DIR"
       +tar cvzf "$BACKUP_DIR/$BACKUP_FILE" \
       +        $(ls -A "$USER_HOME" | grep -v -e tmp -e media -e .cache -e .mozilla -e .dbus)
       +
       +scp "$BACKUP_DIR/$BACKUP_FILE" "${REMOTE_HOST}:${REMOTE_PATH}"
       +
       +rm "$BACKUP_DIR/$BACKUP_FILE"
 (DIR) diff --git a/bin/link-handler b/bin/link-handler
       @@ -1,13 +1,11 @@
        #!/bin/sh
        
       -launcher="setsid"
       -
        # applications
        player="mpv --autofit=30% --really-quiet --no-terminal"
       -gemini="foot -e amfora"
       -gopher="foot -e w3m"
       -pdf="zathura"
       -images="swayimg"
       +gemini="xterm -e amfora"
       +gopher="xterm -e lynx"
       +pdf="mupdf"
       +images="feh"
        torrent="qbittorrent"
        
        uri="$1"
       @@ -29,10 +27,9 @@ case "$uri_lower" in
                *.pdf | *.ps | *.epub)
                        $pdf "$uri"
                        ;;
       -        *.jpg | *.jpe | *.jpeg | *.png | *.gif | *.webp)
       +        *.jpg | *.jpe | *.jpeg | *.png | *.gif | *.svg | *.webp)
                        echo "in"
       -                #$launcher "$images" "$uri"
       -                wget -qO- $uri | $images -
       +                $images "$uri"
                        ;;
                *)
                        $BROWSER "$uri"
 (DIR) diff --git a/bootstrap.sh b/bootstrap.sh
       @@ -2,7 +2,7 @@
        
        DOTFILES=$(pwd)
        
       -FILES='kshrc profile Xdefaults xsession'
       +FILES='cwmrc kshrc profile Xdefaults xsession'
        ROOT='bin'
        CONFIG='git lynx mpd mutt ncmpcpp nvim isync'
        
 (DIR) diff --git a/castgetrc b/castgetrc
       @@ -0,0 +1,44 @@
       +[*]
       +spool=/home/jay/media/podcasts
       +filename=%(date)-%(title).mp3
       +
       +
       +[2600]
       +url=https://www.2600.com/oth-broadband.xml
       +spool=/home/jay/media/podcasts/offthehook
       +
       +[cory-doctorows]
       +url=http://feeds.feedburner.com/doctorow_podcast
       +spool=/home/jay/media/podcasts/cory-doctorows
       +
       +[corecursive]
       +url=https://link.chtbl.com/corecursive?id=corecursive&platform=rss
       +spool=/home/jay/media/podcasts/corecursive
       +
       +[commandlineheroes]
       +url=https://feeds.pacific-content.com/commandlineheroes
       +spool=/home/jay/media/podcasts/commandlineheroes
       +
       +[hpr]
       +url=http://hackerpublicradio.org/hpr_rss.php
       +spool=/home/jay/media/podcasts/hacker-public-radio
       +
       +[tilde-town]
       +url=https://tilde.town/~dozens/podcast/rss.xml
       +spool=/home/jay/media/podcasts/tilde-town
       +
       +[ask-noah]
       +url=https://feeds.fireside.fm/asknoah/rss
       +spool=/home/jay/media/podcasts/ask-noah
       +
       +[2.5-admins]
       +url=https://2.5admins.com/feed/podcast
       +spool=/home/jay/media/podcasts/2.5-admins
       +
       +[going-linux]
       +url=https://goinglinux.com/mp3podcast.xml
       +spool=/home/jay/media/podcasts/going-linux
       +
       +[living-adventurously]
       +url=https://feeds.transistor.fm/living-adventurously
       +spool=/home/jay/media/podcasts/living-adventurously
 (DIR) diff --git a/cwmrc b/cwmrc
       @@ -0,0 +1,37 @@
       +# Set default Xft(3) font
       +fontname "Hack:pixelsize=14:bold"
       +
       +# Turn on sticky-group mode
       +sticky yes
       +
       +# Appearance
       +borderwidth                        2
       +
       +# Autogroup some apps
       +autogroup 2                        "Navigator,firefox-default"
       +
       +# Remove all default keybindings
       +unbind-key                         all
       +
       +# Key bindings
       +bind-key M-m                /home/jay/bin/music
       +bind-key M-space        xterm
       +bind-key M-f                firefox
       +
       +bind-key M-p                menu-exec
       +bind-key M-r                restart
       +bind-key M-c                window-close
       +bind-key M-q                quit
       +bind-key M-return        window-fullscreen
       +
       +bind-key M-1                group-only-1
       +bind-key M-2                group-only-2
       +bind-key M-3                group-only-3
       +bind-key M-4                group-only-4
       +bind-key MS-1                window-movetogroup-1
       +bind-key MS-2                window-movetogroup-2
       +bind-key MS-3                window-movetogroup-3
       +bind-key MS-4                window-movetogroup-4
       +
       +# Mouse bindings
       +unbind-mouse all
 (DIR) diff --git a/lynx/bookmarks.html b/lynx/bookmarks.html
       @@ -12,13 +12,17 @@
        <ol>
        <h2>Gopher</h2>
        <li><a href="gopher://jay.scot/">jay.scot</a></li>
       -<li><a href="gopher://gopher.icu/">Ian J</a>
       -<li><a href="gopher://hngopher.com">Hacker News</a>
       -<LI><a href="gopher://gopherpedia.com/">gopherpedia</a>
       -<LI><a href="gopher://bitreich.org/1/lawn">The Gopher Lawn</a>
       -<LI><a href="gopher://gopher.black/1/moku-pona">Aggregator of phlog</a>
       -<LI><a href="gopher://i-logout.cz/1/bongusta/">Bongusta</a>
       -<LI><a href="gopher://floodgap.com/">Floodgap</a>
       +<li><a href="gopher://1436.ninja/1/Port70News">Port 70 News</a></li>
       +<li><a href="gopher://hngopher.com">Hacker News</a></li>
       +<li><a href="gopher://gopherpedia.com/">gopherpedia</a></li>
       +<li><a href="gopher://bitreich.org/1/lawn">The Gopher Lawn</a></li>
       +<li><a href="gopher://gopher.black/1/moku-pona">Aggregator of phlog</a></li>
       +<li><a href="gopher://i-logout.cz/1/bongusta/">Bongusta</a></li>
       +<li><a href="gopher://gopher.icu/">Ian J</a></li>
       +<li><a href="gopher://floodgap.com/">Floodgap</a></li>
        <hr>
        <h2>Web</h2>
       -<LI><a href="https://text.npr.org/">NPR</a>
       +<li><a href="https://text.npr.org/">NPR</a></li>
       +<li><a href="https://neuters.de/">Reuters</a></li>
       +<li><a href="http://lite.cnn.com/">CNN</a></li>
       +</ol>
 (DIR) diff --git a/mutt/gruvbox b/mutt/gruvbox
       @@ -0,0 +1,121 @@
       +# gruvbox dark (contrast dark):
       +
       +# bg0    = 234
       +# bg1    = 237
       +# bg2    = 239
       +# bg3    = 241
       +# bg4    = 243
       +# 
       +# gray   = 245
       +# 
       +# fg0    = 229
       +# fg1    = 223
       +# fg2    = 250
       +# fg3    = 248
       +# fg4    = 246
       +# 
       +# red    = 167
       +# green  = 142
       +# yellow = 214
       +# blue   = 109
       +# purple = 175
       +# aqua   = 108
       +# orange = 208
       +
       +
       +# See http://www.mutt.org/doc/manual/#color
       +
       +color attachment  color109 color234
       +color bold        color229 color234
       +color error       color167 color234
       +color hdrdefault  color246 color234
       +color indicator   color223 color237
       +color markers     color243 color234
       +color normal      color223 color234
       +color quoted      color250 color234
       +color quoted1     color108 color234
       +color quoted2     color250 color234
       +color quoted3     color108 color234
       +color quoted4     color250 color234
       +color quoted5     color108 color234
       +color search      color234 color208
       +color signature   color108 color234
       +color status      color234 color250
       +color tilde       color243 color234
       +color tree        color142 color234
       +color underline   color223 color239
       +
       +color sidebar_divider    color250 color234
       +color sidebar_new        color142 color234
       +
       +color index color142 color234 ~N
       +color index color108 color234 ~O
       +color index color109 color234 ~P
       +color index color214 color234 ~F
       +color index color175 color234 ~Q
       +color index color167 color234 ~=
       +color index color234 color223 ~T
       +color index color234 color167 ~D
       +
       +color header color214 color234 "^(To:|From:)"
       +color header color142 color234 "^Subject:"
       +color header color108 color234 "^X-Spam-Status:"
       +color header color108 color234 "^Received:"
       +
       +# Regex magic for URLs and hostnames
       +#
       +# Attention: BSD's regex has RE_DUP_MAX set to 255.
       +#
       +# Examples:
       +#   http://some-service.example.com
       +#   example.com
       +#   a.example.com
       +#   some-service.example.com
       +#   example.com/
       +#   example.com/datenschutz
       +#   file:///tmp/foo
       +#
       +# Non-examples:
       +#   1.1.1900
       +#   14.02.2022/24:00
       +#   23.59
       +#   w.l.o.g
       +#   team.its
       +color body color142 color234 "[a-z]{3,255}://[[:graph:]]*"
       +color body color142 color234 "([-[:alnum:]]+\\.)+([0-9]{1,3}|[-[:alpha:]]+)/[[:graph:]]*"
       +color body color142 color234 "([-[:alnum:]]+\\.){2,255}[-[:alpha:]]{2,10}"
       +
       +# IPv4 and IPv6 stolen from https://stackoverflow.com/questions/53497/regular-expression-that-matches-valid-ipv6-addresses
       +color body color142 color234 "((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])"
       +color body color142 color234 "(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))"
       +
       +# Mail addresses and mailto URLs
       +color body color208 color234 "[-a-z_0-9.%$]+@[-a-z_0-9.]+\\.[-a-z][-a-z]+"
       +color body color208 color234 "mailto:[-a-z_0-9.]+@[-a-z_0-9.]+"
       +
       +# some simleys and stuff
       +color body color234 color214 "[;:]-*[)>(<lt;|]"
       +color body color229 color234 "\\*[- A-Za-z]+\\*"
       +
       +color body color214 color234 "^-.*PGP.*-*"
       +color body color142 color234 "^gpg: Good signature from"
       +color body color167 color234 "^gpg: Can't.*$"
       +color body color214 color234 "^gpg: WARNING:.*$"
       +color body color167 color234 "^gpg: BAD signature from"
       +color body color167 color234 "^gpg: Note: This key has expired!"
       +color body color214 color234 "^gpg: There is no indication that the signature belongs to the owner."
       +color body color214 color234 "^gpg: can't handle these multiple signatures"
       +color body color214 color234 "^gpg: signature verification suppressed"
       +color body color214 color234 "^gpg: invalid node with packet of type"
       +
       +color body color142 color234 "^Good signature from:"
       +color body color167 color234 "^.?BAD.? signature from:"
       +color body color142 color234 "^Verification successful"
       +color body color167 color234 "^Verification [^s][^[:space:]]*$"
       +
       +color compose header            color223 color234
       +color compose security_encrypt  color175 color234
       +color compose security_sign     color109 color234
       +color compose security_both     color142 color234
       +color compose security_none     color208 color234
       +
 (DIR) diff --git a/mutt/muttrc b/mutt/muttrc
       @@ -1,5 +1,4 @@
       -
       -source ~/.config/mutt/theme
       +source ~/.config/mutt/gruvbox
        
        # info
        set realname        = 'Jay Scott'
       @@ -40,7 +39,6 @@ set folder           = ~/.mail
        set header_cache     = ~/.config/mutt/cache/headers
        set message_cachedir = ~/.config/mutt/cache/bodies
        set mailcap_path     = ~/.config/mutt/mailcap
       -set alias_file              = ~/.config/mutt/aliases
        set tmpdir           = ~/.cache/
        
        set spoolfile        = "+jay/Inbox"
       @@ -50,9 +48,11 @@ set record      = "+jay/Sent"
        # inbox
        mailboxes ! `echo ~/.mail/jay/*`
        
       -set sort_alias = alias
       -set reverse_alias = yes
       -source $alias_file
       +# aliases
       +set alias_file                = ~/.config/mutt/aliases
       +set sort_alias                = alias
       +set reverse_alias         = yes
       +source                                 $alias_file
        
        # macros
        bind index g noop
       @@ -72,69 +72,14 @@ set pager_index_lines        = 15
        set pager_context                = 1
        set index_format                = '%Z | %{%b %d %Y} | %-15.15F | %s'
        
       -# sidebar
       -set mail_check_stats         = yes
       -set sidebar_visible         = yes
       -set sidebar_width         = 25
       -set sidebar_short_path         = yes
       -set sidebar_folder_indent = yes
       -set sidebar_format = "%B%* %?N?%N?"
       -set sidebar_divider_char = │
       -bind index,pager \Ck sidebar-prev
       -bind index,pager <tab> sidebar-next
       -bind index,pager <backtab> sidebar-prev
       -bind index,pager \Cl sidebar-open
       -
        # disable help menu
       -set help                 = no
       +set help                 = yes
        
        # status bar
        set sidebar_delim_chars = "/"
        set status_chars          = " *%A"
        set status_format         = "───[ Folder: %f ]───[%r%m messages%?n? (%n new)?%?d? (%d to delete)?%?t? (%t tagged)? ]───%>─%?p?( %p postponed )?───"
        
       -# default
       -#color normal color223 color0
       -
       -# status bar
       -#color status color8 color0
       -
       -# highlight bar
       -#color indicator        color223 color237
       -
       -# replied to
       -color index color2 color0 ~Q
       -
       -# email info header
       -#color header color11 color0 "^(To:|From:|Date:|^Subject:)"
       -
       -# web links
       -color body color2 color0 "https?://[^ ]+"
       -color body color2 color0 "www.[^ ]+"
       -
       -# email addresss
       -color body color2 color0 "[-a-z_0-9.%$]+@[-a-z_0-9.]+\\.[-a-z][-a-z]+"
       -color body color2 color0 "mailto:[-a-z_0-9.]+@[-a-z_0-9.]+"
       -
       -# image links
       -color body color2 color0 "\\[image\\ [0-9]+\\]"
       -
       -# sidebar
       -#color sidebar_new bold color11 color0
       -color sidebar_divider bold color2 color0
       -
       -# patch syntax
       -color body brightwhite default ^[[:space:]].*
       -color body brightwhite default ^(diff).*
       -#color body white default ^[\-\-\-].*
       -color body white default ^[\+\+\+].*
       -color body green default ^[\+].*
       -color body red default ^[\-].*
       -color body brightblue default [@@].*
       -color body brightwhite default ^(\s).*
       -color body brightwhite default ^(Signed-off-by).*
       -color body brightwhite default ^(Cc)
       -
        ignore *
        unignore from date subject to cc
        unignore x-mailer
 (DIR) diff --git a/mutt/theme b/mutt/theme
       @@ -1,94 +0,0 @@
       -
       -color body          color136        color234        "(jay|jay.scot)"
       -
       -# basic colors ---------------------------------------------------------
       -color normal        color241        color234
       -color error         color160        color234
       -color tilde         color235        color234
       -color message       color37         color234
       -color markers       color160        color254
       -color attachment    color254        color234
       -color search        color61         color234
       -color status        color241        color235
       -color indicator     color234        color136
       -color tree          color136        color234
       -
       -# basic monocolor screen
       -mono  bold          bold
       -mono  underline     underline
       -mono  indicator     reverse
       -mono  error         bold
       -
       -# index ----------------------------------------------------------------
       -
       -color index         color160        color234        "~A"                        # all messages
       -color index         color166        color234        "~E"                        # expired messages
       -color index         color33         color234        "~N"                        # new messages
       -color index         color33         color234        "~O"                        # old messages
       -color index         color61         color234        "~Q"                        # messages that have been replied to
       -color index         color240        color234        "~R"                        # read messages
       -color index         color33         color234        "~U"                        # unread messages
       -color index         color33         color234        "~U~$"                      # unread, unreferenced messages
       -color index         color241        color234        "~v"                        # messages part of a collapsed thread
       -color index         color241        color234        "~P"                        # messages from me
       -color index         color37         color234        "~p!~F"                     # messages to me
       -color index         color37         color234        "~N~p!~F"                   # new messages to me
       -color index         color37         color234        "~U~p!~F"                   # unread messages to me
       -color index         color240        color234        "~R~p!~F"                   # messages to me
       -color index         color160        color234        "~F"                        # flagged messages
       -color index         color160        color234        "~F~p"                      # flagged messages to me
       -color index         color160        color234        "~N~F"                      # new flagged messages
       -color index         color160        color234        "~N~F~p"                    # new flagged messages to me
       -color index         color160        color234        "~U~F~p"                    # new flagged messages to me
       -color index         color235        color160        "~D"                        # deleted messages
       -color index         color245        color234        "~v~(!~N)"                  # collapsed thread with no unread
       -color index         color136        color234        "~v~(~N)"                   # collapsed thread with some unread
       -color index         color64         color234        "~N~v~(~N)"                 # collapsed thread with unread parent
       -# statusbg used to indicated flagged when foreground color shows other status
       -# for collapsed thread
       -color index         color160        color235        "~v~(~F)!~N"                # collapsed thread with flagged, no unread
       -color index         color136        color235        "~v~(~F~N)"                 # collapsed thread with some unread & flagged
       -color index         color64         color235        "~N~v~(~F~N)"               # collapsed thread with unread parent & flagged
       -color index         color64         color235        "~N~v~(~F)"                 # collapsed thread with unread parent, no unread inside, but some flagged
       -color index         color37         color235        "~v~(~p)"                   # collapsed thread with unread parent, no unread inside, some to me directly
       -color index         color136        color160        "~v~(~D)"                   # thread with deleted (doesn't differentiate between all or partial)
       -
       -# message headers ------------------------------------------------------
       -
       -#color header        color240        color234        "^"
       -color hdrdefault    color240        color234
       -color header        color241        color234        "^(From)"
       -color header        color33         color234        "^(Subject)"
       -
       -# body -----------------------------------------------------------------
       -
       -color quoted        color33         color234
       -color quoted1       color37         color234
       -color quoted2       color136        color234
       -color quoted3       color160        color234
       -color quoted4       color166        color234
       -
       -color signature     color240        color234
       -color bold          color235        color234
       -color underline     color235        color234
       -color normal        color244        color234
       -#
       -color body          color245        color234        "[;:][-o][)/(|]"    # emoticons
       -color body          color245        color234        "[;:][)(|]"         # emoticons
       -color body          color245        color234        "[*]?((N)?ACK|CU|LOL|SCNR|BRB|BTW|CWYL|\
       -                                                     |FWIW|vbg|GD&R|HTH|HTHBE|IMHO|IMNSHO|\
       -                                                     |IRL|RTFM|ROTFL|ROFL|YMMV)[*]?"
       -color body          color245        color234        "[ ][*][^*]*[*][ ]?" # more emoticon?
       -color body          color245        color234        "[ ]?[*][^*]*[*][ ]" # more emoticon?
       -
       -## pgp
       -
       -color body          color160        color234        "(BAD signature)"
       -color body          color37         color234        "(Good signature)"
       -color body          color234        color234        "^gpg: Good signature .*"
       -color body          color241        color234        "^gpg: "
       -color body          color241        color160        "^gpg: BAD signature from.*"
       -mono  body          bold                            "^gpg: Good signature"
       -mono  body          bold                            "^gpg: BAD signature from.*"
       -color body          color160        color234        "([a-z][a-z0-9+-]*://(((([a-z0-9_.!~*'();:&=+$,-]|%[0-9a-f][0-9a-f])*@)?((([a-z0-9]([a-z0-9-]*[a-z0-9])?)\\.)*([a-z]([a-z0-9-]*[a-z0-9])?)\\.?|[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+)(:[0-9]+)?)|([a-z0-9_.!~*'()$,;:@&=+-]|%[0-9a-f][0-9a-f])+)(/([a-z0-9_.!~*'():@&=+$,-]|%[0-9a-f][0-9a-f])*(;([a-z0-9_.!~*'():@&=+$,-]|%[0-9a-f][0-9a-f])*)*(/([a-z0-9_.!~*'():@&=+$,-]|%[0-9a-f][0-9a-f])*(;([a-z0-9_.!~*'():@&=+$,-]|%[0-9a-f][0-9a-f])*)*)*)?(\\?([a-z0-9_.!~*'();/?:@&=+$,-]|%[0-9a-f][0-9a-f])*)?(#([a-z0-9_.!~*'();/?:@&=+$,-]|%[0-9a-f][0-9a-f])*)?|(www|ftp)\\.(([a-z0-9]([a-z0-9-]*[a-z0-9])?)\\.)*([a-z]([a-z0-9-]*[a-z0-9])?)\\.?(:[0-9]+)?(/([-a-z0-9_.!~*'():@&=+$,]|%[0-9a-f][0-9a-f])*(;([-a-z0-9_.!~*'():@&=+$,]|%[0-9a-f][0-9a-f])*)*(/([-a-z0-9_.!~*'():@&=+$,]|%[0-9a-f][0-9a-f])*(;([-a-z0-9_.!~*'():@&=+$,]|%[0-9a-f][0-9a-f])*)*)*)?(\\?([-a-z0-9_.!~*'();/?:@&=+$,]|%[0-9a-f][0-9a-f])*)?(#([-a-z0-9_.!~*'();/?:@&=+$,]|%[0-9a-f][0-9a-f])*)?)[^].,:;!)? \t\r\n<>\"]"
       -color body          color33         color234        "( *[-+=#*~_]){6,}"
 (DIR) diff --git a/rss2email/rss2email.cfg b/rss2email/rss2email.cfg
       @@ -0,0 +1,126 @@
       +[DEFAULT]
       +from = rss@jay.scot
       +user-agent = rss2email/__VERSION__ (__URL__)
       +use-8bit = False
       +force-from = True
       +use-publisher-email = False
       +name-format = {feed-title}: {author}
       +to = me@jay.scot
       +proxy = 
       +feed-timeout = 60
       +same-server-fetch-interval = 0
       +active = True
       +digest = False
       +digest-type = multipart/digest
       +date-header = True
       +date-header-order = modified, issued, created, expired
       +bonus-header = 
       +trust-guid = True
       +trust-link = False
       +reply-changes = False
       +encodings = US-ASCII, ISO-8859-1, UTF-8, BIG5, ISO-2022-JP
       +post-process = rss2email.post_process.prettify process
       +digest-post-process = 
       +subject-format = {feed-title}
       +html-mail = False
       +multipart-html = False
       +use-css = False
       +css = h1 {
       +        font: 18pt Georgia, "Times New Roman";
       +        }
       +        body {
       +        font: 12pt Arial;
       +        }
       +        a:link {
       +        font: 12pt Arial;
       +        font-weight: bold;
       +        color: #0000cc;
       +        }
       +        blockquote {
       +        font-family: monospace;
       +        }
       +        .header {
       +        background: #e0ecff;
       +        border-bottom: solid 4px #c3d9ff;
       +        padding: 5px;
       +        margin-top: 0px;
       +        color: red;
       +        }
       +        .header a {
       +        font-size: 20px;
       +        text-decoration: none;
       +        }
       +        .footer {
       +        background: #c3d9ff;
       +        border-top: solid 4px #c3d9ff;
       +        padding: 5px;
       +        margin-bottom: 0px;
       +        }
       +        .entry {
       +        border: solid 4px #c3d9ff;
       +        }
       +        .body {
       +        margin-left: 5px;
       +        margin-right: 5px;
       +        }
       +unicode-snob = False
       +links-after-each-paragraph = False
       +inline-links = True
       +wrap-links = True
       +body-width = 72
       +email-protocol = sendmail
       +sendmail = /usr/sbin/sendmail
       +sendmail_config = 
       +smtp-auth = False
       +smtp-username = username
       +smtp-password = password
       +smtp-server = smtp.example.net
       +smtp-port = 465
       +smtp-ssl = False
       +imap-auth = False
       +imap-username = username
       +imap-password = password
       +imap-server = imap.example.net
       +imap-port = 143
       +imap-ssl = False
       +imap-mailbox = INBOX
       +maildir-path = ~/Maildir
       +maildir-mailbox = INBOX
       +verbose = info
       +
       +[feed.noted]
       +url = https://noted.lol/rss/
       +
       +[feed.selfhosted]
       +url = https://selfh.st/rss/
       +
       +[feed.planet-kernel]
       +url = https://planet.kernel.org/rss20.xml
       +
       +[feed.bear-blogs]
       +url = https://bearblog.dev/discover/feed/
       +
       +[feed.Uninformativ]
       +url = https://www.uninformativ.de/blog/feeds/en.atom
       +
       +[feed.Joey-H]
       +url = http://joeyh.name/blog/index.rss
       +
       +[feed.Fabiensanglard]
       +url = https://fabiensanglard.net/rss.xml
       +
       +[feed.Pluralistic]
       +url = https://pluralistic.net/feed/
       +
       +[feed.Koutsie]
       +url = https://k0.tel/feed.xml
       +
       +[feed.Jeff-Geerling]
       +url = https://www.jeffgeerling.com/blog.xml
       +
       +[feed.Lab-Notes]
       +url = https://labnotes.org/rss/
       +
       +[feed.1MB-Club]
       +url = https://1mb.club/posts.xml
       +
 (DIR) diff --git a/suckless/dmenu/Makefile b/suckless/dmenu/Makefile
       @@ -1,39 +0,0 @@
       -REPOSITORY = http://git.suckless.org/dmenu
       -SRC_DIR = src
       -PINNED_REVISION = HEAD
       -PATCH_DIR = patches
       -
       -all: $(SRC_DIR)
       -
       -clean: reset
       -        @if test -d $(SRC_DIR); then \
       -                $(MAKE) -C "${SRC_DIR}" -s clean; \
       -                git -C "${SRC_DIR}" clean -f; \
       -        fi
       -
       -$(SRC_DIR): clone reset patch
       -        @cp config.h $@
       -        $(MAKE) -C "${SRC_DIR}" -s
       -
       -patch: $(PATCH_DIR)/*
       -        @for file in $^ ; do \
       -                patch -d "${SRC_DIR}" < $${file}; \
       -        done
       -reset:
       -        @if [ -n "$(strip $(PINNED_REVISION))" ]; then \
       -                git -C "${SRC_DIR}" reset --hard $(PINNED_REVISION); \
       -        fi
       -
       -clone:
       -        @if ! test -d $(SRC_DIR); then \
       -                git clone $(REPOSITORY) $(SRC_DIR); \
       -        fi
       -
       -update: clean
       -        @git -C "${SRC_DIR}" pull
       -
       -install:
       -        $(MAKE) -C "${SRC_DIR}" -s install
       -
       -
       -.PHONY: all clean update install reset clone
 (DIR) diff --git a/suckless/dmenu/config.h b/suckless/dmenu/config.h
       @@ -1,16 +0,0 @@
       -static int topbar = 1;
       -static const char *fonts[] = {
       -        "Hack:pixelsize=14"
       -};
       -static int centered = 1;
       -static const char *prompt      = "run »";
       -static const char *colors[SchemeLast][2] = {
       -        [SchemeNorm] = { "#ebdbb2", "#282828" },
       -        [SchemeSel] = { "#ebdbb2", "#98971a" },
       -        [SchemeOut] = { "#ebdbb2", "#8ec07c" },
       -};
       -
       -static unsigned int lines = 0;
       -static const char worddelimiters[] = " ";
       -static int min_width = 800;
       -static unsigned int border_width = 3;
 (DIR) diff --git a/suckless/dmenu/patches/01-dmenu-border-4.9.diff b/suckless/dmenu/patches/01-dmenu-border-4.9.diff
       @@ -1,36 +0,0 @@
       -diff --git a/config.def.h b/config.def.h
       -index 1edb647..dd3eb31 100644
       ---- a/config.def.h
       -+++ b/config.def.h
       -@@ -21,3 +21,6 @@ static unsigned int lines      = 0;
       -  * for example: " /?\"&[]"
       -  */
       - static const char worddelimiters[] = " ";
       -+
       -+/* Size of the window border */
       -+static unsigned int border_width = 0;
       -diff --git a/dmenu.c b/dmenu.c
       -index 27b7a30..7c130fc 100644
       ---- a/dmenu.c
       -+++ b/dmenu.c
       -@@ -684,9 +684,11 @@ setup(void)
       -         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,
       -+        win = XCreateWindow(dpy, root, x, y, mw, mh, border_width,
       -                             CopyFromParent, CopyFromParent, CopyFromParent,
       -                             CWOverrideRedirect | CWBackPixel | CWEventMask, &swa);
       -+        if (border_width)
       -+                XSetWindowBorder(dpy, win, scheme[SchemeSel][ColBg].pixel);
       -         XSetClassHint(dpy, win, &ch);
       -
       -
       -@@ -757,6 +759,8 @@ main(int argc, char *argv[])
       -                         colors[SchemeSel][ColFg] = argv[++i];
       -                 else if (!strcmp(argv[i], "-w"))   /* embedding window id */
       -                         embed = argv[++i];
       -+                else if (!strcmp(argv[i], "-bw"))
       -+                        border_width = atoi(argv[++i]); /* border width */
       -                 else
       -                         usage();
 (DIR) diff --git a/suckless/dmenu/patches/02-dmenu-center-20200111-8cd37e1.diff b/suckless/dmenu/patches/02-dmenu-center-20200111-8cd37e1.diff
       @@ -1,120 +0,0 @@
       -From 8cd37e1ab9e7cb025224aeb3543f1a5be8bceb93 Mon Sep 17 00:00:00 2001
       -From: Nihal Jere <nihal@nihaljere.xyz>
       -Date: Sat, 11 Jan 2020 21:16:08 -0600
       -Subject: [PATCH] center patch now has adjustable minimum width
       -
       ----
       - config.def.h |  2 ++
       - dmenu.1      |  3 +++
       - dmenu.c      | 39 ++++++++++++++++++++++++++++++++-------
       - 3 files changed, 37 insertions(+), 7 deletions(-)
       -
       -diff --git a/config.def.h b/config.def.h
       -index 1edb647..88ef264 100644
       ---- a/config.def.h
       -+++ b/config.def.h
       -@@ -2,6 +2,8 @@
       - /* Default settings; can be overriden by command line. */
       - 
       - static int topbar = 1;                      /* -b  option; if 0, dmenu appears at bottom     */
       -+static int centered = 0;                    /* -c option; centers dmenu on screen */
       -+static int min_width = 500;                    /* minimum width when centered */
       - /* -fn option overrides fonts[0]; default X11 font or font set */
       - static const char *fonts[] = {
       -         "monospace:size=10"
       -diff --git a/dmenu.1 b/dmenu.1
       -index 323f93c..c036baa 100644
       ---- a/dmenu.1
       -+++ b/dmenu.1
       -@@ -40,6 +40,9 @@ which lists programs in the user's $PATH and runs the result in their $SHELL.
       - .B \-b
       - dmenu appears at the bottom of the screen.
       - .TP
       -+.B \-c
       -+dmenu appears centered on 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.
       -diff --git a/dmenu.c b/dmenu.c
       -index 65f25ce..041c7f8 100644
       ---- a/dmenu.c
       -+++ b/dmenu.c
       -@@ -89,6 +89,15 @@ calcoffsets(void)
       -                         break;
       - }
       - 
       -+static int
       -+max_textw(void)
       -+{
       -+        int len = 0;
       -+        for (struct item *item = items; item && item->text; item++)
       -+                len = MAX(TEXTW(item->text), len);
       -+        return len;
       -+}
       -+
       - static void
       - cleanup(void)
       - {
       -@@ -611,6 +620,7 @@ setup(void)
       -         bh = drw->fonts->h + 2;
       -         lines = MAX(lines, 0);
       -         mh = (lines + 1) * bh;
       -+        promptw = (prompt && *prompt) ? TEXTW(prompt) - lrpad / 4 : 0;
       - #ifdef XINERAMA
       -         i = 0;
       -         if (parentwin == root && (info = XineramaQueryScreens(dpy, &n))) {
       -@@ -637,9 +647,16 @@ setup(void)
       -                                 if (INTERSECT(x, y, 1, 1, info[i]))
       -                                         break;
       - 
       --                x = info[i].x_org;
       --                y = info[i].y_org + (topbar ? 0 : info[i].height - mh);
       --                mw = info[i].width;
       -+                if (centered) {
       -+                        mw = MIN(MAX(max_textw() + promptw, min_width), info[i].width);
       -+                        x = info[i].x_org + ((info[i].width  - mw) / 2);
       -+                        y = info[i].y_org + ((info[i].height - mh) / 2);
       -+                } else {
       -+                        x = info[i].x_org;
       -+                        y = info[i].y_org + (topbar ? 0 : info[i].height - mh);
       -+                        mw = info[i].width;
       -+                }
       -+
       -                 XFree(info);
       -         } else
       - #endif
       -@@ -647,11 +664,17 @@ setup(void)
       -                 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;
       -+
       -+                if (centered) {
       -+                        mw = MIN(MAX(max_textw() + promptw, min_width), wa.width);
       -+                        x = (wa.width  - mw) / 2;
       -+                        y = (wa.height - mh) / 2;
       -+                } else {
       -+                        x = 0;
       -+                        y = topbar ? 0 : wa.height - mh;
       -+                        mw = wa.width;
       -+                }
       -         }
       --        promptw = (prompt && *prompt) ? TEXTW(prompt) - lrpad / 4 : 0;
       -         inputw = MIN(inputw, mw/3);
       -         match();
       - 
       -@@ -709,6 +732,8 @@ main(int argc, char *argv[])
       -                         topbar = 0;
       -                 else if (!strcmp(argv[i], "-f"))   /* grabs keyboard before reading stdin */
       -                         fast = 1;
       -+                else if (!strcmp(argv[i], "-c"))   /* centers dmenu on screen */
       -+                        centered = 1;
       -                 else if (!strcmp(argv[i], "-i")) { /* case-insensitive item matching */
       -                         fstrncmp = strncasecmp;
       -                         fstrstr = cistrstr;
       --- 
       -2.24.1
       -
 (DIR) diff --git a/suckless/dwm/Makefile b/suckless/dwm/Makefile
       @@ -1,41 +0,0 @@
       -REPOSITORY = http://git.suckless.org/dwm
       -SRC_DIR = src
       -PINNED_REVISION = HEAD
       -PATCH_DIR = patches
       -
       -all: $(SRC_DIR)
       -
       -clean: reset
       -        @if test -d $(SRC_DIR); then \
       -                cd $(SRC_DIR); \
       -                $(MAKE) -s clean; \
       -                git clean -f; \
       -        fi
       -
       -$(SRC_DIR): clone reset patch
       -        @cp config.h $@
       -        @cd $@ && $(MAKE) -s
       -
       -reset:
       -        @if [ -n "$(strip $(PINNED_REVISION))" ]; then \
       -                cd $(SRC_DIR) && git reset --hard $(PINNED_REVISION); \
       -        fi
       -
       -patch: $(PATCH_DIR)/*
       -        @for file in $^ ; do \
       -                patch -d "${SRC_DIR}" < $${file}; \
       -        done
       -
       -clone:
       -        @if ! test -d $(SRC_DIR); then \
       -                git clone $(REPOSITORY) $(SRC_DIR); \
       -        fi
       -
       -update: clean
       -        @cd $(SRC_DIR) && git pull
       -
       -install:
       -        $(MAKE) -C "${SRC_DIR}" -s install
       -
       -
       -.PHONY: all clean update install reset clone
 (DIR) diff --git a/suckless/dwm/config.h b/suckless/dwm/config.h
       @@ -1,201 +0,0 @@
       -/* See LICENSE file for copyright and license details. */
       -
       -#include <X11/XF86keysym.h>
       -
       -/* appearance */
       -static const unsigned int borderpx  = 3;
       -static const unsigned int snap      = 32;
       -static const int lockfullscreen            = 1;
       -static const int showbar            = 1;
       -static const int topbar             = 1;
       -static const unsigned int systraypinning = 0;
       -static const unsigned int systrayonleft = 0;
       -static const unsigned int systrayspacing = 2;
       -static const int systraypinningfailfirst = 1;
       -static const int showsystray        = 1;
       -
       -static const char *fonts[]          = { "Hack:size=10" };
       -static const char dmenufont[]       = "Hack:size=10";
       -static const char col_gray1[]       = "#222222";
       -static const char col_gray2[]       = "#98971A";
       -static const char col_gray3[]       = "#bbbbbb";
       -static const char col_gray4[]       = "#eeeeee";
       -static const char col_cyan[]        = "#222222";
       -static const char *colors[][3]      = {
       -        /*               fg         bg         border   */
       -        [SchemeNorm] = { col_gray3, col_gray1, col_cyan },
       -        [SchemeSel]  = { col_gray4, col_cyan,  col_gray2  },
       -};
       -
       -
       -/* custom functions */
       -static void togglefullscreen(const Arg *arg);
       -static void bstack(Monitor *m);
       -static void centeredfloatingmaster(Monitor *m);
       -
       -/* custom defines for mouse buttons */
       -/* only 1-5 are defined in X11/X.h */
       -#define Button8 8
       -#define Button9 9
       -
       -/* tagging */
       -static const char *tags[] = { "1", "2", "3", "4", "5" };
       -
       -static Rule rules[] = {
       -        /* class      instance    title       tags mask     isfloating   monitor */
       -        { NULL,       NULL,       NULL,       0,            False,       -1 },
       -};
       -
       -/* layout(s) */
       -static const float mfact     = 0.65;
       -static const int nmaster     = 1;
       -static const int resizehints = 0;
       -
       -static const Layout layouts[] = {
       -        { "TTT",      bstack },
       -        { "[]=",      tile },
       -        { ">M>",      centeredfloatingmaster },
       -        { "><>",      NULL },
       -};
       -
       -#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} },
       -
       -#define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } }
       -
       -/* commands */
       -static char dmenumon[2] = "0";
       -static const char *dmenucmd[] = { "dmenu_run", NULL };
       -static const char *termcmd[]  = { "xterm", NULL };
       -static const char *webcmd[]  = { "firefox", NULL };
       -static const char *musiccmd[]  = { "/home/jay/bin/music", NULL };
       -static const char *volup[] = { "sndioctl", "output.level=+0.1", NULL };
       -static const char *voldown[] = { "sndioctl", "output.level=-0.1", NULL };
       -
       -
       -static Key keys[] = {
       -        /* modifier                     key        function        argument */
       -        { MODKEY,                       XK_p,      spawn,          {.v = dmenucmd } },
       -        { MODKEY,                       XK_space,  spawn,          {.v = termcmd } },
       -        { MODKEY,                       XK_f,      spawn,          {.v = webcmd } },
       -        { MODKEY,                       XK_m,      spawn,          {.v = musiccmd } },
       -        { MODKEY,                       XF86XK_AudioRaiseVolume,      spawn,          {.v = volup } },
       -        { MODKEY,                       XF86XK_AudioLowerVolume,      spawn,          {.v = voldown } },
       -        { MODKEY,                       XK_j,      focusstack,     {.i = +1 } },
       -        { MODKEY,                       XK_k,      focusstack,     {.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,                       XK_c,      killclient,     {0} },
       -        { MODKEY|ShiftMask,             XK_m,      togglefullscreen, {0} },
       -        { MODKEY,                       XK_period, focusmon,       {.i = +1 } },
       -        { MODKEY,                        XK_comma,  tagmon,         {.i = +1 } },
       -        { MODKEY,                       XK_b,      togglebar,      {0} },
       -        { MODKEY,                       XK_x,      setlayout,      {.v = &layouts[0]} },
       -        { MODKEY|ShiftMask,             XK_x,      setlayout,      {.v = &layouts[1]} },
       -        TAGKEYS(                        XK_1,                      0)
       -        TAGKEYS(                        XK_2,                      1)
       -        TAGKEYS(                        XK_3,                      2)
       -        TAGKEYS(                        XK_4,                      3)
       -        TAGKEYS(                        XK_5,                      4)
       -        { MODKEY|ShiftMask,             XK_q,      quit,           {0} },
       -};
       -
       -/* button definitions */
       -static Button buttons[] = {
       -               { ClkRootWin,        0,              Button8,        spawn,          {.v = voldown } },
       -               { ClkRootWin,        0,              Button9,        spawn,          {.v = volup } },
       -        };
       -
       -void
       -togglefullscreen(const Arg *arg)
       -{
       -        if (!selmon->sel)
       -                return;
       -        setfullscreen(selmon->sel, !selmon->sel->isfullscreen);
       -}
       -
       -static void
       -bstack(Monitor *m) {
       -        int w, h, mh, mx, tx, ty, tw;
       -        unsigned int i, n;
       -        Client *c;
       -
       -        for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++);
       -        if (n == 0)
       -                return;
       -        if (n > m->nmaster) {
       -                mh = m->nmaster ? m->mfact * m->wh : 0;
       -                tw = m->ww / (n - m->nmaster);
       -                ty = m->wy + mh;
       -        } else {
       -                mh = m->wh;
       -                tw = m->ww;
       -                ty = m->wy;
       -        }
       -        for (i = mx = 0, tx = m->wx, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) {
       -                if (i < m->nmaster) {
       -                        w = (m->ww - mx) / (MIN(n, m->nmaster) - i);
       -                        resize(c, m->wx + mx, m->wy, w - (2 * c->bw), mh - (2 * c->bw), 0);
       -                        mx += WIDTH(c);
       -                } else {
       -                        h = m->wh - mh;
       -                        resize(c, tx, ty, tw - (2 * c->bw), h - (2 * c->bw), 0);
       -                        if (tw != m->ww)
       -                                tx += WIDTH(c);
       -                }
       -        }
       -}
       -
       -void
       -centeredfloatingmaster(Monitor *m)
       -{
       -        unsigned int i, n, w, mh, mw, mx, mxo, my, myo, tx;
       -        Client *c;
       -
       -        /* count number of clients in the selected monitor */
       -        for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++);
       -        if (n == 0)
       -                return;
       -
       -        /* initialize nmaster area */
       -        if (n > m->nmaster) {
       -                /* go mfact box in the center if more than nmaster clients */
       -                if (m->ww > m->wh) {
       -                        mw = m->nmaster ? m->ww * m->mfact : 0;
       -                        mh = m->nmaster ? m->wh * 0.9 : 0;
       -                } else {
       -                        mh = m->nmaster ? m->wh * m->mfact : 0;
       -                        mw = m->nmaster ? m->ww * 0.9 : 0;
       -                }
       -                mx = mxo = (m->ww - mw) / 2;
       -                my = myo = (m->wh - mh) / 2;
       -        } else {
       -                /* go fullscreen if all clients are in the master area */
       -                mh = m->wh;
       -                mw = m->ww;
       -                mx = mxo = 0;
       -                my = myo = 0;
       -        }
       -
       -        for(i = tx = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
       -        if (i < m->nmaster) {
       -                /* nmaster clients are stacked horizontally, in the center
       -                 * of the screen */
       -                w = (mw + mxo - mx) / (MIN(n, m->nmaster) - i);
       -                resize(c, m->wx + mx, m->wy + my, w - (2*c->bw),
       -                       mh - (2*c->bw), 0);
       -                mx += WIDTH(c);
       -        } else {
       -                /* stack clients are stacked horizontally */
       -                w = (m->ww - tx) / (n - i);
       -                resize(c, m->wx + tx, m->wy, w - (2*c->bw),
       -                       m->wh - (2*c->bw), 0);
       -                tx += WIDTH(c);
       -        }
       -}
 (DIR) diff --git a/suckless/dwm/patches/01-dwm-systray-6.4.diff b/suckless/dwm/patches/01-dwm-systray-6.4.diff
       @@ -1,746 +0,0 @@
       -diff --git a/config.def.h b/config.def.h
       -index 9efa774..750529d 100644
       ---- a/config.def.h
       -+++ b/config.def.h
       -@@ -3,6 +3,11 @@
       - /* appearance */
       - static const unsigned int borderpx  = 1;        /* border pixel of windows */
       - static const unsigned int snap      = 32;       /* snap pixel */
       -+static const unsigned int systraypinning = 0;   /* 0: sloppy systray follows selected monitor, >0: pin systray to monitor X */
       -+static const unsigned int systrayonleft = 0;    /* 0: systray in the right corner, >0: systray on left of status text */
       -+static const unsigned int systrayspacing = 2;   /* systray spacing */
       -+static const int systraypinningfailfirst = 1;   /* 1: if pinning fails, display systray on the first monitor, False: display systray on the last monitor*/
       -+static const int showsystray        = 1;        /* 0 means no systray */
       - 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" };
       -@@ -101,8 +106,8 @@ static const Key keys[] = {
       - /* 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]} },
       -+        { ClkTagBar,            MODKEY,         Button1,        tag,            {0} },
       -+        { ClkTagBar,            MODKEY,         Button3,        toggletag,      {0} },
       -         { ClkWinTitle,          0,              Button2,        zoom,           {0} },
       -         { ClkStatusText,        0,              Button2,        spawn,          {.v = termcmd } },
       -         { ClkClientWin,         MODKEY,         Button1,        movemouse,      {0} },
       -diff --git a/dwm.c b/dwm.c
       -index 03baf42..4611a03 100644
       ---- a/dwm.c
       -+++ b/dwm.c
       -@@ -57,12 +57,27 @@
       - #define TAGMASK                 ((1 << LENGTH(tags)) - 1)
       - #define TEXTW(X)                (drw_fontset_getwidth(drw, (X)) + lrpad)
       - 
       -+#define SYSTEM_TRAY_REQUEST_DOCK    0
       -+/* XEMBED messages */
       -+#define XEMBED_EMBEDDED_NOTIFY      0
       -+#define XEMBED_WINDOW_ACTIVATE      1
       -+#define XEMBED_FOCUS_IN             4
       -+#define XEMBED_MODALITY_ON         10
       -+#define XEMBED_MAPPED              (1 << 0)
       -+#define XEMBED_WINDOW_ACTIVATE      1
       -+#define XEMBED_WINDOW_DEACTIVATE    2
       -+#define VERSION_MAJOR               0
       -+#define VERSION_MINOR               0
       -+#define XEMBED_EMBEDDED_VERSION (VERSION_MAJOR << 16) | VERSION_MINOR
       -+
       - /* enums */
       - enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */
       - enum { SchemeNorm, SchemeSel }; /* color schemes */
       - enum { NetSupported, NetWMName, NetWMState, NetWMCheck,
       -+       NetSystemTray, NetSystemTrayOP, NetSystemTrayOrientation, NetSystemTrayOrientationHorz,
       -        NetWMFullscreen, NetActiveWindow, NetWMWindowType,
       -        NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */
       -+enum { Manager, Xembed, XembedInfo, XLast }; /* Xembed atoms */
       - enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */
       - enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle,
       -        ClkClientWin, ClkRootWin, ClkLast }; /* clicks */
       -@@ -141,6 +156,12 @@ typedef struct {
       -         int monitor;
       - } Rule;
       - 
       -+typedef struct Systray   Systray;
       -+struct Systray {
       -+        Window win;
       -+        Client *icons;
       -+};
       -+
       - /* function declarations */
       - static void applyrules(Client *c);
       - static int applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact);
       -@@ -172,6 +193,7 @@ 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 unsigned int getsystraywidth();
       - static int gettextprop(Window w, Atom atom, char *text, unsigned int size);
       - static void grabbuttons(Client *c, int focused);
       - static void grabkeys(void);
       -@@ -189,13 +211,16 @@ 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 removesystrayicon(Client *i);
       - static void resize(Client *c, int x, int y, int w, int h, int interact);
       -+static void resizebarwin(Monitor *m);
       - static void resizeclient(Client *c, int x, int y, int w, int h);
       - static void resizemouse(const Arg *arg);
       -+static void resizerequest(XEvent *e);
       - static void restack(Monitor *m);
       - static void run(void);
       - static void scan(void);
       --static int sendevent(Client *c, Atom proto);
       -+static int sendevent(Window w, Atom proto, int m, long d0, long d1, long d2, long d3, long d4);
       - static void sendmon(Client *c, Monitor *m);
       - static void setclientstate(Client *c, long state);
       - static void setfocus(Client *c);
       -@@ -207,6 +232,7 @@ static void seturgent(Client *c, int urg);
       - static void showhide(Client *c);
       - static void sigchld(int unused);
       - static void spawn(const Arg *arg);
       -+static Monitor *systraytomon(Monitor *m);
       - static void tag(const Arg *arg);
       - static void tagmon(const Arg *arg);
       - static void tile(Monitor *m);
       -@@ -224,18 +250,23 @@ static int updategeom(void);
       - static void updatenumlockmask(void);
       - static void updatesizehints(Client *c);
       - static void updatestatus(void);
       -+static void updatesystray(void);
       -+static void updatesystrayicongeom(Client *i, int w, int h);
       -+static void updatesystrayiconstate(Client *i, XPropertyEvent *ev);
       - 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 Client *wintosystrayicon(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 Systray *systray = NULL;
       - static const char broken[] = "broken";
       - static char stext[256];
       - static int screen;
       -@@ -258,9 +289,10 @@ static void (*handler[LASTEvent]) (XEvent *) = {
       -         [MapRequest] = maprequest,
       -         [MotionNotify] = motionnotify,
       -         [PropertyNotify] = propertynotify,
       -+        [ResizeRequest] = resizerequest,
       -         [UnmapNotify] = unmapnotify
       - };
       --static Atom wmatom[WMLast], netatom[NetLast];
       -+static Atom wmatom[WMLast], netatom[NetLast], xatom[XLast];
       - static int running = 1;
       - static Cur *cursor[CurLast];
       - static Clr **scheme;
       -@@ -442,7 +474,7 @@ buttonpress(XEvent *e)
       -                         arg.ui = 1 << i;
       -                 } else if (ev->x < x + TEXTW(selmon->ltsymbol))
       -                         click = ClkLtSymbol;
       --                else if (ev->x > selmon->ww - (int)TEXTW(stext))
       -+                else if (ev->x > selmon->ww - (int)TEXTW(stext) - getsystraywidth())
       -                         click = ClkStatusText;
       -                 else
       -                         click = ClkWinTitle;
       -@@ -485,6 +517,13 @@ cleanup(void)
       -         XUngrabKey(dpy, AnyKey, AnyModifier, root);
       -         while (mons)
       -                 cleanupmon(mons);
       -+
       -+        if (showsystray) {
       -+                XUnmapWindow(dpy, systray->win);
       -+                XDestroyWindow(dpy, systray->win);
       -+                free(systray);
       -+        }
       -+
       -         for (i = 0; i < CurLast; i++)
       -                 drw_cur_free(drw, cursor[i]);
       -         for (i = 0; i < LENGTH(colors); i++)
       -@@ -516,9 +555,58 @@ cleanupmon(Monitor *mon)
       - void
       - clientmessage(XEvent *e)
       - {
       -+        XWindowAttributes wa;
       -+        XSetWindowAttributes swa;
       -         XClientMessageEvent *cme = &e->xclient;
       -         Client *c = wintoclient(cme->window);
       - 
       -+        if (showsystray && cme->window == systray->win && cme->message_type == netatom[NetSystemTrayOP]) {
       -+                /* add systray icons */
       -+                if (cme->data.l[1] == SYSTEM_TRAY_REQUEST_DOCK) {
       -+                        if (!(c = (Client *)calloc(1, sizeof(Client))))
       -+                                die("fatal: could not malloc() %u bytes\n", sizeof(Client));
       -+                        if (!(c->win = cme->data.l[2])) {
       -+                                free(c);
       -+                                return;
       -+                        }
       -+                        c->mon = selmon;
       -+                        c->next = systray->icons;
       -+                        systray->icons = c;
       -+                        if (!XGetWindowAttributes(dpy, c->win, &wa)) {
       -+                                /* use sane defaults */
       -+                                wa.width = bh;
       -+                                wa.height = bh;
       -+                                wa.border_width = 0;
       -+                        }
       -+                        c->x = c->oldx = c->y = c->oldy = 0;
       -+                        c->w = c->oldw = wa.width;
       -+                        c->h = c->oldh = wa.height;
       -+                        c->oldbw = wa.border_width;
       -+                        c->bw = 0;
       -+                        c->isfloating = True;
       -+                        /* reuse tags field as mapped status */
       -+                        c->tags = 1;
       -+                        updatesizehints(c);
       -+                        updatesystrayicongeom(c, wa.width, wa.height);
       -+                        XAddToSaveSet(dpy, c->win);
       -+                        XSelectInput(dpy, c->win, StructureNotifyMask | PropertyChangeMask | ResizeRedirectMask);
       -+                        XReparentWindow(dpy, c->win, systray->win, 0, 0);
       -+                        /* use parents background color */
       -+                        swa.background_pixel  = scheme[SchemeNorm][ColBg].pixel;
       -+                        XChangeWindowAttributes(dpy, c->win, CWBackPixel, &swa);
       -+                        sendevent(c->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_EMBEDDED_NOTIFY, 0 , systray->win, XEMBED_EMBEDDED_VERSION);
       -+                        /* FIXME not sure if I have to send these events, too */
       -+                        sendevent(c->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_FOCUS_IN, 0 , systray->win, XEMBED_EMBEDDED_VERSION);
       -+                        sendevent(c->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_WINDOW_ACTIVATE, 0 , systray->win, XEMBED_EMBEDDED_VERSION);
       -+                        sendevent(c->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_MODALITY_ON, 0 , systray->win, XEMBED_EMBEDDED_VERSION);
       -+                        XSync(dpy, False);
       -+                        resizebarwin(selmon);
       -+                        updatesystray();
       -+                        setclientstate(c, NormalState);
       -+                }
       -+                return;
       -+        }
       -+
       -         if (!c)
       -                 return;
       -         if (cme->message_type == netatom[NetWMState]) {
       -@@ -571,7 +659,7 @@ configurenotify(XEvent *e)
       -                                 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);
       -+                                resizebarwin(m);
       -                         }
       -                         focus(NULL);
       -                         arrange(NULL);
       -@@ -656,6 +744,11 @@ destroynotify(XEvent *e)
       - 
       -         if ((c = wintoclient(ev->window)))
       -                 unmanage(c, 1);
       -+        else if ((c = wintosystrayicon(ev->window))) {
       -+                removesystrayicon(c);
       -+                resizebarwin(selmon);
       -+                updatesystray();
       -+        }
       - }
       - 
       - void
       -@@ -699,7 +792,7 @@ dirtomon(int dir)
       - void
       - drawbar(Monitor *m)
       - {
       --        int x, w, tw = 0;
       -+        int x, w, tw = 0, stw = 0;
       -         int boxs = drw->fonts->h / 9;
       -         int boxw = drw->fonts->h / 6 + 2;
       -         unsigned int i, occ = 0, urg = 0;
       -@@ -708,13 +801,17 @@ drawbar(Monitor *m)
       -         if (!m->showbar)
       -                 return;
       - 
       -+        if(showsystray && m == systraytomon(m) && !systrayonleft)
       -+                stw = getsystraywidth();
       -+
       -         /* 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);
       -+                tw = TEXTW(stext) - lrpad / 2 + 2; /* 2px extra right padding */
       -+                drw_text(drw, m->ww - tw - stw, 0, tw, bh, lrpad / 2 - 2, stext, 0);
       -         }
       - 
       -+        resizebarwin(m);
       -         for (c = m->clients; c; c = c->next) {
       -                 occ |= c->tags;
       -                 if (c->isurgent)
       -@@ -735,7 +832,7 @@ drawbar(Monitor *m)
       -         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 ((w = m->ww - tw - stw - 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);
       -@@ -746,7 +843,7 @@ drawbar(Monitor *m)
       -                         drw_rect(drw, x, 0, w, bh, 1, 1);
       -                 }
       -         }
       --        drw_map(drw, m->barwin, 0, 0, m->ww, bh);
       -+        drw_map(drw, m->barwin, 0, 0, m->ww - stw, bh);
       - }
       - 
       - void
       -@@ -783,8 +880,11 @@ expose(XEvent *e)
       -         Monitor *m;
       -         XExposeEvent *ev = &e->xexpose;
       - 
       --        if (ev->count == 0 && (m = wintomon(ev->window)))
       -+        if (ev->count == 0 && (m = wintomon(ev->window))) {
       -                 drawbar(m);
       -+                if (m == selmon)
       -+                        updatesystray();
       -+        }
       - }
       - 
       - void
       -@@ -870,14 +970,32 @@ getatomprop(Client *c, Atom prop)
       -         unsigned char *p = NULL;
       -         Atom da, atom = None;
       - 
       --        if (XGetWindowProperty(dpy, c->win, prop, 0L, sizeof atom, False, XA_ATOM,
       -+        /* FIXME getatomprop should return the number of items and a pointer to
       -+         * the stored data instead of this workaround */
       -+        Atom req = XA_ATOM;
       -+        if (prop == xatom[XembedInfo])
       -+                req = xatom[XembedInfo];
       -+
       -+        if (XGetWindowProperty(dpy, c->win, prop, 0L, sizeof atom, False, req,
       -                 &da, &di, &dl, &dl, &p) == Success && p) {
       -                 atom = *(Atom *)p;
       -+                if (da == xatom[XembedInfo] && dl == 2)
       -+                        atom = ((Atom *)p)[1];
       -                 XFree(p);
       -         }
       -         return atom;
       - }
       - 
       -+unsigned int
       -+getsystraywidth()
       -+{
       -+        unsigned int w = 0;
       -+        Client *i;
       -+        if(showsystray)
       -+                for(i = systray->icons; i; w += i->w + systrayspacing, i = i->next) ;
       -+        return w ? w + systrayspacing : 1;
       -+}
       -+
       - int
       - getrootptr(int *x, int *y)
       - {
       -@@ -1018,7 +1136,8 @@ killclient(const Arg *arg)
       - {
       -         if (!selmon->sel)
       -                 return;
       --        if (!sendevent(selmon->sel, wmatom[WMDelete])) {
       -+
       -+        if (!sendevent(selmon->sel->win, wmatom[WMDelete], NoEventMask, wmatom[WMDelete], CurrentTime, 0 , 0, 0)) {
       -                 XGrabServer(dpy);
       -                 XSetErrorHandler(xerrordummy);
       -                 XSetCloseDownMode(dpy, DestroyAll);
       -@@ -1105,6 +1224,13 @@ maprequest(XEvent *e)
       -         static XWindowAttributes wa;
       -         XMapRequestEvent *ev = &e->xmaprequest;
       - 
       -+        Client *i;
       -+        if ((i = wintosystrayicon(ev->window))) {
       -+                sendevent(i->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_WINDOW_ACTIVATE, 0, systray->win, XEMBED_EMBEDDED_VERSION);
       -+                resizebarwin(selmon);
       -+                updatesystray();
       -+        }
       -+
       -         if (!XGetWindowAttributes(dpy, ev->window, &wa) || wa.override_redirect)
       -                 return;
       -         if (!wintoclient(ev->window))
       -@@ -1226,6 +1352,17 @@ propertynotify(XEvent *e)
       -         Window trans;
       -         XPropertyEvent *ev = &e->xproperty;
       - 
       -+        if ((c = wintosystrayicon(ev->window))) {
       -+                if (ev->atom == XA_WM_NORMAL_HINTS) {
       -+                        updatesizehints(c);
       -+                        updatesystrayicongeom(c, c->w, c->h);
       -+                }
       -+                else
       -+                        updatesystrayiconstate(c, ev);
       -+                resizebarwin(selmon);
       -+                updatesystray();
       -+        }
       -+
       -         if ((ev->window == root) && (ev->atom == XA_WM_NAME))
       -                 updatestatus();
       -         else if (ev->state == PropertyDelete)
       -@@ -1276,6 +1413,19 @@ recttomon(int x, int y, int w, int h)
       -         return r;
       - }
       - 
       -+void
       -+removesystrayicon(Client *i)
       -+{
       -+        Client **ii;
       -+
       -+        if (!showsystray || !i)
       -+                return;
       -+        for (ii = &systray->icons; *ii && *ii != i; ii = &(*ii)->next);
       -+        if (ii)
       -+                *ii = i->next;
       -+        free(i);
       -+}
       -+
       - void
       - resize(Client *c, int x, int y, int w, int h, int interact)
       - {
       -@@ -1283,6 +1433,14 @@ resize(Client *c, int x, int y, int w, int h, int interact)
       -                 resizeclient(c, x, y, w, h);
       - }
       - 
       -+void
       -+resizebarwin(Monitor *m) {
       -+        unsigned int w = m->ww;
       -+        if (showsystray && m == systraytomon(m) && !systrayonleft)
       -+                w -= getsystraywidth();
       -+        XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, w, bh);
       -+}
       -+
       - void
       - resizeclient(Client *c, int x, int y, int w, int h)
       - {
       -@@ -1298,6 +1456,19 @@ resizeclient(Client *c, int x, int y, int w, int h)
       -         XSync(dpy, False);
       - }
       - 
       -+void
       -+resizerequest(XEvent *e)
       -+{
       -+        XResizeRequestEvent *ev = &e->xresizerequest;
       -+        Client *i;
       -+
       -+        if ((i = wintosystrayicon(ev->window))) {
       -+                updatesystrayicongeom(i, ev->width, ev->height);
       -+                resizebarwin(selmon);
       -+                updatesystray();
       -+        }
       -+}
       -+
       - void
       - resizemouse(const Arg *arg)
       - {
       -@@ -1444,26 +1615,37 @@ setclientstate(Client *c, long state)
       - }
       - 
       - int
       --sendevent(Client *c, Atom proto)
       -+sendevent(Window w, Atom proto, int mask, long d0, long d1, long d2, long d3, long d4)
       - {
       -         int n;
       --        Atom *protocols;
       -+        Atom *protocols, mt;
       -         int exists = 0;
       -         XEvent ev;
       - 
       --        if (XGetWMProtocols(dpy, c->win, &protocols, &n)) {
       --                while (!exists && n--)
       --                        exists = protocols[n] == proto;
       --                XFree(protocols);
       -+        if (proto == wmatom[WMTakeFocus] || proto == wmatom[WMDelete]) {
       -+                mt = wmatom[WMProtocols];
       -+                if (XGetWMProtocols(dpy, w, &protocols, &n)) {
       -+                        while (!exists && n--)
       -+                                exists = protocols[n] == proto;
       -+                        XFree(protocols);
       -+                }
       -+        }
       -+        else {
       -+                exists = True;
       -+                mt = proto;
       -         }
       -+
       -         if (exists) {
       -                 ev.type = ClientMessage;
       --                ev.xclient.window = c->win;
       --                ev.xclient.message_type = wmatom[WMProtocols];
       -+                ev.xclient.window = w;
       -+                ev.xclient.message_type = mt;
       -                 ev.xclient.format = 32;
       --                ev.xclient.data.l[0] = proto;
       --                ev.xclient.data.l[1] = CurrentTime;
       --                XSendEvent(dpy, c->win, False, NoEventMask, &ev);
       -+                ev.xclient.data.l[0] = d0;
       -+                ev.xclient.data.l[1] = d1;
       -+                ev.xclient.data.l[2] = d2;
       -+                ev.xclient.data.l[3] = d3;
       -+                ev.xclient.data.l[4] = d4;
       -+                XSendEvent(dpy, w, False, mask, &ev);
       -         }
       -         return exists;
       - }
       -@@ -1477,7 +1659,7 @@ setfocus(Client *c)
       -                         XA_WINDOW, 32, PropModeReplace,
       -                         (unsigned char *) &(c->win), 1);
       -         }
       --        sendevent(c, wmatom[WMTakeFocus]);
       -+        sendevent(c->win, wmatom[WMTakeFocus], NoEventMask, wmatom[WMTakeFocus], CurrentTime, 0, 0, 0);
       - }
       - 
       - void
       -@@ -1566,6 +1748,10 @@ setup(void)
       -         wmatom[WMTakeFocus] = XInternAtom(dpy, "WM_TAKE_FOCUS", False);
       -         netatom[NetActiveWindow] = XInternAtom(dpy, "_NET_ACTIVE_WINDOW", False);
       -         netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False);
       -+        netatom[NetSystemTray] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_S0", False);
       -+        netatom[NetSystemTrayOP] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_OPCODE", False);
       -+        netatom[NetSystemTrayOrientation] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_ORIENTATION", False);
       -+        netatom[NetSystemTrayOrientationHorz] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_ORIENTATION_HORZ", 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);
       -@@ -1573,6 +1759,9 @@ setup(void)
       -         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);
       -+        xatom[Manager] = XInternAtom(dpy, "MANAGER", False);
       -+        xatom[Xembed] = XInternAtom(dpy, "_XEMBED", False);
       -+        xatom[XembedInfo] = XInternAtom(dpy, "_XEMBED_INFO", False);
       -         /* init cursors */
       -         cursor[CurNormal] = drw_cur_create(drw, XC_left_ptr);
       -         cursor[CurResize] = drw_cur_create(drw, XC_sizing);
       -@@ -1581,6 +1770,8 @@ setup(void)
       -         scheme = ecalloc(LENGTH(colors), sizeof(Clr *));
       -         for (i = 0; i < LENGTH(colors); i++)
       -                 scheme[i] = drw_scm_create(drw, colors[i], 3);
       -+        /* init system tray */
       -+        updatesystray();
       -         /* init bars */
       -         updatebars();
       -         updatestatus();
       -@@ -1711,7 +1902,18 @@ togglebar(const Arg *arg)
       - {
       -         selmon->showbar = !selmon->showbar;
       -         updatebarpos(selmon);
       --        XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, bh);
       -+        resizebarwin(selmon);
       -+        if (showsystray) {
       -+                XWindowChanges wc;
       -+                if (!selmon->showbar)
       -+                        wc.y = -bh;
       -+                else if (selmon->showbar) {
       -+                        wc.y = 0;
       -+                        if (!selmon->topbar)
       -+                                wc.y = selmon->mh - bh;
       -+                }
       -+                XConfigureWindow(dpy, systray->win, CWY, &wc);
       -+        }
       -         arrange(selmon);
       - }
       - 
       -@@ -1807,11 +2009,18 @@ unmapnotify(XEvent *e)
       -                 else
       -                         unmanage(c, 0);
       -         }
       -+        else if ((c = wintosystrayicon(ev->window))) {
       -+                /* KLUDGE! sometimes icons occasionally unmap their windows, but do
       -+                 * _not_ destroy them. We map those windows back */
       -+                XMapRaised(dpy, c->win);
       -+                updatesystray();
       -+        }
       - }
       - 
       - void
       - updatebars(void)
       - {
       -+        unsigned int w;
       -         Monitor *m;
       -         XSetWindowAttributes wa = {
       -                 .override_redirect = True,
       -@@ -1822,10 +2031,15 @@ updatebars(void)
       -         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),
       -+                w = m->ww;
       -+                if (showsystray && m == systraytomon(m))
       -+                        w -= getsystraywidth();
       -+                m->barwin = XCreateWindow(dpy, root, m->wx, m->by, w, bh, 0, DefaultDepth(dpy, screen),
       -                                 CopyFromParent, DefaultVisual(dpy, screen),
       -                                 CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa);
       -                 XDefineCursor(dpy, m->barwin, cursor[CurNormal]->cursor);
       -+                if (showsystray && m == systraytomon(m))
       -+                        XMapRaised(dpy, systray->win);
       -                 XMapRaised(dpy, m->barwin);
       -                 XSetClassHint(dpy, m->barwin, &ch);
       -         }
       -@@ -2002,6 +2216,125 @@ updatestatus(void)
       -         if (!gettextprop(root, XA_WM_NAME, stext, sizeof(stext)))
       -                 strcpy(stext, "dwm-"VERSION);
       -         drawbar(selmon);
       -+        updatesystray();
       -+}
       -+
       -+
       -+void
       -+updatesystrayicongeom(Client *i, int w, int h)
       -+{
       -+        if (i) {
       -+                i->h = bh;
       -+                if (w == h)
       -+                        i->w = bh;
       -+                else if (h == bh)
       -+                        i->w = w;
       -+                else
       -+                        i->w = (int) ((float)bh * ((float)w / (float)h));
       -+                applysizehints(i, &(i->x), &(i->y), &(i->w), &(i->h), False);
       -+                /* force icons into the systray dimensions if they don't want to */
       -+                if (i->h > bh) {
       -+                        if (i->w == i->h)
       -+                                i->w = bh;
       -+                        else
       -+                                i->w = (int) ((float)bh * ((float)i->w / (float)i->h));
       -+                        i->h = bh;
       -+                }
       -+        }
       -+}
       -+
       -+void
       -+updatesystrayiconstate(Client *i, XPropertyEvent *ev)
       -+{
       -+        long flags;
       -+        int code = 0;
       -+
       -+        if (!showsystray || !i || ev->atom != xatom[XembedInfo] ||
       -+                        !(flags = getatomprop(i, xatom[XembedInfo])))
       -+                return;
       -+
       -+        if (flags & XEMBED_MAPPED && !i->tags) {
       -+                i->tags = 1;
       -+                code = XEMBED_WINDOW_ACTIVATE;
       -+                XMapRaised(dpy, i->win);
       -+                setclientstate(i, NormalState);
       -+        }
       -+        else if (!(flags & XEMBED_MAPPED) && i->tags) {
       -+                i->tags = 0;
       -+                code = XEMBED_WINDOW_DEACTIVATE;
       -+                XUnmapWindow(dpy, i->win);
       -+                setclientstate(i, WithdrawnState);
       -+        }
       -+        else
       -+                return;
       -+        sendevent(i->win, xatom[Xembed], StructureNotifyMask, CurrentTime, code, 0,
       -+                        systray->win, XEMBED_EMBEDDED_VERSION);
       -+}
       -+
       -+void
       -+updatesystray(void)
       -+{
       -+        XSetWindowAttributes wa;
       -+        XWindowChanges wc;
       -+        Client *i;
       -+        Monitor *m = systraytomon(NULL);
       -+        unsigned int x = m->mx + m->mw;
       -+        unsigned int sw = TEXTW(stext) - lrpad + systrayspacing;
       -+        unsigned int w = 1;
       -+
       -+        if (!showsystray)
       -+                return;
       -+        if (systrayonleft)
       -+                x -= sw + lrpad / 2;
       -+        if (!systray) {
       -+                /* init systray */
       -+                if (!(systray = (Systray *)calloc(1, sizeof(Systray))))
       -+                        die("fatal: could not malloc() %u bytes\n", sizeof(Systray));
       -+                systray->win = XCreateSimpleWindow(dpy, root, x, m->by, w, bh, 0, 0, scheme[SchemeSel][ColBg].pixel);
       -+                wa.event_mask        = ButtonPressMask | ExposureMask;
       -+                wa.override_redirect = True;
       -+                wa.background_pixel  = scheme[SchemeNorm][ColBg].pixel;
       -+                XSelectInput(dpy, systray->win, SubstructureNotifyMask);
       -+                XChangeProperty(dpy, systray->win, netatom[NetSystemTrayOrientation], XA_CARDINAL, 32,
       -+                                PropModeReplace, (unsigned char *)&netatom[NetSystemTrayOrientationHorz], 1);
       -+                XChangeWindowAttributes(dpy, systray->win, CWEventMask|CWOverrideRedirect|CWBackPixel, &wa);
       -+                XMapRaised(dpy, systray->win);
       -+                XSetSelectionOwner(dpy, netatom[NetSystemTray], systray->win, CurrentTime);
       -+                if (XGetSelectionOwner(dpy, netatom[NetSystemTray]) == systray->win) {
       -+                        sendevent(root, xatom[Manager], StructureNotifyMask, CurrentTime, netatom[NetSystemTray], systray->win, 0, 0);
       -+                        XSync(dpy, False);
       -+                }
       -+                else {
       -+                        fprintf(stderr, "dwm: unable to obtain system tray.\n");
       -+                        free(systray);
       -+                        systray = NULL;
       -+                        return;
       -+                }
       -+        }
       -+        for (w = 0, i = systray->icons; i; i = i->next) {
       -+                /* make sure the background color stays the same */
       -+                wa.background_pixel  = scheme[SchemeNorm][ColBg].pixel;
       -+                XChangeWindowAttributes(dpy, i->win, CWBackPixel, &wa);
       -+                XMapRaised(dpy, i->win);
       -+                w += systrayspacing;
       -+                i->x = w;
       -+                XMoveResizeWindow(dpy, i->win, i->x, 0, i->w, i->h);
       -+                w += i->w;
       -+                if (i->mon != m)
       -+                        i->mon = m;
       -+        }
       -+        w = w ? w + systrayspacing : 1;
       -+        x -= w;
       -+        XMoveResizeWindow(dpy, systray->win, x, m->by, w, bh);
       -+        wc.x = x; wc.y = m->by; wc.width = w; wc.height = bh;
       -+        wc.stack_mode = Above; wc.sibling = m->barwin;
       -+        XConfigureWindow(dpy, systray->win, CWX|CWY|CWWidth|CWHeight|CWSibling|CWStackMode, &wc);
       -+        XMapWindow(dpy, systray->win);
       -+        XMapSubwindows(dpy, systray->win);
       -+        /* redraw background */
       -+        XSetForeground(dpy, drw->gc, scheme[SchemeNorm][ColBg].pixel);
       -+        XFillRectangle(dpy, systray->win, drw->gc, 0, 0, w, bh);
       -+        XSync(dpy, False);
       - }
       - 
       - void
       -@@ -2069,6 +2402,16 @@ wintoclient(Window w)
       -         return NULL;
       - }
       - 
       -+Client *
       -+wintosystrayicon(Window w) {
       -+        Client *i = NULL;
       -+
       -+        if (!showsystray || !w)
       -+                return i;
       -+        for (i = systray->icons; i && i->win != w; i = i->next) ;
       -+        return i;
       -+}
       -+
       - Monitor *
       - wintomon(Window w)
       - {
       -@@ -2122,6 +2465,22 @@ xerrorstart(Display *dpy, XErrorEvent *ee)
       -         return -1;
       - }
       - 
       -+Monitor *
       -+systraytomon(Monitor *m) {
       -+        Monitor *t;
       -+        int i, n;
       -+        if(!systraypinning) {
       -+                if(!m)
       -+                        return selmon;
       -+                return m == selmon ? m : NULL;
       -+        }
       -+        for(n = 1, t = mons; t && t->next; n++, t = t->next) ;
       -+        for(i = 1, t = mons; t && t->next && i < systraypinning; i++, t = t->next) ;
       -+        if(systraypinningfailfirst && n < systraypinning)
       -+                return mons;
       -+        return t;
       -+}
       -+
       - void
       - zoom(const Arg *arg)
       - {
 (DIR) diff --git a/suckless/herbe/Makefile b/suckless/herbe/Makefile
       @@ -1,40 +0,0 @@
       -REPOSITORY = https://github.com/dudik/herbe.git
       -SRC_DIR = src
       -PINNED_REVISION = HEAD
       -PATCH_DIR = patches
       -
       -all: $(SRC_DIR)
       -
       -clean: reset
       -        @if test -d $(SRC_DIR); then \
       -                $(MAKE) -C "${SRC_DIR}" -s clean; \
       -                git -C "${SRC_DIR}" clean -f; \
       -        fi
       -
       -$(SRC_DIR): clone reset
       -        @cp config.h $@
       -        $(MAKE) -C "${SRC_DIR}" -s
       -
       -reset:
       -        @if [ -n "$(strip $(PINNED_REVISION))" ]; then \
       -                git -C "${SRC_DIR}" reset --hard $(PINNED_REVISION); \
       -        fi
       -
       -patch: $(PATCH_DIR)/*
       -        @for file in $^ ; do \
       -                patch -d "${SRC_DIR}" < $${file}; \
       -        done
       -
       -clone:
       -        @if ! test -d $(SRC_DIR); then \
       -                git clone $(REPOSITORY) $(SRC_DIR); \
       -        fi
       -
       -update: clean
       -        @git -C "${SRC_DIR}" pull
       -
       -install:
       -        $(MAKE) -C "${SRC_DIR}" -s install
       -
       -
       -.PHONY: all clean update install reset clone
 (DIR) diff --git a/suckless/herbe/config.h b/suckless/herbe/config.h
       @@ -1,19 +0,0 @@
       -static const char *background_color = "#222222";
       -static const char *border_color = "#008000";
       -static const char *font_color = "#ffd7af";
       -static const char *font_pattern = "Hack:pixelsize=12";
       -static unsigned line_spacing = 5;
       -static unsigned int padding = 12;
       -
       -static unsigned int width = 300;
       -static unsigned int border_size = 3;
       -static unsigned int pos_x = 30;
       -static unsigned int pos_y = 60;
       -
       -enum corners { TOP_LEFT, TOP_RIGHT, BOTTOM_LEFT, BOTTOM_RIGHT };
       -enum corners corner = TOP_RIGHT;
       -
       -static unsigned int duration = 5; /* in seconds */
       -
       -#define DISMISS_BUTTON Button1
       -#define ACTION_BUTTON Button3
 (DIR) diff --git a/suckless/slstatus/Makefile b/suckless/slstatus/Makefile
       @@ -1,35 +0,0 @@
       -REPOSITORY = git://git.suckless.org/slstatus
       -SRC_DIR = src
       -PINNED_REVISION = HEAD
       -
       -all: $(SRC_DIR)
       -
       -clean: reset
       -        @if test -d $(SRC_DIR); then \
       -                cd $(SRC_DIR); \
       -                $(MAKE) -s clean; \
       -                git clean -f; \
       -        fi
       -
       -$(SRC_DIR): clone reset
       -        @cp config.h $@
       -        @cd $@ && $(MAKE) -s
       -
       -reset:
       -        @if [ -n "$(strip $(PINNED_REVISION))" ]; then \
       -                cd $(SRC_DIR) && git reset --hard $(PINNED_REVISION); \
       -        fi
       -
       -clone:
       -        @if ! test -d $(SRC_DIR); then \
       -                git clone $(REPOSITORY) $(SRC_DIR); \
       -        fi
       -
       -update: clean
       -        @cd $(SRC_DIR) && git pull
       -
       -install:
       -        $(MAKE) -C "${SRC_DIR}" -s install
       -
       -
       -.PHONY: all clean update install reset clone
 (DIR) diff --git a/suckless/slstatus/config.h b/suckless/slstatus/config.h
       @@ -1,71 +0,0 @@
       -/* See LICENSE file for copyright and license details. */
       -
       -/* interval between updates (in ms) */
       -const unsigned int interval = 60000;
       -
       -/* text to show if no value can be retrieved */
       -static const char unknown_str[] = "n/a";
       -
       -/* maximum output string length */
       -#define MAXLEN 2048
       -
       -/*
       - * function            description                     argument (example)
       - *
       - * battery_perc        battery percentage              battery name (BAT0)
       - *                                                     NULL on OpenBSD/FreeBSD
       - * battery_remaining   battery remaining HH:MM         battery name (BAT0)
       - *                                                     NULL on OpenBSD/FreeBSD
       - * battery_state       battery charging state          battery name (BAT0)
       - *                                                     NULL on OpenBSD/FreeBSD
       - * cat                 read arbitrary file             path
       - * cpu_freq            cpu frequency in MHz            NULL
       - * cpu_perc            cpu usage in percent            NULL
       - * datetime            date and time                   format string (%F %T)
       - * disk_free           free disk space in GB           mountpoint path (/)
       - * disk_perc           disk usage in percent           mountpoint path (/)
       - * disk_total          total disk space in GB          mountpoint path (/)
       - * disk_used           used disk space in GB           mountpoint path (/)
       - * entropy             available entropy               NULL
       - * gid                 GID of current user             NULL
       - * hostname            hostname                        NULL
       - * ipv4                IPv4 address                    interface name (eth0)
       - * ipv6                IPv6 address                    interface name (eth0)
       - * kernel_release      `uname -r`                      NULL
       - * keyboard_indicators caps/num lock indicators        format string (c?n?)
       - *                                                     see keyboard_indicators.c
       - * keymap              layout (variant) of current     NULL
       - *                     keymap
       - * load_avg            load average                    NULL
       - * netspeed_rx         receive network speed           interface name (wlan0)
       - * netspeed_tx         transfer network speed          interface name (wlan0)
       - * num_files           number of files in a directory  path
       - *                                                     (/home/foo/Inbox/cur)
       - * ram_free            free memory in GB               NULL
       - * ram_perc            memory usage in percent         NULL
       - * ram_total           total memory size in GB         NULL
       - * ram_used            used memory in GB               NULL
       - * run_command         custom shell command            command (echo foo)
       - * swap_free           free swap in GB                 NULL
       - * swap_perc           swap usage in percent           NULL
       - * swap_total          total swap size in GB           NULL
       - * swap_used           used swap in GB                 NULL
       - * temp                temperature in degree celsius   sensor file
       - *                                                     (/sys/class/thermal/...)
       - *                                                     NULL on OpenBSD
       - *                                                     thermal zone on FreeBSD
       - *                                                     (tz0, tz1, etc.)
       - * uid                 UID of current user             NULL
       - * uptime              system uptime                   NULL
       - * username            username of current user        NULL
       - * vol_perc            OSS/ALSA volume in percent      mixer file (/dev/mixer)
       - *                                                     NULL on OpenBSD/FreeBSD
       - * wifi_essid          WiFi ESSID                      interface name (wlan0)
       - * wifi_perc           WiFi signal in percent          interface name (wlan0)
       - */
       -static const struct arg args[] = {
       -        /* function format          argument */
       -        { run_command, "VPN:%4s | ", "if curl -s https://am.i.mullvad.net/connected | grep -q 'server'; then echo 'On'; else echo 'Off'; fi" },
       -        { vol_perc, "VOL:%s | ", NULL },
       -        { datetime, "%s", "%H:%M" },
       -};
 (DIR) diff --git a/xsession b/xsession
       @@ -7,4 +7,5 @@ slstatus &
        mpd &
        
        # window manager
       -exec dwm
       +#exec dwm
       +exec cwm