#!/bin/sh
: 'vim:set noet sw=2 ts=8:

  Revised 090806

  Copyright 2005 KDE e.V., Peter G.
  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; either version 2 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
'

ME="`basename \"$0\"`"

HELP="
    -h|--help		This help

    -c|--nocursor	Do not reset the cursor
    -f|--nofonts	Do not setup extra fonts
    -p|--nopersonalizer	Do not run the KDE personalizer
    -s|--nosplash	Do not run the KDE splash screen
    -w|--wm WM		Use this window manager"

OPTSO='w:hcdfps'
OPTSL='wm:,help,nocursor,nodaemons,nofonts,nopersonalizer,nosplash'

if ARGS="`getopt -n \"$0\" -o \"$OPTSO\" -l \"$OPTSL\" -- \"$@\"`"
then eval set -- "$ARGS"
else
  echo 1>&2 "  $0$HELP"
  exit 1
fi

DO_SET_CURSOR()		{ true; }
DO_NODAEMONS()		{ false; }
DO_FONT_DIRS()		{ true; }
DO_KPERSONALIZER()	{ true; }
DO_KSPLASH()		{ true; }

: '
  The "-d" (dont start daemons) option is undocumented. :-)
  This is because it starts a bit too few of KDE traditional
  services, and is only for those who know what they are doing.
'

while true
do
  case "$1" in
  '-w'|'--wm')			KDEWM="$2"; shift 2;;

  '-c'|'--nocursor')		DO_SET_CURSOR()		{ false; }; shift;;
  '-d'|'--nodaemons')		DO_NODAEMONS()		{ true; }; shift;;
  '-f'|'--nofonts')		DO_FONT_DIRS()		{ false; }; shift;;
  '-p'|'--nopersonalizer')	DO_KPERSONALIZER()	{ false; }; shift;;
  '-s'|'--nosplash')		DO_KSPLASH()		{ false; }; shift;;

  '--')				shift; break;;

  *|'-h'|'--help')
    echo 1>&2 "  $ME$HELP"
    exit 1;;
  esac
done

case "$DISPLAY" in '')
  echo 1>&2 "$0: The 'DISPLAY' environemt variable is unset or empty.

  Before running this command to start KDE, you must start the
  X server. Please make sure the X server is running, for example
  by running 'xinit', before issuing this command.
"
  exit 1;;
esac

DISP1="`expr \"$DISPLAY\" : '\([^:]*\):.*'`"
DISP2="`expr \"$DISPLAY\" : '[^:]*:\([0-9]*\)'`"
DISP3="`expr \"$DISPLAY\" : '[^:]*:[0-9]*\.\([0-9]*\)'`"

: '
  When the X server dies we get a "HUP" signal from "xinit". We must
  ignore it because we still need to do some cleanup.
'
trap "echo 1>&2 \"$ME: got SIGHUP\"" HUP

: '
  We have to unset this for Darwin since it will screw up KDEs
  dynamic-loading.
'
unset DYLD_FORCE_FLAT_NAMESPACE

: '
  Startup sequence <http://WWW.KDE.org/areas/sysadmin/startup.php>:

  "kdeinit" is used to fork off processes which improves memory usage
  and startup time <http://WWW.SUSE.DE/~bastian/Export/linking.txt>,
  <http://Wiki.KDE.org/tiki?page=Performance+Tips>.

  * "kdeinit" starts the dcopserver and klauncher first.

  * Then "kded" is started. "kded" is responsible for keeping the KSyCoCa
    database up to date. When an up-to-date database is present it goes
    into the background and the startup continues.

  * Then "kdeinit" starts "kcminit". "kcminit" performs initialisation of
    certain devices according to the users settings.

  * Then "ksmserver" is started which in turn starts:
    1) the window manager ("kwin" or "$KDEWM");
    2) everything in "$KDEDIR/Autostart"
    3) the rest of the session.

  The users personal KDE directory is usually "~/.kde", but this
  setting may be overridden by setting "$KDEHOME".
'

case "$KDEHOME" in
'') kdehome="$HOME/.kde";;
~*) kdehome="`echo \"$KDEHOME\" | sed -e \"s|^~/|$HOME/|\"`";;
?*) kdehome="$KDEHOME";;
esac

