#!/bin/sh
#  
# $Header: /usr/X/ConfigXF86,v 4.0.1 1994/03/28 05:31:22 Zwaska Exp $
# ConfigXF86 - An XFree86-2.x configurator
#
# This SHOULD work under either SH or BASH
#
# These programs run against $CONFIGDIR/DATAFILES/Cards.dat and Monitors.dat 
# files.
# 
# Functions:
# Banner	Let 'em see who we are...
# CleanUp	Delete temporary work files
# Getline	Select a specific line from a file
# Numln		Since we can't count on the existence of 'nl'
# Pager		Since we can't count on the existence of pg or less
# GenCardList	Read the database and generate a list of cards descriptions
# GenMonList	Read the database and generate a list of monitor descriptions
# GetMouseType	Prompt the user for their mouse type
# GetMouseTty	Prompt the user for their mouse tty port
# GetMouseBaud	Prompt the user for their mouse baud rate
# Check_Entry	Read and determine the correctness of a user selection
# ReadCard	Read a card record into Card_Rec structure based on key
# 		selection
# Breakup_Modes	Create dynamically named variables for each mode line
# ReadMon	Read a monitor record into Monitor_Rec structure based on key
# 		selection
# AssembleMon	Assemble the 'Modedb' section of the Xconfig file
# Edit_Modes	Allow the user to delete unwanted modes and re-order the ones 
# 		they keep
# Calc_Times	Determine the Horiz. sync rate and Vert. refrest rate
# AssembleCard	Assemble the Server and Card section of the Xconfig file
# Save_All	Save the new Xconfig file somewhere useful 
# Help_Handler	Display a help screen - arg is file name prefix from
#		./DATAFILES/help
# ViewFile	Display the current Xconfig file with $PAGER (Thank you Dave!)
#
# Fiddle Functions:
# Show_Options		Main Fiddling menu and status screen
# Split_File		Dissect current Xconfig.test file (in $TMP directory)
# MkTemplate		Extract top half of Xconfig.test file for a test 
#			platform, to which we can add individual 'Modes' 
#			entries anf ModeDB lines for testing and tuning 	
# Fix_ModeDB		Replace the original mode line with the one we 
#			just tuned
# Reset_Mode		Undo Changes to the mode lines
# Reassemble		Reassemble a test Xconfig file with just the mode 
#			line we're working with to test the timings
# Test_Mode		Run Xinit with the new test Xconfig file, display a 
#			test pattern for evaluation
# Save_Xconfig		Save the tuned Xconfig file to the users home 
#			directory as Xconfig
# Setup_Fiddle_File	Run X with the Xconfig.test file built by ConfigXF86 
#			Parse the output to get the actual timing lines X 
#			is using
# Add_Sync		Allows input of sync polarity
#
# Fiddle		Main Fiddling Program for tuning and testing the 
#			Xconfig file produced by this program

# Bail out if we're in X already!
if [ ! -z "$WINDOWID" ]
then
	clear
	echo "
	This program can not be run in the X environment...
	Please EXIT the X server and run this program in character mode.
"
	exit
fi

trap "CleanUp; exit 1" 1 2 3 15

# GLOBAL definitions
VERSION=2.1; export VERSION
TMP=/tmp; export TMP
PROCID=$TMP/$$; export PROCID

if [ -z "$XWINHOME" ]	# It may already be set
then
	XWINHOME=/usr/X386;export XWINHOME
fi

# Use this by default, else assume the current directory

if [ -d $XWINHOME/lib/X11/ConfigXF86 ]
then
	CONFIGDIR=$XWINHOME/lib/X11/ConfigXF86
else
	CONFIGDIR=`pwd`
fi
export CONFIGDIR

PATH=$CONFIGDIR:$PATH:$XWINHOME:$XWINHOME/bin; export PATH
DATADIR=$CONFIGDIR/DATAFILES; export DATADIR
XINITRC=$DATADIR/xinitrc.test; export XINITRC

if [ ! -d $DATADIR ]
then
	clear
	echo "
	Cannot locate the ConfigXF86 data directory.  Either install
	ConfigXF86 in $XWINHOME, or run ConfigXF86 from the directory
	where it is installed.
"
	exit
fi
	

# The following little ditty was contributed by Charlie Brady 
# <charlieb@tplrd.tpl.oz.au>
# so that solaris and other SVR4 w/o BSD support wouldn't barf on 'echo -n':
case `echo -n x` in
-n*)    minus_n=
        slosh_c='\c' ;;
*)      minus_n='-n'
        slosh_c=
esac
# Cute! no?

# End GLOBAL definitions


# ConfigXF86 Function Definitions

Banner() {

	clear
	echo "




		       XFree86[TM] version $VERSION

		       Configuration Utility by
		   Steven T Zwaska <stz@netcom.com>


			 Loading ...









"
	sleep 3
	if [ "X${LINES}" != "X" ]
	then
		ScrnLines=${LINES}
	else
		t=`stty -a | grep rows >/dev/null 2>&1 | \
			sed 's/^.*rows[\t ]*=[\t ]*\(.*\);.*$/\1/'`
		if [ "X${t}" != "X" ]
		then
			ScrnLines=${t}
		else
			ScrnLines=22
		fi
	fi
	if [ "X${PAGER}" = "X" ]
	then
		PAGER=more
	fi
}

CleanUp() {	# Get rid of temp files
rm -f $TMP/$$.* $TMP/CARDLIST $TMP/SCRNLIST $TMP/ScrnPart? $TMP/CardPart 
rm -f $TMP/CardRec $TMP/ScrnRec $TMP/Xconfig.probe $TMP/Xconfig.saved
rm -f xnt.log
}

Getline() {     # Usage Getline <line_num> <filename>
        L=0
        while read TXT
        do
                L=`expr $L + 1`
                if [ $L -eq $1 ]
                then
                        echo $TXT
                        break
                fi
        done<$2
}

