#!/usr/bin/wish
#
# listexec  
#
# a simple list browser, choose an item   
# from a list and connect it on a command by double click 
#
# (c) 1997 SuSE Linux AG (ms@suse.de)
#
# Fri Aug  9 13:53:35 CEST 2002 (Version 4.7)
#

set option(-l) english
set bool_options 1
set option(-E) "vi"
catch { set option(-E) $env(EDITOR) }
set homevz $env(HOME)

proc me {} {
    puts "listexec - execute a list viewer for program execution"
    puts "Version 4.7 - Copyright (c) 2002 SuSE Linux AG\n" 
}

proc usage { } {

    puts "usage: listexec options"
    puts "options:"
    puts "    \[ -E <Editor> \]"
    puts "       if the selected list item is a regular file"
    puts "       you can edit it using the specified editor\n"
    puts "    \[ -e <command string> \]"
    puts "       call the specified command if you double click"
    puts "       on a list item\n"
    puts "    \[ -g <geometry> \]"
    puts "       set the geometry of the application. The format"
    puts "       is: XxY\[+-\]Xoffset\[+-\]Yoffset\n"
    puts "    \[ -i <internal title> \]"
    puts "       use this option to show an internal title string."
    puts "       It is usefull if no windowmanager is present\n"
    puts "    \[ -l <german | english> \]"
    puts "       set the language, german and english is available\n"
    puts "    \[ -o \]"
    puts "       prevent listexec from exiting after a double click" 
    puts "       action\n"
    puts "    \[ -t <title> \]"
    puts "       set the title which appear in the windowmanager"
    puts "       created frame-window\n"
    puts "    \{ -f <listfile> | -p <directory to list> \}"
    puts "       obtain list items from a file (-f) or as the"
    puts "       directory contents (-p)\n"
    puts "Additional information may be found"
    puts "the manual page of listexec"
}


#------------------------#
#   getting startet
#------------------------#

#if { $argc == 0 } {
#
#    usage
#    exit 1
#}

set option(-t) [ file tail [ file rootname "$argv0" ] ]

set option(-e) {}
set optionlist {}
set argcount   0
set option(-)  {}

set fileop  ""

set bool(filelist)  0
set bool(directory) 0
set bool(title)     0
set bool(ititle)    0
set bool(command)   0
set bool(sprache)   0
set bool(editor)    0
set bool(geometry)  0

while { 1 } {

    set arg [ lindex $argv $argcount ]
    incr argcount
    switch -glob -- "$arg" {

        -l           -
        --language   {
            
	    set arg "-l" 
	} 

	-h           -
	--help       {

	    me
	    usage
	    exit 0
	}
	-o           -
	--ontop      {

	    set bool_options 0
	    continue
	}
	-f           -
	--file       {
	    
	    set arg "-f" 
	    set bool(filelist) 1
	    set fileop "-f"
	}
	-p           -
	--pwd        {

	    set arg "-p" 
	    set bool(directory) 1
	    set fileop "-p"
	}

	-E           -
	--editor     {

	    set arg "-E"
	    set bool(editor) 1
	}

	-e           -
	--exec       {
	    set arg "-e"
	    set bool(command) 1
	}

	-g           -
	--geometry   {

	    set arg "-g" 
	    set bool(geometry) 1
	}

	-t           -
	--title      {

	    set arg "-t" 
	    set bool(title) 1
	}

	-i           -
	--ititle     {

	    set arg "-i" 
	    set bool(ititle) 1
	}

	-*           {

	    puts "$option(-t): error: '$arg' is not a valid option."
	    usage
	    exit 1
	}

	default          { break }
    }

    #--Save the content of the Option in option 
    
    set option($arg) [ lindex $argv $argcount ]
    incr argcount

    if { $option($arg) == "" } {

	puts "$option(-t): error: missing parameter to option '$arg'!"
	usage
	exit 1
    }
    
    #--Save the option in optionlist

    lappend optionlist $arg
}

if { $option(-l) != "german" && $option(-l) != "english" } {
    puts "Wrong parameter $option(-l) for language"
    usage
    exit 1
}

#--if command is spezified --> test ist
if { $bool(command) == 1 } {
    set p  ""
    set p1 ""
    set p2 ""
    regexp {(^[a-zA-Z0-9]+)(\ \-(.*)(\ )*)*} $option(-e) p p1 p2
    set p1 [ string trim $p1 ]
    
    set t [ catch { eval { exec which $p1 }} ]
    
    if { $t == 1 } {
	puts "could not find command $p1"
	exit 1 
    }
}

