#!/bin/sh
# @vasm : vxconf
# @level: root
# @description: Set up X.org configuration
#
# This script uses autodetection from vlsetup, ddc and Xorg.
# Hopefully, it will be smarter. Finger crossed.
# 
# (c) Eko M. Budi, 2003
# (c) Vector Linux, 2003
#
# Released under GNU GPL
#

vdir=`dirname $0`
source $vdir/vasm-functions

check_root

## Properties
## The actual config (that we want to change)
config_file="/etc/X11/xorg.conf"

## basic configuration file (template)
basic_file="/etc/X11/xorg.conf-vesa"

## old configuration file
source_file=$basic_file

## newly detected config file 
new_file="$HOME/xorg.conf.new"

xprog="Xorg"
xprogconfig="Xorg -configure"

################################################################
## Initialization
## Find BASIC FILE
if [ ! -f $basic_file ]; then
      errorbox "Cannot find template $basic_file"
      clean_exit 1
fi

## Find the program
if which Xorg &> /dev/null; then
      xprog="Xorg"
      xprogconfig="Xorg -configure"
      config_file="/etc/X11/xorg.conf"
      new_file="$HOME/xorg.conf.new"
elif which XFree86 &> /dev/null; then
      xprog="XFree86"
      xprogconfig="XFree86 -configure"
      config_file="/etc/X11/XF86Config-4"
      new_file="$HOME/XF86Config.new"
else
      errorbox "Cannot find X-Window system."
      clean_exit 1
fi

## Things that we need to change
function default_values()
{
XMOUSE_PROTOCOL="PS/2"
XMOUSE_ZAXISMAPPING=""
XMOUSE_BUTTONS=""
XMOUSE_E3BUTTONS="false"
XMOUSE_ZSENDCOREEVENTS=""

XMONITOR_HSYNCH=""
XMONITOR_VREFRESH=""
XMONITOR_VENDOR="Any"
XMONITOR_MODEL="Generic"

XDEVICE_DRIVER="vesa"
XDEVICE_BOARD="Generic"
XDEVICE_VENDOR="Any"
XDEVICE_SWCURSOR=""
XDEVICE_BUSID=""

XSCREEN_DEPTH="16"
XSCREEN_MODES='"800x600" "640x480"'
XDRI=""

}

# We are looking for
# INITIAL STATE : XMOUSE, XDEPTH, XMODES, XDRIVER, XBOARD, XDRI, are set
# 
function get_config()
{
   default_values

   section=""
   while read line; do
     if echo $line | grep -qe '^\<Section ' ; then
        section=$(echo $line | cut -f 2 -d '"')
     elif echo $line | grep -qe '^\<EndSection' ; then
        section=""
     fi
     case $section in
        InputDevice)
	  if echo $line | grep -qe '^\<Option .*"Protocol"'; then
             XMOUSE_PROTOCOL=$(echo $line | cut -f 4 -d '"')
	     dbug "mouse=$XMOUSE_PROTOCOL"
	  fi
	  ;;
        Monitor)
	  if echo $line | grep -qe '^\<HorizSync .*'; then
	    XMONITOR_HSYNCH=$(echo $line | cut -f 2 -d ' ')      
	    dbug "hsynch=$XMONITOR_HSYNCH"
	  elif echo $line | grep -qe '^\<VertRefrest .*'; then
	    XMONITOR_VREFRESH=$(echo $line | cut -f 2 -d ' ')
	    dbug "vrefresh=$XMONITOR_VREFRESH"
	  elif echo $line | grep -qe '^\<VendorName .*'; then
	    XMONITOR_VENDOR=$(echo $line | cut -f 2 -d '"')
	    dbug "mvendor=$XMONITOR_VENDOR"
	  elif echo $line | grep -qe '^\<ModelName .*'; then
	    XMONITOR_MODEL=$(echo $line | cut -f 2 -d '"')
	    dbug "mmodel=$XMONITOR_MODEL"
	  fi
	  ;;
        Device)
	  if echo $line | grep -qe '^\<Driver .*'; then
	    XDEVICE_DRIVER=$(echo $line | cut -f 2 -d '"')
	    dbug "driver=$XDEVICE_DRIVER"
	  elif echo $line | grep -qe '^\<BoardName .*'; then
	    XDEVICE_BOARD=$(echo $line | cut -f 2 -d '"')
	    dbug "board=$XDEVICE_BOARD"
	  elif echo $line | grep -qe '^\<VendorName .*'; then
	    XDEVICE_VENDOR=$(echo $line | cut -f 2 -d '"')
	    dbug "vendor=$XDEVICE_VENDOR"
	  elif echo $line | grep -qe '^\<Option .*"swcursor"'; then
	    XDEVICE_SWCURSOR=$(echo $line | cut -f 4 -d '"')
	    dbug "swcursor=$XDEVICE_SWCURSOR"
	  elif echo $line | grep -qe '^\<BusID .*'; then
	    XDEVICE_BUSID=$(echo $line | cut -f 2 -d '"')
	    dbug "busid=$XDEVICE_BUSID"
	  fi
	  ;;
       Screen)
	  if echo $line | grep -qe '^\<DefaultDepth .*'; then
	    XSCREEN_DEPTH=$(echo $line | cut -f 2 -d ' ')      
	    dbug "depth=$XSCREEN_DEPTH"
          fi
          ;;
     esac
  done
  
  ## Use HSYNCH and VREFRESH from DDC, if available
  ## Since it is better than Xorg probing 
  if which ddcxinfo &>/dev/null ; then
    DMONITOR_HSYNCH=`ddcxinfo -hsync 2>/dev/null`
    DMONITOR_VREFRESH=`ddcxinfo -vsync 2>/dev/null`
    dbug "hsynch=$DMONITOR_HSYNCH"
    dbug "vrefresh=$DMONITOR_VREFRESH"
    if [ "$DMONITOR_HSYNCH" = "0-0" ] || [ "$DMONITOR_VREFRESH" = "0-0" ]; then
	DMONITOR_HSYNCH=""
	DMONITOR_VREFRESH=""
    fi
    if [ "$DMONITOR_HSYNCH" ] && [ "$DMONITOR_VREFRESH" ]; then
	XMONITOR_HSYNCH="$DMONITOR_HSYNCH"
	XMONITOR_VREFRESH="$DMONITOR_VREFRESH"
    fi
    dbug "hsynch=$XMONITOR_HSYNCH"
    dbug "vrefresh=$XMONITOR_VREFRESH"
  fi
  
  ## Get mouse settings from vector record
  if [ -f /etc/sysconfig/vector ]; then
    eval `grep -e '^X' /etc/sysconfig/vector`
    [ "$XMOUSETYPE0" ] && XMOUSE_PROTOCOL="$XMOUSETYPE0"
  fi
 
}