Pager() {       # Since we can't count on the existence of pg or less
		# Usage Pager "Prompt_String" <File_Name> <Title>

	Entry=""
        kbd=`tty`
        Line_no=0
        Entry_no=0
        FSIZE=`wc $2|awk '{print $1}'`
        # echo "$FSIZE List Entries - Press Return"
        # read x
        clear
        while read Line_txt # This will crap out if a non-number is entered
        do
                echo "$Line_txt"
                Line_no=`expr $Line_no + 1`
                Entry_no=`expr $Entry_no + 1`
                if [ $Line_no -eq ${ScrnLines} -o $Entry_no -eq $FSIZE ]
                then
                        Line_no=0
                        echo $minus_n "$1 $slosh_c"
                        read Entry<$kbd         # The entered number is a key
                                                # into the monitor index
                        if [ ! -z "$Entry" ]
                        then
				case ${Entry} in
					[qQ]*) return 255 ;;
					*) ;;
				esac
                                if [ $Entry -le $FSIZE -a $Entry -gt 0 ]
                                then
                                        return $Entry
                                fi
                        else
                                Entry=0
                        fi
                        clear
                fi
        done<$2
        return $Entry
}

NumLn() {
nn=0
while read inline
do
	nn=`expr $nn + 1`
	echo "$nn	$inline"
done<$1
}


GenCardList() { 	# Generate a list of graphics cards from the database
			# We'll grap the CardID and CardName
	cat $DATADIR/Cards.dat|awk -F"|" '{print $1"	"$2}'>$TMP/CARDLIST
}

GenMonList() {		# Generate a list of monitors from the database
			# We'll grap the ScrnID and ScrnName
	cat $DATADIR/Monitors.dat|awk -F"|" '{print $1"	"$2}'>$TMP/SCRNLIST

}

GetMouseTty() { 
	while [ 1 ]
	do
		echo $minus_n "What port does your mouse use? (ie /dev/tty01, /dev/mouse etc.): $slosh_c"
		read MS_Tty
		if [ -z "$MS_Tty" ]
		then
			continue
		fi
		if [ ! -c "$MS_Tty" ] # Yeah?... Let's just see!
		then
			echo "$MS_Tty is not a character special device, Please try again. "
			continue
		else
			MS_Tty=`echo $MS_Tty|sed "s/\//\\\//g"`
			break
		fi
	done
}

GetMouseType() { 	# Setup the mouse section of the Xconfig file
	
	XQUEUE=" "
	KEYBOARD="Keyboard"
	MouseType=" "
	MS_Baud=" "
	MS_Tty=" "
	
	while [ 1 ]
	do
		clear
		echo $minus_n "

	The first step in the configuration is to configure your mouse
	driver, input port, and/or port speed...

			Select your mouse type:
		
			1)	xqueue		(Use this for SVR4 or SVR4.2)
	        	2)	busmouse	(Use this for ANY bus mouse)
	        	3)	logitech	(Logitech serial mouse only)
	        	4)	microsoft	(Serial mouse only)
	        	5)	mmseries
	        	6)	mouseman	(Serial mouse only)
	        	7)	mousesystems	(Serial mouse only)
	        	8)	ps/2
                        9)      mmhittab	(Hitachi in MM mode)
			
			> $slosh_c"
		read MouseType
		echo $minus_n "Do you need Three button emulation for a two button mouse (y/n): [n] $slosh_c"
		read E3B
		case "$E3B" in
			"y")	E3B="Emulate3Buttons";;
			*)	E3B="";;
		esac
		if [ -z "$MouseType" ]
		then
			continue
		fi
		case $MouseType in
			1) MouseType=" ";
			   XQUEUE=Xqueue;KEYBOARD="# Keyboard";break;;
			2) GetMouseTty;MouseType=busmouse" \"$MS_Tty\"";break;;
			3) GetMouseTty;MouseType=logitech" \"$MS_Tty\"";;
			4) GetMouseTty;MouseType=microsoft" \"$MS_Tty\"";;
			5) GetMouseTty;MouseType=mmseries" \"$MS_Tty\"";;
			6) GetMouseTty;MouseType=mouseman" \"$MS_Tty\"";;
			7) GetMouseTty;MouseType=mousesystems" \"$MS_Tty\"";;
			8) GetMouseTty;MouseType=ps/2" \"$MS_Tty\"";break;;
                        9) GetMouseTty;MouseType=mmhittab" \"$MS_Tty\"";;
			*) continue;;
		esac
		while [ 1 ]
		do
			echo $minus_n "Enter Mouse baud rate (Valid rates: 1200, 2400, 4800 or 9600) or [h]elp [1200]: $slosh_c"
			read MS_Baud
			if [ -z "$MS_Baud" ]
			then
				MS_Baud="BaudRate 1200"
				break
			fi
			if [ "$MS_Baud" = "h" ]
			then
				Help_Handler mouse
				echo "Your selected mouse type is $MouseType $E3B"
				continue
			fi
			case $MS_Baud in
				1200)	MS_Baud="BaudRate 1200";;
				2400)	MS_Baud="BaudRate 2400";;
				4800)	MS_Baud="BaudRate 4800";;
				9600)	MS_Baud="BaudRate 9600";;
				*)	echo "Invalid Baud Rate (choose 1200, 2400, 4800 or 9600)";continue;;
			esac
			break
		done
		break
	done
}

Check_Entry() {
	x=`expr $1 + 1 2>/dev/null`	# Let's see if the value is numeric...
	return $?
}

ReadCard() {
	while [ 1 ]
	do
		Pager "Select the Card that most closely resembles yours (Press [Enter] for more): " $TMP/CARDLIST
		CardSelection=$?
		if [ "X${CardSelection}" = "X255" ]
		then
			WantOut=1
			break
		fi
		if [ -z "$CardSelection" -o "$CardSelection" = "0" ]
		then
			echo "Nothing entered! Please try again"
			sleep 2
			continue
		else
			Check_Entry "$CardSelection"
			IsNumeric=$?
			if [ $IsNumeric -ne 0 ]
			then
				echo "You did not enter a number! Please try again"
				sleep 2
				continue
			fi
		fi
		break
	done

	clear
	# CardSelection Should be a number matching on of the CardID's
	CardRec=`grep "^$CardSelection|" $DATADIR/Cards.dat`

	# We need to echo the record to a temp file
	echo $CardRec>$TMP/CardRec

	# Read in the record fields from the temp file
	oIFS=$IFS
	IFS="|"
	read CardID CardName CardDesc CContributor CLastEdit ChipSet ClockChip ClockProg RamDac CClockRates Vmode64 Vmode86 Vmode107i Vmode107 Vmode121i Vmode121 Options VideoRam BiosBase ViewPort Virtual SpeedUp Driver Server <$TMP/CardRec
	IFS=$oIFS

}