: 'see "kstartupconfig" source for usage'
mkdir -m 700 -p "$kdehome"
mkdir -m 700 -p "$kdehome/share"
mkdir -m 700 -p "$kdehome/share/config"

echo >"$kdehome/share/config/startupconfigkeys" "
kcminputrc Mouse cursorTheme ''
kcminputrc Mouse cursorSize ''
kpersonalizerrc General FirstLogin false
ksplashrc KSplash Theme Default
kcmrandrrc Display ApplyOnStartup false
kcmrandrrc [Screen0]
kcmrandrrc [Screen1]
kcmrandrrc [Screen2]
kcmrandrrc [Screen3]
kcmrandrrc [Screen4]
kcmrandrrc [Screen5]
kcmrandrrc [Screen6]
kcmrandrrc [Screen7]
"

if kstartupconfig
then . "$kdehome/share/config/startupconfig"
else
  MSG="$ME: Could not start 'kstartupconfig'.
Continuining, check your installation."
  echo 1>&2 "$MSG"
  xmessage -geometry 500x100 "$MSG"
fi

if DO_FONT_DIRS
then
: '
    Activate the KDE font directories.

    There are 4 directories that may be used for supplying fonts for KDE.
    There are 2 system directories. These belong to the administrator.
    There are 2 user directories, where the user may add her own fonts.

    The ""override"" versions are for fonts that should come first in
    the list, that is if you have a font in your "override" directory,
    it will be used in preference to any other.

    The preference order looks like this:
      user override, system override, "X", user, system

    Where "X" is the original font database that was set up before
    this script runs.
'

  usr_odir="$HOME/.fonts/kde-override"
  usr_fdir="$HOME/.fonts"

  : 'Add any user-installed font directories to the X font path'
  kde_fontpaths="$usr_fdir/fontpaths"

  do_usr_odir=1
  do_usr_fdir=1

  if test -r "$kde_fontpaths"
  then
    savifs="$IFS"
    IFS='\n'

    grep -v '^[   ]*#' "$kde_fontpaths" \
      | sed -e 's|~|'"$HOME"'|g' \
      | while read FPATH
	do
	  if test -s "$FPATH/fonts.dir"
	  then
	    xset fp+ "$FPATH"
	    case "$FPATH" in "$usr_fdir") do_usr_fdir=0;; esac
	    case "$FPATH" in "$usr_odir") do_usr_odir=0;; esac
	  fi
	done

    IFS="$savifs"
  fi

  : 'Probably KDE not longer has a KDE specific font dir, but no harm here.'
  case "$KDEDIRS" in
  '')
    case "$KDEDIR" in ?*)
      sys_odir="$KDEDIR/share/fonts/override"
      sys_fdir="$KDEDIR/share/fonts";;
    esac;;
  ?*)
    kdedirs_first="`echo \"$KDEDIRS\" | sed -e 's|:.*||'`"
    sys_odir="$kdedirs_first/share/fonts/override"
    sys_fdir="$kdedirs_first/share/fonts";;
  esac

  : '
    We run \"mkfontdir\" on the users font dirs (if we have permission)
    to pick up any new fonts they may have installed. If "mkfontdir"
    fails, we still add the users dirs to the font path, as they might
    simply have been made read-only by the administrator, for whatever
    reason.
  '

  : 'Only do usr_fdir and usr_odir if they are *not* listed in fontpaths.'

  test -n "$sys_odir" -a  -d "$sys_odir" && xset +fp "$sys_odir"
  if test "$do_usr_odir" -eq 1 -a -n "$usr_odir" -a -d "$usr_odir"
  then mkfontdir "$usr_odir" && xset +fp "$usr_odir"
  fi

  if test "$do_usr_fdir" -eq 1 -a -n "$usr_fdir" -a -d "$usr_fdir"
  then mkfontdir "$usr_fdir" && xset fp+ "$usr_fdir"
  fi
  test -n "$sys_fdir" -a -d "$sys_fdir" && xset fp+ "$sys_fdir"

  xset fp rehash
fi

: '
  Get Ghostscript to look into users KDE fonts dir for additional
  "Fontmap".
