#!/bin/sh
# The installation file for the X-Files
# The next line is executed by /bin/sh, but not Tcl \
exec wish $0 ${1+"$@"}

proc MAIN {} {
    global choice setting warning

    set warning ""
    catch {
	if {[string match "root" [exec whoami]] == 0} {
	    set warning "\n\n\nNOTE: You are not running this as root. You may encounter errors if you select system directories or try to make new directories in them..."
	}
    }
	
    set setting(1) "/usr/X11/bin/"
    set setting(2) "/usr/X11/lib/X11/x-files/"
    set setting(3) "/usr/X11/include/X11/pixmaps/"
    set setting(4) "/usr/X11/man/man1/"

    wm withdraw .
    wm geometry . 400x200
    wm title . "X-Files Installation v1.0"

    Frame

    bind . <Return> {
       .buttons.ok invoke
    }
    bind . <Escape> {
        .buttons.abort invoke
    }
 
    wm deiconify .

    set choice 0
    while {$choice >= 0} {
        tkwait variable choice
        ProcessChoice $choice
    }
    exit

}


proc Frame {} {
    global choice e_text warning

    frame .buttons -relief groove -bd 2
    frame .text -relief ridge -bd 3
    
    button .buttons.ok -text "Install" -command {incr choice} -width 7
    button .buttons.abort -text "Abort" -command {exit} -width 7
    button .buttons.no -width 7 -text "UnInstall" -command {UnInstall} 
    pack .buttons.ok .buttons.no -side left
    pack .buttons.abort -side right
    
    message .text.t -justify center -width 394 \
	    -text "Welcome to X-Files installation!\n\n$warning" -font *fixed*14*
    
    pack .text.t -side top -fill both -expand 1
    pack .buttons -side bottom -fill x
    pack .text -side top -fill both -expand 1
    
    frame .entry -relief groove -bd 3
    label .entry.l -text "Path:"
    entry .entry.e -textvariable e_text -highlightthickness 1
    pack .entry.l -side left
    pack .entry.e -side left -fill x -expand 1
	
    update idletasks
    
}


proc ProcessChoice {choice} {
    global e_text setting
    
    set t .text.t
    . config -cursor watch
    update idletasks
    switch -- $choice {
        1 {
            pack .entry -side bottom -fill x
	    focus .entry.e

            catch {pack forget .buttons.no}
            .buttons.ok config -text "Next" -width 5 -command {incr choice}
            .buttons.abort config -width 5 -cursor pirate
	    .text.t config -justify left
            
            $t config -text "Where do you want to put the main executable?\n\nRemember that at every step you can change our proposal by editing the text in the entry field.\n\nIf you input a non-existing directory, it will be made for you."
            set e_text $setting(1)
	    .entry.e select range 0 end
	    .entry.e icursor end
        }
        2 {
            set setting(1) [TildeSubst $e_text]
            $t config -text "Where do you want to put the system-default configuration files?"
            set e_text $setting(2)
	    .entry.e select range 0 end
	    .entry.e icursor end

        }
        3 {
            set setting(2) [TildeSubst $e_text]
            $t config -text "Do you want to use the X-Files icon?\n\nIf you do, remember to edit your window manager configuration file accordingly.\n\nIf you do not wish to install the icon, click \"Skip\"."
	    
	    .buttons.ok config -text "Yes" -command {set setting(icon) 1 ; incr choice}
	    .buttons.no config -text "Skip" -command {set setting(icon) 0 ; incr choice} -width 5
	    pack .buttons.no -side left
            set e_text $setting(3)
	    .entry.e select range 0 end
	    .entry.e icursor end
        }
        4 {
            set setting(3) [TildeSubst $e_text]
            $t config -text "Do you want to install the X-Files man page?\n\nIf you do not wish to install the man page, click \"Skip\"."
	    
	    .buttons.ok config -text "Yes" -command {set setting(man) 1 ; incr choice}
	    .buttons.no config -text "Skip" -command {set setting(man) 0 ; incr choice} -width 5
	    pack .buttons.no -side left
            set e_text $setting(4)
	    .entry.e select range 0 end
	    .entry.e icursor end
        }
        5 {
            set setting(4) [TildeSubst $e_text]
	    if $setting(icon) {
		set tmp "X-Files icon in:"
		set tmp1 $setting(3)
	    }  {
		set tmp "Icon will not be installed."
		set tmp1 ""
	    }
	    if $setting(man) {
		set tmp2 "Man page in:"
		set tmp3 $setting(4)\n
	    }  {
		set tmp2 "Man page will not be installed."
		set tmp3 "\n"
	    }
            $t config -text "You have chosen:\n\
                    [format "%-25s%-s\n%-25s%-s\n%-25s%-s\n%-25s%-s" "\nExecutable in:" " $setting(1)" \
                    "System-defaults in:" $setting(2) $tmp $tmp1 $tmp2 $tmp3] \
                    \nAre these correct? Select:\n\"Yes\",to start the actual installation\n\"No\", to input the directories again"

            pack forget .entry

            .buttons.ok config -text "Yes" -command {Install}
            .buttons.no config -text "No" -command {set choice 1}
        }

    }
    . config -cursor top_left_arrow
    update idletasks

} 