Breakup_Modes() {               # Build a Env Var for each mode line
	n=0     # Init the counter
	oIFS=$IFS
	IFS="|"
	rm -f $TMP/$$.Modes
	for NewLine in $ModeLineS       # Since IFS="|" - for each mode line...
	do
        	n=`expr $n + 1`         # Bump the counter
        	EvarName="Mode$n"               # Make a variable name
        	eval "$EvarName='$NewLine'"     # assign the mode line to the
        	ClockRate=`echo $NewLine|cut -f2 -d" "`
        	ClockRates=$ClockRates$ClockRate" "
		echo $NewLine|sed 's/:/ /'>>$TMP/$$.Modes
	done
	IFS=$oIFS
}



ReadMon() {
	while [ 1 ]
	do
		Pager "Select the Monitor that most closely resembles yours (Press [Enter] for more): " $TMP/SCRNLIST
		ScrnSelection=$?
		if [ "X${ScrnSelection}" = "X255" ]
		then
			WantOut=1
			break
		fi
		if [ -z "$ScrnSelection" -o "$ScrnSelection" = "0" ]
		then
			echo "Nothing entered! Please try again"
			sleep 2
			continue
		else
			Check_Entry "$ScrnSelection"
			IsNumeric=$?
			if [ $IsNumeric  -ne 0 ]
			then
				echo "You did not enter a number! Please try again"
				sleep 2
				continue
			fi
		fi
		break
	done

	if [ "X${WantOut}" = "X1" ]
	then
		return
	fi

	clear
	echo "Please wait while I extract the available modes for this monitor..."
	# ScrnSelection Should be a number matching on of the ScrnID's
	ScrnRec=`grep "^$ScrnSelection|" $DATADIR/Monitors.dat`

	# We need to echo the record to a temp file
	echo $ScrnRec>$TMP/ScrnRec

	# Read in the record fields from the temp file
        cut -f7- -d"|" $TMP/ScrnRec>$TMP/$$.jk2
        cut -f1-6 -d"|" $TMP/ScrnRec>$TMP/$$.jk1
        ModeLineS=`cat $TMP/$$.jk2`
	oIFS=$IFS
	IFS="|"
        read ScrnID ScrnName ScrnDesc MContributor MLastEdit MClockRates <$TMP/$$.jk1
	IFS=$oIFS
        SaveClockRates=$MClockRates
        NumModes=`cat $TMP/$$.jk2|awk -F"|" '{print NF}'`
        NumModes=`expr $NumModes - 1`
	# Parse the mode lines into separate dynamically named variables
        Breakup_Modes
        MClockRates=$SaveClockRates
        LastEdit=`date '+%m/%d/%y'`
	rm $TMP/$$.jk?
}

AssembleMon() {	# Assemble the monitor section of the config file
	rm -f $TMP/ScrnPart1 $TMP/ScrnPart2
	echo "
#-------------------------------------------------------------
# Monitor Definition
# Monitor ID            $ScrnID
# Monitor Name:         $ScrnName">$TMP/ScrnPart1
	if [ ! -z "$ScrnDesc" -a "$ScrnDesc" != '0' ]
	then
	echo "#                       $ScrnDesc">>$TMP/ScrnPart1
	fi
	echo "# Contributed By:       $MContributor
# Last Change:          $MLastEdit
ModeDB">>$TMP/ScrnPart1
	n=0
       	cat $TMP/$$.Modes|\
		sed -e 's/:/ /g' -e 's/^/"/' -e 's/ /" /'>>$TMP/ScrnPart2
}

Edit_Modes() {

cp $TMP/$$.msel $TMP/$$.bak1
cp $TMP/$$.MLs $TMP/$$.bak2
cp $TMP/$$.work $TMP/$$.bak3
str1="Here are the modes I was able discern from your hardware:
"
while [ 1 ]
do
	clear
	echo $str1
	str1="Here are the modes you've selected:
"
	NumLn $TMP/$$.msel

	echo $minus_n "
Order them as you would like them (Leave out the mode numbers you
don't want) put the default mode number first. 

Separate the mode numbers with SPACES. 

Pressing [Enter] without entering any numbers will save the list as is. 

Entering only a 'u' will re-set the list to the original order and 
allow you to start over: $slosh_c"
	read j
	if [ -z "$j" ]
	then
		return
	fi
	if [ "$j" = "u" ]
	then
		rm -f $TMP/$$.tmp2 $TMP/$$.tmp3 $TMP/$$.tmp4
		cp $TMP/$$.bak1 $TMP/$$.msel
		cp $TMP/$$.bak2 $TMP/$$.MLs
		cp $TMP/$$.bak3 $TMP/$$.work
		str1="Here are the modes I was able discern from your hardware:
"
		continue
	fi

	for i in $j
	do
		Getline $i $TMP/$$.msel>>$TMP/$$.tmp2
		Getline $i $TMP/$$.MLs>>$TMP/$$.tmp3
		Getline $i $TMP/$$.work>>$TMP/$$.tmp4
	done
	mv $TMP/$$.tmp2 $TMP/$$.msel
	mv $TMP/$$.tmp3 $TMP/$$.MLs
	mv $TMP/$$.tmp4 $TMP/$$.work
done
}


Calc_Times() {
n=0
awk '{print $1" "$2" "$3" "$4" "$5" "$6" "$7" "$8" "$9" "$10" "$11}' $TMP/$$.work >$TMP/$$.junk
while read RES CK HR HS HE HL VR VS VE VL Ilace
do
#echo "Figuring for $RES $CK $HR $HS $HE $HL $VR $VS $VE $VL"
Clock=$CK
# CK1=`expr \( $CK \* 1000 \) + 500`
# Change per Harald Koenig
case $CK in
	*.*) CK1=`echo ${CK}000 | sed 's/\.\(...\).*/\1/'`  ;;
	*) CK1=`expr \( $CK \* 1000 \) ` ;;