'
case "$GS_LIB" in
'') export GS_LIB; GS_LIB="$usr_fdir";;
?*) export GS_LIB; GS_LIB="$usr_fdir:$GS_LIB";;
esac

: '
  If the user has overwritten fonts, the cursor font may be different now
  so dont move this up.
'

if DO_SET_CURSOR
then
  : '
    Set a left cursor instead of the standard X11 "X" cursor, since I have
    heard from some users that they are confused and dont know what to do.
    This is especially necessary on slow machines, where starting KDE
    takes one or two minutes until anything appears on the screen.
    
    The standard X background is nasty, causing moire effects and exploding
    peoples heads. We use colours from the standard KDE palette for those
    with palettised displays.
  '

  for N in 0 1 2 3 4 5 6 7 8 9
  do xsetroot -display "$DISP1:$DISP2.$N" -solid '#707070' -cursor_name left_ptr  2> /dev/null
  done
fi

: '
   "XCursor" mouse theme needs to be applied here to work
   with "kded" or "ksmserver" too.
'

case "$kcminputrc_mouse_cursortheme;$kcminputrc_mouse_cursorsize" in ?*';'?*)
  export XCURSOR_THEME
  if kapplymousetheme "$kcminputrc_mouse_cursortheme" \
    "$kcminputrc_mouse_cursorsize"
  then
    case "$kcminputrc_mouse_cursortheme" in ?*)
      XCURSOR_THEME='kcminputrc_mouse_cursortheme';;
    esac
    case "$kcminputrc_mouse_cursorsize" in ?*)
      export XCURSOR_SIZE
      XCURSOR_SIZE="$kcminputrc_mouse_cursorsize";;
    esac
  else
    XCURSOR_THEME='default'
  fi;;
esac

: 'Apply the RandR settings'

case "$kcmrandrrc_display_applyonstartup" in 'true')
  for S in 0 1 2 3 4 5 6 7
  do
    W="${kcmrandrrc_screen${S}_width}"
    H="${kcmrandrrc_screen${S}_height}"
    R="${kcmrandrrc_screen${S}_refresh}"
    X="${kcmrandrrc_screen${S}_reflectx}"
    Y="${kcmrandrrc_screen${S}_reflecty}"
    O="${kcmrandrrc_screen${S}_rotation}"
    A=''

    case "$W;$H" in ?*';'?*) A="$A -s ${W}x${H}";; esac
    case "$R" in ?*) A="$A -r ${R}";; esac
    case "$X" in 'true') A="$A -x";; esac
    case "$Y" in 'true') A="$A -y";; esac
    case "$O" in
    0)	args="$A -o 'normal'";; 90) args="$A -o 'right'";;
    180) args="$A -o 'inverted'";; 270) args="$A -o 'left'";;
    esac

    case "$A" in ?*) xrandr --screen "$S" $A;; esac
  done
esac

: '
  Link tmp resource to directory in "/tmp/".
  Creates a directory "/tmp/kde-$USER" and links
  "$KDEHOME/tmp-$HOSTNAME" to it.
'
lnusertemp tmp >/dev/null

: '
  Link socket resource to directory in "/tmp/".
  Creates a directory "/tmp/ksocket-$USER" and links
  "$KDEHOME/socket-$HOSTNAME" to it.
'
lnusertemp socket >/dev/null

: '
  Link cache resource to directory in "/var/tmp/".
  Creates a directory "/var/tmp/kdecache-$USER" and links
  "$KDEHOME/cache-$HOSTNAME" to it.
'
lnusertemp cache >/dev/null

: 'In case of DCOP sockets left by a previous session, cleanup.'
dcopserver_shutdown

: '
  Remove one trailing space from each prompt to avoid too
  much nesting, for those systems that add a space for each
  level of nesting. The lines are replicated because a loop
  is too hairy under shell expansions/quoting rules.
'
case "$PS0" in ?*' ')
  PS0="`expr \"$PS0\" : '\(.*\) '`"
  PS1="`expr \"$PS1\" : '\(.*\) '`"
  PS2="`expr \"$PS2\" : '\(.*\) '`"
  PS3="`expr \"$PS3\" : '\(.*\) '`"
  PS4="`expr \"$PS4\" : '\(.*\) '`";;
