#!/bin/sh
# Small Tk command window

# the next line restarts using tclsh \
exec wish "$0" "$@"


# I don't know where the binding <Return> is documented 
# Todo	: might want to catch errors 
# Menubutton widgets won't take focus (tried -takefocus 1), see "man n options"

wm title . Tkexe
wm minsize . 200 26
wm resizable . true false	;# only allow to resize width

if { [info exists env(DESKTOP)] && $env(DESKTOP) == "kde" } {
        # bloody kde's colour inheritance makes tkexe's colours wrong
	# but I can't really fix it nice !^%#@
	set colour grey
	wm geometry . +596+525	;# bottom right corner
} else {
	set colour grey
}

set relief raised
set history {~/.tkexerc}
set font {6x12}

set processes {}

# initialise a command history (commands)
if { [file isfile $history] && ! [catch {set fid [open $history]} ] } {
        set commands {}
	set item "[gets $fid]"
        while { ! [eof $fid] } {
		# this is a bit clumsy as tk will read an empty
		# line with the last read
                lappend commands $item
		set item "[gets $fid]"
        }
        close $fid
} else {set commands {{}}}


proc DoEntry {} {
	global processes
	
	set pid [eval exec [.e get] {&}]
	if { $pid != {} & $pid > 10 } { lappend processes $pid }
}

proc Insert {command} {
	.e delete 0 end
	.e insert 0 "$command"
}

proc Edit {op} {
	global commands

	if {$op == "add"} {;			# add
		# add the new command to the top (except if th etop is a blank)
                if {[lindex $commands 0] == "" } {set i 1} else {set i 0}
		set commands [linsert $commands $i [.e get]]
	} elseif {$op == "delete"} {;		# delete
		set i [lsearch -exact $commands [.e get]]
		if {$i != -1 } {
			set commands [lreplace $commands $i $i]
		}
	} else {;				# sort
		set commands [lsort $commands]
	}
	destroy .b0.menu
	menu .b0.menu -tearoff 0
	UpdateMenu
}

proc UpdateMenu {} {
	global commands
	foreach i $commands {.b0.menu add command -label $i \
		-hidemargin 0 -command "Insert \{$i\}"}
}


# kill the first process in the list if it's still running
proc KillProcess {} {
        global processes

	if {[llength $processes] == 0} { return }

	set pid [lindex $processes 0]

	if {[catch {exec ps $pid}] == 0} { exec kill -1 $pid }

	set processes [lreplace $processes 0 0]
}

proc Exit {} {
	global commands history

	if {[catch {set fid [open $history {w+}]}] == 0} {
		foreach i $commands { puts $fid $i }
		close $fid
        } else {
		puts stderr "tkexe: can't write history: $history"
	}
	destroy .
}

proc Drag {} {
    wm geometry . +[expr [winfo pointerx .] - 155]+[expr [winfo pointery .] - 10]
    # update
}


