ref: a4c1f8359d8e4aadf881585ecb137cf6d4904ce2
author: kitzman <[email protected]>
date: Fri Nov 17 11:15:00 EST 2023
first commit
--- /dev/null
+++ b/bin/rc/chatcat
@@ -1,0 +1,6 @@
+#!/bin/rc
+chan=$1
+label $chan
+echo JOIN $nick to chat >>/n/chat.9p.zone/$chan
+cat /n/chat.9p.zone/$chan &
+while() cat | sed '1s/^/'$nick' → /' >>/n/chat.9p.zone/$chan
--- /dev/null
+++ b/bin/rc/gemhist
@@ -1,0 +1,6 @@
+#!/bin/rc
+
+while(){
+ syscall -o read 0 buf 512 </mnt/plumb/gemini >[2]/dev/null | tail -1
+ echo ''
+}
--- /dev/null
+++ b/bin/rc/gfetch
@@ -1,0 +1,80 @@
+#!/bin/rc
+# Warning, parts of this script have been STOLEN!
+
+# TODO:
+# fs usage
+# kernel
+
+fn storage {
+ disks = `{ls -d /dev/sd* | uniq}
+ anydisk = 'false'
+ for(i in $disks){
+ if(test -f $i/data){
+ full = `{ls -l $i/data}
+ disk = `{echo $full | awk -F '/' '{print $3}'}
+ size = `{echo $full | awk '{print $6}'}
+ echo $disk^': '^`{echo $size^' / 1024 / 1024 /1024' | bc}^GB
+ anydisk = 'true'
+ }
+ }
+ if(~ $anydisk -c 'false')
+ echo Running in the diskless
+}
+
+fn fs {
+ if(ls /srv | grep -s '*.cmd')
+ ls /srv/*.cmd | sed 's/.cmd//g' | sed 's/\/srv\///g'
+ if(test -f /srv/fscons)
+ echo fossil
+ # Logic from storage to scrape for venti arenas
+ v='false'
+ disks = `{ls -d /dev/sd* | uniq}
+ for(i in $disks){
+ if(ls $i | grep -s arena)
+ v='true'
+ }
+ if(~ $v -c 'true')
+ echo venti
+}
+
+fn cpuid {
+ if(test -f /bin/aux/cpuid)
+ aux/cpuid >[2]/dev/null | grep procname | sed 's/.*procname//'
+}
+
+os=`{
+ if(grep -s 'zrv' /dev/drivers)
+ echo 9ants
+ if not if(grep -s 'vmx' /dev/drivers)
+ echo 9front
+ if not
+ echo Bell Labs
+}
+
+# fs and storage require #S bound on /dev
+bind -b '#S' /dev
+
+arch=`{echo $cputype}
+shell=/bin/rc
+uptime=`{uptime| sed 's/.*up//; s/..........$//'}
+scr=`{dd -count 1 < /dev/screen|[2];}
+scr=($scr(4) x $scr(5))
+ram=(`{tr / ' '</dev/swap})
+free=`{echo $ram(1)'/1024^2'|bc}
+used=`{echo '('$ram(3)'*('$ram(7)^+$ram(5)^'))/1024^2'|bc}
+cpu=`{cpuid}
+files=`{fs}
+strg=`{storage}
+
+cat <<EOF
+ $user@$sysname
+ (\(\ -----------
+ j". .. os: Plan 9 from $os/$arch
+ ( . .) shell: $shell
+ | ° ¡ uptime: $uptime
+ ¿ ; ram: $used/$free MiB
+ c?".UJ cpu: $cputype $cpu
+ resolution: $scr
+ fs: $files
+ $strg
+EOF
--- /dev/null
+++ b/bin/rc/gridup
@@ -1,0 +1,15 @@
+#!/bin/rc
+
+srv tcp!registry.9p.zone!6675 registry /n/registry
+srv tcp!chat.9p.zone!9990 9p.zone.chat /n/chat.9p.zone
+# srv tcp!oat.nine.sirjofri.de!564 sirjofripub /n/sirjofripub
+srv -c tcp!9p.zone!9991 9p.zone.disk /n/griddisk
+
+fn clean {
+ echo $1 | sed 's/.*!([^!]+)!.*/\1/'
+}
+
+for(s in /n/registry/tcp*){
+ s=`{basename $s}
+ srv $s `{clean $s} /n/^`{clean $s} &
+}
--- /dev/null
+++ b/bin/rc/inferno
@@ -1,0 +1,40 @@
+#!/bin/rc
+
+rfork ne
+
+ROOT=/sys/inferno
+
+main=4M
+image=8M
+heap=8M
+
+# font=/fonts/pelm/unicode.8.font
+font=/fonts/lucidasans/typeunicode.7.font
+
+if(! ~ $#* 0 && ! ~ $#* 3) {
+ echo 'usage: inferno [main image heap]'
+ exit
+}
+
+if(~ $#* 3) {
+ main=$*(1)
+ image=$*(2)
+ heap=$*(3)
+}
+
+if (! test -d /sys/inferno/usr) {
+ echo '/sys/inferno does not exist'
+ exit
+}
+
+unionfs -m /n/iusr /usr $ROOT/usr
+bind -c /n/iusr $ROOT/usr
+bind -c $ROOT/usr/$user/lib/keydb.inferno \
+ $ROOT/keydb
+bind -c $home/lib/ndb.inferno /sys/inferno/lib/ndb
+# bind -a /net /n/inferno/net
+# bind -a /dev /n/inferno/dev
+
+cd /sys/inferno
+Plan9/arm/bin/emu '-pmain='$main '-pimage='$image '-pheap='$heap \
+ -g800x1024 -c1 -f$font
--- /dev/null
+++ b/bin/rc/librarysrv
@@ -1,0 +1,59 @@
+#!/bin/rc
+
+librarysrv=/n/santiago/srv/library
+libraryrmtpt=/n/libraryroot
+librarymtpt=/n/library
+cachemtpt=/n/ramfs.library
+
+cmd=$1
+switch($cmd) {
+case start
+ echo 'starting cached library'
+case halt
+ echo 'halting cached library'
+ for(mtpt in $librarymtpt $libraryrmtpt $cachemtpt) {
+ echo 'unmounting' $mtpt
+ unmount $mtpt
+ }
+
+ for(srvf in /srv/library.cached /srv/ramfs.library) {
+ echo 'removing' $srvf
+ rm $srvf
+ }
+
+ echo 'done halting; you may kill ramfs and cfs now'
+ exit
+case *
+ echo 'usage: librarysrv start|halt'
+ exit
+}
+
+#cachesize=8192 # 32
+cachesize=16384 # 64M
+
+if(! test -f $librarysrv) {
+ echo 'library server' $librarysrv 'not found'
+ exit
+}
+
+if(! test -f /srv/ramfs.library) {
+ echo 'running ramfs'
+ ramfs -S ramfs.library -m $cachemtpt
+}
+if not {
+ mount /srv/ramfs.library $cachemtpt
+}
+
+if(! test -f $cachemtpt^'/cache') {
+ echo 'creating cache:' $cachesize 'blocks'
+ dd -if /dev/zero -of $cachemtpt^'/cache' -bs 4096 -count $cachesize
+}
+
+echo 'running cfs'
+cfs -S -n -r -f $cachemtpt^'/cache' -F $librarysrv $libraryrmtpt
+
+mkdir /tmp/library
+
+libraryc=`{ls `{ls $libraryrmtpt | tail -n 1} | tail -n 1}
+
+unionfs -m $librarymtpt -s library.cached /tmp/library $libraryc $librarymtpt
--- /dev/null
+++ b/bin/rc/themeswitch
@@ -1,0 +1,39 @@
+#!/bin/rc
+
+switch($themespec) {
+case green
+ font=/lib/font/bit/uni-vga/u_vga16.font
+ # font=/lib/font/bit/zevv-peep/zevv-peep-14.font
+ # font=/lib/font/bit/spleen/spleen.12.font
+ # font=/lib/font/bit/tamzen/tamzen14.font
+ themepath=$home/lib/theme/green.theme
+case blit
+ font=/lib/font/bit/fixed/unicode.9x18B.font
+ font=/lib/font/bit/fixed/unicode.9x15B.font
+ themepath=$home/lib/theme/blit.theme
+case orange
+ font=/lib/font/bit/zevv-peep/zevv-peep-14.font
+ font=/lib/font/bit/tamzen/tamzen16.font
+ themepath=$home/lib/theme/orange.theme
+case gruvbox
+ font=/lib/font/bit/uni-vga/u_vga16.font
+ themepath=$home/lib/theme/gruvbox.theme
+case gruvboxl
+ font=/lib/font/bit/uni-vga/u_vga16.font
+ themepath=$home/lib/theme/gruvboxl.theme
+case white
+ font=/lib/font/bit/lucm/unicode.9.font
+ font=/lib/font/bit/lucidasans/typeunicode.7.font
+ # font=/lib/font/bit/pelm/unicode.8.font
+ themepath=$home/lib/theme/white.theme
+case greeng
+ font=/lib/font/bit/zevv-peep/zevv-peep-16.font
+ themepath=$home/lib/theme/greengold.theme
+case nord
+ font=/lib/font/bit/pelm/unicode.8.font
+ themepath=$home/lib/theme/nord.theme
+}
+
+if(test -f /dev/theme) {
+ cat $themepath >/dev/theme
+}
--- /dev/null
+++ b/bin/rc/txcheck
@@ -1,0 +1,81 @@
+#!/bin/rc
+
+flagfmt='r procroot, u unit, m maxsize, D delay'
+args='txpid txfd'
+
+# variables and functions
+
+txpid=()
+txfd=()
+
+pidfile=()
+delay=()
+fdpath=()
+maxsz=()
+unitfrac=1
+
+fn usage {
+ aux/usage
+ exit usage
+}
+
+fn fatal {
+ echo $* >[1=2]
+ exit $"*
+}
+
+fn isnum {
+ echo $1 | grep -s '^[0-9]+$'
+}
+
+fn isfloat {
+ echo $1 | grep -s '^[0-9]+\.[0-9]+$'
+}
+
+# argument parsing
+
+if(! eval `{aux/getflags -r /proc -u b -D 3 $*})
+ usage
+
+txpid=$1
+txfd=$2
+
+if(~ $#txpid 0 || ~ $#txfd 0)
+ usage
+
+# util and sanity checks
+
+fdpath=$flagr^'/'^$txpid^'/fd'
+if(! test -r $fdpath)
+ fatal 'unable to read' $fdpath
+
+switch($flagu) {
+case b or B
+ unitfrac='1'
+case kb or KB
+ unitfrac='1024'
+case mb or MB
+ unitfrac='1024 * 1024'
+case *
+ if(! isnum $flagu)
+ fatal 'unknown unit or not a number'
+ unitfrac=$flagu
+}
+
+if(! isnum $flagD)
+ fatal 'delay is not a number'
+delay=$flagD
+
+if(! isfloat $flagm)
+ fatal 'maximum size is not a float'
+maxsz=$flagm
+
+pidfile=/tmp/txcheck.$txpid
+touch $pidfile
+
+while(test -f $pidfile) {
+ fdamt=`{cat $fdpath | grep '^ '^$txfd | awk '{print $9}'}
+ amt=`{echo 'scale = 2;' $fdamt '/ (' $unitfrac ')' | bc}
+ echo ($amt $maxsz)
+ sleep $delay
+}
--- /dev/null
+++ b/bin/rc/vtb
@@ -1,0 +1,6 @@
+#!/bin/rc
+
+# vtfont=/lib/font/bit/fixed/unicode.9x18B.font
+vtfont=/lib/font/bit/fixed/unicode.9x15B.font
+
+exec vt.green -bcx -f $vtfont $*
--- /dev/null
+++ b/lib/pico/gruvboxl.pico
@@ -1,0 +1,4 @@
+!f somefile? img
+!s 1920 1080
+
+z == 0 && sqrt(pow(x - 344, 2) + pow(y - 764, 2)) < 192 ? 142 : z == 1 && sqrt(pow(x - 344, 2) + pow(y - 764, 2)) < 192 ? 192 : z == 2 && sqrt(pow(x - 344, 2) + pow(y - 764, 2)) < 192 ? 124 : z == 0 && sqrt(pow(x - 760, 2) + pow(y - 764, 2)) < 192 ? 131 : z == 1 && sqrt(pow(x - 760, 2) + pow(y - 764, 2)) < 192 ? 165 : z == 2 && sqrt(pow(x - 760, 2) + pow(y - 764, 2)) < 192 ? 152 : z == 0 && sqrt(pow(x - 1176, 2) + pow(y - 764, 2)) < 192 ? 250 : z == 1 && sqrt(pow(x - 1176, 2) + pow(y - 764, 2)) < 192 ? 189 : z == 2 && sqrt(pow(x - 1176, 2) + pow(y - 764, 2)) < 192 ? 47 : z == 0 && sqrt(pow(x - 1592, 2) + pow(y - 764, 2)) < 192 ? 251 : z == 1 && sqrt(pow(x - 1592, 2) + pow(y - 764, 2)) < 192 ? 73 : z == 2 && sqrt(pow(x - 1592, 2) + pow(y - 764, 2)) < 192 ? 52 : z == 0 && sqrt(pow(x - 344, 2) + pow(y - 316, 2)) < 192 ? 251 : z == 1 && sqrt(pow(x - 344, 2) + pow(y - 316, 2)) < 192 ? 73 : z == 2 && sqrt(pow(x - 344, 2) + pow(y - 316, 2)) < 192 ? 52 : z == 0 && sqrt(pow(x - 760, 2) + pow(y - 316, 2)) < 192 ? 250 : z == 1 && sqrt(pow(x - 760, 2) + pow(y - 316, 2)) < 192 ? 189 : z == 2 && sqrt(pow(x - 760, 2) + pow(y - 316, 2)) < 192 ? 47 : z == 0 && sqrt(pow(x - 1176, 2) + pow(y - 316, 2)) < 192 ? 131 : z == 1 && sqrt(pow(x - 1176, 2) + pow(y - 316, 2)) < 192 ? 165 : z == 2 && sqrt(pow(x - 1176, 2) + pow(y - 316, 2)) < 192 ? 152 : z == 0 && sqrt(pow(x - 1592, 2) + pow(y - 316, 2)) < 192 ? 142 : z == 1 && sqrt(pow(x - 1592, 2) + pow(y - 316, 2)) < 192 ? 192 : z == 2 && sqrt(pow(x - 1592, 2) + pow(y - 316, 2)) < 192 ? 124 : z == 0 ? 235 : z == 1 ? 219 : z == 2 ? 178 : 0
--- /dev/null
+++ b/lib/theme/black.theme
@@ -1,0 +1,20 @@
+rioback 101010
+back 000000
+high bdae93
+border 1d2021
+text ffffff
+htext 1d2021
+title d65d0e
+ltitle 1d2021
+hold 458588
+lhold 83a598
+palehold 83a598
+paletext ffffff
+size cc241d
+menubar 8b8d8d
+menuback 000000
+menuhigh fbf1c7
+menubord d65d0e
+menutext ffffff
+menuhtext 000000
+
--- /dev/null
+++ b/lib/theme/blit.theme
@@ -1,0 +1,19 @@
+rioback 00100c
+back 000000
+high 00ee1a
+border d0d0d0
+text 00ee1a
+htext 000000
+title 00ee1a
+ltitle 00551a
+hold ee0000
+lhold 991000
+palehold 991000
+paletext 00ee1a
+size f1f1f1
+menubar 448844
+menuback 000000
+menuhigh ffffff
+menubord 00ee1a
+menutext 00ee1a
+menuhtext 000000
--- /dev/null
+++ b/lib/theme/green.theme
@@ -1,0 +1,19 @@
+rioback /usr/kitzman/lib/wallpapers/green2.wallpaper
+back 000000
+high ffffff
+border d0d0d0
+text f1f1f1
+htext 000000
+title 00ee1a
+ltitle 00551a
+hold 005dbb
+lhold 000099
+palehold 0943ff
+paletext 6f6f6f
+size f1f1f1
+menubar 448844
+menuback 000000
+menuhigh ffffff
+menubord 00ee1a
+menutext f1f1f1
+menuhtext 000000
--- /dev/null
+++ b/lib/theme/greengold.theme
@@ -1,0 +1,19 @@
+rioback /usr/kitzman/lib/wallpapers/green1.wallpaper
+back 0A2018
+high ffffff
+border d0d0d0
+text f1f1f1
+htext 000000
+title FF7030
+ltitle E8A060
+hold C81018
+lhold 804040
+palehold 804040
+paletext 6f6f6f
+size 1b5dbb
+menubar 448844
+menuback 0A2018
+menuhigh ffffff
+menubord FF7838
+menutext f1f1f1
+menuhtext 000000
--- /dev/null
+++ b/lib/theme/gruvbox.theme
@@ -1,0 +1,19 @@
+rioback /usr/kitzman/lib/wallpapers/gruvbox.wallpaper
+back 1d2021
+high ebdbb2
+border 3c3836
+text fbf1c7
+htext 000000
+title 8ec07c
+ltitle 83a598
+hold fb4934
+lhold fabd2f
+palehold fabd2f
+paletext 665c54
+size d3869b
+menubar 000000
+menuback 1d2021
+menuhigh 000000
+menubord 8fbcbb
+menutext fbf1c7
+menuhtext ffffff
--- /dev/null
+++ b/lib/theme/gruvboxl.theme
@@ -1,0 +1,19 @@
+rioback /usr/kitzman/lib/wallpapers/gruvboxl.wallpaper
+back ebdbb2
+high 1d2021
+border 3c3836
+text 1d2021
+htext ebdbb2
+title 8ec07c
+ltitle 83a598
+hold fb4934
+lhold fabd2f
+palehold fabd2f
+paletext 665c54
+size d3869b
+menubar 000000
+menuback ebdbb2
+menuhigh 000000
+menubord 8fbcbb
+menutext 1d2021
+menuhtext ffffff
--- /dev/null
+++ b/lib/theme/nord.theme
@@ -1,0 +1,19 @@
+rioback /usr/kitzman/lib/wallpapers/nord.wallpaper
+back 2e3440
+high d8dee9
+border 222222
+text eceff4
+htext 000000
+title 8fbcbb
+ltitle 4c566a
+hold bf616a
+lhold d08770
+palehold d08770
+paletext 838c9e
+size ebcb8b
+menubar 000000
+menuback 2e3440
+menuhigh 000000
+menubord 8fbcbb
+menutext d8dee9
+menuhtext ffffff
--- /dev/null
+++ b/lib/theme/orange.theme
@@ -1,0 +1,19 @@
+rioback 1d2021
+back 1d2021
+high ebdbb2
+border 222222
+text fbf1c7
+htext 000000
+title fb4934
+ltitle fabd2f
+hold 8ec07c
+lhold 83a598
+palehold 83a598
+paletext 665c54
+size d3869b
+menubar 000000
+menuback 1d2021
+menuhigh 000000
+menubord fb4934
+menutext fbf1c7
+menuhtext ffffff
--- /dev/null
+++ b/lib/theme/plateau.theme
@@ -1,0 +1,16 @@
+back 1b1818
+high e7dfdf
+border 292424
+text f4ecec
+htext 1b1818
+title 5485b6
+ltitle 7272ca
+hold ca4949
+lhold a06e3b
+palehold a06e3b
+paletext 655d5d
+size 8464c4
+menuback 1b1818
+menubord 5485b6
+menutext f4ecec
+rioback 1b1818
--- /dev/null
+++ b/lib/theme/white.theme
@@ -1,0 +1,19 @@
+rioback /usr/kitzman/lib/wallpapers/white.wallpaper
+back ffffff
+high 88ccaa
+border 222222
+text 000000
+htext 000000
+title 555555
+ltitle 888888
+hold 007dee
+lhold 557dee
+palehold 4998dd
+paletext 555555
+size ff0000
+menubar 000000
+menuback ffffff
+menuhigh 000000
+menubord 555555
+menutext 000000
+menuhtext ffffff
--- /dev/null
+++ b/patches/faces.patch
@@ -1,0 +1,195 @@
+diff a/main.c b/main.c
+60a61
+> Image *txtc; /* text color */
+81a83,179
+> static char *
+> readall(int f, int *osz)
+> {
+> int bufsz, sz, n;
+> char *s;
+>
+> bufsz = 1023;
+> s = nil;
+> for(sz = 0;; sz += n){
+> if(bufsz-sz < 1024){
+> bufsz *= 2;
+> s = realloc(s, bufsz);
+> }
+> if((n = readn(f, s+sz, bufsz-sz-1)) < 1)
+> break;
+> }
+> if(n < 0 || sz < 1){
+> free(s);
+> return nil;
+> }
+> s[sz] = 0;
+> *osz = sz;
+>
+> return s;
+> }
+>
+> enum {
+> Colrioback,
+>
+> /* the following group has to be in order, they are used by libframe */
+> Colback,
+> Colhigh,
+> Colbord,
+> Coltext,
+> Colhtext,
+>
+> Coltitle,
+> Colltitle,
+> Colhold,
+> Collhold,
+> Colpalehold,
+> Colpaletext,
+> Colsize,
+>
+> /* menuhit */
+> Colmenubar,
+> Colmenuback,
+> Colmenuhigh,
+> Colmenubord,
+> Colmenutext,
+> Colmenuhtext,
+>
+> Numcolors
+> };
+>
+> typedef struct Color Color;
+>
+> struct Color {
+> char *id;
+> union {
+> u32int rgb;
+> char *path;
+> };
+> int flags;
+> };
+>
+> static Color theme[Numcolors] = {
+> [Colrioback] = {"rioback", {0x777777}, 0},
+> [Colback] = {"back", {0xffffff}, 0},
+> [Colhigh] = {"high", {0xcccccc}, 0},
+> [Colbord] = {"border", {0x999999}, 0},
+> [Coltext] = {"text", {DBlack>>8}, 0},
+> [Colhtext] = {"htext", {DBlack>>8}, 0},
+> [Coltitle] = {"title", {DGreygreen>>8}, 0},
+> [Colltitle] = {"ltitle", {DPalegreygreen>>8}, 0},
+> [Colhold] = {"hold", {DMedblue>>8}, 0},
+> [Collhold] = {"lhold", {DGreyblue>>8}, 0},
+> [Colpalehold] = {"palehold", {DPalegreyblue>>8}, 0},
+> [Colpaletext] = {"paletext", {0x666666}, 0},
+> [Colsize] = {"size", {DRed>>8}, 0},
+> [Colmenubar] = {"menubar", {DDarkgreen>>8}, 1},
+> [Colmenuback] = {"menuback", {0xeaffea}, 1},
+> [Colmenuhigh] = {"menuhigh", {DDarkgreen>>8}, 1},
+> [Colmenubord] = {"menubord", {DMedgreen>>8}, 1},
+> [Colmenutext] = {"menutext", {DBlack>>8}, 1},
+> [Colmenuhtext] = {"menuhtext", {0xeaffea}, 1},
+> };
+>
+> u32int
+> color2rgb(Color c, int scale)
+> {
+> return ((((c.rgb >> 16) & 0xff) / scale) << 24) |
+> ((((c.rgb >> 8) & 0xff) / scale) << 16) |
+> (((c.rgb & 0xff) / scale) << 8) |
+> 0xff;
+> }
+>
+82a181,228
+> themeload(char *s, int n)
+> {
+> int i;
+> char *t, *a[2], *e;
+> Image *newc;
+> u32int rgb;
+>
+> if((t = malloc(n+1)) == nil)
+> return;
+> memmove(t, s, n);
+> t[n] = 0;
+>
+> for(s = t; s != nil && *s; s = e){
+> if((e = strchr(s, '\n')) != nil)
+> *e++ = 0;
+> if(tokenize(s, a, 2) == 2){
+> for(i = 0; i < nelem(theme); i++) {
+> if(strcmp(theme[i].id, a[0]) == 0) {
+> rgb = strtoul(a[1], nil, 16);
+> if((newc = allocimage(display, Rect(0, 0, 1, 1), RGB24, 1, rgb<<8 | 0xff)) != nil) {
+> theme[i].rgb = rgb;
+> }
+> break;
+> }
+> }
+> }
+> }
+> free(t);
+> }
+>
+> char *
+> themestring(int *n)
+> {
+> char *s, *t, *e;
+> int i;
+>
+> if((t = malloc(512)) != nil){
+> s = t;
+> e = s+512;
+> for(i = 0; i < nelem(theme); i++)
+> s = seprint(s, e, "%s\t%06ux\n", theme[i].id, theme[i].rgb);
+> *n = s - t;
+> }
+>
+> return t;
+> }
+>
+> void
+99a246,256
+> // load theme
+> int sz, f;
+> char *s;
+>
+> if((f = open("/dev/theme", OREAD|OCEXEC)) >= 0){
+> if((s = readall(f, &sz)) != nil)
+> themeload(s, sz);
+> free(s);
+> close(f);
+> }
+>
+101,104c258,263
+< bgrnd = allocimagemix(display, DPalebluegreen, DWhite);
+< blue = allocimage(display, Rect(0,0,1,1), screen->chan, 1, 0x008888FF); /* blue-green */
+< left = allocimage(display, leftright, GREY1, 0, DWhite);
+< right = allocimage(display, leftright, GREY1, 0, DWhite);
+---
+> bgrnd = allocimagemix(display, color2rgb(theme[Colback], 1), color2rgb(theme[Colback], 1));
+> blue = allocimage(display, Rect(0,0,1,1), screen->chan, color2rgb(theme[Colltitle], 1), color2rgb(theme[Coltext], 1)); /* blue-green */
+> left = allocimage(display, leftright, GREY1, color2rgb(theme[Coltext], 1), color2rgb(theme[Coltext], 1));
+> right = allocimage(display, leftright, GREY1, color2rgb(theme[Coltext], 1), color2rgb(theme[Coltext], 1));
+> txtc = allocimage(display, leftright, GREY1, color2rgb(theme[Colback], 1), color2rgb(theme[Coltext], 1));
+>
+142c301
+< string(screen, r.min, display->black, ZP, datefont, date);
+---
+> string(screen, r.min, txtc, ZP, datefont, date);
+263c422
+< center(mediumfont, r.min, f->str[Suser], display->black);
+---
+> center(mediumfont, r.min, f->str[Suser], txtc);
+266c425
+< center(mediumfont, r.min, tstr, display->black);
+---
+> center(mediumfont, r.min, tstr, txtc);
+272c431
+< center(tinyfont, r.min, f->str[Sdomain], display->black);
+---
+> center(tinyfont, r.min, f->str[Sdomain], bgrnd);
+diff a/mkfile b/mkfile
+6c6
+< TARG=faces
+---
+> TARG=facest
--- /dev/null
+++ b/patches/stats.patch
@@ -1,0 +1,459 @@
+9a10,154
+> static char *
+> readall(int f, int *osz)
+> {
+> int bufsz, sz, n;
+> char *s;
+>
+> bufsz = 1023;
+> s = nil;
+> for(sz = 0;; sz += n){
+> if(bufsz-sz < 1024){
+> bufsz *= 2;
+> s = realloc(s, bufsz);
+> }
+> if((n = readn(f, s+sz, bufsz-sz-1)) < 1)
+> break;
+> }
+> if(n < 0 || sz < 1){
+> free(s);
+> return nil;
+> }
+> s[sz] = 0;
+> *osz = sz;
+>
+> return s;
+> }
+>
+> enum {
+> Colrioback,
+>
+> /* the following group has to be in order, they are used by libframe */
+> Colback,
+> Colhigh,
+> Colbord,
+> Coltext,
+> Colhtext,
+>
+> Coltitle,
+> Colltitle,
+> Colhold,
+> Collhold,
+> Colpalehold,
+> Colpaletext,
+> Colsize,
+>
+> /* menuhit */
+> Colmenubar,
+> Colmenuback,
+> Colmenuhigh,
+> Colmenubord,
+> Colmenutext,
+> Colmenuhtext,
+>
+> Numcolors
+> };
+>
+> typedef struct Color Color;
+>
+> struct Color {
+> char *id;
+> union {
+> u32int rgb;
+> char *path;
+> };
+> int flags;
+> };
+>
+> static Color theme[Numcolors] = {
+> [Colrioback] = {"rioback", {0x777777}, 0},
+> [Colback] = {"back", {0xffffff}, 0},
+> [Colhigh] = {"high", {0xcccccc}, 0},
+> [Colbord] = {"border", {0x999999}, 0},
+> [Coltext] = {"text", {DBlack>>8}, 0},
+> [Colhtext] = {"htext", {DBlack>>8}, 0},
+> [Coltitle] = {"title", {DGreygreen>>8}, 0},
+> [Colltitle] = {"ltitle", {DPalegreygreen>>8}, 0},
+> [Colhold] = {"hold", {DMedblue>>8}, 0},
+> [Collhold] = {"lhold", {DGreyblue>>8}, 0},
+> [Colpalehold] = {"palehold", {DPalegreyblue>>8}, 0},
+> [Colpaletext] = {"paletext", {0x666666}, 0},
+> [Colsize] = {"size", {DRed>>8}, 0},
+> [Colmenubar] = {"menubar", {DDarkgreen>>8}, 1},
+> [Colmenuback] = {"menuback", {0xeaffea}, 1},
+> [Colmenuhigh] = {"menuhigh", {DDarkgreen>>8}, 1},
+> [Colmenubord] = {"menubord", {DMedgreen>>8}, 1},
+> [Colmenutext] = {"menutext", {DBlack>>8}, 1},
+> [Colmenuhtext] = {"menuhtext", {0xeaffea}, 1},
+> };
+>
+> u32int
+> color2rgb(Color c, int scale)
+> {
+> return ((((c.rgb >> 16) & 0xff) / scale) << 24) |
+> ((((c.rgb >> 8) & 0xff) / scale) << 16) |
+> (((c.rgb & 0xff) / scale) << 8) |
+> 0xff;
+> }
+>
+> void
+> themeload(char *s, int n)
+> {
+> int i;
+> char *t, *a[2], *e;
+> Image *newc;
+> u32int rgb;
+>
+> if((t = malloc(n+1)) == nil)
+> return;
+> memmove(t, s, n);
+> t[n] = 0;
+>
+> for(s = t; s != nil && *s; s = e){
+> if((e = strchr(s, '\n')) != nil)
+> *e++ = 0;
+> if(tokenize(s, a, 2) == 2){
+> for(i = 0; i < nelem(theme); i++) {
+> if(strcmp(theme[i].id, a[0]) == 0) {
+> rgb = strtoul(a[1], nil, 16);
+> if((newc = allocimage(display, Rect(0, 0, 1, 1), RGB24, 1, rgb<<8 | 0xff)) != nil) {
+> theme[i].rgb = rgb;
+> }
+> break;
+> }
+> }
+> }
+> }
+> free(t);
+> }
+>
+> char *
+> themestring(int *n)
+> {
+> char *s, *t, *e;
+> int i;
+>
+> if((t = malloc(512)) != nil){
+> s = t;
+> e = s+512;
+> for(i = 0; i < nelem(theme); i++)
+> s = seprint(s, e, "%s\t%06ux\n", theme[i].id, theme[i].rgb);
+> *n = s - t;
+> }
+>
+> return t;
+> }
+>
+29c174
+< /* /dev/swap */
+---
+> /* old /dev/swap */
+34,35c179
+< Reclaim,
+< Maxreclaim,
+---
+>
+52d195
+<
+74c217
+< uvlong devswap[10];
+---
+> uvlong devswap[8];
+125d267
+< Mreclaim,
+150d291
+< "add reclaim ",
+174d314
+< reclaimval(Machine*, uvlong*, uvlong*, int),
+200d339
+< reclaimval,
+214c353
+< char argchars[] = "8bcdeEfiIkmlnprstwz";
+---
+> char argchars[] = "8bcdeEfiIkmlnpstwz";
+222,224c361
+< int sleeptime = 1000;
+< int batteryperiod = 1000;
+< int tempperiod = 1000;
+---
+> int sleeptime = 1000;
+227a365,366
+> Image *stext;
+>
+278c417
+< cols[i][0] = allocimagemix(display, c0, DWhite);
+---
+> cols[i][0] = allocimagemix(display, c0, DBlack);
+287c426
+< mkcol(0, 0xFFAAAAFF, 0xFFAAAAFF, 0xBB5D5DFF);
+---
+> mkcol(0, color2rgb(theme[Coltitle], 1), color2rgb(theme[Colhold], 1), color2rgb(theme[Collhold], 1));
+289c428
+< mkcol(1, DPalebluegreen, DPalegreygreen, DPurpleblue);
+---
+> mkcol(1, color2rgb(theme[Coltitle], 1), color2rgb(theme[Colhold], 1), color2rgb(theme[Collhold], 1));
+291c430
+< mkcol(2, DPaleyellow, DDarkyellow, DYellowgreen);
+---
+> mkcol(2, color2rgb(theme[Coltitle], 1), color2rgb(theme[Colhold], 1), color2rgb(theme[Collhold], 1));
+293c432
+< mkcol(3, DPalegreen, DMedgreen, DDarkgreen);
+---
+> mkcol(3, color2rgb(theme[Coltitle], 1), color2rgb(theme[Colhold], 1), color2rgb(theme[Collhold], 1));
+295c434
+< mkcol(4, 0x00AAFFFF, 0x00AAFFFF, 0x0088CCFF);
+---
+> mkcol(4, color2rgb(theme[Coltitle], 1), color2rgb(theme[Colhold], 1), color2rgb(theme[Collhold], 1));
+297,299c436,438
+< cols[5][0] = allocimage(display, Rect(0,0,1,1), CMAP8, 1, 0xEEEEEEFF);
+< cols[5][1] = allocimage(display, Rect(0,0,1,1), CMAP8, 1, 0xCCCCCCFF);
+< cols[5][2] = allocimage(display, Rect(0,0,1,1), CMAP8, 1, 0x888888FF);
+---
+> cols[5][0] = allocimage(display, Rect(0,0,1,1), CMAP8, 1, color2rgb(theme[Colhigh], 1));
+> cols[5][1] = allocimage(display, Rect(0,0,1,1), CMAP8, 1, color2rgb(theme[Coltext], 1));
+> cols[5][2] = allocimage(display, Rect(0,0,1,1), CMAP8, 1, color2rgb(theme[Collhold], 1));
+342c481
+< runestring(screen, p, display->black, ZP, font, r);
+---
+> runestring(screen, p, stext, ZP, font, r);
+442c581
+< string(screen, g->overtmp->r.min, display->black, ZP, font, buf);
+---
+> string(screen, g->overtmp->r.min, stext, ZP, font, buf);
+476,477d614
+< static int xxx = 0;
+<
+481a619,622
+> a[0] = a[3];
+> a[1] = a[4];
+> a[2] = a[5];
+> a[3] = a[6];
+483,499c624,625
+< a[Mem] = a[3];
+< a[Maxmem] = a[4];
+< a[Swap] = a[5];
+< a[Maxswap] = a[6];
+<
+< a[Reclaim] = 0;
+< a[Maxreclaim] = 0;
+< if(m->bufp = strstr(m->buf, "reclaim")){
+< while(m->bufp > m->buf && m->bufp[-1] != '\n')
+< m->bufp--;
+< a[Reclaim] = strtoull(m->bufp, &m->bufp, 10);
+< while(*m->bufp++ == '/')
+< a[Maxreclaim] = strtoull(m->bufp, &m->bufp, 10);
+< }
+<
+< a[Kern] = 0;
+< a[Maxkern] = 0;
+---
+> a[4] = 0;
+> a[5] = 0;
+503c629
+< a[Kern] = strtoull(m->bufp, &m->bufp, 10);
+---
+> a[4] = strtoull(m->bufp, &m->bufp, 10);
+505c631
+< a[Maxkern] = strtoull(m->bufp, &m->bufp, 10);
+---
+> a[5] = strtoull(m->bufp, &m->bufp, 10);
+508,509c634,635
+< a[Draw] = 0;
+< a[Maxdraw] = 0;
+---
+> a[6] = 0;
+> a[7] = 0;
+513c639
+< a[Draw] = strtoull(m->bufp, &m->bufp, 10);
+---
+> a[6] = strtoull(m->bufp, &m->bufp, 10);
+515c641
+< a[Maxdraw] = strtoull(m->bufp, &m->bufp, 10);
+---
+> a[7] = strtoull(m->bufp, &m->bufp, 10);
+521,527c647,650
+< a[Reclaim] = 0;
+< a[Maxreclaim] = 0;
+< a[Kern] = 0;
+< a[Maxkern] = 0;
+< a[Draw] = 0;
+< a[Maxdraw] = 0;
+<
+---
+> a[4] = 0;
+> a[5] = 0;
+> a[6] = 0;
+> a[7] = 0;
+625c748
+< snprint(buf, sizeof buf, "%s/mnt/pm/battery", mpt);
+---
+> snprint(buf, sizeof buf, "%s/mnt/acpi/battery", mpt);
+630d752
+< batteryperiod = 10000;
+642,643c764
+< tempperiod = 5000;
+< snprint(buf, sizeof buf, "%s/mnt/pm/cputemp", mpt);
+---
+> snprint(buf, sizeof buf, "%s/mnt/acpi/cputemp", mpt);
+665c786
+< return init | present[Mmem] | present[Mswap] | present[Mreclaim] | present[Mkern] | present[Mdraw];
+---
+> return init | present[Mmem] | present[Mswap] | present[Mkern] | present[Mdraw];
+686,693c807
+< static uint step = 0;
+<
+< if(++step*sleeptime >= batteryperiod){
+< step = 0;
+< return init | present[Mbattery];
+< }
+<
+< return 0;
+---
+> return init | present[Mbattery];
+705,712c819
+< static uint step = 0;
+<
+< if(++step*sleeptime >= tempperiod){
+< step = 0;
+< return init | present[Mtemp];
+< }
+<
+< return 0;
+---
+> return init | present[Mtemp];
+758,763c865,868
+< if(needbattery(init)){
+< if(loadbuf(m, &m->batteryfd) && readnums(m, nelem(m->batterystats), a, 0))
+< memmove(m->batterystats, a, sizeof(m->batterystats));
+< else if(loadbuf(m, &m->bitsybatfd) && readnums(m, 1, a, 0))
+< memmove(m->batterystats, a, sizeof(m->batterystats));
+< }
+---
+> if(needbattery(init) && loadbuf(m, &m->batteryfd) && readnums(m, nelem(m->batterystats), a, 0))
+> memmove(m->batterystats, a, sizeof(m->batterystats));
+> if(needbattery(init) && loadbuf(m, &m->bitsybatfd) && readnums(m, 1, a, 0))
+> memmove(m->batterystats, a, sizeof(m->batterystats));
+792,800d896
+< reclaimval(Machine *m, uvlong *v, uvlong *vmax, int)
+< {
+< *v = m->devswap[Reclaim];
+< *vmax = m->devswap[Maxreclaim];
+< if(*vmax == 0)
+< *vmax = 1;
+< }
+<
+< void
+899c995
+< etherval(Machine *m, uvlong *v, uvlong *vmax, int)
+---
+> etherval(Machine *m, uvlong *v, uvlong *vmax, int init)
+902c998,1000
+< *vmax = sleeptime;
+---
+> *vmax = sleeptime*m->nproc;
+> if(init)
+> *vmax = sleeptime;
+906c1004
+< etherinval(Machine *m, uvlong *v, uvlong *vmax, int)
+---
+> etherinval(Machine *m, uvlong *v, uvlong *vmax, int init)
+909c1007,1009
+< *vmax = sleeptime;
+---
+> *vmax = sleeptime*m->nproc;
+> if(init)
+> *vmax = sleeptime;
+913c1013
+< etheroutval(Machine *m, uvlong *v, uvlong *vmax, int)
+---
+> etheroutval(Machine *m, uvlong *v, uvlong *vmax, int init)
+916c1016,1018
+< *vmax = sleeptime;
+---
+> *vmax = sleeptime*m->nproc;
+> if(init)
+> *vmax = sleeptime;
+920c1022
+< ethererrval(Machine *m, uvlong *v, uvlong *vmax, int)
+---
+> ethererrval(Machine *m, uvlong *v, uvlong *vmax, int init)
+926,927c1028,1031
+< *v += m->netetherstats[i]-m->prevetherstats[i];
+< *vmax = (sleeptime/1000)*10;
+---
+> *v += m->netetherstats[i];
+> *vmax = (sleeptime/1000)*10*m->nproc;
+> if(init)
+> *vmax = (sleeptime/1000)*10;
+962c1066
+< *vmax = 100;
+---
+> *vmax = sleeptime;
+967c1071
+< *v = l;
+---
+> *v = (l-20)*27;
+1109c1213
+< draw(screen, screen->r, display->white, nil, ZP);
+---
+> draw(screen, screen->r, display->black, nil, ZP);
+1119c1223
+< draw(screen, Rect(x, y-1, screen->r.max.x, y), display->black, nil, ZP);
+---
+> draw(screen, Rect(x, y-1, screen->r.max.x, y), stext, nil, ZP);
+1128c1232
+< draw(screen, Rect(x-1, starty-1, x, screen->r.max.y), display->black, nil, ZP);
+---
+> draw(screen, Rect(x-1, starty-1, x, screen->r.max.y), stext, nil, ZP);
+1138c1242
+< string(screen, Pt(x+Labspace, screen->r.min.y + Labspace), display->black, ZP, font, buf);
+---
+> string(screen, Pt(x+Labspace, screen->r.min.y + Labspace), stext, ZP, font, buf);
+1146c1250
+< if(wid < dx-10){
+---
+> if(wid < (maxx-startx)-30){
+1149c1253
+< draw(screen, Rect(maxx, starty, maxx+1, screen->r.max.y), display->black, nil, ZP);
+---
+> draw(screen, Rect(maxx, starty, maxx+1, screen->r.max.y), stext, nil, ZP);
+1161c1265
+< draw(screen, Rect(maxx+1, ly, maxx+1+Lx, ly+1), display->black, nil, ZP);
+---
+> draw(screen, Rect(maxx+1, ly, maxx+1+Lx, ly+1), stext, nil, ZP);
+1163c1267
+< string(screen, Pt(maxx+1+Lx, ly), display->black, ZP, font, labs[k]);
+---
+> string(screen, Pt(maxx+1+Lx, ly), stext, ZP, font, labs[k]);
+1171,1173c1275,1277
+< machr = Rect(startx+i*dx, starty, startx+(i+1)*dx - 1, screen->r.max.y);
+< if(i == nmach-1)
+< machr.max.x = maxx;
+---
+> machr = Rect(startx+i*dx, starty, maxx, screen->r.max.y);
+> if(i < nmach-1)
+> machr.max.x = startx+(i+1)*dx - 1;
+1199,1200d1302
+< if(vmax == 0)
+< vmax = 1;
+1375,1377d1476
+< case 'r':
+< addgraph(Mreclaim);
+< break;
+1412a1512,1524
+>
+> // load theme
+> int sz, f;
+> char *s;
+>
+> if((f = open("/dev/theme", OREAD|OCEXEC)) >= 0){
+> if((s = readall(f, &sz)) != nil)
+> themeload(s, sz);
+> free(s);
+> close(f);
+> }
+>
+> stext = allocimage(display, Rect(0,0,1,1), CMAP8, 1, color2rgb(theme[Coltitle], 1));
+1429,1430d1540
+< if(vmax == 0)
+< vmax = 1;
--- /dev/null
+++ b/patches/vtg.patch
@@ -1,0 +1,23 @@
+diff a/main.c b/main.c
+326a327,328
+> ulong MyGreen = 0x00ee1aff;
+>
+328c330
+< green = allocimage(display, Rect(0,0,1,1), screen->chan, 1, DGreen);
+---
+> green = allocimage(display, Rect(0,0,1,1), screen->chan, 1, MyGreen);
+338,341c340,343
+< bgcolor = (blkbg? display->black: display->white);
+< fgcolor = (blkbg? display->white: display->black);
+< bgselected = allocimage(display, Rect(0,0,1,1), CMAP8, 1, blkbg ? 0x333333FF : 0xCCCCCCFF);
+< fgselected = allocimage(display, Rect(0,0,1,1), CMAP8, 1, blkbg ? 0xCCCCCCFF : 0x333333FF);
+---
+> bgcolor = (blkbg? display->black: display->black);
+> fgcolor = (blkbg? green: green);
+> bgselected = allocimage(display, Rect(0,0,1,1), CMAP8, 1, blkbg ? MyGreen : MyGreen);
+> fgselected = allocimage(display, Rect(0,0,1,1), CMAP8, 1, blkbg ? DBlack : DBlack);
+diff a/mkfile b/mkfile
+3c3
+< TARG=vt
+---
+> TARG=vtg
--- /dev/null
+++ b/patches/winwatch.patch
@@ -1,0 +1,184 @@
+8a9,34
+> static char *
+> readall(int f, int *osz)
+> {
+> int bufsz, sz, n;
+> char *s;
+>
+> bufsz = 1023;
+> s = nil;
+> for(sz = 0;; sz += n){
+> if(bufsz-sz < 1024){
+> bufsz *= 2;
+> s = realloc(s, bufsz);
+> }
+> if((n = readn(f, s+sz, bufsz-sz-1)) < 1)
+> break;
+> }
+> if(n < 0 || sz < 1){
+> free(s);
+> return nil;
+> }
+> s[sz] = 0;
+> *osz = sz;
+>
+> return s;
+> }
+>
+9a36,106
+> Colrioback,
+>
+> /* the following group has to be in order, they are used by libframe */
+> Colback,
+> Colhigh,
+> Colbord,
+> Coltext,
+> Colhtext,
+>
+> Coltitle,
+> Colltitle,
+> Colhold,
+> Collhold,
+> Colpalehold,
+> Colpaletext,
+> Colsize,
+>
+> /* menuhit */
+> Colmenubar,
+> Colmenuback,
+> Colmenuhigh,
+> Colmenubord,
+> Colmenutext,
+> Colmenuhtext,
+>
+> Numcolors
+> };
+>
+> typedef struct Color Color;
+>
+> struct Color {
+> char *id;
+> union {
+> u32int rgb;
+> char *path;
+> };
+> int flags;
+> };
+>
+> static Color theme[Numcolors] = {
+> [Colrioback] = {"rioback", {0x777777}, 0},
+> [Colback] = {"back", {0xffffff}, 0},
+> [Colhigh] = {"high", {0xcccccc}, 0},
+> [Colbord] = {"border", {0x999999}, 0},
+> [Coltext] = {"text", {DBlack>>8}, 0},
+> [Colhtext] = {"htext", {DBlack>>8}, 0},
+> [Coltitle] = {"title", {DGreygreen>>8}, 0},
+> [Colltitle] = {"ltitle", {DPalegreygreen>>8}, 0},
+> [Colhold] = {"hold", {DMedblue>>8}, 0},
+> [Collhold] = {"lhold", {DGreyblue>>8}, 0},
+> [Colpalehold] = {"palehold", {DPalegreyblue>>8}, 0},
+> [Colpaletext] = {"paletext", {0x666666}, 0},
+> [Colsize] = {"size", {DRed>>8}, 0},
+> [Colmenubar] = {"menubar", {DDarkgreen>>8}, 1},
+> [Colmenuback] = {"menuback", {0xeaffea}, 1},
+> [Colmenuhigh] = {"menuhigh", {DDarkgreen>>8}, 1},
+> [Colmenubord] = {"menubord", {DMedgreen>>8}, 1},
+> [Colmenutext] = {"menutext", {DBlack>>8}, 1},
+> [Colmenuhtext] = {"menuhtext", {0xeaffea}, 1},
+> };
+>
+> u32int
+> color2rgb(Color c, int scale)
+> {
+> return ((((c.rgb >> 16) & 0xff) / scale) << 24) |
+> ((((c.rgb >> 8) & 0xff) / scale) << 16) |
+> (((c.rgb & 0xff) / scale) << 8) |
+> 0xff;
+> }
+>
+> enum {
+30c127
+< Image *statecol[4];
+---
+> Image *statecol[5];
+178c275
+< _string(screen, addpt(win[i].r.min, Pt(2,0)), display->black, ZP,
+---
+> _string(screen, addpt(win[i].r.min, Pt(2,0)), statecol[4], ZP,
+181c278
+< border(screen, win[i].r, 1, display->black, ZP);
+---
+> border(screen, win[i].r, 1, statecol[4], ZP);
+316a414,461
+> themeload(char *s, int n)
+> {
+> int i;
+> char *t, *a[2], *e;
+> Image *newc;
+> u32int rgb;
+>
+> if((t = malloc(n+1)) == nil)
+> return;
+> memmove(t, s, n);
+> t[n] = 0;
+>
+> for(s = t; s != nil && *s; s = e){
+> if((e = strchr(s, '\n')) != nil)
+> *e++ = 0;
+> if(tokenize(s, a, 2) == 2){
+> for(i = 0; i < nelem(theme); i++) {
+> if(strcmp(theme[i].id, a[0]) == 0) {
+> rgb = strtoul(a[1], nil, 16);
+> if((newc = allocimage(display, Rect(0, 0, 1, 1), RGB24, 1, rgb<<8 | 0xff)) != nil) {
+> theme[i].rgb = rgb;
+> }
+> break;
+> }
+> }
+> }
+> }
+> free(t);
+> }
+>
+> char *
+> themestring(int *n)
+> {
+> char *s, *t, *e;
+> int i;
+>
+> if((t = malloc(512)) != nil){
+> s = t;
+> e = s+512;
+> for(i = 0; i < nelem(theme); i++)
+> s = seprint(s, e, "%s\t%06ux\n", theme[i].id, theme[i].rgb);
+> *n = s - t;
+> }
+>
+> return t;
+> }
+>
+> void
+342d486
+< lightblue = allocimagemix(display, DPalebluegreen, DWhite);
+344c488,501
+< statecol[0] = allocimage(display, Rect(0,0,1,1), screen->chan, 1, 0xCCCCCCFF);
+---
+> // load theme
+> int sz, f;
+> char *s;
+>
+> if((f = open("/dev/theme", OREAD|OCEXEC)) >= 0){
+> if((s = readall(f, &sz)) != nil)
+> themeload(s, sz);
+> free(s);
+> close(f);
+> }
+>
+> lightblue = allocimagemix(display, color2rgb(theme[Colback], 1), color2rgb(theme[Colback], 1));
+>
+> statecol[0] = allocimage(display, Rect(0,0,1,1), screen->chan, 1, color2rgb(theme[Colhold], 2));
+347c504,505
+< statecol[3] = allocimage(display, Rect(0,0,1,1), screen->chan, 1, DPalegreygreen);
+---
+> statecol[3] = allocimage(display, Rect(0,0,1,1), screen->chan, 1, color2rgb(theme[Colltitle], 1));
+> statecol[4] = allocimage(display, Rect(0,0,1,1), screen->chan, 1, color2rgb(theme[Colmenubord], 1));