#!/usr/local/bin/wish -f
#
# filesaver.t,  a file saver dialog
# in is input file/pipe to save, "-" means save stdin
# out is default output/pipe to present in dialog save, "-" means save stdin
# defdir is directory to concatenate onto $out if out is a file
#


# this should be more through
proc saveProc {w in} {
    set out [.file.e get]
    set defdir [.dir.e get]

    if {$in=="-"} {
	set in stdin
    } else {
	set in [open $in "r"]
    }
    case $out "-" {
	set out stdout
    } "|*" {
	set out [open $out "w"]
    } default {
	# not a pipe
	# XXX check for existing file here... ??
	# right now we just append to it if it exists
	set out [open $defdir/$out "a+"]
    }

    while {[set x [gets $in buf]]>-1} { puts $out $buf }
    flush $out
    exit
}

proc filesaver {{defdir ""} {in -} {out -}} {
    # XXX should probably use winfo to check, not catch
    set isnew [expr ![catch {
	set w [frame .GroupList]
	wm geometry . 400x100
	wm minsize . 100 64
    }]]

    if {[string length $defdir]==0} {
	set defdir [glob ~]
    }

    if {$isnew} {
	makeEntry .dir Directory $defdir .file
	makeEntry .file File $out .dir "saveProc %W $in"
    } else {
	bindEntry .dir.e .file.e
	bindEntry .file.e .dir.e "saveProc %W $in"
    }

    # pack it up
    if {$isnew} {
	pack append . .dir {expand fill}
	pack append . .file  {expand fill}
    }
    return $w
}

proc makeEntry {w label {text ""} {next ""} {doit ""}} {
    frame $w

    message $w.l \
	-justify left \

    $w.l configure -text $label

    entry $w.e \
	-width 40 \
	-borderwidth 2 \
	-relief sunken
    $w.e insert 0 $text

    bindEntry $w.e $next.e $doit
    pack append $w $w.l {top fillx}
    pack append $w $w.e {bottom}
    return $w
}

proc bs win {
    set x [expr {[$win index cursor] - 1}]
    if {$x != -1} {$win delete $x}
}
proc inschar {w c} {
    if {$c<" "||$c>"~"} {return}
    $w insert cursor $c
}

proc bindEntry {w {next ""} {doit ""}} {
        bind $w <Any-KeyPress> {inschar %W "%A"}
        bind $w <quotedbl> {%W insert cursor \"}
        bind $w <backslash> {%W insert cursor \\}
        bind $w <dollar> {%W insert cursor {$}}
        ## bind $w <2> {puts stdout "character [%W index @%x]"}
        bind $w <Delete> {bs %W}
        bind $w <BackSpace> {bs %W}
        bind $w <Control-h> {bs %W}
        bind $w <1> {%W cursor @%x; focus %W; %W select from @%x}
        bind $w <B1-Motion> {%W select to @%x}
        bind $w <Shift-1> {%W select adjust @%x}
        bind $w <Shift-B1-Motion> {%W select to @%x}
        bind $w <3> {%W scan mark %x}
        bind $w <B3-Motion> {%W scan dragto %x}
        bind $w <Control-d> {%W delete sel.first sel.last}
        bind $w <Control-v> {%W insert cursor [selection get]}
        bind $w <Control-u> {%W delete 0 end}

        # Control-c cancels the dialog
        bind $w <Control-c> {close stdin; close stdout; exit}

        # Tab is next field char
        if {$next!=""} {bind $w <Tab> "focus $next"} else {bind $w <Tab> ""}

        # Return will run $doit is specified
        if {$doit!=""} { 
	    bind $w <Return> $doit
	} else {
	    if {$next!=""}  {bind $w <Return> "focus $next"} else \
			    {bind $w <Return> ""}
	}
}

case $argc 1 {
    puts stderr "called with: <$argc> $argv"
    filesaver ~ - saveFile
} 2 {
    puts stderr "called with: <$argc> $argv"
    filesaver ~ [lindex $argv 1] saveFile
} 3 {
    puts stderr "called with: <$argc> $argv"
    filesaver ~ [lindex $argv 1] [lindex $argv 2]
} default {
    puts stderr "Usage: filesaver dir input file"
}

focus .file.e