esac
CK1=`expr $CK1 + \( $HL / 2 \)`
# End Change
Hs=`expr $CK1 / $HL`
# Hs1=`expr \( $Hs \* 1000 \) + 500`
Hs1=`expr \( $Hs \* 1000 \) + \( $VL / 2 \)` # Change per Harald Koenig
Vr=`expr $Hs1 / $VL`
echo $Ilace|grep "[iI]nterlace" >/dev/null 2>&1
if [ $? -eq 0 ]
then
	#
	# For an interlaced mode, the refresh rate is actually twice what
	# we've just calculated.
	#
	Vr=`expr $Vr \* 2`
fi
echo "$RES - Clock=${CK}MHz, Horiz. sync=${Hs}kHz, Vert. refresh=${Vr}Hz">>$TMP/$$.msel
done <$TMP/$$.junk
}

AssembleCard() { # After Monitor section has been built...
#
# Output the heading.
#
	if [ ! -z "$Driver" -a "$Driver" != "0" ]
	then
        	echo "$Driver">$TMP/CardPart
	fi
	echo "

#-------------------------------------------------------------
# Video Card Definition
# Video Card ID $CardID
# Video Card Name:      $CardName
#                       $CardDesc
# Contributed By:       $CContributor
# Last Change:          $CLastEdit
">>$TMP/CardPart
	if [ ! -z "$ChipSet" -a "$ChipSet" != "0" ]
	then
        	echo "# Chipset $ChipSet">>$TMP/CardPart
	fi

#
# Handle the virtual resolution
#
	echo ""
	if [ ! -z "$Virtual" -a "$Virtual" != "0" ]
	then
		virtual=$Virtual
	else
		virtual="unset"
	fi
        echo $minus_n "
XFree86 supports a virtual desktop - a default root window that may
be larger than the physical displayed resolution on your screen
(refer to the manual page for more information.  The default Virtual 
desktop size is:

	$virtual

Leaving the virtual size unset will cause the server to calculate the
correct size based on the specified display modes.  You can press 
[Enter] to accept this default, or enter new horizontal and vertical 
numbers to change the defaults, or type in \"unset\" to let the server
calculate it: $slosh_c"
	while [ 1 ]
	do
        	read virtual
        	if [ -z "$virtual" ]
        	then
			break
        	fi
		case $virtual in
		[0-9][0-9]*\ [0-9][0-9]*)
                	Virtual=$virtual
			break
			;;
		unset)
			Virtual=$virtual
			break
			;;
		0)
			Virtual=$virtual
			break
			;;
		*)
			echo $minus_n "
You have entered the numbers in an incorrect format.  Please enter
horizontal and vertical numbers, separated by a space: $slosh_c"
			;;
		esac
	done
        if [ ! -z "$Virtual" -a "$Virtual" != "0" -a "$Virtual" != "unset" ]
        then
                echo Virtual $Virtual>>$TMP/CardPart
        fi

#
# Handle the viewport
#
	clear
	if [ ! -z "$ViewPort" -a "$ViewPort" != "0" ]
	then
		viewport=$ViewPort
	else
		viewport="0 0"
	fi
	echo $minus_n "
The Viewport defines the initial upper left corner of the displayed
portion of the virtual root window, if it is larger than the physical
screen resolution.  The default ViewPort is:

	$viewport
	
You can press [Enter] to accept this, or enter new X and Y coordinates 
here: $slosh_c"
	while [ 1 ]
	do
		read viewport
        	if [ -z "$viewport" ]
        	then
			break
        	fi
		case $viewport in
		[0-9][0-9]*\ [0-9][0-9]*)
                	ViewPort=$viewport
			break
			;;
		*)
			echo $minus_n "
You have entered the numbers in an incorrect format.  Please enter
X and Y coordinate numbers, separated by a space: $slosh_c"
			;;
		esac
	done
	if [ ! -z "$ViewPort" -a "$ViewPort" != "0" ]
	then
        	echo ViewPort $ViewPort>>$TMP/CardPart
	fi
#
# Don't put Video RAM into the Xconfig.  The database entry can match
# cards with different amounts of memory, and the server had damn well
# better be able to determine the amount of memory installed.
#
#	if [ ! -z "$VideoRam" -a "$VideoRam" != "0" ]
#	then
#        	echo VideoRam $VideoRam>>$TMP/CardPart
#	fi

	if [ ! -z "$SpeedUp" -a "$SpeedUp" != "0" ]
	then
        	echo SpeedUp $SpeedUp>>$TMP/CardPart
	fi

#
# Handle option flags
#
	clear
	if [ ! -z "$Options" -a "$Options" != "0" ]
	then
        	Options=`echo $Options|tr ':' ' '`
		options=$Options
	else
		options="none"
	fi
	echo $minus_n "
The video driver for your chipset/board may support option flags,
as defined in the appropriate server manual page.  It is advised that
you NOT change the defaults unless you know what you are doing.  The 
default list of options for your chipset/card is:

	$options

You can accept this default list by pressing [Enter], or you can create
your own list options by entering them here in the format: 
	option1 option2 ... (no quotes or commas!)

	Options? > $slosh_c"
	read options
        if [ ! -z "$options" ]
        then
		Options=$options
	fi
	if [ ! -z "$Options" -a "$Options" != "0" -a "$Options" != "none" ]
	then
        	for i in $Options
        	do
                	echo "Option \"$i\"">>$TMP/CardPart
        	done
	fi
	clear
        echo $minus_n "
	Will you be accessing a font server in addition to the 
	default font paths? (Answer [n]o if your not sure) (y/n) [n] > $slosh_c"
	read x
	case $x in 
		y) FServe=1;;
		*) FServe=0;;
	esac
	if [ $FServe -eq 1 ]
	then
		echo $minus_n "
	Enter the location of the font server in the form:
		<hostname>:<tcp_port_number> (ie: zok:7000)
			> $slosh_c"
		read FServe
		if [ ! -z $FServe ]
		then
			echo $minus_n " 
	Do you want the server to be checked [b]efore or [a]fter the 
	default font path (b/a) > $slosh_c"
			read x
			case $x in
			a)	AFONTSERVER="FontPath        \"tcp/$FServe\"";;
			b)	BFONTSERVER="FontPath        \"tcp/$FServe\"";;
			esac
		export AFONTSERVER BFONTSERVER
		fi
	fi

