#!/usr/bin/wish -f

frame .left -relief flat

frame .right -relief flat

frame .upperleft -relief flat
frame .upperright -relief flat

frame .mbar -relief raised -bd 2

menubutton .mbar.file -text File -underline 0 -menu .mbar.file.menu
menubutton .mbar.edit -text Edit -underline 0 -menu .mbar.edit.menu
menubutton .mbar.help -text Help -underline 0 -menu .mbar.help.menu

pack .mbar.file .mbar.edit -side left
pack .mbar.help -side right

menu .mbar.file.menu
menu .mbar.edit.menu
menu .mbar.help.menu

.mbar.help.menu add command -label "Help..." -command { dohelp }
.mbar.help.menu add separator 
.mbar.help.menu add command -label "About xnewscan ..." -command { about }

.mbar.file.menu add command -label "New Query" -command { newQuery } 
.mbar.file.menu add checkbutton -label "Audio" -variable audio_state
.mbar.file.menu add separator
.mbar.file.menu add command -label "Quit" -command exit

.mbar.edit.menu add command -label "Edit Query" -command { editQuery $query }

label .query -text "Query File: "
label .qfile -textvariable query -relief sunken

pack .query .qfile -in .upperright -side left -fill x

button .new -text "New Query" -command { 
newQuery
}

button .edit -text "Edit Query" -command { 
editQuery $query
}

button .do -text "Do Query" -command {
#    puts "Doing Query ..."

if { $audio_state } {
    set scan_proc [ open "|$scanner -a -s -X RUN -c $query" r+ ]
} else {
    set scan_proc [ open "|$scanner -s -X RUN -c $query" r+ ]
}
    qrun;  # create in progress dialog box

# echo the results from process to stdout for now

#    flush $scan_proc; # don't know if this is needed

#    while { [eof $scan_proc] != 1 } {
#	set result [ read $scan_proc ]
#	puts -nonewline $result
#	flush stdout; # make sure written to standard out
#    }
    catch { close $scan_proc }; # get rid of child process
}
button .view -text "View Result" -command {
    if { [file exists $mbox] } {
	exec xterm -e $reader $ropt $mbox
    } else { filewarn $mbox }
}
button .vstat -text "View Statistics" -command {
	editfile $statfile
}
button .quit -text "Quit" -command { exit }

pack .upperright .new .edit .do .view .vstat .quit -in .right -side top \
-expand 1 -fill both


label .label1 -text "Filter: "
entry .filter -relief sunken -textvariable filter
listbox .files -relief sunken -yscrollcommand ".fscroll set"

scrollbar .fscroll -command ".files yview"


pack .mbar -side top -fill x
pack .left -side left
pack .right -side right -fill y

pack .upperleft -anchor n -in .left

frame .upperleft.top 
label .upperleft.top.cwd -text "Current Directory: " -anchor w
label .upperleft.top.curdir -textvariable curdir -anchor w

pack .upperleft.top -side top -fill x
pack .upperleft.top.cwd -in .upperleft.top -side left -anchor w
pack .upperleft.top.curdir -in .upperleft.top -side left -anchor w


pack .label1 -in .upperleft -side left 
pack .filter -in .upperleft -side left -expand 1

pack .files -in .left -side left -anchor sw -expand 1 -fill y  
pack .fscroll -in .left -side left -expand 1 -fill y


bind .files <Double-Button-1> {
#
    # switch to watch cursor while processing so user knows somethiing
    # is happening
#
global curdir
. config -cursor watch 
update 
set query [selection get]
update;  # need this to update the label displaying selected query file
set test [string compare $query ".."]
set dirtest [file isdirectory $query]
if { $test == 0 } {
    cd .. ; catch { listfiles $filter } ; update ;
    set query ""
} elseif { $dirtest == 1 } {
    cd $query ; catch { listfiles $filter } ; update ;
    set query ""
} else {
    checkquery $query
    if {$qvalid == 0} { qwarn $query }
    update
}
. config -cursor top_left_arrow
update

set curdir [pwd]

} 

bind .filter <Return> { catch { listfiles $filter } }
#bind .filter <Tab> { focus .files }

# support procedures - screw these up and it breaks


proc newquery {} {
    global query;  # name for query file
    global queryroot; # name of query
    global filter qvalid;
    set query "$queryroot.cfg"
    if { ![file exists $query] } {
	set fp [open $query a+]
	puts $fp "MBOX $queryroot.art"
	puts $fp "SELECT <list of USENET newsgroups -- space delimited>"
	puts $fp "COLLECT STATISTICS IN $queryroot.stat"
	close $fp
	editfile $query
	catch { listfiles $filter }
	checkquery $query
	if { $qvalid == 0 } { qwarn $query }
    }
}

proc listfiles {filter} {
.files delete 0 end
.files insert end "..";  # add way to climb the directory tree
foreach i [lsort [glob $filter] ] { .files insert end $i }
}

proc editfile {filename} {
    global editor
    #
    # only edit files that exist.  Must explicitly create files otherwise! 
    #
    if { [file exists $filename] } {
	set isemacs [string compare $editor "emacs"]
	set isvi [string compare $editor "vi"]
	if { $isemacs == 0 } { exec $editor $filename 
	} elseif { $isvi == 0 } { exec xterm -e vi $filename 
	} else { }
    } else { filewarn $filename }
}

