| 1 | #! /bin/bash |
| 2 | ### |
| 3 | ### X startup script |
| 4 | |
| 5 | ###-------------------------------------------------------------------------- |
| 6 | ### Utility functions. |
| 7 | |
| 8 | ## Progress indicators. |
| 9 | info=yes |
| 10 | info () { |
| 11 | case $info in yes) echo "- $*" >&2 ;; esac |
| 12 | } |
| 13 | |
| 14 | run=yes |
| 15 | run () { |
| 16 | local what=$1; shift |
| 17 | local bg=no |
| 18 | |
| 19 | case $what in bg*) bg=yes what=${what#bg} ;; esac |
| 20 | info "run $what: $*" |
| 21 | |
| 22 | case "$run,$bg" in |
| 23 | yes,no) "$@" ;; |
| 24 | yes,yes) "$@" & ;; |
| 25 | esac |
| 26 | } |
| 27 | |
| 28 | ## Program choice |
| 29 | pick_program () { |
| 30 | local what=$1; shift |
| 31 | local choice=false |
| 32 | for i in "$@"; do |
| 33 | if type -t >/dev/null "$i"; then choice=$i; break; fi |
| 34 | done |
| 35 | info "pick $what = $choice" |
| 36 | echo "$choice" |
| 37 | } |
| 38 | |
| 39 | ###-------------------------------------------------------------------------- |
| 40 | ### Parse arguments. |
| 41 | |
| 42 | vnc=no |
| 43 | atomtag= |
| 44 | start=yes |
| 45 | wait=yes |
| 46 | |
| 47 | for opt; do |
| 48 | case "$opt" in |
| 49 | help) |
| 50 | cat <<EOF |
| 51 | Options: |
| 52 | tag=TAG |
| 53 | [no]trace |
| 54 | [no]info |
| 55 | [no]run |
| 56 | [no]start |
| 57 | [no]wait |
| 58 | [no]vnc |
| 59 | EOF |
| 60 | exit |
| 61 | ;; |
| 62 | |
| 63 | tag=*) atomtag=/${opt#tag=} ;; |
| 64 | trace) set -x ;; |
| 65 | notrace) set +x ;; |
| 66 | info | run | start | wait | vnc) eval "$opt=yes" ;; |
| 67 | noinfo | norun | nostart | nowait | novnc) eval "${opt#no}=no" ;; |
| 68 | |
| 69 | *) echo "unknown option $opt" >&2; exit 1 ;; |
| 70 | esac |
| 71 | done |
| 72 | |
| 73 | ###-------------------------------------------------------------------------- |
| 74 | ### Preliminary hook. |
| 75 | |
| 76 | if [ -r $HOME/.xinitrc-prehook ]; then |
| 77 | . $HOME/.xinitrc-prehook |
| 78 | fi |
| 79 | |
| 80 | ###-------------------------------------------------------------------------- |
| 81 | ### Iniitial settings. |
| 82 | |
| 83 | ## Assume X sessions are secure. |
| 84 | export __mdw_sechost="`hostname`" |
| 85 | |
| 86 | ## Obtain the screen dimensions. |
| 87 | case ",$XWIDTH,$XHEIGHT," in |
| 88 | *,,*) eval $(xscsize -bx) ;; |
| 89 | esac |
| 90 | info "screen size = $XWIDTH x $XHEIGHT" |
| 91 | |
| 92 | initialize () { |
| 93 | ## Load the X resource database. |
| 94 | run init xrdb -override $HOME/.Xdefaults |
| 95 | |
| 96 | ## Random xsettery. |
| 97 | run init xset b 5 2000 50 |
| 98 | run init xset r rate 500 50 |
| 99 | run init xset m 2 1 |
| 100 | |
| 101 | ## Key mappings. |
| 102 | xmodmap -e 'keysym BackSpace = BackSpace BackSpace' |
| 103 | } |
| 104 | |
| 105 | ###-------------------------------------------------------------------------- |
| 106 | ### Start a window manager. |
| 107 | |
| 108 | wm=$(pick_program window-manager enlightenment e16 twm) |
| 109 | wmopts="" |
| 110 | case "$wm,$vnc" in |
| 111 | enlightenment,yes | e16,yes) |
| 112 | wmopts="$eopts -econfdir $HOME/.enlightenment-vnc" |
| 113 | ;; |
| 114 | esac |
| 115 | |
| 116 | start-e16 () { |
| 117 | run bginit $wm $wmopts |
| 118 | win=nil |
| 119 | for i in $(seq 10); do |
| 120 | sleep 1 |
| 121 | if eesh version >/dev/null 2>&1; then |
| 122 | win=t |
| 123 | break |
| 124 | fi |
| 125 | done |
| 126 | case $win in |
| 127 | t) |
| 128 | info "$wm started ok" |
| 129 | run init xsetroot -cursor_name left_ptr |
| 130 | ;; |
| 131 | nil) |
| 132 | info "$wm failed to start!" |
| 133 | ;; |
| 134 | esac |
| 135 | } |
| 136 | |
| 137 | start-window-manager () { |
| 138 | case $(type -t start-$wm || echo "not-found") in |
| 139 | function) |
| 140 | start-$wm $wmopts |
| 141 | ;; |
| 142 | *) |
| 143 | run bginit $wm $wmopts |
| 144 | ;; |
| 145 | esac |
| 146 | } |
| 147 | |
| 148 | ###-------------------------------------------------------------------------- |
| 149 | ### Random useful clients. |
| 150 | |
| 151 | start-clients-local () { :; } |
| 152 | |
| 153 | start-clients () { |
| 154 | ## Gnome session. |
| 155 | case $vnc in no) run bginit gnome-session ;; esac |
| 156 | |
| 157 | ## Local clients. |
| 158 | start-clients-local |
| 159 | } |
| 160 | |
| 161 | ###-------------------------------------------------------------------------- |
| 162 | ### Main screen layout. |
| 163 | |
| 164 | ## Choose appropriate clients. |
| 165 | emacs=$(pick_program emacs emacs23 emacs22 emacs21 emacs) |
| 166 | term=$(pick_program terminal pterm Eterm xterm) |
| 167 | |
| 168 | ## Emacs window measurements. |
| 169 | case "$emacs" in |
| 170 | emacs21 | emacs) |
| 171 | e_colwd=492 e_hextra=34 |
| 172 | e_colchars=82 e_cextra=-2 |
| 173 | e_lineht=13 e_vextra=52 |
| 174 | ;; |
| 175 | emacs22 | emacs23) |
| 176 | e_colwd=492 e_hextra=8 |
| 177 | e_colchars=82 e_cextra=-6 |
| 178 | e_lineht=13 e_vextra=46 |
| 179 | ;; |
| 180 | esac |
| 181 | |
| 182 | ## Terminal window measurements. |
| 183 | case "$term" in |
| 184 | pterm) t_wd=504 t_lineht=13 t_vextra=23 geom=-geometry;; |
| 185 | Eterm) t_wd=504 t_lineht=13 t_vextra=23 geom=-g;; |
| 186 | xterm) t_wd=507 t_lineht=13 t_vextra=27 geom=-geometry;; |
| 187 | esac |
| 188 | |
| 189 | ## GNOME stuff measurements. |
| 190 | declare -i xbound="XWIDTH - 113" |
| 191 | |
| 192 | ## Choose a width for Emacs. |
| 193 | ## |
| 194 | ## We'd like it to be as wide as possible, allowing for a column of xterms |
| 195 | ## down the right hand side. However, I'd prefer a double-width Emacs to a |
| 196 | ## single-width Emacs and xterms. If it's not going to work at all, a single |
| 197 | ## Emacs column will have to do. Also, there's a strange thing with Emacs21 |
| 198 | ## and the toolbar, so we add on some rows which are later mysteriously |
| 199 | ## subtracted. |
| 200 | |
| 201 | declare -i ecols="(xbound - t_wd - e_hextra)/e_colwd" |
| 202 | if (( ecols < 2 && xbound > e_colwd * 2 + e_hextra )); then |
| 203 | ecols=2 |
| 204 | elif (( ecols < 1 )); then |
| 205 | ecols=1 |
| 206 | fi |
| 207 | |
| 208 | declare -i \ |
| 209 | emacsx="ecols * e_colchars + e_cextra" \ |
| 210 | emacsy="(XHEIGHT - e_vextra)/e_lineht" |
| 211 | |
| 212 | start-emacs () { |
| 213 | GDK_NATIVE_WINDOWS=1 run bgclients noip \ |
| 214 | $emacs -geometry ${emacsx}x${emacsy}+0+0 |
| 215 | } |
| 216 | |
| 217 | ## Now place some xterms. |
| 218 | ## |
| 219 | ## A few smaller xterms are in general better than one great big one. 35 |
| 220 | ## lines is a good height for most terminals. 25 lines is a minimum. The |
| 221 | ## strategy for doling out xterms into a column is to make as many 35-liners |
| 222 | ## as we can, until the remaining space would be too small for a 25-liner. |
| 223 | ## If we can get two 25s out of that then we do (largest first); otherwise |
| 224 | ## just make one big one. We stop at the end of a page, once we've made |
| 225 | ## three xterms. |
| 226 | |
| 227 | start-xterms () { |
| 228 | |
| 229 | ## Initialize some parameters. |
| 230 | declare -i x="ecols * e_colwd + e_hextra" xb=xbound |
| 231 | declare -i n=0 pgx=0 l h y ht |
| 232 | declare -i hstd="35 * t_lineht + t_vextra" hmin="25 * t_lineht + t_vextra" |
| 233 | |
| 234 | ## Do the placement. |
| 235 | while :; do |
| 236 | |
| 237 | ## Start a new iteration. |
| 238 | if ((x + t_wd > xb)); then |
| 239 | if ((n >= 3)); then break; fi |
| 240 | x="pgx + XWIDTH" pgx="pgx + XWIDTH" xb="xb + XWIDTH" |
| 241 | fi |
| 242 | |
| 243 | ## Make large xterms. |
| 244 | y=0 ht=XHEIGHT |
| 245 | while ((ht - hstd >= hmin)); do |
| 246 | run bgclients $term $geom 80x35+$x+$y |
| 247 | y="y + hstd" ht="ht - hstd" n="n + 1" |
| 248 | done |
| 249 | |
| 250 | ## Fill the remaining space. |
| 251 | if ((ht >= 2 * hmin)); then h="ht - hmin"; else h=ht; fi |
| 252 | l="(h - t_vextra)/t_lineht" h="l * t_lineht + t_vextra" |
| 253 | run bgclients $term $geom 80x$l+$x+$y |
| 254 | y="y + h" ht="ht - h" n="n + 1" |
| 255 | if ((ht >= hmin)); then |
| 256 | run bgclients $term $geom 80x25+$x+$y |
| 257 | n="n + 1" |
| 258 | fi |
| 259 | x="x + t_wd" |
| 260 | done |
| 261 | } |
| 262 | |
| 263 | ###-------------------------------------------------------------------------- |
| 264 | ### Requesters. |
| 265 | |
| 266 | req () { |
| 267 | declare title=$1 hist=$2; shift 2 |
| 268 | cmd=$(xgetline -t "$title" -p "_Command:" -Hl "$HOME/$hist") && |
| 269 | exec "$@" "$cmd" |
| 270 | } |
| 271 | |
| 272 | ###-------------------------------------------------------------------------- |
| 273 | ### Final waiting. |
| 274 | |
| 275 | atom=XINIT_COMMAND$atomtag |
| 276 | |
| 277 | xwait () { |
| 278 | while :; do |
| 279 | xatom delete $atom |
| 280 | info "waiting on $atom" |
| 281 | line=$(xatom wait $atom) |
| 282 | info "xatom: $line" |
| 283 | |
| 284 | case "$line" in |
| 285 | :help) |
| 286 | xmsg -I -t "xinitrc help" -d "xinitrc commands" - <<EOF & |
| 287 | :help |
| 288 | :emacs :xterms :window-manager :clients |
| 289 | :ask-run :ask-command |
| 290 | :init |
| 291 | :terminal |
| 292 | ! SHELL-COMMAND |
| 293 | CLIENT |
| 294 | EOF |
| 295 | ;; |
| 296 | :emacs | :xterms | :window-manager | :clients) |
| 297 | start-${line#:} |
| 298 | ;; |
| 299 | :terminal) |
| 300 | run bgclients $term |
| 301 | ;; |
| 302 | :init) |
| 303 | initialize |
| 304 | ;; |
| 305 | :exec) |
| 306 | info "restarting xinitrc" |
| 307 | exec "$0" wait nostart |
| 308 | ;; |
| 309 | :ask-run) |
| 310 | req "Shell command" .cmd.hist xcatch -FMiscFixed6x13 -- sh -c& |
| 311 | ;; |
| 312 | :ask-command) |
| 313 | req "xinit command" .xinit.hist xatom set XINIT_COMMAND$atomtag& |
| 314 | ;; |
| 315 | :*) |
| 316 | xmsg -E -t "xinitrc error" "Unknown command \`$line'" & |
| 317 | ;; |
| 318 | !*) |
| 319 | eval "${line#!}" |
| 320 | ;; |
| 321 | *) |
| 322 | set -- $line |
| 323 | run bgclients "$@" |
| 324 | ;; |
| 325 | esac |
| 326 | done |
| 327 | } |
| 328 | |
| 329 | ###-------------------------------------------------------------------------- |
| 330 | ### Actually start things up. |
| 331 | |
| 332 | if [ -f $HOME/.xinitrc-local ]; then |
| 333 | . $HOME/.xinitrc-local |
| 334 | fi |
| 335 | |
| 336 | case "$start" in |
| 337 | yes) |
| 338 | info "starting standard clients" |
| 339 | initialize |
| 340 | start-window-manager |
| 341 | start-clients |
| 342 | start-emacs |
| 343 | start-xterms |
| 344 | ;; |
| 345 | no) |
| 346 | info "not starting standard clients" |
| 347 | ;; |
| 348 | esac |
| 349 | |
| 350 | case "$wait" in |
| 351 | yes) |
| 352 | xwait |
| 353 | ;; |
| 354 | no) |
| 355 | info "not waiting before exit" |
| 356 | ;; |
| 357 | esac |
| 358 | |
| 359 | ###----- That's all, folks -------------------------------------------------- |