#
# Handle clocks
#
	echo ""
	echo $minus_n "Please wait while I do some calculation...$slosh_c"
	# Handler for programmable clock chips
	if [ ! -z "$ClockChip" -a "$ClockChip" != "0" ]
	then
		echo "Clocks \"$ClockChip\"">>$TMP/CardPart
		cut -f1 -d" " $TMP/ScrnPart2|sort|uniq>$TMP/$$.tmp
		cp $TMP/ScrnPart2 $TMP/$$.work
	else	# Handle Clocks in normal way
		echo Clocks $CClockRates>>$TMP/CardPart
		rm -f $TMP/$$.cr
		# See if there is a corresponding modedb
		# entry for each card dot clock and if 
		# so, echo its resolution field to 
		# a temp table
		for i in `echo $CClockRates`	
		do				
			i=`echo $i|sed 's/\.[0-9]*//'`
			# The server will match clocks +/- 1MHz
			for j in `expr $i - 1` $i `expr $i + 1`
			do
				grep " $j " $TMP/ScrnPart2 >/dev/null
				if [ $? -eq 0 ]
				then
					grep " $j " $TMP/ScrnPart2>>$TMP/$$.work
					grep " $j " $TMP/ScrnPart2|\
						cut -f1 -d" ">>$TMP/$$.MLs
				fi
			done
				
		done
	fi

#
# Now get the modes
#
	# Sort the temp table and get rid of duplicates
	sort $TMP/$$.work|uniq>$TMP/$$.tmp 	
	mv $TMP/$$.tmp $TMP/$$.work
	cut -f1 -d" " $TMP/$$.work>$TMP/$$.MLs
	Calc_Times
	echo "done!"
	Edit_Modes
	for i in `cat $TMP/$$.MLs`	# Build the 'Modes' line
	do
		ModeLine="$ModeLine "`echo $minus_n "$i$slosh_c"`
	done
	# Add the 'Modes' line to the Card part of the Xconfig file
	echo "Modes "$ModeLine >>$TMP/CardPart 
	# rm $TMP/$$.MLs $TMP/ScrnPart2		# Clean up temp files
}

ViewFile() {
	clear
	Pager "Press [Enter] to continue or [q] to quit: " $TMP/Xconfig.test
}

Save_All() {	# Save the new Xconfig file somewhere
	clear
	echo ' Enabling New Server...'
	# Backup the old X server
	mv $XWINHOME/bin/X $XWINHOME/bin/X.$$ 2>/dev/null	
	cp $XWINHOME/bin/$Server $XWINHOME/bin/X 2>/dev/null
	if [ $? -ne 0 ]
	then
		echo "
Copy Failed! - you might not have permission to overwrite the X server
If not, you will need to do this after your finished with this program.

The command you'll need to run is

	cp $XWINHOME/bin/$Server $XWINHOME/bin/X
"
		echo $minus_n "
Press [Enter] to continue $slosh_c"
		read x
	fi
	while [ 1 ]
	do
        	clear
        	echo $minus_n "
        Where would you like to save the NEW Xconfig file:

        1)      (Personal Xconfig)      \$HOME/Xconfig

        2)      (System Xconfig)        /etc/Xconfig

        3)      (Host Xconfig)          $XWINHOME/lib/X11/Xconfig.`uname -n`

        4)      (DEFAULT)               $XWINHOME/lib/X11/Xconfig

	5)	Leave it where it is ($TMP/Xconfig.test)
        -------------------------------------------------
                Enter Your Selection: $slosh_c"

        	read dest
        	if [ -z "$dest" ]
        	then
                	dest=$XWINHOME/lib/X11/Xconfig
        	fi
        	case $dest in
                	1)      echo $minus_n "Enter your HOME directory: $slosh_c"
                        	read USER
                        	if [ -d "${USER}" ]
                        	then
                                	dest=$USER/Xconfig;
                        	else
                                	echo "No such directory: ~${USER}"
                                	sleep 2
                                	continue
                        	fi
                        	;;
                	2)      dest=/etc/Xconfig;;
                	3)      dest=$XWINHOME/lib/X11/Xconfig.`uname -n`;;
                	4)      dest=$XWINHOME/lib/X11/Xconfig;;
			5)	echo "File will be left in $TMP..."; break;;
                	*)      continue;;
        	esac
		if [ -f $dest ] 	# Save the old one it it exists
		then
			mv $dest $dest.$$
			echo "Saved $dest to $dest.$$..."
		fi
		cp  $TMP/Xconfig.test $dest
		if [ $? -ne 0 ]
		then
			echo "Save Failed! - you might not have permission to write to $dest"
			sleep 2
			echo "Please try again..."
			sleep 2
		else
			break
		fi
	done
}

Help_Handler() { 	# Pass this function a filename corresponding to the 
			# help screen in ./DATAFILES/help

	if [ -r ${DATADIR}/help/$1.hlp ]
	then
		clear	# The calling function is responsible for returning 
			# the screen back to normal

		cat ${DATADIR}/help/$1.hlp
		echo ""
		if [ "$#" != "2" ]
		then
			echo $minus_n "Press [Enter] to continue $slosh_c"
		else
			echo $minus_n "$2 $slosh_c"
		fi
	else
		echo ""
		echo $minus_n "No help on $1 available; press [Enter]: $slosh_c"
	fi
	read x
}

# End ConfigXF Function Definitions
#
#
# Fiddle Function Definitions
#