proc filewarn { filename } {
    toplevel .filewarn
    message .filewarn.msg -width 8c -justify left \
-text "Warning: File $filename does not exist!"
    pack .filewarn.msg -side top -fill both
    button .filewarn.ok -text "OK" -command { destroy .filewarn }
    pack .filewarn.ok -side bottom -fill both
}

proc about {} {
    set version {$Revision: 1.24 $}
    toplevel .message
    message .message.msg -width 8c -justify left \
    -text "xnewscan  $version \n\nxnewscan is an X Window \
Graphical User Interface for \
newscan, a network news scanner.\n\n  \
(C) 1994,1995 by John F. McGowan, Ph.D."
    button .message.ok -text "OK" -relief raised \
-command { destroy .message }
    pack .message.msg .message.ok -side top -fill both
}


proc dohelp {} {
    toplevel .helpbox
    frame .helpbox.upper
    text .helpbox.text -relief sunken -bd 2 \
-yscrollcommand ".helpbox.scroll set" 
    scrollbar .helpbox.scroll -command ".helpbox.text yview"
    pack .helpbox.upper -side top


    .helpbox.text insert end "xnewscan On Line Help\n\nxnewscan \
is an X Window\
 System Graphical User Interface for newscan, \
a Network News scanning program.\
  xnewscan was written using the Tcl scripting language and \
the associated Tk\
 toolkit.  Tcl/Tk is a high-level tool for rapid creation of X GUI \
applications.\n\nxnewscan selects queries by double \
clicking on the list of \
query files in the list box on the left side of the application.  xnewscan \
parses the selected query to extract the names \
of the associated results and \
statistics files.  In this way, the user need not know or \
recall the names of \
these files.\n\nxnewscan can create new queries using the New Query \
Button.\n\nxnewscan can edit query by clicking on the Edit Query Button.  \
xnewscan invokes a Unix editor such as vi or emacs to edit the query \
file.\n\nxnewscan runs a query by clicking on the Do Query button.  \
xnewscan will pop up an in-progress dialog box to report the state of the \
search.\n\nxnewscan can view results of a search by \
clicking on View Results \
Button.  xnewscan uses a Unix mail reader such as elm to read the results \
which are in the Unix mailbox format.\n\nxnewscan can \
view the statistics of \
the search by clicking on View Statistics Button.  xnewscan uses a Unix \
editor such as emacs or vi to view the statistics file which is a human \
readable text file."

    button .helpbox.ok -text "OK" -relief raised \
-command { destroy .helpbox }
    pack .helpbox.ok -side bottom -fill both

    pack .helpbox.scroll -side right -fill y -in .helpbox.upper
    pack .helpbox.text -side left -in .helpbox.upper

    .helpbox.text configure -state disabled
}

proc checkquery { query } {
    global mbox statfile qvalid scanner
    set result [exec $scanner -c $query -X "QUERY"]
    set results [split $result \n]

    foreach line $results {
	set code [lindex $line 0]
	set data [lindex $line 1]
	switch $code {
	    100 { if { $data == "TRUE" } { set qvalid 1 } \
else { set qvalid 0 } }
	    101 { set mbox $data }
	    102 { set statfile $data }
	}
    }
}

proc qwarn { query } {
    toplevel .qwarning 
    message .qwarning.msg -width 8c -justify left \
-text "Warning: Query $query is invalid (syntax error)."
    pack .qwarning.msg -side top -fill both
    button .qwarning.ok -text "OK" -command { destroy .qwarning }
    pack .qwarning.ok -side bottom -fill both
}