esac

echo "$ME: Starting up..."

: ' Konqueror preloading and other features work only with full KDE'
export KDE_FULL_SESSION
KDE_FULL_SESSION='true'

exitcode=0

if DO_NODAEMONS
then
  if LD_BIND_NOW=true kdeinit kicker "${KDEWM:-kwin}"
  then : 'good'
  else
    exitcode="$?"
    MSG="$ME: Could not start 'kdeinit kicker $KDEWM'.
Continuing, check your installation."
    echo 1>&2 "$MSG"
    xmessage -geometry 500x100 "$MSG"
  fi
else
  if DO_KPERSONALIZER
  then
    : 'Run "kpersonalizer" before the session, if this is the first login.'
    if kreadconfig --file kpersonalizerrc \
      --group General --key FirstLogin --default true --type bool
    then
      : 'Start only "dcopserver", dont start whole "kdeinit" (takes too long).'
      echo "$ME: Running 'kpersonalizer'..."
      dcopserver
      kwin --lock &
      if ! kpersonalizer --before-session
      then
	: 'Handle "kpersonalizer" restarts (language change).'
	until kpersonalizer --r --before-session
	do : 'run it again'
	done

	dcopserver_shutdown
	: 'Shutdown will also make "kwin" quit, give it time to do so.'
	sleep 1
      fi
    fi
  fi

  if DO_KSPLASH
  then
    : 'The splashscreen and progress indicator.'
    case "$ksplashrc_ksplash_theme" in
    'None') : 'no splash';;
    'Simple') ksplashsimple;;
    *) ksplash --nodcop;;
    esac
  fi

  : '
    We set "LD_BIND_NOW" to increase the efficiency of "kdeinit".
    "kdeinit" unsets this variable before loading applications.
  '
  if LD_BIND_NOW=true kdeinit --new-startup +kcminit_startup
  then : 'good'
  else
    MSG="$ME: Could not start 'kdeinit +kcminit +knotify'.
Continuing, check your installation."
    echo 1>&2 "$MSG"
    xmessage -geometry 500x100 "$MSG"
  fi

  : '
    If the session should be locked from the start (locked autologin),
    lock now and do the rest of the KDE startup underneath the locker.
  '
  case "$DESKTOP_LOCKED" in '1'|[Yy]*)
    unset DESKTOP_LOCKED
    kwrapper kdesktop_lock --forcelock &
    : 'Should wait until started, but cannot, so just wait a bit'
    sleep 1;;
  esac

  : '
    Finally, the session manager to create and control the session.

    If the "KDEWM" environment variable has been set, then it will be used
    as KDEs window manager instead of "kwin". If KDEWM is not set,
    "ksmserver" will ensure "kwin" is started.

    "kwrapper" is used to reduce startup time and memory usage. "kwrapper"
    does not return useful error codes such as the exit code of "ksmserver".

    We only check for 255 which means that the "ksmserver" process could
    not be started, any problems thereafter, e.g. "ksmserver" failing to
    initialize, will remain undetected.
  '

  if
    case "$KDEWM" in
    '') kwrapper ksmserver;;
    ?*) kwrapper ksmserver --windowmanager "$KDEWM";;
    esac
  then : 'good'
  else
    exitcode="$?"

    MSG="$ME: Could not start 'ksmserver'.
Check your KDE installation."
    echo 1>&2 "$MSG"
    xmessage -geometry 500x100 "$MSG"
  fi

  echo "$ME: Shutting down..."

  for N in 0 1 2 3 4 5 6 7 8 9
  do xsetroot -display "$DISP1:$DISP2.$N" -solid '#707070' 2> /dev/null
  done

  : 'Clean up.'
  kdeinit_shutdown
  dcopserver_shutdown --wait
  artsshell -q terminate

  echo "$ME: Running shutdown scripts..."

  : 'Run scripts found in "$KDEDIRS/shutdown".'
  kde-config --path exe \
  | sed -e 's|bin/|shutdown/|g; s|:| |g' \
  | while read PREFIX
    do 
      for FILE in "$PREFIX"/*
      do test -x "$FILE" && "$FILE"
      done
    done
fi

echo "$ME: Done."
exit "$exitcode"