function set_config()
{

   ## Detect some implicits settings
   case $XDEVICE_DRIVER in 
      ati|radeon|trident|neomagic) 
        XDEVICE_SWCURSOR="true"
	;;
      vmware)
        XDEVICE_BUSID="PCI:0:15:0"
	XSCREEN_DEPTH=""
	;;
   esac 

   ## Save the old file
   if [ -f $config_file ]; then
      cp $config_file ${config_file}.backup   
   fi   
  
   ## Make a new one from the basic file
   echo '### xorg.conf' > $config_file
   echo '### generated by Xorg -configure and vxconf' >> $config_file
   grep -v -e "^###" $source_file >> $config_file

   ## OK, sed it one by one
   ## Too complicated to do all at once ;-)
   
   ## MOUSE_PROTOCOL must be always set, default=auto
   sed -i \
   "s!.*## MOUSE_PROTOCOL!    Option  \"Protocol\"  \"$XMOUSE_PROTOCOL\"   ## MOUSE_PROTOCOL!" \
   $config_file

   if [ "$XMOUSE_ZAXISMAPPING" ] && [ "$XMOUSE_BUTTONS" ]; then
      sed -i \
      "s!.*## MOUSE_ZAXISMAPPING!    Option \"ZAxisMapping\" \"$XMOUSE_ZAXISMAPPING\"    ## MOUSE_ZAXISMAPPING!" \
      $config_file
      sed -i \
      "s!.*## MOUSE_BUTTONS!    Option \"Buttons\" \"$XMOUSE_BUTTONS\"    ## MOUSE_BUTTONS!" \
      $config_file
   else
      sed -i \
      "s!.*## MOUSE_ZAXISMAPPING!#    Option \"ZAxisMapping\" \"$XMOUSE_ZAXISMAPPING\"    ## MOUSE_ZAXISMAPPING!" \
      $config_file
      sed -i \
      "s!.*## MOUSE_BUTTONS!#    Option \"Buttons\" \"$XMOUSE_BUTTONS\"    ## MOUSE_BUTTONS!" \
      $config_file
   fi

   if [ "$XMOUSE_E3BUTTONS" = "true" ]; then
   sed -i \
   's!.*## MOUSE_E3BUTTONS!    Option "Emulate3Buttons"      ## MOUSE_E3BUTTONS!' \
   $config_file
   else
   sed -i \
   's!.*## MOUSE_E3BUTTONS!#    Option "Emulate3Buttons"      ## MOUSE_E3BUTTONS!' \
   $config_file
   fi

   if [ "$XMOUSE_SENDCOREEVENTS" = "true" ]; then
   sed -i \
   's!.*## MOUSE_SENDCOREEVENTS!    Option "SendCoreEvents"      ## MOUSE_SENDCOREEVENTS!' \
   $config_file
   else
   sed -i \
   's!.*## MOUSE_SENDCOREEVENTS!#    Option "SendCoreEvents"      ## MOUSE_SENDCOREEVENTS!' \
   $config_file
   fi

   if [ "$XMONITOR_HSYNCH" ]; then
   cat $config_file | sed \
   "s!.*## MONITOR_HSYNCH!    HorizSync $XMONITOR_HSYNCH    ## MONITOR_HSYNCH!" \
   > $config_file
   else
   cat $config_file | sed \
   's!.*## MONITOR_HSYNCH!#    HorizSync      ## MONITOR_HSYNCH!' \
   > $config_file
   fi
   
   if [ "$XMONITOR_VREFRESH" ]; then
   cat $config_file | sed \
   "s!.*## MONITOR_VREFRESH!    VertRefresh $XMONITOR_VREFRESH    ## MONITOR_VREFRESH!" \
   > $config_file
   else
   cat $config_file | sed \
   's!.*## MONITOR_VREFRESH!#    VertRefresh      ## MONITOR_VREFRESH!' \
   > $config_file
   fi

   cat $config_file | sed \
   "s!.*## MONITOR_VENDOR!    VendorName    \"$XMONITOR_VENDOR\"   ## MONITOR_VENDOR!" \
   > $config_file

   cat $config_file | sed \
   "s!.*## MONITOR_MODEL!    ModelName    \"$XMONITOR_MODEL\"   ## MONITOR_MODEL!" \
   > $config_file

   ## DEVICE_DRIVER must be always set, default=vesa
   cat $config_file | sed \
   "s!.*## DEVICE_DRIVER!    Driver    \"$XDEVICE_DRIVER\"   ## DEVICE_DRIVER!" \
   > $config_file

   ## DEVICE_BOARD must be always set, default=Generic
   cat $config_file | sed \
   "s!.*## DEVICE_BOARD!    BoardName    \"$XDEVICE_BOARD\"      ## DEVICE_BOARD!" \
   > $config_file

   ## DEVICE_VENDOR must be always set, default=Any
   cat $config_file | sed \
   "s!.*## DEVICE_VENDOR!    VendorName  \"$XDEVICE_VENDOR\"    ## DEVICE_VENDOR!" \
   > $config_file

   if [ "$DEVICE_SWCURSOR" = "true" ]; then
   cat $config_file | sed \
   's!.*## DEVICE_SWCURSOR!    Option "swcursor" "true"    ## DEVICE_SWCURSOR!' \
   > $config_file
   else
   cat $config_file | sed \
   's!.*## DEVICE_SWCURSOR!#    Option "swcursor" "true"    ## DEVICE_SWCURSOR!' \
   > $config_file
   fi

   if [ "$XDEVICE_BUSID" ]; then
   cat $config_file | sed \
   "s!.*## DEVICE_BUSID!    BusID \"$XDEVICE_BUSID\"    ## DEVICE_BUSID!" \
   > $config_file
   else
   cat $config_file | sed \
   's!.*## DEVICE_BUSID!#    BusID  "PCI:1:0:0"   ## DEVICE_BUSID!' \
   > $config_file
   fi

   ## SCREEN_DEPTH must be always set, default=16
   cat $config_file | sed \
   "s!.*## SCREEN_DEPTH!    DefaultDepth $XSCREEN_DEPTH   ## SCREEN_DEPTH!" \
   > $config_file


   ## Change all modes
   cat $config_file | sed \
   "s!.*## SCREEN_MODES!        Modes $XSCREEN_MODES  ## SCREEN_MODES!" \
   > $config_file
   
   ## That's all
   return 0
}