proc Install {} {
    global setting env

    . config -cursor watch
    pack forget .entry
    pack forget .buttons.no
    .buttons.ok config -state disabled
    update idletasks

    if ![file exists $setting(1)] {
	if [catch {eval exec mkdir -p -m 0755 $setting(1)}] {
	    if [catch {MakeDirProc $setting(1)}] {
		Error "Unable to create directory $setting(1)\n\nPlease check permissions."
	    }
	}
    } 
    if ![file exists $setting(2)] {
	if [catch {eval exec mkdir -p -m 0755 $setting(2)}] {
	    if [catch {MakeDirProc $setting(1)}] {
		Error "Unable to create directory $setting(2)\n\nPlease check permissions."
	    }
	}
    } 
    if $setting(icon) {
	if ![file exists $setting(3)] {
	    if [catch {eval exec mkdir -p -m 0755 $setting(3)}] {
		if [catch {MakeDirProc $setting(1)}] {
		    Error "Unable to create directory $setting(3)\n\nPlease check permissions."
		}
	    }
	} 
    }
    if $setting(man) {
	if ![file exists $setting(4)] {
	    if [catch {eval exec mkdir -p -m 0755 $setting(4)}] {
		if [catch {MakeDirProc $setting(1)}] {
		    Error "Unable to create directory $setting(3)\n\nPlease check permissions."
		}
	    }
	} 
    }

    set pwd [pwd]

    .text.t config -justify center -text "Installing main executable in $setting(1)\n..."
    update idletasks
    set out [open X-Files {WRONLY APPEND CREAT} 0755]
    set source [open X-Files.tcl r]
    puts $out "#! /bin/sh"
    puts $out "# The main file for the X-Files"
    puts $out "# The next line is executed by /bin/sh, but not Tcl \\"
    puts $out "exec wish \$0 \$\{1+\"\$\@\"\}"
    puts $out "set xf(xf_home) \"$setting(2)\""
    puts $out [read $source]
    
    close $source
    close $out
    eval exec chmod 755 X-Files
    after 2000
    if [catch {exec mv -f ./X-Files $setting(1)}] {
	Error "Unable to move \"X-Files\" to $setting(1)\n\nPlease check permissions."
    }

    .text.t config -justify center -text "Installing configuration files in $setting(2)\n..."
    update idletasks
    after 2000
    cd $pwd
    if [file exists $setting(2)xfilesrc] {
	if [Query "Config file (xfilesrc) already exists in\n$setting(2)\n\nSelect 'Yes' to overwrite and 'No' to append the new features to the end of the old file!"] {
	    if [catch {eval exec cp -r xfilesrc $setting(2)}] {
		Error "Unable to copy config file xfilesrc to $setting(2)\n\nPlease check permissions and that directory exists."
		exit
	    }
	} {
	    set fh [open $setting(2)xfilesrc r]
	    set new [open xfilesrc r]
	    if {[string match {*mail_check*} [read $fh]] == 0} {
		close $fh
		set fh [open $setting(2)xfilesrc a]
		while {[gets $new line] >= 0} {
		    if [string match {*Mail*} $line] {break}
		}
		puts $fh $line
		while {[gets $new line] >= 0} {
		    puts $fh $line
		}
	    }
	    close $fh
	    close $new
	}
	set configs ""
    } {
	set configs "xfilesrc"
    }
    lappend configs xfiles.buttons xfiles.extensions xfiles.headers xfiles.user_pophelp
    foreach f $configs {
	if [file exists $setting(2)$f] {
	    if [Query "Config file ($f) already exists in\n$setting(2)\n\nOverwrite?"] {
		if [catch {eval exec cp -r $f $setting(2)}] {
		    Error "Unable to copy config file $f to $setting(2)\n\nPlease check permissions and that directory exists."
		    exit
		}
	    } {
		continue
	    }
	} {
	    eval exec cp $f $setting(2)
	}
    }
    set files {xfiles.main_pophelp xfiles.manual xflogo.gif}
    if [catch {eval exec cp -r $files $setting(2)}] {
	Error "Unable to copy library files to $setting(2)\n\nPlease check permissions and that directory exists."
	exit
    }
    cd $setting(2)
    if [catch {eval exec chmod 644 [concat $files $configs]}] {
	Error "Unable to change library files to mode 644."
    }
    cd $pwd

    if $setting(icon) {	
	.text.t config -justify center -text "Installing icon in $setting(3)\n..."
	update idletasks
	after 2000
	if [catch {exec cp  -r ./xfiles.xpm $setting(3)}] {
	    Error "Unable to copy xfiles.xpm to $setting(3)\n\nPlease check permissions."
	}
	cd $setting(3)
	if [catch {eval exec chmod 644 xfiles.xpm}] {
	    Error "Unable to change icon permissions to 644."
	}
	cd $pwd
    }
    if $setting(man) {
	.text.t config -justify center -text "Installing man page in $setting(4)\n..."
	update idletasks
	after 2000

	set man [open X-Files.1x r]
	set man_new [open X-Files.1x.new w]

	while {[gets $man line] >= 0} {
	    if [string match {*configuration files are located in*} $line] {
		puts $man_new $line
		puts $man_new ".IR $setting(2)"
	    } elseif [string match {*can be found in*} $line] {
		puts $man_new $line
		puts $man_new ".IR $setting(2)xfiles.manual"
	    }  {
		puts $man_new $line
	    }
	}
	close $man
	close $man_new
	
	if [catch {exec mv -f ./X-Files.1x.new $setting(4)X-Files.1x}] {
	    Error "Unable to copy X-Files.1x to $setting(4).\n\nPlease check permissions."
	}
	cd $setting(4)
	if [catch {eval exec chmod 644 X-Files.1x}] {
	    Error "Unable to change man page permissions to 644."
	}
	cd $pwd
    }

    set try1 [string trimright $setting(1) /]
    regsub X11 $setting(1) X11R6 try2
    set try2 [string trimright $try2 /]

    if {[string match *$try1* $env(PATH)] || [string match *$try2* $env(PATH)]} {
	set path ""
    }  {
	set path $setting(1)
    }

    . config -cursor top_left_arrow
    .text.t config -justify center -text "Thank you for installing X-Files.\n\nYou can now start the program by typing \"${path}X-Files\".\n\nWe hope you find it useful."
    pack forget .buttons.no .buttons.abort .buttons.ok
    .buttons.ok config -text "End of install" -command exit -state normal -width 17
    .buttons.no config -text "Start X-Files NOW!" -command "exec $setting(1)X-Files &;exit" -state normal -width 17
    pack .buttons.no -side left
    pack .buttons.ok -side right
    focus .buttons.no
    update idletasks

}

