xinitrc: Update pterm width.
[profile] / xinitrc
diff --git a/xinitrc b/xinitrc
index 17471fe..1eed5ba 100755 (executable)
--- a/xinitrc
+++ b/xinitrc
 #! /bin/bash
+###
+### X startup script
 
-xrdb -override $HOME/.Xdefaults
+###--------------------------------------------------------------------------
+### Utility functions.
+
+## Progress indicators.
+info=yes
+info () {
+  case $info in yes) echo "- $*" >&2 ;; esac
+}
+
+run=yes
+run () {
+  local what=$1; shift
+  local bg=no
+
+  case $what in bg*) bg=yes what=${what#bg} ;; esac
+  info "run $what: $*"
+
+  case "$run,$bg" in
+    yes,no) "$@" ;;
+    yes,yes) "$@" & ;;
+  esac
+}
+
+## Program choice
+pick_program () {
+  local what=$1; shift
+  local choice=false
+  for i in "$@"; do
+    if type -t >/dev/null "$i"; then choice=$i; break; fi
+  done
+  info "pick $what = $choice"
+  echo "$choice"
+}
+
+###--------------------------------------------------------------------------
+### Parse arguments.
+
+vnc=no
+atomtag=
+start=yes
+wait=yes
+
+for opt; do
+  case "$opt" in
+    help)
+      cat <<EOF
+Options:
+  tag=TAG
+  [no]trace
+  [no]info
+  [no]run
+  [no]start
+  [no]wait
+  [no]vnc
+EOF
+      exit
+      ;;
+
+    tag=*) atomtag=/${opt#tag=} ;;
+    trace) set -x ;;
+    notrace) set +x ;;
+    info | run | start | wait | vnc) eval "$opt=yes" ;;
+    noinfo | norun | nostart | nowait | novnc) eval "${opt#no}=no" ;;
+
+    *) echo "unknown option $opt" >&2; exit 1 ;;
+  esac
+done
+
+###--------------------------------------------------------------------------
+### Iniitial settings.
+
+## Assume X sessions are secure.
 export __mdw_sechost="`hostname`"
 
-# --- Do some fiddling ---
+## Obtain the screen dimensions.
+case ",$XWIDTH,$XHEIGHT," in
+  *,,*) eval $(xscsize -bx) ;;
+esac
+info "screen size = $XWIDTH x $XHEIGHT"
 
-cleanup=":"
-xset b 10 2000 50
-xset r rate 500 50
-xset m 1 1
-gnome-settings-daemon&
-mail-notification&
-gkrellm&
-eval `xscsize -bx`
+initialize () {
+  ## Load the X resource database.
+  run init xrdb -override $HOME/.Xdefaults
 
-# --- Crank up ESD ---
+  ## Random xsettery.
+  run init xset b 10 2000 50
+  run init xset r rate 500 50
+  run init xset m 2 1
 
-if ! [ -r /tmp/.esd/socket ]; then
-  esd -nobeeps -as 10&
-  cleanup="$cleanup; kill $!"
-fi
+  ## Key mappings.
+  xmodmap -e 'keysym BackSpace = BackSpace BackSpace'
 
-# --- Start a nice window manager ---
+  ## Gnome settings.
+  case $vnc in no) run bginit gnome-settings-daemon ;; esac
+}
 
-enlightenment $EOPTS&
+###--------------------------------------------------------------------------
+### Start a window manager.
 
-# --- Crank up a screenlock program ---
+wm=$(pick_program window-manager enlightenment e16 twm)
+wmopts=""
+case "$wm,$vnc" in
+  enlightenment,yes | e16,yes)
+    wmopts="$eopts -econfdir $HOME/.enlightenment-vnc"
+    ;;
+esac
 
-if ${SCSAVE-true}; then
-  xscreensaver-command -exit
-  xscreensaver -no-splash&
-fi
-gnome-panel&
-mail-notification&
+start-window-manager () {
+  run bginit $wm $wmopts
+}
+
+###--------------------------------------------------------------------------
+### Random useful clients.
+
+start-clients-local () { :; }
+
+start-clients () {
+  ## Mail notification.
+  run bginit mail-notification
+
+  ## System monitor.
+  case $vnc in no) run bginit gkrellm ;; esac
+
+  ## Screensaver.
+  case $vnc in
+    no)
+      run init xscreensaver-command -exit
+      run bginit xscreensaver -no-splash
+      ;;
+  esac
+
+  ## Panel.
+  case $vnc in no) run bginit gnome-panel ;; esac
 