Show_Options() {
# Main Fiddling Menu
	clear

	echo $minus_n " Mode Info: $calcstr
       HORIZONTAL VALUES    		 |        VERTICAL VALUES
      Resolution Sync    Sync    Frame   |  Resolution Sync    Sync    Frame
                 Start   End     Length  |             Start   End     Length
-----------------------------------------+------------------------------------
       $HR       $HS      $HE    $HL         $VR        $VS    $VE      $VL
Porch Vals   $HBP         $HSP      $HFP                    $VBP      $VSP      $VFP
Image Tuning ----- Action ------ Units --+-------- Action ------------ Units -
    L)  Move Image Left        (by n*4)  | U)  Move Image Up          (by n*1)
    R)  Move Image Right       (by n*4)  | D)  Move Image Down        (by n*1)
    W)  Widen Image            (by n*8)  | H)  Highten Image          (by n*2)
    N)  Narrower Image         (by n*8)  | S)  Shorten Image          (by n*2)
Scan Line Tuning - Action ------ Units --+-------- Action ------------ Units -
    1)  increment Sync Start   (by n*4)  | a)  increment Sync Start   (by n*1)
    2)  decrement Sync Start   (by n*4)  | b)  decrement Sync Start   (by n*1)
    3)  increment Sync End     (by n*4)  | c)  increment Sync End     (by n*1)
    4)  decrement Sync End     (by n*4)  | d)  decrement Sync End     (by n*1)
    5)  increment Frame Length (by n*8)  | e)  increment Frame Length (by n*1)
    6)  decrement Frame Length (by n*8)  | f)  decrement Frame Length (by n*1)

 [n]ew mode  [h]elp  [q]uit  [t]est  [s]ave changes  [r]eset to orig.values
 To add hsync or vsync polorization enter [P] 
                      What next? > $slosh_c"
}

Split_File() {	# Dissect current Xconfig file
	echo "Parsing Xconfig File..."
	echo ""
	Start=`grep -n "^ModeDB" $1|cut -f1 -d":"`
	# Grab the top half of the Xconfig file
	awk "NR == 1,NR == $Start {print}" $1>$PROCID.tmp
	XX=`wc $1|awk '{print$1}'`
	# Grab the bottom half of the Xconfig file
	Start=`expr $Start + 1`
	awk "NR == $Start,NR == $XX {print}" $1>$PROCID.scrn
}

MkTemplate() {
# Copy the Xconfig file and strip off the Modes, ModeDB and monitor mode lines
	XCFGDIR=$TMP; export XCFGDIR
	#echo backing up $XCFGDIR/Xconfig.test
	cp $XCFGDIR/Xconfig.test $XCFGDIR/Xconfig.saved
	Split_File $XCFGDIR/Xconfig.saved 	# Produces $PROCID.tmp
	sed '/^ *Modes/d' $PROCID.tmp | sed '/^ *ModeDB/d'>$PROCID.tplt
	rm $PROCID.tmp
}

Fix_ModeDB() {
	MODE_LINE="$MD $CK $HR $HS $HE $HL $VR $VS $VE $VL $IL"
	sed "s/$MD *$CK .*/$MODE_LINE/" $PROCID.tmdb>$PROCID.tmp
	mv $PROCID.tmp $PROCID.tmdb
}

Reset_Mode() {
	echo $RL>$PROCID.tmp
	read MD CK HR HS HE HL VR VS VE VL IL<$PROCID.tmp
	rm $PROCID.tmp
}
	
Reassemble() {
	#echo "Re-building $PROCID.xcfg"
	cp $PROCID.tplt $PROCID.xcfg
	MODE_LINE="$MD $CK $HR $HS $HE $HL $VR $VS $VE $VL $IL"
	echo  "Modes $MD">>$PROCID.xcfg
	echo  "ModeDB" >>$PROCID.xcfg
	echo $MODE_LINE|sed 's/:/ /'>>$PROCID.xcfg
}

Test_Mode() {
	Reassemble
	XINITRC=$DATADIR/xinitrc.test; export XINITRC
	XCONFIG=$PROCID.xcfg; export XCONFIG
	LD_LIBRARY_PATH=$XWINHOME/lib; export LD_LIBRARY_PATH
	# test the new Xconfig file
	clear
	xinit -- $XWINHOME/bin/$Server -xconfig $XCONFIG >$PROCID.xlog 2>&1
}

Save_Xconfig() {
	Fix_ModeDB
	#echo "Re-building $PROCID.xcfg"
	cp $PROCID.tplt $PROCID.xcfg
	for i in `cut -f1 -d" " $PROCID.tmdb`
	do
		mdentries="$mdentries "$i
	done
	echo  "Modes $mdentries">>$PROCID.xcfg
	echo  "ModeDB" >>$PROCID.xcfg
	cat $PROCID.tmdb|sed 's/:/ /'>>$PROCID.xcfg
	#echo 'Saving new Xconfig file '
	cp $PROCID.xcfg $TMP/Xconfig.test
}


