#!/bin/bash
# the next line restarts using wish \
exec wish "$0" "$@"

#
# This program configures DOSEmu. It will either modify a local file, or a
# system file.
#
# Setup is this:
# User selects global or local.
# Global:
#  If there is no global file and global is selected, copy in 
#  './etc/config.dist'.
# Both:
#  Scan global file for "defaults".
# Local:
#  Scan local file for "overrides".
# Both:
#  Handle responses until done.
# Global:
#  Write all changes
# Local:
#  Write out any non-global-default changes.
#
# This script is (c) Copyright 1997 Alistair MacDonald 
#                                   <alistair@slitesys.demon.co.uk>
#
# It is made available to the DOSEmu project under the GPL Version 2, or at
# your option any later version. Details of this Licence can be found in the
# file 'COPYING' in the distribution's top level directory.
#
# Version
# 0.1	Initial Version - No Save
# 0.2	Changed to use 'DESC' files. Now Saves
# 0.3   First Released version: Now uses Hans' parser to get/set information
#

#A Few settings
set conf_infile ""
set dosemuconf "/etc/dosemu.conf"
set dosemurc ".dosemurc"
set dosemutemplate "../etc/dosemu.conf"
set temp "$env(HOME)/.dosemu/tmp/runtime_setup."
append temp [ pid ]

if {[info exists env(AWK)]} {
  set awk $env(AWK)
} else {
  set awk awk
}

set parser "./parser/parser"
if { ![file exists $parser] } {
  exec bash -c "cd parser; make 2>&1" >@ file1
}

# source the help stuff
source runtime_setup.help.patterns
source browse.tk

proc init_help {} {
    global helptx helpcount readme
    set helptx ""
    set helpcount 0
    readin_readme $readme helptx helpcount {^  2.2\..\. } {^  3.3\..\. }
}

# Housekeeping ...

proc clean_up {} {
  global temp

  catch { exec rm -f $temp }

  exit
}

proc positionWindow w {
  wm geometry $w +100+100
}

proc positionWindowRelative {w masterw dx dy} {
  set xx [split [wm geometry $masterw] +]
  wm geometry $w "+[expr [lindex $xx 1] + $dx]+[expr [lindex $xx 2] + $dy]"
}

proc positionSubWindow {w} {
  positionWindowRelative $w . 0 +45
}

proc select_configuration_file {} {
  global dosemuconf dosemurc mainDx
  toplevel .configure -class Dialog
  positionWindow .
  positionSubWindow .configure
  wm title .configure "DOSEMU Run-Time Configuration"
  label .configure.header -text "Select a file to configure:\n \
NOTE: All comments of an existing file will be removed !!"
  pack .configure.header -fill x -padx 12

  button .configure.system -text "System Wide                            " -command { destroy .configure; load_system; do_menus }
  pack .configure.system -fill x -padx 10
  entry .configure.system.entry -textvariable dosemuconf
  pack .configure.system.entry -side right -anchor e -fill x

  button .configure.local -text "Local                                  " -command { destroy .configure; load_local; do_menus }
  pack .configure.local -fill x -padx 10
  entry .configure.local.entry -textvariable dosemurc
  pack .configure.local.entry -side right -anchor e -fill x

  wm title . "DOSEMU Run-Time Configuration - Status" 
  label .description -text "Status:" 
  label .status -text "Choose a Configuration File" -relief sunken
  pack .description .status -side left -padx 40

  frame .configure.footer
  pack .configure.footer
  button .configure.footer.exit -text "Cancel" -command { clean_up }
  button .configure.footer.help -text "Help" -command { display_help "Help - Select Config File" "Select the configuration file that you wish to configure. You will probably only be able to amend the System Wide file if you are root." }
  pack configure .configure.footer.exit .configure.footer.help -fill x -side left -padx 5

}

proc load_system {} {
    global conf_type temp
    global conf_file conf_infile
    global awk
    global parser
    global dosemuconf dosemutemplate

    .status configure -text "Reading System Wide Configuration ..."
    pack .status
    update idletasks

    exec $parser -t -p $dosemutemplate -u $dosemuconf | $awk -f parse-config-new -f parse-misc \
	-f parse-config-new-tk -v PREFIX=SYSTEM_ > $temp
    source $temp

  parse_debug_flags

  set conf_file "$dosemuconf"
  set conf_infile $conf_file
  set conf_type "system"
}

proc load_local {} {
  global conf_type temp
  global env
  global conf_file conf_infile dosemurc dosemutemplate dosemuconf
  global awk
  global parser

  .status configure -text "Reading Local Configuration ..."
  pack .status
  update idletasks

  set conf_file [ set env(HOME) ]
  append conf_file "/$dosemurc"
  set conf_infile $conf_file

  exec  $parser -r -p $dosemutemplate -u $dosemuconf | \
	$parser -r -t -p - -u $conf_file | \
	$awk -f parse-config-new -f parse-misc \
	-f parse-config-new-tk -v PREFIX=SYSTEM_ > $temp
  source $temp

  parse_debug_flags

  set conf_type "local"
}

proc parse_debug_flags {} {
    global var_SYSTEM_array

    set debug_str $var_SYSTEM_array(debug)
    set str_length [ string length $debug_str ]
    set flag 1
    set var_SYSTEM_array(debug_a) 1

    for { set i 0 } { $i < $str_length } { incr i } {
	set this_char [ string index $debug_str $i ]

	switch -regexp -- $this_char {
	    \\+ { set flag 1 }
	    - { set flag 0 }
	    ^[0-9]$ { set flag $this_char }
	    \# { set var_SYSTEM_array(debug_hash) $flag }
	    default { set var_SYSTEM_array(debug_$this_char) $flag }
	}
    }
}