-# --- Emacs window measurements ---
-#
-# Horizontal column pixel width = 492; window manager overhead = 34
-# Column character width = 82; Emacs magic overhead = -2
-# Vertical line pixel height = 13; misc overhead = 52
+  ## Local clients.
+  start-clients-local
+}
 
-emacs="noip emacs"
+###--------------------------------------------------------------------------
+### Main screen layout.
 
-# --- Xterm window measurements ---
-#
-# Window width is 504 (fixed).
-# Vertical line pixel height = 13; misc overhead = 23
+## Choose appropriate clients.
+emacs=$(pick_program emacs emacs22 emacs21 emacs)
+term=$(pick_program terminal pterm Eterm xterm)
 
-xterm="Eterm" xgeom=-geometry
+## Emacs window measurements.
+case "$emacs" in
+  emacs21 | emacs)
+    e_colwd=492 e_hextra=34
+    e_colchars=82 e_cextra=-2
+    e_lineht=13 e_vextra=52
+    ;;
+  emacs22)
+    e_colwd=492 e_hextra=8
+    e_colchars=82 e_cextra=-6
+    e_lineht=13 e_vextra=46
+    ;;
+esac
 
-# --- GNOME stuff measurements ---
-#
-# GNOME panel width = 113
+## Terminal window measurements.
+case "$term" in
+  pterm) t_wd=504 t_lineht=13 t_vextra=23 geom=-geometry;;
+  Eterm) t_wd=504 t_lineht=13 t_vextra=23 geom=-g;;
+  xterm) t_wd=507 t_lineht=13 t_vextra=27 geom=-geometry;;
+esac
 
+## GNOME stuff measurements.
 declare -i xbound="XWIDTH - 113"
 
-# --- Choose a width for Emacs ---
-#
-# We'd like it to be as wide as possible, allowing for a column of xterms
-# down the right hand side.  However, I'd prefer a double-width Emacs to a
-# single-width Emacs and xterms.  If it's not going to work at all, a single
-# Emacs column will have to do.  Also, there's a strange thing with Emacs21
-# and the toolbar, so we add on some rows which are later mysteriously
-# subtracted.
-
-declare -i ecols="(xbound - 504 - 34)/492"
-if (( ecols < 2 && xbound > 492 * 2 + 34 )); then
+## Choose a width for Emacs.
+##
+## We'd like it to be as wide as possible, allowing for a column of xterms
+## down the right hand side.  However, I'd prefer a double-width Emacs to a
+## single-width Emacs and xterms.  If it's not going to work at all, a single
+## Emacs column will have to do.  Also, there's a strange thing with Emacs21
+## and the toolbar, so we add on some rows which are later mysteriously
+## subtracted.
+
+declare -i ecols="(xbound - t_wd - e_hextra)/e_colwd"
+if (( ecols < 2 && xbound > e_colwd * 2 + e_hextra )); then
   ecols=2
 elif (( ecols < 1 )); then
   ecols=1
 fi
 
