#!/usr/bin/wish

# This program is part of Geoduck, a set of graphical user
# interfaces for UNIX programs.
# Copyright (C) 2002 Allen B. Downey
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# For a copy of the GNU General Public License, go to
# www.gnu.org/copyleft/gpl.html
# or write to the Free Software Foundation, Inc.
# 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
#
# Contact the author: me@allendowney.com

set dir [file dirname [info script]]
source [file join $dir geoduck.tcl]

proc getCommand {} {
    set cmd find

    set opts  { cb_follow cb_xdev cb_depth cb_noleaf cb_daystart \
                en_mindepth en_maxdepth }
    set tests   { file user group cb_nouser cb_nogroup inode size cb_empty \
		  links mb_type en_access en_status \
                  en_mod en_accessfile en_statusfile en_modfile en_used \
                  en_fstype mb_perm }
    set acts { mb_action cb_print0 }

    set names [concat $opts $tests $acts]

    append cmd [getEntry en_input " "]
    append cmd [getFlags $names]
}

proc fr_topcol1 {args} {
    eval {fr fr_topcol1 -side left} $args

    la "Files or directories to search"
    en 0 en_input " " browse
    fillEntry en_input .

    endfr fr_topcol1
}

proc fr_col1 {args} {
    eval {fr fr_col1 -side left} $args

    mb "File name matches pattern:"      mb_file name
    mb "Link name matches pattern:"      mb_file lname
    mb "Path name matches pattern:" mb_file path
    mb "Path name matches regexp:"  mb_file regexp

    en 0 file "fileName"
    cb "Case insensitive?" cb_filecase

    la ""
    gr 2 {0 1}
    la "User name or id:"
    en 0 user "idName user -user -uid"

    la "Group name or id:"
    en 0 group "idName group -group -gid"

    la "Inode number:"
    en 0 inode "idName inode -inum -inum"

    cb "No user for uid."  cb_nouser  -nouser
    cb "No group for gid." cb_nogroup -nogroup
    endgr

    la ""
    la "Options"
    cb "Follow links?" cb_follow -follow
    cb "Exclude mounted directories?" cb_xdev -xdev
    cb "Process dirs before contents?" cb_depth -depth
    cb "Suppress UNIX optimization?" cb_noleaf -noleaf
    cb "Measure times from start of day?" cb_daystart -daystart

    la ""
    gr 2 {0 1}
    la "Min depth for subdirs"
    en 0 en_mindepth "-mindepth "
    la "Max depth for subdirs" 
    en 0 en_maxdepth "-maxdepth "
    endgr

    endfr fr_col1
}

proc comp {name args} {
    set name comp$name
    mb "=" $name "" ""
    mb "<" $name -  ""
    mb ">" $name +  ""
    eval repack $name -padx 2 -expand 0 $args
}

proc units {name prefix args} {
    set name units$name
    set min min
    set time time
    mb "minutes" $name $prefix$min  ""
    mb "days"    $name $prefix$time
    eval repack $name -expand 0 $args
}

proc time {name prefix} {
    fr
    comp $name -side left
    en 0 en_$name "timeExpr $name" "" -side left
    units $name $prefix -side left
    la "ago."
    endfr
}

proc newer {name prefix} {
    set file file
    set newer newer
    la "or newer than file:"
    en 0 en_$name$file "-$prefix$newer " browse
}

proc timeExpr {name} {
    return " -[mbValue units$name] [mbValue comp$name][mbValue en_$name]"
}

proc idName {entry flag1 flag2} {
    set arg [getEntry $entry]
    if {$arg == ""} { return }
    if {[string is integer $arg]} {
	return " $flag2 $arg"
    } else {
	return " $flag1 $arg"
    }
}

proc fileName {} {
    set flag [mbValue mb_file]
    if {[cbValue cb_filecase]} {
	set pre1 i
    } else {
	set pre1 ""
    }
    set name [enValue file]
    if {$name != ""} {
	return " -$pre1$flag \"$name\""
    }
}

proc enSize {} {
    set size [enValue size]
    if {$size != ""} {
	return " -size [mbValue compsize]$size[mbValue mb_size]"
    }
}

proc enLinks {} {
    set links [enValue links]
    if {$links != ""} {
	return " -links [mbValue complinks]$links"
    }
}