############################################################
# AUTO DETECT
# Autodetect video mode
# We are using double detection from xprogconfig and vlsetup 
function menuA11() {

TITLE="VIDEO DRIVER VOTE"
TEXT="\n
The smart autodetectors give different opinions.\n
So, we need your wisdom. Which one is correct ?"
DIMENSION="12 64 3"

$DCMD --backtitle "$BACKTITLE" --title "$TITLE" --menu "$TEXT" $DIMENSION \
"$XMODULE"   "`echo $XDESC | cut -f2 -d '|'`" \
"$XDEVICE_DRIVER" "$XDEVICE_BOARD" \
"NONE"   "Please, forgive the humble autodetectors" \
2> $freply || return $?

  reply=$(cat $freply)
  case $reply in
    $XMODULE)
	DEVICE_DRIVER=$XMODULE
	DEVICE_VENDOR=`echo $XDESC | cut -f1 -d '|'`
	DEVICE_BOARD=`echo $XDESC | cut -f2 -d '|'`
      ;;
    NONE)
	return 1
      ;;
  esac 
return 0
}

auto_detect()
{
  clear
  echo "Autodetecting X-Window"
  echo "Hold tight ... the screen will be shaken a bit !!!"
  sleep 2

  ## Autodetect using X-Server detection
  ## this will produce the $new_file
  modprobe apm
  $xprogconfig >/dev/null 2>&1 
  if [ $? = 0 ] && [ -r $new_file ]; then
    get_config < $new_file
    rm $new_file
    source_file=$basic_file
    # double check
    [ "$XDEVICE_DRIVER" = "$XMODULE" ] && return 0
    ## dang, got to ask
    menuA11
    return $?
  elif [ "$XMODULE" ]; then
    # X-server detection was failed, vlsetup to the rescue
    get_config < $basic_file
    source_file=$basic_file
    XDEVICE_DRIVER=$XMODULE
    XDEVICE_VENDOR=`echo $XDESC | cut -f1 -d '|'`
    XDEVICE_BOARD=`echo $XDESC | cut -f2 -d '|'`
    return 0
  fi
  ## fail
  return 1
}

