proc tkeditpr_usage {{str ""}} {
    bell
    wm withdraw .
    tk_dialog .tkgnatsError "TkGnats Error" \
            "${str}usage: tkeditpr -prid nnnn -server 'ServerInfo' \[-categories 'list'\] \
            \[-classes 'list'\] \[-states 'list'\] \
            \[-submitters 'list'\] \[-responsible 'list'\]" "error" 0 "OK"
    exit
}

proc tkeditpr_process_args {} {
    global TkGnats Tkeditpr argc argv env

    set TkGnats(CurrentProgram) tkeditpr
    
    if {$argc != 0} {
        if {$argc%2 != 0} {
            tkeditpr_usage
        }
        for {set x 0} {$x<$argc} {incr x 2} {
            set opt [lindex $argv $x]
            set val [lindex $argv [expr $x+1]]
            switch -exact -- $opt -server {
                set TkGnats(ServerInfo) $val
            } -categories {
                set TkGnats(CategoryList) $val
            } -submitters {
                set TkGnats(SubmitterList) $val
            } -responsible {
                set TkGnats(ResponsibleFile) $val
            } -classes {
                set TkGnats(ClassesFile) $val
            } -states {
                set TkGnats(StatesFile)  $val
            } -prid {
                set Tkeditpr(prid) $val
            } default {
                tkeditpr_usage "Illegal option pair:\n'$opt $val'\n\n"
            }
        }
    }

    if {![info exists TkGnats(ServerInfo)]} {
        tkeditpr_usage "No -server argument given.\n\n"
    }
    
    foreach var {TKGNATSLIB TKGNATSINI} {
        if {[info exists env($var)]} {
            set TkGnats($var) $env($var)
        }
    }
    
    set TkGnats(lib) $TkGnats(TKGNATSLIB)

    if {[info exists TkGnats(TKGNATSINI)]} {
        if {[file readable $TkGnats(TKGNATSINI)]} {
            source $TkGnats(TKGNATSINI)
        } {
            bell
            wm withdraw .
            tk_dialog .tkgnatsError "TkGnats Error" \
                    "TkGnats INI file '$TkGnats(TKGNATSINI)' not readable" "error" 0 "OK"
            exit
        }
    }

    if {[file exists $TkGnats(lib)/tkgnatsini]} {
        source       $TkGnats(lib)/tkgnatsini
    }
}

proc headingMsg {a {flash 1}} {
    .action.msg configure -text $a
    update idletasks
    if {$flash} {
        foreach rep {1 2 3 4 5} {
            foreach r {raised sunken flat} {
                .action.msg configure -relief $r;
                update idletasks
                after 50
            }
        }
    }
}

proc merge_into_list {lname new_value {omit_value {}}} {
    upvar 1 $lname l
    set omit_addr [lindex [extract_email_address $omit_value] 0]
    # set omit_name [lindex [extract_email_address $omit_value] 1]
    set adds  [split $new_value ,]
    set nadds [llength $adds]
    for {set i 0} {$i < $nadds} {incr i} {
        set add      [string trim [lindex $adds $i]]
        set new_addr [lindex [extract_email_address $add] 0]
        # set new_name [lindex [extract_email_address $add] 1]
        if {"$new_addr" != "$omit_addr"} {
            if {[lsearch $l $new_addr] < 0} {
                lappend l $new_addr
            }
        }
    }
}

proc file_report {} {
    global TkGnats Tkeditpr flds
    if {[real_file_report] == -1} {
        # bell
        headingMsg "Error filing report!"
        headingMsg "" 0
        return -1
    }
    bind . <Destroy> ""
    unlock_pr $Tkeditpr(prid)
    exit
}