#--Set title  
wm title . $option(-t)
wm iconname . $option(-t)

#--------------------------------#
# Main Frame
#--------------------------------#

set w(main)     .main

frame $w(main)
pack $w(main) \
	-expand yes -fill both


#---------------------------------#
# Set speach                      #
#---------------------------------#

set file(german)  "Datei"
set file(english) "File" 

set help(german)  "Hilfe"
set help(english) "Help"

set execute(german)  "Ausfhren"
set execute(english) "Execute"

set quit(german)   "Ende"
set quit(english)  "Quit"

set about(german)  "Kurzrefferenz"
set about(english) "short help"

set info(german)   "Info"
set info(english)  "Info"

set options(german)  "Optionen"
set options(english) "Options"

set bool(german)  "Schlieen nach Ausfhrung"
set bool(english) "Exit after Execute" 

set edit(german)  "Editieren"
set edit(english) "Edit"

set create_filename(german)  "Dateiname:"
set create_filename(english) "Filename:"

#----------------------------------#
#  Frames for Menu,View,Buttons
#----------------------------------#
 
set w(menu) [ \
	frame $w(main).mbar \
	-relief raised -bd 1 \
	]

set w(view) [ \
	frame $w(main).view \
	]

set w(btns) [ \
	frame $w(main).btns \
	]

if { $bool(ititle) } {

    set w(ititle) [ \
	    label $w(main).ititle \
	    -relief raised -bd 1 \
	    -text "$option(-i)" \
	]

    pack $w(ititle) \
	-side top -fill x \
	-padx 2m -pady 2m
}


pack  $w(menu) \
	-side top -fill x 	

pack  $w(view) \
	-side top -fill both \
	-expand yes

pack  $w(btns) \
	-side top -fill x


#---------------------------------------# 
#  Listbox which shows items to chose
#---------------------------------------#

set w(list) [ \
	listbox $w(view).lb \
	-relief raised -bd 1 \
	-yscrollcommand "$w(view).scroll set" \
	-height 15 \
	-selectmode browse \
	]

set w(scroll) [ \
	scrollbar $w(view).scroll \
	-command "$w(list) yview" \
	-bd 1 \
	]

bind $w(list) <Double-Button-1> { doit %W }
    

pack $w(list) \
	-side left \
	-expand yes -fill both \
	-anchor nw

pack $w(scroll) \
	-side right -fill y


#-----------------------------------#
#  generate buttons Execute , Quit
#-----------------------------------#

button $w(btns).execute \
	-text $execute($option(-l)) \
	-underline 0 \
	-bd 1 \
	-command {doit $w(list)} 

button $w(btns).quit \
	-text $quit($option(-l)) \
	-underline 0 \
	-bd 1 \
	-command ende

pack $w(btns).execute $w(btns).quit \
	-side left -expand yes \
	-padx 1m -pady 1m \
	-padx 1m -pady 1m 

bind all <Any-Key-e> {

    $w(btns).execute invoke
}

bind all <Any-Key-Return> {

    $w(btns).execute invoke
}

bind all <Any-Key-q> {

    $w(btns).quit invoke
}

bind all <Any-Key-Down> {

    set sel [ $w(list) curselection ]
    if { $sel == "" } { 
     set sel -1 
    }
    set size [ $w(list) size ]
    if { $sel < $size } {

	$w(list) selection clear $sel
	incr sel
	$w(list) selection set $sel
    }
    $w(list) yview scroll 1 u
}

bind all <Any-Key-Up> {

    set sel [ $w(list) curselection ]
    if { $sel > 0 } {

	$w(list) selection clear $sel
	$w(list) yview $sel
	incr sel -1
	$w(list) selection set $sel
    }
    $w(list) yview scroll -1 u
}

#---------------------------------------------#
#  Menubutton File , Options, Help and Menus
#---------------------------------------------#

set w(filemenu) [\
	menubutton $w(menu).file -text $file($option(-l)) -menu $w(menu).file.menu \
	]

menu $w(filemenu).menu \
	-tearoff no
$w(filemenu).menu add command \
	-label $edit($option(-l)) \
	-command {edit_buffer $w(list)}
$w(filemenu).menu add command \
	-label $execute($option(-l)) \
	-command {doit $w(list)} 
$w(filemenu).menu add command \
	-label $quit($option(-l)) \
	-command ende


set w(helpmenu) [\
	menubutton $w(menu).help -text $help($option(-l)) -menu $w(menu).help.menu \
	]

