#
#	$Id: UnixFile.tcl,v 1.1.1.1 2001-06-15 23:23:46 darrel Exp $
#
# UnixFile.tcl --
#
#	Unix file access portibility routines.
#
# Copyright (c) 1996, Expert Interface Technologies
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#

proc tixInitFileCmpt:Unix {} {

# tixFSSplit --
# 
# Splits a directory into its hierarchical components
#
# "hlist-type hierachical path"		<- "vpath"
# "name"
# "directory name"			<- "path"
#
proc tixFSSplit {dir} {
    if {[string compare [tixFSPathType $dir] "absolute"]} {
	error "$dir must be an absolute path"
    }

    set path ""
    set p ""
    foreach d [tixFileSplit $dir] {
	set p [tixFSJoin $p $d]
	lappend path [list $p $d $p]
    }
    return $path
}

# returns true if $dir is an valid path (always true in Unix)
#
proc tixFSValid {dir} {
    return 1
}

# Directory separator
#
proc tixFSSep {} {
    return "/"
}

# tixFSIntName
#
#	Returns the "virtual path" of a filename
#
proc tixFSIntName {dir} {
    if {[string compare [tixFSPathType $dir] "absolute"]} {
	error "$dir must be an absolute path"
    }

    return $dir
}

proc tixFSResolveName {p} {
    return $p
}


# These subcommands of "file" only exist in Tcl 7.5+. We define the following
# wrappers so that the code also works under Tcl 7.4
#
global tcl_version
if {![string compare $tcl_version 7.4]} {

    proc tixFSPathType {dir} {
	if {![string compare [string index $dir 0] /]} {
	    return "absolute"
	}
	if {![string compare [string index $dir 0] ~]} {
	    return "absolute"
	}
	return "relative"
    }

    proc tixFSJoin {dir sub} {
	set joined $dir/$sub

	regsub -all {[/]+} $joined / joined
	return $joined
    }

} else {
    proc tixFSPathType {dir} {
	return [file pathtype $dir]
    }

    proc tixFSJoin {dir sub} {
	return [file join $dir $sub]
    }
}

# dir:		Make a listing of this directory
# showSubDir:	Want to list the subdirectories?
# showFile:	Want to list the non-directory files in this directory?
# showPrevDir:	Want to list ".." as well?
# showHidden:	Want to list the hidden files?
#
# return value:	a list of files and/or subdirectories
#
proc tixFSListDir {dir showSubDir showFile showPrevDir showHidden {pattern ""}} {
    set appPWD [pwd]

    if {[catch {cd $dir} err]} {
	# The user has entered an invalid directory
	# %% todo: prompt error, go back to last succeed directory
	cd $appPWD
	return ""
    }

    if {$pattern == ""} {
	if $showHidden {
	    set pattern "* .*"
	} else {
	    set pattern *
	}
    } elseif {$pattern == "*"} {
	if $showHidden {
	    set pattern "* .*"
	}
    }

    set list ""
    foreach pat $pattern {
	if {[catch {set names [lsort [glob -nocomplain $pat]]} err]} {
	    # Cannot read directory
	    # %% todo: show directory permission denied
	    continue
	}

	catch {
	    # We are catch'ing, just in case the "file" command
	    # returns unexpected errors
	    #
	    foreach fname $names {
		if {![string compare . $fname]} {
		    continue
		}
		if {[file isdirectory $fname]} {
		    if {![string compare ".." $fname] && !$showPrevDir} {
			continue
		    }
		    if $showSubDir {
			lappend list [file tail $fname]
		    }
		} else {
		    if $showFile {
			lappend list [file tail $fname]
		    }
		}
	    }
	}
    }

    cd $appPWD

    if {[llength $pattern] > 1} {
	# get rid of duplicated names
	#
	set list1 ""
	set oldfile ""
	foreach name [lsort $list] {
	    if {$name == $oldfile} {
		continue
	    }
	    lappend list1 $name
	    set oldfile $name
	}
	return [_tixFSMakeList $dir $list1]
    } else {
	return [_tixFSMakeList $dir $list]
    }
}

# _tixFSMakeList -
#
#	Internal procedure. Used only by tixFSListDir
proc _tixFSMakeList {dir list} {
    set l ""
    foreach file $list {
	set path [tixFSJoin $dir $file]
	lappend l [list $path $file $path]
    }

    return $l
}

# Directory separator
#
proc tixDirSep {} {
    return "/"
}


# tixFSInfo --
#
#	Returns information about the file system of this OS
#
# hasdrives: Boolean
#	Does this file system support seperate disk drives?
#
proc tixFSInfo {args} {
    case [lindex $args 0] {
	hasdrives {
	    return 0
	}
    }
}

#----------------------------------------------------------------------
# Obsolete
#----------------------------------------------------------------------

# nativeName:	native filename used in this OS, comes from the user or
#		application programmer
# defParent:	if the filename is not an absolute path, treat it as a
#		subfolder of $defParent
proc tixFileIntName {nativeName {defParent ""}} {
    if {![tixIsAbsPath $nativeName]} {
	if {$defParent != ""} {
	    set path [tixSubFolder $defParent $nativeName]
	} else {
	    set path $nativeName
	}
    } else {
	set path $nativeName
    }

    set intName ""
    set path [tixFile trimslash [tixFile tildesubst $path]]
    foreach name [tixFileSplit $path] {
	set intName [tixSubFolder $intName $name]
    }
    return $intName
}

proc tixNativeName {name {mustBeAbs ""}} {
    return $name
}

proc tixFileDisplayName {intName} {
    if {$intName == "/"} {
	return "/"
    } else {
	return [file tail $intName]
    }
}


proc tixFileSplit {intName} {

    set l ""
    foreach n [split $intName /] {
	if {$n == ""} {
	    continue
	}
	if {$n == "."} {
	    continue
	}

	lappend l $n
    }
    

    while {1} {
	set idx [lsearch $l ".."]
	if {$idx == -1} {
	    break;
	}
	set l [lreplace $l [expr $idx -1] $idx]
    }


    if {[string index $intName 0] == "/"} {
	return [concat "/" $l]
    } else {
	return $l
    }
}

proc tixSubFolder {parent sub} {
    if {$parent == ""} {
	return $sub
    }
    if {$parent == "/"} {
	return /$sub
    } else {
	return $parent/$sub
    }
}

# dir:		Make a listing of this directory
# showSubDir:	Want to list the subdirectories?
# showFile:	Want to list the non-directory files in this directory?
# showPrevDir:	Want to list ".." as well?
# showHidden:	Want to list the hidden files?
#
# return value:	a list of files and/or subdirectories
#
proc tixListDir {dir showSubDir showFile showPrevDir showHidden {pattern ""}} { 

    set appPWD [pwd]

    if {[catch {cd $dir} err]} {
	# The user has entered an invalid directory
	# %% todo: prompt error, go back to last succeed directory
	cd $appPWD
	return ""
    }

    if {$pattern == ""} {
	if $showHidden {
	    set pattern "* .*"
	} else {
	    set pattern *
	}
    } elseif {$pattern == "*"} {
	if $showHidden {
	    set pattern "* .*"
	}
    }

    set list ""
    foreach pat $pattern {
	if {[catch {set names [lsort [glob -nocomplain $pat]]} err]} {
	    # Cannot read directory
	    # %% todo: show directory permission denied
	    continue
	}

	catch {
	    # We are catch'ing, just in case the "file" command
	    # returns unexpected errors
	    #
	    foreach fname $names {
		if {![string compare . $fname]} {
		    continue
		}
		if {[file isdirectory $fname]} {
		    if {![string compare ".." $fname] && !$showPrevDir} {
			continue
		    }
		    if $showSubDir {
			lappend list [file tail $fname]
		    }
		} else {
		    if $showFile {
			lappend list [file tail $fname]
		    }
		}
	    }
	}
    }

    cd $appPWD

    if {[llength $pattern] > 1} {
	set list1 ""
	set oldfile ""
	foreach name [lsort $list] {
	    if {$name == $oldfile} {
		continue
	    }
	    lappend list1 $name
	    set oldfile $name
	}
	return $list1
    } else {
	return $list
    }
}

# returns the "root directory" of this operating system
#
proc tixRootDir {} {
    return "/"
}

proc tixIsAbsPath {nativeName} {
    set c [string index $nativeName 0]
    if {$c == "~" || $c == "/"} {
	return 1
    } else {
	return 0
    }
}

proc tixVerifyFile {file} {
    return [tixFileIntName $file]
}

proc tixFilePattern {args} {
    if {[lsearch $args allFiles] != -1} {
	return *
    }
    return *
}
}