proc qrun {} {
    global scan_proc; # want to access pipe to newscan process
    toplevel .qrun
    canvas .qrun.canvas -width 13c -height 10c
    frame .qrun.action
    button .qrun.action.ok -text "OK" -command { destroy .qrun }
    button .qrun.action.cancel -text "CANCEL" \
-command { catch { close $scan_proc } ; destroy .qrun }
    button .qrun.action.help -text "HELP" -command { dohelp }
    pack .qrun.canvas .qrun.action -side top -fill both -expand 1
    pack .qrun.action.ok .qrun.action.cancel .qrun.action.help -side left \
-fill both -expand 1

# create the gauge indicating percent done
# c centimeters
# m millimeters
# i inches
# p printer's points
#
    set ruler [ .qrun.canvas create rectangle 1c 2c 1c 3c -width 1m \
-outline blue -fill green ]

    set border [ .qrun.canvas create rectangle 0.9c 1.9c 11.1c 3.1c \
-width 1m -outline red ]

    set pct [ .qrun.canvas create text 1c 3.2c -text "0.00%" -anchor nw ]

    set group [ .qrun.canvas create text 0.9c 4.5c -text "News Group" \
-anchor nw ]

 set group_scanned [ .qrun.canvas create text 0.9c 6.0c -text "0 Scanned" \
-anchor sw ]

 set sum [ .qrun.canvas create text 12.5c 6.0c -text "0 Found" -anchor se ]

    set total_txt [ .qrun.canvas create text 0.9c 7.5c \
-text "Results of Scanning All News Groups So Far" -anchor sw ]

    set total_scanned [ .qrun.canvas create text 0.9c 8.5c \
-text "0 Scanned" -anchor sw ]

    set total_found_lbl [ .qrun.canvas create text 12.5c 8.5c \
-text "0 Found" -anchor se ]
#
# spawn the newscan process here.  Use pipe to communicate 
# between Perl script and xnewscan
#

# defaults to anchor center
    set textout [ .qrun.canvas create text 1c 0.5c -anchor nw -text "" ]
    set title [ .qrun.canvas create text 6c 1.5c -text "Percent Complete" ] 


# gets blocks until there is data in the FIFO (pipe)
    set the_group ""; # name of newsgroup being scanned
    set group_txt "News Group";
    set the_pct 0; # percent of group scanned
    set pct_txt "0.00%"; # percent of group scanned
    set the_num 0;  # number of articles found in group
    set total_group 0; # number of articles searched in group
    set total_found 0; # total number of articles found all groups
    set total_searched 0; # total number of articles searched all groups

#    puts "Just before loop ... ";

    set result ""

     while { [gets $scan_proc result] >= 0 } {
#        puts "Just inside loop ...";
#        set byte [read $scan_proc 1]
#        while { $byte != "\n" } {
#	    append result $byte;
#	}
#        append result $byte; # add newline
#        puts $result;
	set output [split $result]; # output is list generated by \
splitting result string
	set newscan_code [lindex $output 0]
	if { $newscan_code == "105" } {
	    set the_group [lindex $output 1];
	    set the_pct [lindex $output 2];
	    set pct_txt [lindex $output 2];
	    append pct_txt "%";
	    set the_num [lindex $output 3];
            set total_group [lindex $output 4];
            set total_found [lindex $output 5];
            set total_searched [lindex $output 6];
	}
        set num_found $the_num;
	append num_found " Found";
	set max [expr $the_pct * 0.1]; # get size in cm (10 cm is 100 percent)
	set max [expr $max + 1.0]; # zero is located at 1 cm in x coordinates
	append max "c"; # append c to indicate size in centimeters
# update the display
	.qrun.canvas itemconfigure $textout -text $result
	.qrun.canvas coords $ruler 1c 2c $max 3c
	.qrun.canvas coords $pct $max 3.2c 
	.qrun.canvas itemconfigure $pct -text $pct_txt
	.qrun.canvas itemconfigure $sum -text $num_found
# show user name of news group being scanned
        set group_txt "Scanning News Group ";
        append group_txt $the_group;
	.qrun.canvas itemconfigure $group -text $group_txt
	set scan_txt $total_group;  # total number of articles scanned in group
        append scan_txt " Scanned";
        .qrun.canvas itemconfigure $group_scanned -text $scan_txt
	
	set total_scan_txt $total_searched;
	append total_scan_txt " Scanned";
	.qrun.canvas itemconfigure $total_scanned -text $total_scan_txt

	set total_found_txt $total_found;
	append total_found_txt " Found";
	.qrun.canvas itemconfigure $total_found_lbl -text $total_found_txt



	update; # force update, otherwise won't see anything

	set sleep_result [ exec sleep 1]; # don't put sleep 1 in quotes
#
#	puts $result
#	flush stdout;  # make sure send output to standard out
#
	if { $newscan_code == "205" } {
	    break; # exits enclosing loop
	}
    }
    catch { close $scan_proc }; # close the pipe
    destroy .qrun; # get rid of the popup box when finished
}

proc newQuery {} {
#    set procid [pid]
#    set query "$procid.cfg"

    toplevel .getquery
    frame .getquery.upper
    pack .getquery.upper -side top
    frame .getquery.lower
    pack .getquery.lower -side top -fill x
    label .getquery.upper.label1 -text "Enter Name of Query: "
    pack .getquery.upper.label1 -side left
    entry .getquery.upper.query -textvariable queryroot -relief sunken
    pack .getquery.upper.query -side left -fill x 
    button .getquery.lower.ok -text "OK" -command { 
	newquery
	destroy .getquery 
    }
    pack .getquery.lower.ok -side bottom -anchor s -fill both
    bind .getquery.upper.query <Return> { newquery 
    destroy .getquery
}

}

proc editQuery { query } {
    global qvalid
    editfile $query 
    checkquery $query
    if { $qvalid == 0 } { qwarn $query }
}

# initialization code

set filter "*.cfg";   # default filter for newscan query files

set bool [ catch { set editor $env(EDITOR) } ]
if { $bool == 1 } { # EDITOR environment variable is not defined
   set editor "emacs";  # default to emacs 
}
set scanner "newscan";  # default name for newscan script

# use mail reader specified in environment variable if exists
set bool [ catch {set reader $env(READER)} ]
if { $bool == 1 } {
set reader "elm"; # mail reader for reading results
}

set ropt "-f"; # mail reader option
set mbox ""
set statfile ""
set queryroot ""
set curdir [pwd]

set audio_state 1

catch { listfiles $filter }