Setup_Fiddle_File() {

	echo ""
	echo $minus_n "
I am about to start the X server to set up the timing lines for you to 
fiddle with.  This will cause your screen to flicker a bit.  It should 
return you to a character screen within a few seconds (<15).  If X 
hangs your system (i.e. does not come back to a character screen 
within 20 seconds), simply re-boot it and re-run this program. It will 
automatically take up at the place it left off (assuming your boot 
scripts don't clear /tmp).

        Press [Enter] to continue [Delete] to abort: $slosh_c"

	read x

	# Use our test xinif file (starts and quits - thats all!)
	XINITRC=$DATADIR/xinitrc.probe;export XINITRC
	
	# Use the xconfig file we just built
	XCONFIG=$XCFGDIR/Xconfig.saved;export XCONFIG

	clear
	$Server  -probeonly >xnt.log 2>&1 # Grab stdout and stderr so we can parse it later
}

Add_Sync() {
	echo "Enter Sync polarization as: [+-]hsync [+-]vsync (ie +hsync -vsync):"
	read Sync_Pol
	if [ ! -z "$Sync_Pol" ]
	then 
		IL="$IL $Sync_Pol"
	fi
}

Fiddle_Help() {
	Help_Handler Fiddle1
}

Fiddle() {
	if [ ! -f $TMP/Xconfig.test ]
	then 
		echo "This program must be run against an Xconfig.test file in $TMP!"
		exit
	fi
	
	MkTemplate
	Setup_Fiddle_File
	cat $PROCID.scrn |sed '/^ *#/d'>$PROCID.scfl
	grep "Mode  *\"[0-9]*" xnt.log |awk '{ printf("%s %s\n",$4, $8) }'|\
		sed -e 's/://' -e 's/\.[0-9]*//' -e 's/,//'>$PROCID.tmp
	while read xxx
	do
		resln=`echo $xxx|cut -f1 -d' '`
		modeclk=`echo $xxx|cut -f2 -d' '`
		hres=`echo $xxx|cut -f1 -d'x'|sed 's/"//'`
		echo "$modeclk $hres $resln">>$PROCID.tgs
	done<$PROCID.tmp
	rm $PROCID.tmp
	MODE_NO=0
	while read TN
	do
		MODE_NO=`expr $MODE_NO + 1`
		grep_target1=`echo $TN|cut -f1 -d' '`
		grep_target2=`echo $TN|cut -f2 -d' '`
		resln=`echo $TN|cut -f3 -d' '`
	
		MODE_LN=`grep " ${grep_target1}  *${grep_target2} " \
			$PROCID.scfl|\
			sed 's/\"[0-9]*x[0-9]*i*\"//'`
		MODE_LN="$resln $MODE_LN"
		echo $MODE_LN>>$PROCID.tmdb
		echo "		$MODE_NO $resln">>$PROCID.tmnu
	done<$PROCID.tgs
	OMODE_LN=$MODE_LN
	
	# Whew! Now we have a predictable modedb table
	# lets figure out how the user wants to edit it
	while [ 1 ]
	do
		clear
		echo ""
		echo ""
		echo ""
		echo "	These are your available modes:"
		echo ""
		cat $PROCID.tmnu
		echo $minus_n "
	Enter the number of the resolution mode to fiddle with: $slosh_c"
		read l
		if [ -z "$l" ]
		then
			continue
		fi
		resln=`grep "		$l" $PROCID.tmnu|awk '{print $2}'`
		#echo editting $resln
		RL=`grep $resln $PROCID.tmdb`
		echo $RL>$PROCID.tmp
		read MD CK HR HS HE HL VR VS VE VL IL<$PROCID.tmp
		rm $PROCID.tmp
		export MD CK HR HS HE HL VR VS VE VL IL
		while [ 1 ]
		do
			sleep 1
			HBP=`expr $HS - $HR`
			HFP=`expr $HL - $HE`
			HSP=`expr $HE - $HS`
			VBP=`expr $VS - $VR`
			VFP=`expr $VL - $VE`
			VSP=`expr $VE - $VS`
			# Change per Harald Koenig
			# CK1=`expr \( $CK \* 1000 \) + 500`
                        case $CK in
                        	*.*) CK1=`echo ${CK}000 | sed 's/\.\(...\).*/\1/'`  ;;
                        	*) CK1=`expr \( $CK \* 1000 \) ` ;;
                        esac
                        CK1=`expr $CK1 + \( $HL / 2 \)`
			# End Change
			Hs=`expr $CK1 / $HL`
			# Hs1=`expr \( $Hs \* 1000 \) + 500`
			# Change per Harald Koenig
                        Hs1=`expr \( $Hs \* 1000 \) + \( $VL / 2 \)`

			Vr=`expr $Hs1 / $VL`
			echo $IL|grep "[iI]nterlace" >/dev/null 2>&1
			if [ $? -eq 0 ] # One of the post line options is Interlace
			then
				#
				# For an interlaced mode, the refresh rate 
				# is actually twice what we've just calculated.
				#
				Vr=`expr $Vr \* 2`
			fi
			calcstr="$MD - Clock=${CK}MHz, H sync=${Hs}kHz, V refresh=${Vr}Hz "`echo $IL|sed 's/:/ /'`
			Show_Options
			read option
			case $option in
				P*)	Add_Sync;;
		   [1-6a-fLRWNUDHS]*)	echo $minus_n "By How many units? $slosh_c";
					read units;;
				h*)	Fiddle_Help;;
				n*)	Fix_ModeDB; break;;
				q*)	echo QUITTING without saving!;sleep 3;;
				r*)	Reset_Mode;;
				t*)	echo Testing...
					Test_Mode;;
				s*)	echo Saving... 
					Save_Xconfig
					rm $PROCID.*
					return;;
				*)	continue;;
			esac
			case $option in
				1*) 	x=`expr $units \* 4`
					HS=`expr $HS + $x`;;
				2*) 	x=`expr $units \* 4`
					HS=`expr $HS - $x`;;
				a*) 	x=`expr $units \* 1`
					VS=`expr $VS + $x`;;
				b*) 	x=`expr $units \* 1`
					VS=`expr $VS - $x`;;
				3*) 	x=`expr $units \* 4`
					HE=`expr $HE + $x`;;
				4*) 	x=`expr $units \* 4`
					HE=`expr $HE - $x`;;
				c*) 	x=`expr $units \* 1`
					VE=`expr $VE + $x`;;
				d*) 	x=`expr $units \* 1`
					VE=`expr $VE - $x`;;
				5*) 	x=`expr $units \* 8`
					HL=`expr $HL + $x`;;
				6*) 	x=`expr $units \* 8`
					HL=`expr $HL - $x`;;
				e*) 	x=`expr $units \* 1`
					VL=`expr $VL + $x`;;
				f*) 	x=`expr $units \* 1`
					VL=`expr $VL - $x`;;
				L*)	x=`expr $units \* 4`
					if [ $HE -lt `expr $HL - $x` ]; then
	                                	HS=`expr $HS + $x`
	                                	HE=`expr $HE + $x`
					fi;;
				R*)	x=`expr $units \* 4`
					if [ $HS -gt `expr $HR + $x` ]; then
	                                	HS=`expr $HS - $x`
	                                	HE=`expr $HE - $x`
					fi;;
				W*)	x=`expr $units \* 4`
	                               	HS=`expr $HS + $x`
	                               	HE=`expr $HE + $x`
					x=`expr $units \* 8`
					HL=`expr $HL + $x`;;
				N*)	x=`expr $units \* 4`
					if [ $HS -gt `expr $HR + $x` ]; then
	                                	HS=`expr $HS - $x`
	                                	HE=`expr $HE - $x`
	                                	x=`expr $units \* 8`
	                                	HL=`expr $HL - $x`
					fi;;
				U*)	x=`expr $units \* 1`
					if [ $VE -lt `expr $VL - $x` ]; then
	                                	VS=`expr $VS + $x`
	                                	VE=`expr $VE + $x`
					fi;;
				D*)	x=`expr $units \* 1`
					if [ $VS -gt `expr $VR + $x` ]; then
	                                	VS=`expr $VS - $x`
	                                	VE=`expr $VE - $x`
					fi;;
				H*)	x=`expr $units \* 1`
	                               	VS=`expr $VS + $x`
	                               	VE=`expr $VE + $x`
					x=`expr $units \* 2`
					VL=`expr $VL + $x`;;
				S*)	x=`expr $units \* 1`
					if [ $VS -gt `expr $VR + $x` ]; then
	                                	VS=`expr $VS - $x`
	                                	VE=`expr $VE - $x`
	                                	x=`expr $units \* 2`
	                                	VL=`expr $VL - $x`
					fi;;
				n*)	break;;
	
				q*)	rm $PROCID.* ; return;;
			esac
			HORIZ_LN="$HR $HS $HE $HL"
			VERT_LN="$VR $VS $VE $VL"
			if [ "$option" = "n" ]
			then
				break
			fi
		done
	done
}
# End Fiddle Function Defs