proc real_file_report_batch {rep} {
    global TkGnats Tkeditpr
    upvar 1 $rep errs
    
    if {[catch {set fout [eval open \"|$TkGnats(pr-edit) $TkGnats(UseridPassword)\" w]} errs]} {
        Msg "Error executing \"$TkGnats(pr-edit)\" to update PRID $Tkeditpr(prid):\n" "$errs"
        return -1
    }

    write_pr $fout

    return [catch {close $fout} errs]
}

proc real_file_report_socket {rep} {
    global TkGnats Tkeditpr
    upvar 1 $rep errs

    set errs ""
    
    if {[set s [open_socket_gnatsd]] == "-1"} {
        return -2
    }

    puts $s "EDIT $Tkeditpr(prid)"
    set rep [get_socket_reply $s]
    if {![string match 2* [lindex $rep 0]]} {
        set errs "GNATSD error sending EDIT command for PRID $Tkeditpr(prid):\n[join $rep \n]"
        return -1
    }

    write_pr   $s

    puts $s "."

    set rep [get_socket_reply $s]
    if {![string match 2* [lindex $rep 0]]} {
        set errs "GNATSD error updating PRID $Tkeditpr(prid): [join $rep \n]"
        return -1
    }

    return 0
}

proc real_file_report {} {
    global TkGnats Tkeditpr flds frm errorCode
    flush_singletext $Tkeditpr(singletextflds)
    flush_multitext

    #
    # do some local field checking..
    #
    
    headingMsg "Checking fields..." 0

    # - Check Category field...
    if {[lsearch -exact $TkGnats(CategoryList) $frm(>Category)] < 0} {
        Msg "You have specified an invalid Category!"
        return -1
    }
    # - Check Submitter field...
    if {[lsearch -exact $TkGnats(SubmitterList) $frm(>Submitter-Id)] < 0} {
        Msg "You have specified an invalid Submitter-Id!"
        return -1
    }
    # - Check Responsible field...
    if {[lsearch -exact $TkGnats(ResponsibleList) $frm(>Responsible)] < 0} {
        Msg "You have specified an invalid Responsible!"
        return -1
    }

    # - Check that indexed text fields do not have a | char. (hoses tkquerypr)
    foreach t {>Release >Synopsis} {
        if {[string first "|" [textget $t]] != -1} {
            Msg " '|' is an illegal character for the '$t' field!"
            return -1
        }
    }

    #
    # now see if any fields changed that trigger notifiers or audit records
    #
    
    set mail_list ""
    set all_changes ""
    set datestr [clock format [clock seconds]]

    set responsible_addr     [get_responsible_addr $frm(>Responsible)]
    set old_responsible_addr [get_responsible_addr $flds(>Responsible)]
 
    set t ">Responsible"
    if {$frm($t) != $flds($t)} {

        # Mail to the old and new responsible persons
        merge_into_list mail_list $old_responsible_addr $TkGnats(EmailAddr)
        merge_into_list mail_list $responsible_addr $TkGnats(EmailAddr)

        set change_msg   "\nResponsible-Changed-From-To: $flds($t)->$frm($t)\n"
        append change_msg  "Responsible-Changed-By:      $TkGnats(FullName) <[lindex [extract_email_address $TkGnats(EmailAddr)] 0]>\n"
        append change_msg  "Responsible-Changed-When:    $datestr\n"
        set whyText ""
        catch {
            set whyText [entryDialog "Enter reason for RESPONSIBLE change" no_cancel]
        }
        append change_msg  "Responsible-Changed-Why:     $whyText\n"

        append all_changes $change_msg 
    }
 
    set t ">State"
    if {$frm($t) != $flds($t)} {

        # Mail to the responsible person
        merge_into_list mail_list $responsible_addr $TkGnats(EmailAddr)

        set change_msg    "\nState-Changed-From-To: $flds($t)->$frm($t)\n"
        append change_msg   "State-Changed-By:      $TkGnats(FullName) <[lindex [extract_email_address $TkGnats(EmailAddr)] 0]>\n"
        append change_msg   "State-Changed-When:    $datestr\n"
        set whyText ""
        catch {
            set whyText [entryDialog "Enter reason for STATE change" no_cancel]
        }
        append change_msg   "State-Changed-Why:     $whyText\n"

        append all_changes $change_msg 
    }
 
    set t ">Priority"
    if {$frm($t) != $flds($t)} {

        # Mail to the responsible person
        merge_into_list mail_list $responsible_addr $TkGnats(EmailAddr)

        set change_msg    "\nPriority-Changed-From-To: $flds($t)->$frm($t)\n"
        append change_msg   "Priority-Changed-By:      $TkGnats(FullName) <[lindex [extract_email_address $TkGnats(EmailAddr)] 0]>\n"
        append change_msg   "Priority-Changed-When:    $datestr\n"
        set whyText ""
        catch {
            set whyText [entryDialog "Enter reason for PRIORITY change" no_cancel]
        }
        append change_msg   "Priority-Changed-Why:     $whyText\n"

        append all_changes $change_msg 
    }
 
    set t ">Severity"
    if {$frm($t) != $flds($t)} {

        # Mail to the responsible person
        merge_into_list mail_list $responsible_addr $TkGnats(EmailAddr)

        set change_msg    "\nSeverity-Changed-From-To: $flds($t)->$frm($t)\n"
        append change_msg   "Severity-Changed-By:      $TkGnats(FullName) <[lindex [extract_email_address $TkGnats(EmailAddr)] 0]>\n"
        append change_msg   "Severity-Changed-When:    $datestr\n"
        set whyText ""
        catch {
            set whyText [entryDialog "Enter reason for SEVERITY change" no_cancel]
        }
        append change_msg   "Severity-Changed-Why:     $whyText\n"

        append all_changes $change_msg 
    }

    #
    # did any notifiable changes take place ??
    #
    if {"$all_changes" != ""} {

        # Send to the original sender and the Reply-To list
        merge_into_list mail_list $flds(From)    $TkGnats(EmailAddr)
        merge_into_list mail_list $frm(Reply-To) $TkGnats(EmailAddr)
        ##puts "maillist=$mail_list"
        
        if {"$mail_list" != ""} {
            headingMsg "Sending mail..." 0
            set addrs [join $mail_list ", "]
            ##puts "maillist=$addrs"
            set mailtxt ""
            append mailtxt "From: $TkGnats(EmailAddr)\n"
            append mailtxt "Reply-To: $TkGnats(EmailAddr)\n"
            append mailtxt "To: $addrs\n"
            append mailtxt "Subject: Re: $frm(>Category)/$Tkeditpr(prid): Changed information\n\n"
            append mailtxt "Synopsis: $frm(>Synopsis)\n\n"
            append mailtxt "Priority: $frm(>Priority)\n"
            append mailtxt "Severity: $frm(>Severity)\n"
            append mailtxt \n$all_changes

            if {[TkGnats_sendmail $addrs $mailtxt] == "-1"} {
                Msg "Error sending mail notification.\n\nPR changes will still be saved."
            }
        }
        append frm(>Audit-Trail) "\n$all_changes"
    }
    headingMsg "Filing report..." 0

    set stat [real_file_report_$TkGnats(GNATS_ACCESS_METHOD) errs]
    #puts "stat=$stat errs=$errs"    
    if {$stat} {
        # If the failure is opening gnatsd socket, stat= -2
        if {$stat != -2} {
            if {[string first "currently locked" $errs] >= 0} {
                # GNATS is locked! Try again later.
            } elseif {[string first "lock file exists" $errs] >= 0} {
                set errs "GNATS is presently locked.\nPlease try again in a moment."
            }
            Msg "Error filing $frm(>Category)/$Tkeditpr(prid):\n" "$errs"
        }
        return -1
    } {
        headingMsg "Done" 0
    }
    return 0
}

proc TTDescape_dots_gnatsd {txt} {
    set txttmp [split $txt \n]
    set len    [llength $txttmp]
    for {set l 0} {$l < $len} {incr l} {
        set line [lindex $txttmp $l]
        # TTD: This is what RFC821 uses for SMTP, but we can't use this since gnatsd
        # doesn't remove the extra dot and you'd get another dot every time the PR is edited.
        # When gnatsd is fixed this proc goes away and we just need escape_dots.
        #if {[string match .* $line]}
        if {$line == "."} {
            #puts "escaping this line: $line"
            set txttmp [lreplace $txttmp $l $l .$line]
        }
    }
    set newlen [llength $txttmp]
    if {$len != $newlen} {
        Msg "Internal programming error escaping .'s in message body.\n" \
                "Lines in=$len; lines out=$newlen"
        return $txt
    }
    return [join $txttmp \n]
}

proc write_multitextfld {fout flds tag} {
    global TkGnats
    upvar 1 $flds f
    set txt [string trimleft "$tag: \n[string trim $f($tag) "\n"]" "\n"]
    if {$TkGnats(GNATS_ACCESS_METHOD) == "batch"} {
        puts $fout $txt
    } {
        # TTD change this to escape_dots if gnatsd is ever fixed
        # (it doesn't remove the extra dot at its end)
        puts $fout [escape_dots $txt]
    }
}

proc write_pr {fout} {
    global Tkeditpr flds frm

    foreach tag [array names frm] {
        set still_left($tag) $tag
    }

    #
    # for each parsed field from the PR form...
    #
    foreach tag $Tkeditpr(parsed_flds) {
        case $tag {_prefix_} {
            #
            #   The mail header, stored under the _prefix_ tag, is written out
            #   unadulterated, except for the edited Reply-To field.
            #
            set lines [split $flds($tag) \n]
            set repin [lsearch -regexp $lines "^Reply-To: "]
            set repto "Reply-To: $frm(Reply-To)"
            set newlines [lreplace $lines $repin $repin $repto]
            set frm($tag) [join $newlines \n]
            puts $fout $frm($tag) nonewline
        } {Reply-To} {
            #
            # Taken care of above with the mail header
            #
            unset still_left($tag)
        } {>Unformatted} {
            #
            # Taken care of later in the function...
            #
            unset still_left($tag)
        } {>*} {
            # When writing out the fields
            #   first check for data present in the form (the frm bag)
            #   If not present use data read from the PR file (the flds bag)
            #
            if {[info exists frm($tag)]} {
                set data $frm($tag)
                unset still_left($tag)
            } {
                set data $flds($tag)
            }

            #
            # Write out fields
            #
            #   Multi line fields are newline trimmed to a single leading
            #   and trailing newline
            #
            #   Single line text fields are whitespace trimmed to a leading
            #   tab and a trailing newline
            #
            case $tag $Tkeditpr(singletextflds) {
                if {$tag != "Reply-To"} {
                    puts $fout "$tag:\t[string trim [textget $tag] "\t\n "]"
                }
            } [concat >Category >Responsible >Submitter-Id $Tkeditpr(radioflds)] {
                puts $fout "$tag:\t$frm($tag)"
            } $Tkeditpr(multitextflds) {
                write_multitextfld $fout frm $tag
            } default {
                puts $fout "$tag:$data" nonewline
            }
        }
    }

    #
    # now write any fields in the form that were not in the parsed report
    #
    foreach tag [array names still_left] {
        write_multitextfld $fout frm $tag
    }

    #
    # Finally, write the >Unformatted field
    #   (BUG: >Unformatted should not really be stripped)
    #
    write_multitextfld $fout frm ">Unformatted"
}

proc cancel_report {} {
    global Tkeditpr
    bind . <Destroy> ""
    unlock_pr $Tkeditpr(prid)
    exit
}

proc get_tkeditpr_listbox_height {} {
    global TkGnats Tkeditpr
    set ch [llength $TkGnats(CategoryList)]
    set sh [llength $TkGnats(SubmitterList)]
    set rh [llength $TkGnats(ResponsibleList)]
    set h $ch
    if {$h  < $sh } {
        set h $sh
    }
    if {$h  < $rh } {
        set h $rh
    }
    if {$h > 6 } {
        set h 6
    }
    set Tkeditpr(listbox_height) $h
}
    
proc edit_category_listbox {p {pat *} {valwid 0}} {
    global TkGnats Tkeditpr flds frm
    if {$valwid == 0} {
        set valwid [string length [ftrim $flds(>Category)]]
    }

    set wid [expr 2 + [get_max_strlen $TkGnats(CategoryList)]]
    set Tkeditpr(listbox_width) $wid
    
    frame  $p.cat -relief flat
    pack   $p.cat -side top -anchor w
    button $p.cat.lab -text "Category: " -width 14 -anchor w -command "helpMsg Category" \
            -relief flat -padx 0 -pady 0 -borderwidth 0 -highlightthickness 1
    frame  $p.cat.msg -relief flat
    label  $p.cat.msg.val -text "[ftrim $flds(>Category)]" -relief groove -anchor w \
            -width $wid -background $TkGnats(ReadOnlyBackground)
    set ew [entry $p.cat.msg.ent -width $wid -insertwidth 1 -insertofftime 400 \
            -relief sunken -borderwidth 2 -background $TkGnats(EditFieldBackground) -highlightthickness 2 \
            -textvariable frm(>Category)]
    lappend Tkeditpr(tlist) $ew
    set_focus_style $ew
    bind $ew <BackSpace> { tkEntrySetCursor %W [%W index insert] }
    bind $ew <Control-h> { tkEntrySetCursor %W [%W index insert] }
    scrollbar $p.cat.msg.sb -command "$p.cat.msg.list yview" -borderwidth 2 -relief sunken
    listbox $p.cat.msg.list -yscroll "$p.cat.msg.sb set" -setgrid 1 -relief sunken -borderwidth 2 \
            -width $wid -height $Tkeditpr(listbox_height) -exportselection false
    pack $p.cat.msg.val  -side top   -fill both -expand true -anchor center
    pack $p.cat.msg.ent  -side top   -fill both -expand true -anchor w
    pack $p.cat.msg.list -side left  -fill both -expand true
    pack $p.cat.msg.sb   -side right -fill y
    eval $p.cat.msg.list insert end $TkGnats(CategoryList)
    trace variable frm(>Category) w set_edit_category_ew
    pack $p.cat.lab $p.cat.msg -side left -anchor n
    bind   $p.cat.msg.list <B1-ButtonRelease> "set_edit_category $p.cat.msg %W %y"
    return $p.cat.msg.list
}

proc edit_responsible_listbox {p {pat *} {valwid 0}} {
    global TkGnats Tkeditpr flds frm
    if {$valwid == 0} {
        set valwid [string length [ftrim $flds(>Responsible)]]
    }

    set wid [expr 2 + [get_max_strlen $TkGnats(ResponsibleList)]]
    frame  $p.res -relief flat
    pack   $p.res -side top -anchor w
    button $p.res.lab -text "Responsible: " -width 14 -anchor w -command "helpMsg Responsible" \
            -relief flat -padx 0 -pady 0 -borderwidth 0 -highlightthickness 1
    frame  $p.res.msg -relief flat
    label  $p.res.msg.val -text "[ftrim $flds(>Responsible)]" -relief groove -anchor w \
            -width $wid -background $TkGnats(ReadOnlyBackground)
    set ew [entry $p.res.msg.ent -width $wid -insertwidth 1 -insertofftime 400 \
            -relief sunken -borderwidth 2 -background $TkGnats(EditFieldBackground) -highlightthickness 2 \
            -textvariable frm(>Responsible)]
    lappend Tkeditpr(tlist) $ew
    set_focus_style $ew
    bind $ew <BackSpace> { tkEntrySetCursor %W [%W index insert] }
    bind $ew <Control-h> { tkEntrySetCursor %W [%W index insert] }
    scrollbar $p.res.msg.sb -command "$p.res.msg.list yview" -borderwidth 2 -relief sunken
    set height [llength $TkGnats(ResponsibleList)]
    if {$height > 6 } {
        set height 6
    }
    listbox $p.res.msg.list -yscroll "$p.res.msg.sb set" -setgrid 1 -relief sunken \
            -borderwidth 2 -width $wid -height $Tkeditpr(listbox_height) -exportselection false
    pack $p.res.msg.val  -side top   -fill both -expand true -anchor center
    pack $p.res.msg.ent  -side top   -fill both -expand true -anchor w
    pack $p.res.msg.list -side left  -fill both -expand true
    pack $p.res.msg.sb   -side right -fill y
    eval $p.res.msg.list insert end $TkGnats(ResponsibleList)
    trace variable frm(>Responsible) w set_edit_responsible_ew
    pack $p.res.lab $p.res.msg -side left -anchor n
    bind   $p.res.msg.list <B1-ButtonRelease> "set_edit_responsible $p.res.msg %W %y"
    return $p.res.msg.list
}

proc edit_submitter_listbox {p {pat *} {valwid 0}} {
    global TkGnats Tkeditpr flds frm
    if {$valwid == 0} {
        set valwid [string length [ftrim $flds(>Submitter-Id)]]
    }
    set wid [expr 2 + [get_max_strlen $TkGnats(SubmitterList)]]
    frame  $p.sub -relief flat
    pack   $p.sub -side top -anchor w
    button $p.sub.lab -text "Submitter-Id: " -width 14 -anchor w -command "helpMsg Submitter-Id" \
            -relief flat -padx 0 -pady 0 -borderwidth 0 -highlightthickness 1
    frame  $p.sub.msg -relief flat
    label  $p.sub.msg.val -text "[ftrim $flds(>Submitter-Id)]" -relief groove -anchor w \
            -width $wid -background $TkGnats(ReadOnlyBackground)
    set ew [entry $p.sub.msg.ent -width $wid -insertwidth 1 -insertofftime 400 \
            -relief sunken -borderwidth 2 -background $TkGnats(EditFieldBackground) \
            -highlightthickness 2 -textvariable frm(>Submitter-Id)]
    lappend Tkeditpr(tlist) $ew
    set_focus_style $ew
    bind $ew <BackSpace> { tkEntrySetCursor %W [%W index insert] }
    bind $ew <Control-h> { tkEntrySetCursor %W [%W index insert] }
    scrollbar $p.sub.msg.sb -command "$p.sub.msg.list yview" -borderwidth 2 -relief sunken
    set height [llength $TkGnats(SubmitterList)]
    if {$height > 6 } {
        set height 6
    }
    listbox $p.sub.msg.list -yscroll "$p.sub.msg.sb set" -setgrid 1 -relief sunken \
            -borderwidth 2 -width $wid -height $Tkeditpr(listbox_height) -exportselection false
    pack $p.sub.msg.val  -side top   -fill both -expand true -anchor center
    pack $p.sub.msg.ent  -side top   -fill both -expand true -anchor w
    pack $p.sub.msg.list -side left  -fill both -expand true
    pack $p.sub.msg.sb   -side right -fill y
    eval $p.sub.msg.list insert end $TkGnats(SubmitterList)
    trace variable frm(>Submitter-Id) w set_edit_submitter_ew
    pack $p.sub.lab $p.sub.msg -side left -anchor n
    bind   $p.sub.msg.list <B1-ButtonRelease> "set_edit_submitter $p.sub.msg %W %y"
    return $p.sub.msg.list
}

proc set_edit_category_ew {a b c} {
    upvar #0 $a f
    global TkGnats
    quickfill_entry_from_listbox f($b) .eboxs.clb.cat.msg.ent .eboxs.clb.cat.msg.list \
            $TkGnats(CategoryList)
}

proc set_edit_submitter_ew {a b c} {
    upvar #0 $a f
    global TkGnats
    quickfill_entry_from_listbox f($b) .eboxs.slb.sub.msg.ent .eboxs.slb.sub.msg.list \
            $TkGnats(SubmitterList)
}

proc set_edit_responsible_ew {a b c} {
    upvar #0 $a f
    global TkGnats
    quickfill_entry_from_listbox f($b) .eboxs.rlb.res.msg.ent .eboxs.rlb.res.msg.list \
            $TkGnats(ResponsibleList)
}

proc set_edit_category {msg w y} {
    global frm
    trace vdelete  frm(>Category) w set_edit_category_ew
    $msg.ent delete 0 end
    set idx [$w nearest $y]
    set frm(>Category) [$w get $idx]
    trace variable frm(>Category) w set_edit_category_ew
}

proc set_edit_responsible {msg w y} {
    global frm
    trace vdelete  frm(>Responsible) w set_edit_responsible_ew
    $msg.ent delete 0 end
    set idx [$w nearest $y]
    set frm(>Responsible) [$w get $idx]
    trace variable frm(>Responsible) w set_edit_responsible_ew
}

proc set_edit_submitter {msg w y} {
    global frm
    trace vdelete  frm(>Submitter-Id) w set_edit_submitter_ew
    $msg.ent delete 0 end
    set idx [$w nearest $y]
    set frm(>Submitter-Id) [$w get $idx]
    trace variable frm(>Submitter-Id) w set_edit_submitter_ew
}

proc fillfrm {} {
    global Tkeditpr flds frm

    ### re-set editable PR values to values currently in the PR

    # clear listbox entry widgets
    trace vdelete  frm(>Category)     w set_edit_category_ew
    trace vdelete  frm(>Submitter-Id) w set_edit_submitter_ew
    trace vdelete  frm(>Responsible)  w set_edit_responsible_ew
    .eboxs.clb.cat.msg.ent delete 0 end
    .eboxs.slb.sub.msg.ent delete 0 end
    .eboxs.rlb.res.msg.ent delete 0 end
    trace variable frm(>Category)     w set_edit_category_ew
    trace variable frm(>Submitter-Id) w set_edit_submitter_ew
    trace variable frm(>Responsible)  w set_edit_responsible_ew

    # listboxes and radio (enumerated) fields
    foreach tag [concat >Category >Responsible >Submitter-Id $Tkeditpr(radioflds)] {
        set  flds($tag) [string trim $flds($tag) "\t\n "]
        #unset frm($tag)
        set   frm($tag) $flds($tag)
    }

    # now the 1 line textual flds
    foreach tag $Tkeditpr(singletextflds) {
        set flds($tag) [string trim $flds($tag) "\t\n "]
        textset $tag $flds($tag)
    }

    # now the multi line textual flds
    foreach tag $Tkeditpr(multitextflds) {
        if {[info exists flds($tag)]} {
            set flds($tag) [string trim $flds($tag) "\n"]
            set frm($tag) $flds($tag)
        } {
            set frm($tag)  "\n"
            set flds($tag) "\n"
        }
    }
    switch_txt ">Description" $Tkeditpr(multitextflds)
}

proc reset_report {} {
    global Tkeditpr flds current_multi_text
    # load the current text widget with the original text
    .multiline.text delete 1.0 end
    .multiline.text insert 1.0 $flds($current_multi_text)
    # reset everything
    set current $current_multi_text
    fillfrm
    switch_txt $current $Tkeditpr(multitextflds)
}

proc edit_cleanup {} {
    global Tkeditpr
    bind . <Destroy> ""
    unlock_pr $Tkeditpr(prid)
    exit
}

proc edit_window {} {
    global TkGnats Tkeditpr flds env current_multi_text

    set prid $Tkeditpr(prid)
    
    set prtxt [lock_pr $prid]
    # if {$prtxt == ""} {
    #     exit 1
    # }

    # Unlock the PR if the user nukes the window
    bind . <Destroy> edit_cleanup
    
    get_tkeditpr_listbox_height

    set Tkeditpr(radioflds) {
        >State
        >Confidential
        >Severity
        >Priority
        >Class
    }
    
    set Tkeditpr(singletextflds) {
        >Originator
        Reply-To
        >Release
        >Synopsis
    }

    if {$TkGnats(ReleaseBased)} {
        lappend Tkeditpr(singletextflds) >Keywords
        lappend Tkeditpr(singletextflds) >$TkGnats(Quarter)
        lappend Tkeditpr(singletextflds) >Date-Required
    }
    
    set Tkeditpr(multitextflds) {
        >Description
        >How-To-Repeat
        >Environment
        >Organization
        >Audit-Trail
        >Unformatted
        >Fix
        >Release-Note
    }
    
    # List of entry widgets for traverse key binding
    set Tkeditpr(tlist) {}
    
    set current_multi_text ""
    
    # load a bunch of defaults into flds.
    set Tkeditpr(parsed_flds) [parsepr_txt $prtxt flds]
    set missing_list [load_field_defaults flds]

    frame   .mframe     -borderwidth 1 -relief raised
    pack    .mframe     -side top -fill x

    menubutton .mframe.file -text "File" -menu .mframe.file.m -underline 0
    menu       .mframe.file.m
    .mframe.file.m add command -label "Save Changes"              -command file_report
    .mframe.file.m add command -label "Reset to Starting Values"  -command reset_report
    .mframe.file.m add command -label "Send Email..."  -command \
            "email_originator [list [ftrim $flds(Reply-To)]] \
            [list [ftrim $flds(>Responsible)]] [list [ftrim $flds(From)]] \
            [ftrim $flds(>Category)]/$Tkeditpr(prid) [list [ftrim $flds(>Synopsis)]]"
    .mframe.file.m add separator
    .mframe.file.m add command -label "Cancel"                    -command cancel_report
    
    menubutton .mframe.edit -text "Edit" -menu .mframe.edit.m -underline 0
    menu       .mframe.edit.m
    .mframe.edit.m add command -label "Fonts..." -command "edit_fonts"
    
    pack .mframe.file .mframe.edit -side left
    
    menubutton .mframe.help -text "Help" -menu .mframe.help.m -underline 0
    menu       .mframe.help.m
    .mframe.help.m add command -label "Overview" \
            -command "helpMsg Edit_Overview"
    .mframe.help.m add separator
    .mframe.help.m add command -label "Field Definitions" \
            -command "helpMsg Field_Definitions"
    .mframe.help.m add separator
    .mframe.help.m add command -label "Radio Buttons (Class, etc)" \
            -command "helpMsg Edit_Radio_Buttons"
    .mframe.help.m add command -label "Listbox Selectors (Category, etc)" \
            -command "helpMsg Edit_Listbox_Selectors"
    .mframe.help.m add command -label "Entry Fields (Originator, etc)" \
            -command "helpMsg Edit_Entry_Fields"
    .mframe.help.m add command -label "Text Fields (Description, etc)" \
            -command "helpMsg Edit_Text_Fields"
    .mframe.help.m add separator
    .mframe.help.m add command -label "View Configuration Variables" \
        -command "helpMsg TkGnats_Variables"
    .mframe.help.m add separator
    .mframe.help.m add command -label "About" \
            -command "helpMsg TkGnats_About"
    pack       .mframe.help -side right
    
    frame  .action -borderwidth 1 -relief raised
    pack   .action -side top -fill x -anchor w
    button .action.send   -borderwidth 1 -text "Save Changes"              -command file_report
    #button .action.cancel -borderwidth 1 -text "Cancel"                    -command cancel_report
    button .action.reset  -borderwidth 1 -text "Reset to Starting Values"  -command reset_report
    button .action.email  -borderwidth 1 -text "Send Email..."             -command \
            "email_originator [list [ftrim $flds(Reply-To)]] [list [ftrim $flds(>Responsible)]] \
            [list [ftrim $flds(From)]] [ftrim $flds(>Category)]/$Tkeditpr(prid) \
            [list [ftrim $flds(>Synopsis)]]"
    
    #pack .action.send .action.reset .action.email .action.cancel -side left -padx 0
    pack .action.send .action.reset .action.email -side left -padx 0
    
    message .action.msg -aspect 10000  -relief sunken -bd 1 -text ""
    pack    .action.msg -side left -fill x -expand 1

    # Get the maximum width of the value fields for the bagged_radiobar
    set Tkeditpr(value_width) 0
    foreach tag [concat >Category >Responsible $Tkeditpr(radioflds)] {
        set f [ftrim $flds($tag)]
        if {[string length $f] > $Tkeditpr(value_width)} {
            set Tkeditpr(value_width) [string length $f]
        }
    }
    
    # Get the maximum width of the value fields for the readonly_singletext fields
    ###set Tkeditpr(singletextvalue_width) \
            ###        [string length "[ftrim $flds(>Originator)] (email: $flds(Reply-To))"]
    set Tkeditpr(singletextvalue_width) 0
    set flist {>Last-Modified >Arrival-Date >Closed-Date}
    foreach tag $flist {
        set f [ftrim $flds($tag)]
        if {[string length $f] > $Tkeditpr(singletextvalue_width)} {
            set Tkeditpr(singletextvalue_width) [string length $f]
        }
    }
    
    ###readonly_singletext Originator   "[ftrim $flds(>Originator)] (email: $flds(Reply-To))"  14 \
            ###        $Tkeditpr(singletextvalue_width)
    readonly_singletext Arrival-Date  [ftrim $flds(>Arrival-Date)]  14 \
            $Tkeditpr(singletextvalue_width)
    readonly_singletext Last-Modified [ftrim $flds(>Last-Modified)] 14 \
            $Tkeditpr(singletextvalue_width)
    readonly_singletext Closed-Date   [ftrim $flds(>Closed-Date)]   14 \
            $Tkeditpr(singletextvalue_width)

    frame .eflds
    radiobar_frame .eflds .eflds.lb
    bagged_radiobar .eflds.lb class Class \
            $TkGnats(ClassesList) None frm $Tkeditpr(value_width)
#####            {sw-bug doc-bug change-request support mistaken duplicate} None frm $Tkeditpr(value_width)
    bagged_radiobar .eflds.lb state State \
            $TkGnats(StatesList)  None frm $Tkeditpr(value_width)
#####            {open analyzed feedback closed suspended} None frm $Tkeditpr(value_width)
    bagged_radiobar .eflds.lb priority Priority \
            {low medium high} None frm $Tkeditpr(value_width)
    bagged_radiobar .eflds.lb severity Severity \
            {non-critical serious critical} None frm $Tkeditpr(value_width)
    bagged_radiobar .eflds.lb confidential Confidential \
            {no yes} None frm $Tkeditpr(value_width)
    pack .eflds.lb -side left -pady 0
    pack .eflds    -side top  -pady 0 -fill x -anchor w
    
    frame .eboxs
    frame .eboxs.clb -relief groove -borderwidth 2
    edit_category_listbox .eboxs.clb * $Tkeditpr(value_width)
    frame .eboxs.slb -relief groove -borderwidth 2
    edit_submitter_listbox   .eboxs.slb * $Tkeditpr(value_width)
    frame .eboxs.rlb -relief groove -borderwidth 2
    edit_responsible_listbox .eboxs.rlb * $Tkeditpr(value_width)
    
    pack .eboxs.clb -side left -anchor w -pady 2 -padx  0
    pack .eboxs.slb -side left -anchor w -pady 2 -padx 20
    pack .eboxs.rlb -side left -anchor w -pady 2 -padx  0
    pack .eboxs     -side top  -anchor w -pady 2 -padx  0 -fill x
    
    lappend Tkeditpr(tlist) [singletext . >Originator  80 "" 14]
    lappend Tkeditpr(tlist) [singletext . Reply-To     80 "" 14]
    lappend Tkeditpr(tlist) [singletext . >Release     80 "" 14]
    lappend Tkeditpr(tlist) [singletext . >Synopsis    80 "" 14]

    if {$TkGnats(ReleaseBased)} {
        lappend Tkeditpr(tlist) [singletext . >Keywords          80 "" 14]
        lappend Tkeditpr(tlist) [singletext . >$TkGnats(Quarter) 80 "" 14]
        lappend Tkeditpr(tlist) [singletext . >Date-Required     80 "" 14]
    }
    
    lappend Tkeditpr(tlist) [make_txt_mb $Tkeditpr(multitextflds)]
    
    set_text_traversal $Tkeditpr(tlist)
    
    wm title      . "TkGnats - [lindex $TkGnats(ServerInfo) 0] - Edit Problem Report: [ftrim $flds(>Category)]/[ftrim $flds(>Number)]"
    wm iconbitmap . @$TkGnats(lib)/tkeditpr.xbm
    wm iconname   . "$TkGnats(LogName)'s tkeditpr [ftrim $flds(>Number)]"
    fillfrm

    tkwait visibility .
    
    if {"$missing_list" != ""} {
        Msg "The following fields were missing from the report but will be added when you Save Changes:\n" [join $missing_list \n]
        set Tkeditpr(parsed_flds) [concat $Tkeditpr(parsed_flds) $missing_list]
    }
}

##################################################################

set Tkeditpr(prid)           ""

tkeditpr_process_args

foreach f { tkpr_library.tcl tkprhelp.tcl tkprfont.tcl tkprdatesel.tcl } {
    source $TkGnats(lib)/$f
}

# If TkGnats(GNATS_ACCESS_METHOD) != "socket" then this does nothing
if {[open_socket_gnatsd 1] == "-1"} {
    exit
}

if {[get_gnats_config] == "-1"} {
    exit
}

#TTD remove me after testing
#set TkGnats(ReleaseBased) 1

set  numerrs 0

if {$Tkeditpr(prid) == ""} {
    wm withdraw .
    Msg "No problem report id supplied!\n" "Usage:  tkeditpr -prid=nnnn"
    incr numerrs
}

if {"$TkGnats(LogName)" == "root"} {
    wm withdraw .
    Msg "You cannot edit problem reports as root.\n" "Please use your own login."
    incr numerrs
}

if {$numerrs > 0} {
    close_socket_gnatsd 1
    exit 1
}

edit_window

# If TkGnats(GNATS_ACCESS_METHOD) != "socket" then this does nothing
close_socket_gnatsd 1
