#!/usr/local/bin/wish -f
#
# TkTailf
# Copyright(c) 1996 by Gaku UEDA.  All rights reserved.
#
# Redistribution and use in source and binary forms are permitted
# provided that the above copyright notice are remain intact.
# This software is provided AS-IS and WITHOUT ANY EXPRESS or
# IMPLIED WARRANTIES, including, without limitation, the implied
# warranties of merchantibility and fitness for a perticular purpose.

# TkTailf - Multiple tail -f in One window

# parameters
set fontset "-misc-fixed-medium-r-normal-*-10-*-*-*-c-*-iso8859-*"
# msec
set NOTIFY_TIME 3000
set NOTIFY_COLOR "alice blue"
set VERSION "TkTailf Version 7.1b"
# msec
set UPDATE_INTERVAL 1000

# initalize
set max 0
# Keep file list(number like {0 1 2 4 5})
set flst {}
set selected ""
# fds: File discriptor list
set fds {}
# spos: start position
set spos {}
# fnames: file names
set fnames {}


wm title . "Tktailf"

proc AddFrame {file i} {
    global fontset
    global flst 
    global fds
    global spos
    global fnames

#    puts [format "AddFrame %s %d" $file $i]
    if {![file readable $file]}  {
	puts [format "It's not readable: %s" $file]  	
    } elseif {![file isfile $file]} {
	puts [format "It's not normal file: %s" $file]
    } else {
	# window setup
	frame .$i
	frame .$i.top 
	label .$i.top.title -text $file
	button .$i.top.close -text close -command "DeleteItem $i"
	button .$i.top.reopen -text reopen -command "Reopen $i"

	scrollbar .$i.vscroll -relief sunken -orient vertical\
		-command ".$i.text yview"
	text .$i.text -width 80 -height 10\
		-yscrollcommand ".$i.vscroll set"\
		-font $fontset

	pack .$i -expand 1 -fill both
	pack .$i.top -side top -fill x
	pack .$i.top.close -side right
	pack .$i.top.reopen -side right
	pack .$i.top.title -side left
	pack .$i.vscroll -side right -fill y
	pack .$i.text -side top -expand 1 -fill both

	

	set fd [open $file r]
	seek $fd 0 end
	set pos	[tell $fd]
	if [expr $pos > 1000] {
	    seek $fd -1000 end
	} else {
	    seek $fd 0
	}
	lappend fnames $file
	lappend spos [tell $fd]
	lappend fds $fd
	lappend flst $i

	incr i
    }

    return $i
}



# Action for Reopen button
proc Reopen {i} {
    global fds
    global spos
    global fnames
    
    puts $fds

    set fd [lindex $fds $i]
    set fname [lindex $fnames $i]

    # clear original
    .$i.text delete 1.0 end
    close $fd

    # re-open it.
    if {![file readable $fname]}  {
	puts [format "It's not readable: %s" $file]  	
    } elseif {![file isfile $fname]} {
	puts [format "It's not normal file: %s" $file]
    } else {
	set fdnew [open $fname r]
	# seek back to original start position
	seek $fdnew [lindex $spos $i] start
    }
}





# Action for Close button
# 1. Delete item from file list(number)
# 2. Destroy frame for it.
proc DeleteItem {i} {
    global flst
#    puts $flst
    set pos [lsearch -exact $flst $i]
#    puts [format "pos=%d i=%d" $pos $i]
    set flst [lreplace $flst $pos $pos]
#    puts $flst
    destroy .$i

}

proc AddNewItem {} {
    global selected
    global max
    # OpenDialog
    OpenFile .menubar .enter "Open File"
    tkwait variable selected
    destroy .enter
#    puts $selected

    if {[string compare $selected ""]} {
	set max [AddFrame $selected $max]
    }
}

proc SelectCancel {} {
    global selected
    set selected ""
}

proc Select {w} {
    global selected
    set selected [$w.entry get]
}

# procedure for Open file
#
#
proc OpenFile {parent widget title} {
    toplevel $widget	
    wm title $widget $title
    label $widget.message -text "Input path"
    entry $widget.entry -relief sunken
    frame $widget.b
    button $widget.b.ok -text Open -padx .5 -command "Select $widget"
    button $widget.b.cancel -text Cancel -padx .5 -command "SelectCancel"

    bind $widget.entry <Any-Return> "Select $widget"

    pack $widget.message -fill x -side top
    pack $widget.entry
    pack $widget.b -fill x -side top
    pack $widget.b.ok -side left 
    pack $widget.b.cancel -side right
 
    wm withdraw $widget
    update idletasks

    set geomstr [wm geometry .]
    scan $geomstr "%dx%d+%d+%d"  w h x y

    set x [expr $x + 30]
    set y [expr $y + 60] 
    wm geom $widget +$x+$y
    wm deiconify $widget
}

# Is it bottom of scrollbar?
#
#
proc BottomP {scrollwidget} {
#    puts [$scrollwidget yview]
    set ep [lindex [$scrollwidget yview] 1]

    if {($ep == 1) || ($ep == 0)} {
#	puts "YES. Buttom"
	set retv 1
    } else {
#	puts "Not Buttom"
	set retv 0
    } 
}

# main -----

frame .menubar
pack .menubar -side top -fill x
menubutton .menubar.file -text File -menu .menubar.file.m     -relief raised
menu .menubar.file.m
.menubar.file.m add command -label Open -command {AddNewItem} 
.menubar.file.m add command -label Quit -command {exit}
pack .menubar.file -side left
label .menubar.version -text $VERSION
pack .menubar.version -side right

foreach file $argv {
#    puts $max
    set max [AddFrame $file $max]
}
set DefaultBgColor [. cget -background]



#
#
#
proc reset {w} {
    global NOTIFY_COLOR DefaultBgColor

    .$w configure -background $DefaultBgColor
    .$w.top.title configure -background $DefaultBgColor
}


proc main {} {
    global fds	
    global flst
    global NOTIFY_COLOR DefaultBgColor
    global UPDATE_INTERVAL NOTIFY_TIME
    # puts "proc main"



    foreach i $flst {
	set notify 0
	set bp [BottomP .$i.text]
	while {[string length [set str [read [lindex $fds $i]]]]} {
	    # puts $str
	    .$i.text insert end $str
	    if {$bp == 1} {
		.$i.text see end
	    }
            set notify 1
        }
	if {$notify == 1} {
	    .$i.top.title configure -background $NOTIFY_COLOR
	    .$i configure -background $NOTIFY_COLOR
	    update idletasks
	    after $NOTIFY_TIME "reset $i"
	}
    }
    after $UPDATE_INTERVAL "main"
}

bind . <Map> "main"