# MAIN
Banner
#
# Produce  User Menus
#
GenCardList
GenMonList
#
# Get mouse configuration
#
while [ 1 ]
do
	GetMouseType
	clear
	echo ""
	echo ""
	echo "		You have selected the following:"
	echo ""
	if [ "X${XQUEUE}" != "X " ]
	then
		echo "			The Xqueue Driver"
	else
		set ${MouseType}
		echo "			Mouse Driver:	${1}"
		if [ "X${MS_Tty}" != "X " ]
		then
			echo "			Mouse Device:	${MS_Tty}"
		fi
		if [ "X${MS_Baud}" != "X " ]
		then
			set ${MS_Baud}
			echo "			Mouse Speed:	${2}"
		fi
	fi
	echo 		     "                  	$E3B"
	echo ""
	echo $minus_n "		Is this correct [y]: $slosh_c"
	read x
	case $x in
		[Nn]*)
			;;
		*)
			break
			;;
	esac
done
#
# Now get the video card
#
Help_Handler VidCrdQry "Press [Enter] for the Video Card Menu:"
ReadCard
if [ "X${WantOut}" = "X1" ]
then
	CleanUp
	exit 0
fi
#
# Now get the monitor
#
Help_Handler MonQry "Press [Enter] for the Monitor Menu: "
ReadMon
if [ "X${WantOut}" = "X1" ]
then
	CleanUp
	exit 0
fi
#
# Put the Xconfig file together, prompting the user for some stuff
#
echo ""
echo "Building Monitor portion of Xconfig file..."
AssembleMon
sleep 2
echo ""
echo "Building Video Card portion of Xconfig file..."
AssembleCard
echo ""
echo ""
cat $DATADIR/Template|sed -e "s:@XWINHOME:$XWINHOME:" -e \
	"s/@XQUEUE/$XQUEUE/" -e \
	"s/@Emulate3B/$E3B/" -e \
	"s/@KEYBOARD/$KEYBOARD/" -e \
	"s:@MouseType:$MouseType:" -e \
	"s/@MS_Baud/$MS_Baud/" >$TMP/Xconfig.test
cat $TMP/CardPart $TMP/ScrnPart1 $TMP/$$.work >>$TMP/Xconfig.test
grep '^FontPath' $TMP/Xconfig.test | \
	sed 's/FontPath[ 	]*"\(.*\)"/\1/' > $TMP/$$.fps
for i in `cat $TMP/$$.fps`
do
	if [ ! -d $i ]
	then
		egrep -v "^FontP.*$i.*\$" < $TMP/Xconfig.test > $TMP/$$.xc1
		mv $TMP/$$.xc1 $TMP/Xconfig.test
	fi
done
cat $TMP/Xconfig.test|sed -e "s;@AFONTSERVER;$AFONTSERVER;" -e \
	"s;@BFONTSERVER;$BFONTSERVER;" >$TMP/$$.j
mv $TMP/$$.j $TMP/Xconfig.test
CleanUp

#
# Now fiddle
#
while [ 1 ]
do
	clear
	echo "The new X Server will be $Server"
	echo ""
	echo $minus_n "
You may now save the new Xconfig file as it is, or, you may run the tune 
and test utility 'Fiddle'.  It is HIGHLY recommended that you run through 
the tuning procedures, especially if you have chosen to use the 
VESA/Generic modes.

Selecting [v]iew lets you view the current Xconfig file.

Selecting [s]ave saves the new Xconfig file somewhere useful and enables the 
new server.

Selecting [t]une lets you fiddle with the settings then brings you back here 
to save them.

Selecting [e]xit will leave the new Xconfig file in $TMP/Xconfig.test and 
will not enable the new server, you'll have to do this by hand by using 
the command: 

	cp $XWINHOME/bin/$Server $XWINHOME/bin/X

So what do you want to do? ([v]iew, [m]anual_edit, [s]ave, [t]une or [e]xit)? $slosh_c"
	read x
	case "$x" in 
		v*)	ViewFile;continue;;
		m*)	if [ -z "$EDITOR" ]
			then
				EDITOR=vi;export EDITOR
			fi
			$EDITOR $TMP/Xconfig.test;;
		e*)	CleanUp;exit 0;;
		s*)	Save_All;CleanUp;exit 0;;
		t*)	clear;Fiddle;continue;;
		*)	continue;;
	esac
done