-declare -i x="ecols * 492 + 34"
-$emacs -geometry $((ecols * 82 - 2))x$(((XHEIGHT - 52)/13))+0+0&
-
-# --- Now place some xterms ---
-#
-# A few smaller xterms are in general better than one great big one.  35
-# lines is a good height for most terminals.  25 lines is a minimum.  The
-# strategy for doling out xterms into a column is to make as many 35-liners
-# as we can, until the remaining space would be too small for a 25-liner.  If
-# we can get two 25s out of that then we do (largest first); otherwise just
-# make one big one.  We stop at the end of a page, once we've made three
-# xterms.
-
-declare -i n=0 pgx=0 l h y ht
-declare -i hstd="35 * 13 + 23" hmin="25 * 13 + 23"
-while true; do
-  if ((x + 504 > xbound)); then
-    if ((n >= 3)); then break; fi
-    x="pgx + XWIDTH" pgx="pgx + XWIDTH" xbound="xbound + XWIDTH"
-  fi
-  y=0 ht=XHEIGHT
-  while ((ht - hstd >= hmin)); do
-    $xterm -$xgeom 80x35+$x+$y&
-    y="y + hstd" ht="ht - hstd" n="n + 1"
+declare -i \
+  emacsx="ecols * e_colchars + e_cextra" \
+  emacsy="(XHEIGHT - e_vextra)/e_lineht"
+
+start-emacs () {
+  run bgclients noip $emacs -geometry ${emacsx}x${emacsy}+0+0
+}
+
+## Now place some xterms.
+##
+## A few smaller xterms are in general better than one great big one.  35
+## lines is a good height for most terminals.  25 lines is a minimum.  The
+## strategy for doling out xterms into a column is to make as many 35-liners
+## as we can, until the remaining space would be too small for a 25-liner.
+## If we can get two 25s out of that then we do (largest first); otherwise
+## just make one big one.  We stop at the end of a page, once we've made
+## three xterms.
+
+start-xterms () {
+
+  ## Initialize some parameters.
+  declare -i x="ecols * e_colwd + e_hextra" xb=xbound
+  declare -i n=0 pgx=0 l h y ht
+  declare -i hstd="35 * t_lineht + t_vextra" hmin="25 * t_lineht + t_vextra"
+
+  ## Do the placement.
+  while :; do
+
+    ## Start a new iteration.
+    if ((x + t_wd > xb)); then
+      if ((n >= 3)); then break; fi
+      x="pgx + XWIDTH" pgx="pgx + XWIDTH" xb="xb + XWIDTH"
+    fi
+
+    ## Make large xterms.
+    y=0 ht=XHEIGHT
+    while ((ht - hstd >= hmin)); do
+      run bgclients $term $geom 80x35+$x+$y
+      y="y + hstd" ht="ht - hstd" n="n + 1"
+    done
+
+    ## Fill the remaining space.
+    if ((ht >= 2 * hmin)); then h="ht - hmin"; else h=ht; fi
+    l="(h - t_vextra)/t_lineht" h="l * t_lineht + t_vextra"
+    run bgclients $term $geom 80x$l+$x+$y
+    y="y + h" ht="ht - h" n="n + 1"
+    if ((ht >= hmin)); then
+      run bgclients $term $geom 80x25+$x+$y
+      n="n + 1"
+    fi
+    x="x + t_wd"
   done
-  if ((ht >= 2 * hmin)); then h="ht - hmin"; else h=ht; fi
-  l="(h - 23)/13" h="l * 13 + 23"
-  $xterm -$xgeom 80x$l+$x+$y&
-  y="y + h" ht="ht - h" n="n + 1"
-  if ((ht >= hmin)); then
-    $xterm -$xgeom 80x25+$x+$y&
-    n="n + 1"
-  fi
-  x="x + 504"
-done
+}
+
+###--------------------------------------------------------------------------
+### Requesters.
+
+req () {
+  declare title=$1 hist=$2; shift 2
+  cmd=$(xgetline -t "$title" -p "Command:" -Hl "$HOME/$hist") &&
+  exec "$@" "$cmd"
+}
+
+###--------------------------------------------------------------------------
+### Final waiting.
+
+atom=XINIT_COMMAND$atomtag
+
+xwait () {
+  while :; do
+    xatom delete $atom
+    info "waiting on $atom"
+    line=$(xatom wait $atom)
+    info "xatom: $line"
+
+    case "$line" in
+      :help)
+       xmsg -I -t "xinitrc help" -d "xinitrc commands" - <<EOF &
+:help
+:emacs :xterms :window-manager :clients
+:ask-run :ask-command
+:init
+:terminal
+! SHELL-COMMAND
+CLIENT
+EOF
+       ;;
+      :emacs | :xterms | :window-manager | :clients)
+       start-${line#:}
+       ;;
+      :terminal)
+       run bgclients $term
+       ;;
+      :init)
+       initialize
+       ;;
+      :exec)
+       info "restarting xinitrc"
+       exec "$0" wait nostart
+       ;;
+      :ask-run)
+       req "Shell command" .cmd.hist xcatch -FMiscFixed6x13 -- sh -c&
+       ;;
+      :ask-command)
+       req "xinit command" .xinit.hist xatom set XINIT_COMMAND$atomtag&
+       ;;
+      :*)
+       xmsg -E -t "xinitrc error" "Unknown command \`$line'" &
+       ;;
+      !*)
+       eval "${line#!}"
+       ;;
+      *)
+        set -- $line
+       run bgclients "$@"
+       ;;
+    esac
+  done
+}
+
+###--------------------------------------------------------------------------
+### Actually start things up.
+
+if [ -f $HOME/.xinitrc-local ]; then
+  . $HOME/.xinitrc-local
+fi
+
+case "$start" in
+  yes)
+    info "starting standard clients"
+    initialize
+    start-window-manager
+    start-clients
+    start-emacs
+    start-xterms
+    ;;
+  no)
+    info "not starting standard clients"
+    ;;
+esac
 
-# --- Wait for the world to end ---
+case "$wait" in
+  yes)
+    xwait
+    ;;
+  no)
+    info "not waiting before exit"
+    ;;
+esac
 
-xwait XWAIT_DIE:XWAIT_DIE_NOW
-eval "$cleanup"
+###----- That's all, folks --------------------------------------------------