menu $w(helpmenu).menu \
	-tearoff no
$w(helpmenu).menu add command \
	-label $about($option(-l)) \
	-command about
$w(helpmenu).menu add command \
	-label $info($option(-l)) \
	-command linfo

set w(optionmenu) [\
	menubutton $w(menu).options -text $options($option(-l)) -menu $w(menu).options.menu \
	]

menu $w(optionmenu).menu \
	-tearoff no
$w(optionmenu).menu add checkbutton \
	-label $bool($option(-l)) \
        -variable bool_options


pack $w(filemenu) \
	-side left

pack $w(optionmenu) \
	-side left

pack $w(helpmenu) \
	-side right


if { $bool(geometry) } {
    
    set gx 0
    set gy 0
    set gh 0
    set gw 0
    
    if [ regexp -- {([+\-][0-9]+)([+\-][0-9]+)} $option(-g) dummy gx gy ] {
	
	wm geometry . $gx$gy
    }
    if [ regexp -- {([0-9]+)x([0-9]+)} $option(-g) dummy gw gh ] {
	
	wm geometry . [ format "%sx%s" $gw $gh ]
    }
    if [ regexp -- {([0-9]+)x([0-9]+)([+\-][0-9]+)([+\-][0-9]+)} $option(-g) dummy gw gh gx gy ] {
	
	wm geometry . [ format "%sx%s%s%s" $gw $gh $gx $gy ]
    }
}

#---------------------------------#
#          PROZEDUREN
#---------------------------------#