function menuA1()
{
dbug "Autodetect"
TITLE="AUTODETECT X-WINDOW"
if [ -z $(skill -n X) ]; then
  auto_detect && return 0
  errorbox "Sorry, unable to autodetect X-Window. Try VESA."
  return 1
else
  case $(runlevel | cut -f 2) in 
    4|5) 
TEXT="\
Cannot autodetect because the GUI system is running.\n
Please change runlevel first.\n
  - go to the console (press Ctrl-Alt-F1)\n
  - login as root\n
  - call init 2\n
  - call $0 again\n"
DIMENSION="12 60"
;;
    *)
TEXT="\
Hmmm ... X-Window is running. Cannot autodetect.\n
Please kill or logoff from it first.\n"
DIMENSION="8 60"
  esac

  $DCMD --backtitle "$BACKTITLE" --title "ERROR" --msgbox "$TEXT" $DIMENSION 
  return 1
fi
}

##################################################
# Use OLD
function menuA2()
{
    if [ "$config_file" ] && [ -r $config_file ]; then
	get_config < $config_file
	source_file=${config_file}.backup
        return 0
    fi
    errorbox "Old configuration is not exist. Try AUTO or VESA."
    return 1
}

##################################################
# Use VESA
function menuA3()
{
    if [ "$basic_file" ] && [ -r $basic_file ]; then
	get_config < $basic_file
	source_file=${basic_file}
        return 0
    fi
    errorbox "The basic VESA configuration is not exist" "FATAL ERROR"
    return 1
}

##################################################
# Ask method
function menuA() {

while [ 1 ]; do
TITLE="X-WINDOW CONFIGURATION"
TEXT="\n
Welcome to X-Window configurator. It is supposed\n
to be an easy way to make X-Window works for you.\n
Finger crossed :)\n\n
First, select what config do you want to use."
DIMENSION="15 60 3"

$DCMD --backtitle "$BACKTITLE" --title "$TITLE" --menu "$TEXT" $DIMENSION \
"AUTO"   "Autodetect a new configuration" \
"CURRENT" "Update the current configuration" \
"BASIC"   "Use the basic (VESA) configuration" \
2> $freply

  status=$?
  [ $status != 0 ] && return $status
  
  reply=$(cat $freply)
  case $reply in
    AUTO)
      menuA1
      ;;
    CURRENT)
      menuA2
      ;;
    BASIC)
      menuA3
      ;;
  esac 
  [ $? = 0 ] && return 0
done;
}

########################################################
# Ask resolution
function build_menuB()
{
    LAST_RES=""
    while read LINE; do
	[ "$LAST_RES" = "$LINE" ] && continue
	LAST_RES=$LINE
	case $LINE in
	    "640x480")
		echo "'$LINE'" '"Low resolution" \' >> $fmenu
		;;
	    "800x600") 
		echo "'$LINE'" '"Modest resolution" \' >> $fmenu
		;;
	    "1024x768")
		echo "'$LINE'" '"Medium resolution" \' >> $fmenu
		;;
	    "1152x864") 
		echo "'$LINE'" '"Medium resolution" \' >> $fmenu
		;;
	    "1280x1024") 
		echo "'$LINE'" '"High resolution" \' >> $fmenu
		;;
	    "1600x1200")
		echo "'$LINE'" '"Very high resolution" \' >> $fmenu
		;;
	    "1800x1440") 
		echo "'$LINE'" '"I wish I have this one" \' >> $fmenu
		;;
	esac
    done
}