#source load_gif
#image create photo buttonpic -file {/usr/local/share/tv.gif}
image create photo buttonpic
buttonpic put {
{#bebebe #bebebe #bebebe #bebebe #bebebe #bebebe #bebebe #bebebe
 #f9af07 #f9b720 #bebebe #bebebe #bebebe #bebebe #bebebe #bebebe}
{#bebebe #bebebe #bebebe #bebebe #bebebe #bebebe #bebebe #bebebe
 #f7c859 #f9c752 #bebebe #bebebe #bebebe #bebebe #bebebe #bebebe}
{#bebebe #bebebe #bebebe #bebebe #bebebe #bebebe #bebebe #f9b311
 #f8f8e7 #f8c74f #bebebe #bebebe #bebebe #bebebe #bebebe #bebebe}
{#bebebe #bebebe #bebebe #bebebe #bebebe #bebebe #f9ab01 #f9df9c
 #f5f1c7 #f6cc53 #bebebe #bebebe #bebebe #bebebe #bebebe #bebebe}
{#f8b417 #fbd988 #fac755 #f9b211 #f9ab03 #f9a701 #f8c64c #f5edbe
 #f6e891 #f6d954 #bebebe #bebebe #bebebe #bebebe #bebebe #bebebe}
{#bebebe #fad585 #f9ffff #f6f8ff #f8f7ef #f8e4a7 #f6ebb2 #f6e686
 #f4e15d #f1d53c #fbac05 #bebebe #bebebe #bebebe #bebebe #bebebe}
{#bebebe #f9ab00 #f8dc9f #f8f5e5 #f7efc5 #f6e7a2 #f6e47c #f4de55
 #efd53b #ecd438 #efcf33 #f4c225 #f6b716 #faaf0c #bebebe #bebebe}
{#bebebe #bebebe #f9aa00 #f7e4a5 #f6e79f #f7e272 #f3db4e #eed337
 #edd236 #edd33a #edd53c #ecd73f #ecd942 #ecd941 #f1ca2e #f9b10f}
{#bebebe #bebebe #bebebe #f8bc27 #f6e674 #f2da4a #eed236 #edd236
 #edd339 #edd33a #edd53c #ecd73f #edd43b #f5c021 #fab00e #bebebe}
{#bebebe #bebebe #bebebe #f8be23 #f1dd4e #eed337 #edd237 #edd339
 #eed33a #edd43c #eed43a #f6be1e #faae0a #bebebe #bebebe #bebebe}
{#bebebe #bebebe #faae0b #f2d13a #ecd53b #edd43a #edd43b #edd43b
 #edd43b #edd53d #f4c124 #bebebe #bebebe #bebebe #bebebe #bebebe}
{#bebebe #bebebe #f5c022 #ebd941 #ecd73f #eed43b #f1cb31 #ecd73f
 #edd53d #edd63e #f4c326 #bebebe #bebebe #bebebe #bebebe #bebebe}
{#bebebe #fab10e #ecd73f #efcf35 #f5be1f #f9b10e #fcac06 #f8b413
 #edd63d #ecd841 #f4c327 #bebebe #bebebe #bebebe #bebebe #bebebe}
{#bebebe #f8b412 #f7b716 #faae0b #bebebe #bebebe #bebebe #bebebe
 #f8b615 #ecd840 #f3c528 #bebebe #bebebe #bebebe #bebebe #bebebe}
{#bebebe #bebebe #bebebe #bebebe #bebebe #bebebe #bebebe #bebebe
 #bebebe #f7b817 #eed036 #bebebe #bebebe #bebebe #bebebe #bebebe}
{#bebebe #bebebe #bebebe #bebebe #bebebe #bebebe #bebebe #bebebe
 #bebebe #bebebe #f8b413 #bebebe #bebebe #bebebe #bebebe #bebebe}}

menubutton .b0 -image buttonpic -direction below -menu .b0.menu -height 20 \
  -bg  $colour -activebackground  $colour -relief $relief -width 24
menu .b0.menu -tearoff 0

UpdateMenu

button .go -font $font -text Go -fg green \
	-activeforeground green -bg $colour -relief $relief \
	-activebackground $colour -command DoEntry -width 1 -height 1

button .exit -font $font -text Exit -fg red \
	-activeforeground red -bg $colour -relief $relief \
	-activebackground $colour -command {Exit} -width 1 -height 1

menubutton .edit -font $font -text Edit -direction below -menu .edit.menu \
	-bg  $colour -activebackground  $colour -relief $relief \
	-activeforeground SteelBlue -fg SteelBlue -padx .5

menu .edit.menu -tearoff 0

foreach i {add delete sort} {
	.edit.menu add command -label $i -command "Edit $i" -hidemargin 0
}

entry .e -width 10 -relief flat -font 7x14bold -insertofftime 0
.e insert 0 $argv

pack .e -side left -fill x -expand 1
pack .b0 -side left
pack .go -side left
pack .edit -side left -ipady 1 ;# menubutton packs a little different
#pack .exit -side left

bind .e <Return> DoEntry
bind .e <Control-Key-c> {KillProcess}
bind .e <Control-Key-q> {Exit}
bind .e <FocusIn> {.e selection range end end}
bind .e <ButtonRelease-3> {lower .}
bind .go <B1-Motion>     "Drag"
bind . <Destroy> {Exit}

focus .e