proc UnInstall {} {
    global e_text setting

    pack forget .buttons.no .entry.l
    pack .entry -side bottom -fill x
    set e_text "X-Files"
    .entry.e select range 0 end
    .entry.e icursor end
    .text.t config -justify center -text "Give either the name or the full path of the executable.\n\nThen click \"Start\" to begin uninstalling."
    .buttons.ok config -text "Start" -command {set s 1} -width 7
    focus .entry.e
    update idletasks
    tkwait variable s
    .buttons.ok config -state disabled 
    pack forget .entry
    . config -cursor watch
    update idletasks

    set e_text [string trimright [TildeSubst $e_text] /]
    if [string match */* $e_text] {
	set files $e_text
        if ![file exists $files] {
            Error "File does not exist:\n\n$files"
            exit
        } 
    }  {
	.text.t config -text "Searching for $e_text\n\nThis may take a while..."
	update idletasks
	set files [Find $e_text]
    }
    
    if {[string compare {} $files] == 0} {
	Error "Could not find file $e_text\n\nPlease check name and start again!"
	exit
    }
    
    if {[llength $files] == 1} {
        ProcessFile $files
    }  {
	if [Query "Found multiple files matching $e_text\nAre you sure about this?"] {
	    foreach res $files {
		ProcessFile $res
	    }
	}
    }

    if [Query "Do you want me to search the icon? (xfiles.xpm)\n\nNOTE! In big systems it can take a LONG time..."] {
	.text.t config -text "Searching the icon.\n\nThis may take a while..."
	.buttons.ok config -state disabled
	.buttons.no config -state disabled
	update idletasks
	after 2000
	set pics [Find "xfiles.xpm"]
	
	.text.t config -text "Removing the icon..."
	.buttons.ok config -state normal
	.buttons.no config -state normal
	update idletasks
	foreach p $pics {
	    if [Query "Do you want to remove\n\n$p\n?"] {
		if [catch {eval exec rm -f $p}] {
		    Error "Unable to remove file\n$p"
		}			
	    }
	}
    }

    if [Query "Do you want me to search the man page? (X-Files.1x)\n\nNOTE! in big systems it can take a LONG time..."] {
	.text.t config -text "Searching the man page.\n\nThis may take a while..."
	.buttons.ok config -state disabled
	.buttons.no config -state disabled
	update idletasks
	after 2000
	set mans [Find "X-Files.1x"]
	
	.text.t config -text "Removing the man page..."
	.buttons.ok config -state normal
	.buttons.no config -state normal
	update idletasks
	foreach m $mans {
	    if [Query "Do you want to remove\n\n$m\n?"] {
		if [catch {eval exec rm -f $m}] {
		    Error "Unable to remove file\n$m"
		}			
	    }
	}
	after 2000
    }

    . config -cursor top_left_arrow
    .text.t config -justify center -text "Finished!!!\n\nX-Files uninstalled.\n\nIf you encountered errors, please check paths and permissions and try again."
    pack forget .buttons.no .buttons.abort .buttons.ok
    .buttons.ok config -text "OK!" -command exit -state normal
    pack .buttons.ok -side bottom
    focus .buttons.ok
    update idletasks
}

proc ProcessFile {file} {
    global s

    set id [open $file r]
    while {[gets $id try] >= 0} {
        if [string match {set xf(xf_home)*} $try] {
            break
        }
    }
    close $id
    if ![string match {set xf(xf_home)*} $try] {
        Error "Could not find library path definition.\nAre you sure $file is an X-Files file?"
	set lib_path "N/A"
    }  {
	regexp {.*\"(.*)\".*} $try grg path
	set lib_path [string trimright $path /]
    }

    .text.t config -justify center -text "Do you want to remove\n$file\n\nand it's library directory\n$lib_path\n?"

    .buttons.ok config -text "Yes" -command {set s 1} -state normal
    .buttons.no config -text "No" -command {set s 0} -state normal
    pack .buttons.no -side left
    . config -cursor top_left_arrow
    update idletasks
    tkwait variable s

    if {$s == 0} {return}

    .text.t config -justify center -text "Removing executable:\n\n$file"
    .buttons.ok config -state disabled
    .buttons.no config -state disabled
    . config -cursor watch
    update idletasks

    after 2000
    if [catch {eval exec rm -f $file}] {
        Error "Could not remove file $file\n\nPlease check the path and permissions."
    }
    
    .text.t config -text "Removing the library directory:\n\n$lib_path"
    update idletasks
    after 2000
    if [catch {eval exec rm -rf $lib_path}] {
	Error "Could not remove directory $lib_path\n\n Please check the path and permissions."
    }

}

proc Query {string} {
    global s
    . config -cursor top_left_arrow
    .text.t config -justify center -text $string

    .buttons.ok config -text "Yes" -command {set s 1} -state normal
    .buttons.no config -text "No" -command {set s 0} -state normal
    pack .buttons.no -side left
    . config -cursor top_left_arrow
    update idletasks
    tkwait variable s
    return $s
}

proc Error {string} {
    . config -cursor top_left_arrow
    pack forget .buttons.no
    .text.t config -justify center -text "ERROR!!!\n\n$string"
    .buttons.ok config -state normal -text "Go on" -command {set s 1}
    update idletasks
    tkwait variable s
    .buttons.ok config -state disabled
    . config -cursor watch
    update idletasks
}

proc Find {file} {
    global result

    catch {set res [exec find / -name $file -print]} res
    
    set res [split $res \n]
    set index [lsearch $res *$file]
    set result {}
    while {$index != -1} {
	lappend result [lindex $res $index]
	set res [lreplace $res 0 $index]
	set index [lsearch $res *$file]
    }
    return $result
}

proc TildeSubst {path} {
    global env

    if {[string match "\." $path] || [string match "\./" $path]} {
	return [string trimright [pwd] /]/
    } 
    if [string match ~/* $path] {
        regsub ^(~) $path $env(HOME) temp
        return [string trimright $temp /]/
    } 
    if [string match ~* $path] {
        set dir [pwd]/
        regexp {^[^/]*} $path polku
        if [catch {cd $polku} err] {
            return [string trimright $env(HOME) /]/
        }
        set tmp [pwd]
        cd $dir
        regsub {^[^/]*} $path $tmp temp
        return [string trimright $temp /]/
    }
    return [string trimright $path /]/
}

proc MakeDirProc {dir {parent {}}} {
    if {[string compare {} $dir] == 0} {return}
    set dir [string trimright $dir /]/
    regexp {^[^/]*/} $dir alku
    append parent $alku
    regsub {^[^/]*/} $dir {} loppu
    if ![file exists $parent] {
	exec mkdir $parent
    }
    MakeDirProc $loppu $parent
}
MAIN