function menuB() {
MEMORY=`ddcprobe 2>/dev/null | grep '^Memory installed' | cut -f3 -d=`
MEMORY=${MEMORY:-unknown}
TIMING=`ddcprobe 2>/dev/null | grep '^Standard timing 0:' | cut -f2 -d:`
TIMING=${TIMING:-800x600}
TITLE="SET SCREEN RESOLUTION"
TEXT="\n
X-Window will be configured with these settings:\n
  Driver  = $XDEVICE_DRIVER\n
  Card    = $XDEVICE_BOARD\n
  Monitor = $XMONITOR_VENDOR $XMONITOR_MODEL\n
  Standard= `echo $TIMING`\n
Select the highest screen resolution you wish to use:"
DIMENSION="20 70 7"

echo '$WCMD --backtitle "$BACKTITLE" --title "$TITLE" \' > $fmenu
echo '--menu "$TEXT" $DIMENSION \' >> $fmenu

# Bah, this one causing errors.
# ddcxinfo -modelines 2>/dev/null | grep -e '^ModeLine' | cut -f 2 -d '"' > $freply
# build_menuB < $freply
# let's go manual
build_menuB << _EOF_
640x480
800x600
1024x768
1152x864
1280x1024
1600x1200
1800x1440
_EOF_
echo '2> $freply' >> $fmenu

. $fmenu
status=$?
[ $status != 0 ] && return $status

case `cat $freply` in
 '1800x1440')
 XSCREEN_MODES='"1800x1440" "1600x1200" "1280x1024" "1152x864" "1024x768" "800x600" "640x480"'
 ;;
 '1600x1200')
 XSCREEN_MODES='"1600x1200" "1280x1024" "1152x864" "1024x768" "800x600" "640x480"'
 ;;
 '1280x1024')
 XSCREEN_MODES='"1280x1024" "1152x864" "1024x768" "800x600" "640x480"'
 ;;
 '1152x864')
 XSCREEN_MODES='"1152x864" "1024x768" "800x600" "640x480"'
 ;;
 '1024x768')
 XSCREEN_MODES='"1024x768" "800x600" "640x480"'
 ;;
 '800x600')
 XSCREEN_MODES='"800x600" "640x480"'
 ;;
 *)
 XSCREEN_MODES='"640x480"'
 ;;
esac
dbug "XSCREEN_MODES=$XSCREEN_MODES"

return 0
}

########################################################
# Ask depth
function menuC() {
TITLE="SET COLOR DEPTH"
TEXT="\n
Select the color depth you want. High colors is good for your eye,
but might not be supported by your video card and generally slower.
Most users will be happy with 16 bit colors. If you have a good 
computer and video card, 24 bit true color is recommended."
DIMENSION="19 60 5"

$WCMD --backtitle "$BACKTITLE" --title "$TITLE" --menu "$TEXT" $DIMENSION \
"8" "8 bit 256 pseudo colors" \
"15" "15 bit (for some NVidia cards)" \
"16" "16 bit 65536 pseudo color" \
"24" "24 bit True color" \
"32" "32 bit True color" \
2> $freply

status=$?
[ $status != 0 ] && return $status

XSCREEN_DEPTH=$(cat $freply)
dbug "XDEPT=$XSCREEN_DEPTH"
return 0
}

###############################################################
# Save settings
menuD()
{
   set_config
   if pidof X &>/dev/null; then
      infobox "X-Window is running, config is not tested" "WARNING"
      sleep 2
      return 0
   fi
   clear
   echo "Hold on, testing the configuration ..."
   sleep 2
   if $xprog -probeonly 2> $freply; then
      infobox "X-Window has been configured" "DONE"
      sleep 2
      clean_exit 0
   fi
   echo > $fmenu
   cat $freply | grep -e '^(..)' >> $fmenu
   echo >> $fmenu
   echo "Press <EXIT> to retry again" >> $fmenu
   $WCMD --backtitle "$BACKTITLE" --title "X-WINDOW ERROR" \
   --ok-label "Retry" --textbox $fmenu 18 70 2> /dev/null
   return 255
}

###############################################################
# MAIN 

wizard menuA menuB menuC menuD