proc form_debug_string {} {
    global var_array
    set debug_string "-a"

    foreach flag [ list d R W D C v X k i T s m \# p g c w h I E x M n P r S e a] {
	if { $flag == "\#" } { 
	    set this_level [ get_value debug_hash ]
	    if { $this_level != "" } {
		append debug_level($this_level) \#
	    }
	} elseif { $flag == "a" } {
	    set this_level [ get_value debug_a ]
	    if { $this_level == 0 || $this_level == "" } {
		set debug_string "-a"
	    } elseif { $this_level == 1 } {
		set debug_string "+a"
	    } else {
		set debug_string "${this_level}a"
	    }
	} else {
	    set this_flag [ string range $flag end end ]
	    set this_level [ get_value debug_$this_flag ]
	    if { $this_level != "" } {
		append debug_level($this_level) $this_flag
	    }
	}
    }

    foreach level [ array names debug_level ] {
	if { $level == 0 } {
	    append debug_string "-" $debug_level($level)
	} elseif { $level == 1 } {
	    append debug_string "+" $debug_level($level)
	} else {
	    append debug_string $level $debug_level($level)
	}
    }
    set var_array(debug) $debug_string
}


proc do_menus {} {
  global temp
    global awk

  catch { 
    .status configure -text "Loading Menus ..."
    pack .status
    update idletasks
  }

    catch { exec $awk -f parse-menu -f parse-misc -f parse-menu-tk \
		runtime_setup-new.menu > $temp }
  source $temp

  .status configure -text "Running Menus ..."
  pack .status
  update idletasks

  start
}

proc handle_help { help_item } {
  global helptx helpcount 
  global hlp
  if {[info exists hlp($help_item)]} {
	show_readme_text helptx $helpcount $help_item $hlp($help_item)
  } else {
	display_help "Help - $help_item" "Sorry - Help is not available at the moment"
  }
}

proc display_help { help_title help_text } {
  toplevel .help -class Dialog
  positionSubWindow .help
  wm title .help $help_title

  message .help.message -text $help_text
  pack .help.message

  button .help.exit -text "Ok" -command { destroy .help }
  pack .help.exit
}

proc get_value { var_name } {
  global var_SYSTEM_array var_LOCAL_array
  global var_array
    global conf_type

  # Initial dummy ...
  set temp ""
    
    if {! [ info exists var_array($var_name) ] } {
	catch {
	    set temp [ set var_SYSTEM_array($var_name) ]
	}

	if { $conf_type == "local" } {
	    catch {
		set temp [ set var_LOCAL_array($var_name) ]
	    }
	}
	return $temp
    } else {
	return $var_array($var_name)
    }

}

proc write_values { file_name } {
    global var_array
    global var_SYSTEM_array var_LOCAL_array
    global var_type_array

    form_debug_string

    set values_file [ open $file_name w ]

    foreach array_name [ array names var_array ] {
	if [ string match debug_* $array_name ] { continue }

	set local_value ""
	set system_value ""
	catch {	set local_value $var_SYSTEM_array($array_name) }
	catch {	set system_value $var_SYSTEM_array($array_name) }

	set this_var $var_array($array_name)

	if { $this_var != $local_value && $this_var != $system_value } {
	    set this_type ""
	    catch { set this_type $var_type_array($array_name) }
	    if { $this_var == "*" } {
		set this_var ""
	    }
	    if { $this_type == "S" } {
		if { [ regexp {[\"\']} $this_var ] || 
		     [ string index $this_var 0 ] == "$" } { 
		    puts $values_file "\$_$array_name = $this_var"
		} else {
		    puts $values_file "\$_$array_name = \"$this_var\""
		}
	    } elseif { $this_type == "N" } {
		    puts $values_file "\$_$array_name = ($this_var)"
	    }
	}
    }

    close $values_file
}



proc show_error { error_message } {
  catch [ toplevel .error -class Dialog ]
  positionSubWindow .error
  wm title .error "Error"

  message .error.message -text $error_message

  button .error.exit -text "OK" -command { destroy .error }

  pack .error.message .error.exit
}

proc MainMenu_End {} {
    global var_array

    set var_array(output) "abort"

    handle_Output_File
}

proc Output_File_exit {} {
    global configure
    global conf_file
    global var_array

    set configure $var_array(output)

    destroy 

    if { $configure == "new" } {
	handle_New_File
    } else {
	do_Output_File
    }
}

proc New_File_exit {} {
    global var_array
    global conf_file

    set result $var_array(output_file)
    
    if { [ string length $result ] == 0 } {
	clean_up
    } else {
	set conf_file $result
    }

    do_Output_File
}

proc do_Output_File {} {
    global var_SYSTEM_array
    global conf_file conf_infile conf_type
    global temp
    global awk
    global parser
    global dosemuconf dosemutemplate

    global configure
    
    if { $configure == "abort" } {
	# Nothing to do.
	clean_up
    }

    .status configure -text "Writing Results ..."
    pack .status
    update idletasks

    write_values $temp

    .status configure -text "Building Configuration ..."
    pack .status
    update idletasks

    if { [string compare $conf_type "local"] == 0 } {
	catch { exec $parser -r -p $conf_infile -u $temp > ${conf_file}.tmp }
    } else {
	catch { exec $parser -p $dosemutemplate -u $conf_infile | $parser -u $temp -p - > ${conf_file}.tmp }
    }
    catch { exec cp -f $conf_file ${conf_file}.old 2> /dev/null }
    catch { exec mv -f ${conf_file}.tmp $conf_file }
    if { ![string compare $conf_type "local"] && ![file size $conf_infile]} {
	catch { exec rm -f $conf_file }
    }
    puts file1 "following changes were updated to $conf_file:"
    catch { exec cat $temp >@ file1 }
    clean_up
}

init_help
select_configuration_file