set items(1) {}
proc fill_list { w spezify parameter } {

    global items
    global option
    global itemlist {} 
    
    set buffer   {}
    set dummy1   {}
    set dummy2   {}
    
    switch -- "$spezify" {
	
	-  {

	    set itemlist $parameter
	    foreach i $itemlist {
		
		set items($i) $i
	    }
	}

	-p { 
	  
	    if [ file isdirectory $parameter ] {

		cd $parameter

		foreach i [lsort [glob *]] {
		    
		    if { [ file isfile $i] } {
			
			set items($i) $i
			lappend itemlist $i
		    }
		}  
		
	    } else {

		puts "$parameter no directory"
		exit 1
	    }
	}
	
	-f {
            if [ file isfile $parameter ] {

		set handle [ open "$parameter" "r" ]

		if { $handle == -1 } { 

		    puts "Error while trying to open File $FILE"
		    exit 1
		}

	    } else { puts "$parameter no such File"

		exit 1
	    }

	    #-- is there a command string
	    gets $handle buffer
	    
	    regexp -- {(^\#\$)(.*)} $buffer dummy1 dummy2 buffer
	    regexp -- {(.*)\#(.*)} $buffer dummy1 buffer dummy2
	    
	    if { $dummy2 == "#$" } { 
		set option(-e) $buffer 
	    } else {
		seek $handle 0
	    }
	    while { [ gets $handle buffer ] != -1  } {
		
		#-- is there a comment
		regexp -- {(.*)\#(.*)} $buffer dummy1 buffer dummy2
		
		#-- is there any whitespace
		set buffer [ string trim $buffer ]

		#-- is there an empty string
		if { $buffer == {} } {
		    continue
		}
		
		set dummy2 $buffer
		regexp -- {(.*)[ \t]*\,[ \t]*(.*)} $buffer \
			dummy1 dummy2 buffer
		
                lappend itemlist $buffer
		set items($buffer) $dummy2
		
	    }
	    close $handle
	}
	
	default {
	} 
    }

    foreach i [ lsort $itemlist ] {

	$w insert end $i
    }

    $w selection set 0
}


proc doit { w } {

    global bool_options 
    global fileop
    global items
    global option

    . configure -cursor "watch"
    update

    set dummy ""
    set str_left ""
    set str_right ""

    set index [ $w curselection ]    
    if { $index != {} } {
	
	set wahl [ $w get $index ]

	if { $option(-e) == "" } {

	    if { ! [ file executable "$wahl" ] } {
		
		. configure -cursor ""

		tk_dialog .critical \
			$option(-t) \
			"File $wahl not executable" error 0 "Abort"
		
		return -1
	    }
	}

	
	
	regexp -- {(.*)[ \t]*\[ \t]*(.*)} $option(-e) \
			dummy str_left str_right

	if { $dummy == $str_left } { 

	    set err [ catch {eval exec $option(-e) $items($wahl) & } ]
			    
	} else {
	    catch { eval exec $str_left $items($wahl) $str_right & }
	}

        if { $bool_options } {
	    ende
	}
    }
    
    . configure -cursor ""
    update
}


proc showtext { texte } {

    if { ! [ winfo exists .about ] } {

	toplevel     .about		
	wm withdraw  .about
	wm title     .about "listexec"

	message .about.msg \
		-text $texte \
                -width 300  

	button .about.btn \
		-text "OK" \
		-command { grab release .about; destroy .about}

	pack .about.msg .about.btn \
		-side top \
		-fill x
    }

    wm deiconify .about
    tkwait visibility .about    
    grab set .about
    focus .about.btn
}

#proc entry_field { constant } {
#
#    global  textstring ""
#    global  prozedur
#    toplevel    .input
#    wm withdraw .input
#    wm title    .input ""
#
#    label .input.label \
#	    -text $constant
#
#    entry .input.entry \
#	    -width 30 \
#	    -relief sunken \
#	    -bd 2 \
#	    -textvariable textstring
#
#    pack  .input.label .input.entry \
#	    -side left \
#	    -padx 1m \
#	    -pady 2m 
#
#        
#    wm deiconify .input
#    tkwait visibility .input    
#    grab set .input
#    focus .input.entry
# 
#    bind .input.entry <Any-Key-Return> {
#	$prozedur 	
#	destroy .input
#	    
#    }
# 
#}

 
proc edit_buffer { w } {
    global itemlist
    global option
    global homevz
    global bool
    
	set index [ $w curselection ]
	if { $index == {} } {
		return
	}
	set wahl [ $w get $index ]
	set wahl "$option(-p)/$wahl"
    set editor $option(-E)
    set tmpdat ""

    if { $bool(editor) == 1 } {
	
	if { $option(-E) == "" } {
	    set editor "/usr/bin/emacs"
	} else {
	    catch {eval { exec which $option(-E) }} editor
	    	    
	}
    } else {
	catch {eval { exec which $option(-E) }} editor
    }
    

    if { ! [ file executable "$editor" ] } {
	tk_dialog .critical \
		$editor \
		"File $editor not a valid Editor: not executable" \
		error 0 "Abort"	
	return -1
    } 

	set notXlib [ catch { exec ldd $editor | grep -q libX11 } ]
	if { $notXlib } {
		catch { eval { exec xterm -e $editor $wahl & }}
	} else {
		catch { eval { exec $editor $wahl & }}
	}

}


proc about {} {

    global option

    set text(1) "dummy" 
    append text(german) "Hi, so wird listexec bedient:\n"
    append text(german) "\n"
    append text(german) "mit der Maus ein Element der Liste\n"
    append text(german) "waehlen : \n\n"
    append text(german) "--> mit Doppelklick ausfhren \n"
    append text(german) "\n"
    append text(german) "--> oder den Ausfhren button \n" 
    append text(german) "       anklicken.\n"
    
    append text(english) "Hi, how to use listexec:\n"
    append text(english) "\n"
    append text(english) "select an element of the list \n"
    append text(english) "by using the mouse: \n\n"
    append text(english) "--> execute with a double-klick \n"
    append text(english) "\n"
    append text(english) "--> or klick on the Execute \n" 
    append text(english) "       button \n"
        
    showtext $text($option(-l))
}

proc ende {} {

global homevz
set tmpdat ""
set tmpdat [ join " $homevz listexec.tmp" / ]
if { [ file isfile "$tmpdat" ] } {

    if { [ file exists "$tmpdat" ] } {
	catch { eval { exec rm $tmpdat }}
    }
}
exit 0
}

proc linfo {} {

    global option

    set infotext(german)  ""
    set infotext(english) ""
    append infotext(german) "Listexec ist (c) 1997 S.u.S.E GmbH,Frth,Gr\n"
    append infotext(german) "Entwickelt von Marcus Schfer  <ms@suse.de>\n"
    
    append infotext(english) "Listexec is (c) 1997 S.u.S.E GmbH,Frth,Gr\n"
    append infotext(english) "it was written by Marcus Schfer <ms@suse.de>\n"
      
    showtext $infotext($option(-l))
}

#--if no option spezified

if { ($bool(filelist) || $bool(directory)) == 0 } {

    set buffer [ read stdin 10000 ]

    set option(-) "$buffer"
    set fileop "-"
}

#--do not use option p and f together
if { $bool(filelist) && $bool(directory) } {

    puts "Do not use option f and p"
    exit 1
}


#--fill listbar with option -f or -p

fill_list $w(list) "$fileop" $option($fileop)
   
#-----ENDE-----------------