proc fr_col2 {args} {
    eval {fr fr_col2 -side left} $args

    fr
    la "Size" -side left
    comp size -side left
    en 0 size "enSize" "" -side left
    mb "512b blocks"  mb_size b ""
    mb "bytes"        mb_size c ""
    mb "kilobytes"    mb_size k ""
    mb "2 byte words" mb_size w ""
    endfr

    cb "Empty file or dir." cb_empty -empty

    la ""
    fr
    la "\# of links" -side left
    comp links -side left
    en 0 links "enLinks" "" -side left
    endfr

    la ""
    fr
    la "File type:" -side left
    mb "any" mb_type a ""
    mb "regular file" mb_type f " -type f"
    mb "directory" mb_type d " -type d"
    mb "symbolic link" mb_type l " -type l"
    mb "block (buffered) special" mb_type b " -type b"
    mb "char (unbuffered) special" mb_type c " -type c"
    mb "named pipe" mb_type p " -type p"
    mb "socket" mb_type s " -type s"
    mb "door (Solaris)" mb_type D " -type D"
    endfr

    la ""
    la "File system type:"
    en 0 en_fstype "-fstype "

    la ""
    fr
    la "Permissions" -side left
    mb "no check"      mb_perm none    ""
    mb "any of these"  mb_perm atmost   "permissions +"
    mb "all of these" mb_perm atleast  "permissions -"
    mb "exactly these"  mb_perm exact    "permissions"
    endfr
    makePerm

    endfr fr_col2
}

proc permissions {{flag ""}} {
    foreach party {S u g o} {
	set oct 0
	foreach perm {r w x} {
	    set name cb_$party$perm
	    set bit [cbValue $name]
	    set oct [expr $oct*2 + $bit]
	}
	append flag $oct
    }
    return " -perm $flag"
}

proc makePerm {} {
    gr 4 { 1 1 1 1 }
    foreach party {"" user group other} {
	la $party
    }

    set label(r) read
    set label(w) write
    set label(x) exec

    foreach perm {r w x} {
	la $label($perm)
	foreach party {u g o} {
	    cb "" cb_$party$perm "" -sticky e
	}
    }
    la "set id"
    cb "" cb_Sr "" -sticky e
    cb "" cb_Sw "" -sticky e
    endgr

    cb "Text image bit" cb_Sx
}

proc actionExec {flag} {
    set arg [getEntry en_arg]
    if {$arg != ""} {
	return " $flag $arg \\;"
    }
}

proc actionPrint {} {
    set flag " -"
    set output [enValue output]
    if {$output != ""} {
	append flag f
    }
    append flag [mbValue mb_format]

    if {$output != ""} {
	append flag " $output"
    }

    set format [enValue format]
    if {[mbValue mb_format] == "printf"} {
	append flag " \"$format\""
    }
    return $flag
}

proc fr_col3 {args} {
    eval {fr fr_col3 -side left} $args

    la "Last access time:"
    time access a
    newer access a

    la ""
    la "Last status change:"
    time status c
    newer status c

    la ""
    la "Last modification:"
    time mod m
    newer mod ""

    la ""
    fr
    la "Last used" -side left
    comp used -side left
    en 0 en_used "-used " "" -side left
    la "days"
    endfr
    la "after last status change."

    endfr fr_col3
}

proc buCommand {command} {
    fillEntry en_arg "$command '{}'"
}

proc buAction {command} {
    bu $command $command "buCommand $command"
    config $command -padx 1 -pady 1
}    

proc fr_col4 {args} {
    eval {fr fr_col4 -side left} $args

    la "Action:"
    mb "print file name" mb_action print "actionPrint"
    mb "execute command" mb_action exec "actionExec -exec"
    mb "prompt and exec" mb_action ok "actionExec -ok"

    la "Command:"
    en 0 en_arg

    gr 2 {1 1}
    buAction rm
    buAction rmdir
    buAction chmod
    buAction chgrp
    endgr

    la ""
    la "Print format:" 
    mb "default"          mb_format print   ""
    mb "ls"               mb_format ls      ""
    mb "null terminate"   mb_format print0  ""
    mb "format string"    mb_format printf  ""

    la "Format string:" 
    en 0 format "" "%p\n"

    la ""
    la "Output file:"
    en 0 output
    
    la ""
    la ""

    endfr fr_col4
}

proc fr_page1 {args} {

    eval {fr fr_page1 -pady 10} $args

    set fill both

    fr_col1 -padx 5 -fill $fill

    fr_col2 -padx 5 -fill $fill

    fr_col3 -padx 5 -fill $fill

    fr_col4 -padx 5 -fill $fill

    endfr fr_page1
}

topFrame

fr fr_middle

fr fr_files -pady 5
fr_topcol1 -padx 5
#fr_topcol2 -padx 5
endfr fr_files

fr_page1 -fill both

endfr fr_middle

fr fr_bottom -padx 5 -pady 5
te text 20
endfr fr_bottom

showCommand