package provide RE 1.1

proc ResourceEditor {rcfile} {
    global all RE_saved RE_upd xf

    set xf(re_on) 1
    # if dialog exists, show it
    if {[winfo exists .rcedit]} {
	wm deiconify .rcedit
	raise .rcedit
	return
    }
    
    set all(opt.all) {startup_dir_left startup_dir_right trash_dir selectBg_left selectBg_right pack_order_reverse hidden_files_left hidden_files_right button_line_1 button_line_2 button_line_3 button_line_4 button_line_5 button_line_6 button_line_7 button_line_8 button_set_1 button_set_2 button_set_3 button_set_4  mail_reader geometry messagelog_file log_font button_cols button_spacing focus_follows_mouse messages_always_on_top peek_file_header user_email confirm_vfs_exit ftp_chunk ftp_endcommand ftp_do_endcommand ftp_show_endmessage history_menu_length vfs_mode_bg writepath_mode_bg undo_mode_bg hyperlist_mode_bg fileselector_make_backup}
    
    # What should be listed on each panel

    # Old resources, do not list
    set all(opt.deprecated) {turbo_file_operations protection_bits auto_update show_link_dest safe_deletion mem_label time_label mail_check mail_message_box read_on_ack log_messages log_messages_to_file sort_by_extension}
    
    set all(opt.startup) {startup_dir_left startup_dir_right trash_dir pack_order_reverse hidden_files_left hidden_files_right geometry messagelog_file focus_follows_mouse user_email mail_reader messages_always_on_top peek_file_header history_menu_length fileselector_make_backup}
    
    set all(opt.colors) {selectBg_left selectBg_right vfs_mode_bg writepath_mode_bg undo_mode_bg hyperlist_mode_bg}
    
    set all(opt.fonts) {log_font}
    
    set all(opt.vfs) {confirm_vfs_exit ftp_chunk ftp_endcommand ftp_do_endcommand ftp_show_endmessage}
    
    set all(opt.ab) {button_line_1 button_line_2 button_line_3 button_line_4 button_line_5 button_line_6 button_line_7 button_line_8 button_set_1 button_set_2 button_set_3 button_set_4 button_cols button_spacing}
    
    set RE_saved 0
    set RE_upd 0
    set w [toplevel .rcedit]
    wm withdraw $w
    wm title $w "X-Files Resource Editor v1.1"
    wm resizable $w 0 0
    #wm geometry $w +100+50
    wm protocol $w WM_DELETE_WINDOW RE_Close

    SetCnfMenuBg

    # action buttons in the bottom
    frame $w.bot -bd 3 -relief ridge
    button $w.bot.close -text Close -width 8 -command RE_Close
    button $w.bot.save -text Save -width 8 -command RE_Save
    button $w.bot.add -text Add... -width 8 -command RE_Add
    button $w.bot.remove -text Remove -width 8 -command RE_Remove
    button $w.bot.edit -text "Edit Name..." -width 8 -command RE_Edit

    grid $w.bot.add $w.bot.remove $w.bot.edit $w.bot.save $w.bot.close -sticky e -pady 5 -padx 5
    grid columnconfigure $w.bot 4 -weight 1
    
    # 'tab' buttons on the left
    frame $w.tab -bd 2 -relief sunken
    frame $w.tab.d
    button $w.tab.d.fonts -text Fonts -width 10 -command {RE_Tab fonts}
    button $w.tab.d.colors -text Colours -width 10 -command {RE_Tab colors}
    button $w.tab.d.startup -text Startup -width 10 -command {RE_Tab startup}
    button $w.tab.d.vfs -text "FTP + VFS"  -width 10 -command {RE_Tab vfs}
    button $w.tab.d.ab -text ActionButtons -width 10 -command {RE_Tab ab}
    button $w.tab.d.popup -text PopupMenu -width 10 -command {RE_Tab popup}

    grid $w.tab.d.startup
    grid $w.tab.d.colors
    grid $w.tab.d.fonts
    grid $w.tab.d.ab
    grid $w.tab.d.vfs
    grid $w.tab.d.popup

    grid $w.tab.d -sticky new -padx 5 -pady 5

    # 'tab' panels
    frame $w.startup
    frame $w.colors
    frame $w.fonts
    frame $w.ab
    frame $w.vfs
    frame $w.popup

    # show frames
    grid $w.tab $w.startup -sticky news
    grid rowconfigure $w.tab 0 -weight 1
    grid $w.bot - -sticky news
    grid columnconfigure $w 1 -weight 1 -minsize 500p
    grid rowconfigure $w 0 -weight 1 -minsize 350p

    RE_GetOptions $rcfile
    RE_PackOptions $w 0
    # show startup first
    set all(selected) startup
    RE_Tab startup

    bind $w <Escape> {RE_Close}
    bind $w <Control-c> {RE_Close}
    focus $w.bot.close
    #trace variable all w RE_Upd
    wm deiconify $w

    set la [llength $all(opt.all)]
    set lr [llength $all(opt.read)]

    # check if rcfile contains all options...
    if {$la > $lr} {
	set diff {}
	foreach l $all(opt.all) {
	    if {[lsearch -exact $all(opt.read) $l] == -1} {
		lappend diff $l
	    }
	}
	set x [winfo pointerx .]
	set y [winfo pointery .]
	MessageBox "The resource file in \"~/.x-files/\"-directory is not up to date. I will now add the missing resources..." {} -50 -50 $x $y
	set i $all(size)
	#DEBUG $diff
	foreach a $diff {
	    set all($i.name) *xfiles.$a:
	    set all($i.val) [option get .xfiles $a {}]
	    if {[string compare {} $all($i.val)] == 0} {
		MessageBox "Value for option '*xfiles.$a' is missing!!\nInform the system administrator to update '$xf(xf_home)xfilesrc'." {} -50 -50 $x $y
	    }
	    set all($i.comment) {}
	    incr i
	}
	set old $all(size)
	set all(size) $i
	RE_PackOptions $w $old
	RE_Save

	MessageBox "If you need the comments, add them by hand from the file\n$xf(xf_home)xfilesrc" {} -50 -50 $x $y
    }
}

proc RE_Upd {arr index op} {
    global RE_upd

    set RE_upd 1
}
proc RE_GetOptions {rcfile} {
    global all

    # read file
    set fid [open $rcfile r]
    set options [split [read $fid] \n]
    close $fid

    # get file comment
    set i 0
    while {[string compare {} [lindex $options $i]] != 0} {
	lappend all(comment) [lindex $options $i]
	incr i
    }

    # parse options
    set options [lreplace $options 0 $i]
    set i 0
    set comment {}
    foreach line $options {
	if {[string compare $line {}] == 0} {
	    continue
	}
	if {[string match {!*} $line]} {
	    lappend comment $line
	} else {
	    regexp {^([^:]*): (.*)$} $line g option value
	    set option [string trim $option]:
	    set value [string trim $value]
	    # check if deprecated
	    regexp {([^\.]*):$} $option gfg name 
	    if {[lsearch $all(opt.deprecated) $name] > -1} {
		set comment {}
		continue
	    }
	    set all($i.name) $option
	    set all($i.val) $value
	    set all($i.comment) $comment
	    set comment {}

	    # make note what options has been read
	    # TODO keksi parempi geneerinen tapa!!
	    if {[string match {\*xfiles*} $option] \
		    && ![string match {*popup_user_item*} $option]} {
		regexp {^[^.]*.([^:]*):$} $option gfg b
		lappend all(opt.read) $b
	    }
	    incr i
	}
    }
    set all(size) $i
}

proc RE_PackOptions {w idx} {
    global all

    #parray all
    for {set i $idx} {$i < $all(size)} {incr i} {
	# see in what tab panel it belongs
	regexp {([^\.]*):$} $all($i.name) gfg name 
	if {[lsearch $all(opt.startup) $name] > -1} {
	    set panel startup
	} elseif {[lsearch $all(opt.ab) $name] > -1} {
	    set panel ab
	} elseif {[string match {*font} $name]} {
	    set panel fonts
	} elseif {[lsearch $all(opt.vfs) $name] > -1} {
	    set panel vfs
	} elseif {[string match {popup_user_item*} $name]} {
	    set panel popup
	} else {
	    # must be a color definition
	    set panel colors
	}

	#DEBUG "$name: $panel"
	RE_PackItem $panel $i $w
    }
    grid columnconfigure $w.startup 0 -weight 1
    grid columnconfigure $w.colors 0 -weight 1
    grid columnconfigure $w.fonts 0 -weight 1
    grid columnconfigure $w.ab 0 -weight 1
    grid columnconfigure $w.vfs 0 -weight 1
    grid columnconfigure $w.popup 0 -weight 1

}
proc RE_PackItem {panel i w} {
    global all

    frame $w.$panel.$i -highlightthickness 1
    if {[regexp {^[01]$} $all($i.val)] && \
	    ![regexp {button_set} $all($i.name)] && \
	    ![regexp {button_cols} $all($i.name)] && \
	    ![regexp {button_spacing} $all($i.name)]} {
	label $w.$panel.$i.l -text $all($i.name) -width 27 -anchor w
	checkbutton $w.$panel.$i.c -variable all($i.val) \
		-command [list focus $w.$panel.$i] -highlightthickness 0
	grid $w.$panel.$i.l $w.$panel.$i.c - - -sticky w
    } {
	label $w.$panel.$i.l -text $all($i.name) -width 27 -anchor w
	entry $w.$panel.$i.e -textvariable all($i.val) \
		-highlightthickness 0
	if {[string match {*_dir*} $all($i.name)] || \
		[string match {*_file*} $all($i.name)]} {
	    # directory or file entry, show Browse... button
	    button $w.$panel.$i.b -text Browse... -width 9 -padx 0 -pady 0\
		    -command [list RE_GetFSName $w.$panel.$i.e [string match {*_dir*} $all($i.name)]] -highlightthickness 0
	    grid $w.$panel.$i.l $w.$panel.$i.e - $w.$panel.$i.b -sticky w
	    #pack $w.$panel.$i.b -side right -padx 0 -pady 0
	    bind $w.$panel.$i.b <1> [list focus $w.$panel.$i]
	} elseif {[string match {*font*} $all($i.name)]} {
	    # font entry, show Select... button
	    button $w.$panel.$i.b -text Select... -width 9 -padx 0 -pady 0\
		    -command [list RE_GetFont $w.$panel.$i.e] -highlightthickness 0
	    grid $w.$panel.$i.l $w.$panel.$i.e - $w.$panel.$i.b -sticky w
	    #pack $w.$panel.$i.b -side right -padx 0 -pady 0
	    bind $w.$panel.$i.b <1> [list focus $w.$panel.$i]
	} elseif {[string compare colors $panel] == 0} {
	    # color entry, show Select... button
	    button $w.$panel.$i.b -text Select... -width 9 -padx 0 -pady 0\
		    -command [list RE_GetColor $w.$panel.$i.e] -highlightthickness 0
	    label $w.$panel.$i.cl -highlightthickness 0 -width 4 -relief ridge
	    catch {$w.$panel.$i.cl config -bg $all($i.val)}
	    grid $w.$panel.$i.l $w.$panel.$i.e $w.$panel.$i.cl $w.$panel.$i.b -sticky w
	    #pack $w.$panel.$i.b $w.$panel.$i.cl -side right -padx 0 -pady 0
	    bind $w.$panel.$i.cl <1> [list focus $w.$panel.$i]
	    bind $w.$panel.$i.b <1> [list focus $w.$panel.$i]
	    bind $w.$panel.$i.e <Return> {
		regsub {[^\.]*$} %W "cl" cl
		$cl config -bg [%W get]
	    }
	} elseif {[string match *xfiles.geometry* $all($i.name)]} {
	    # geometry entry, show Get button
	    button $w.$panel.$i.b -text Get -width 9 -padx 0 -pady 0\
		    -command [list RE_GetGeom $w.$panel.$i.e] -highlightthickness 0
	    grid $w.$panel.$i.l $w.$panel.$i.e - $w.$panel.$i.b -sticky w
	    #pack $w.$panel.$i.b -side right -padx 0 -pady 0
	    bind $w.$panel.$i.b <1> [list focus $w.$panel.$i]
	} else {
	    grid $w.$panel.$i.l $w.$panel.$i.e - - -sticky w
	    #pack $w.$panel.$i.e -side right -fill x -expand 1
	}
	grid config $w.$panel.$i.e -sticky we
    }
    grid columnconfigure $w.$panel.$i 1 -weight 1
    #pack $w.$panel.$i.l -side left
    #pack $w.$panel.$i -side top -fill x -expand 1
    grid $w.$panel.$i -sticky news
    bind $w.$panel.$i.l <3> [list RE_PopUp $w.$panel.$i %X %Y]
    bind $w.$panel.$i <3> {RE_PopUp %W %X %Y}
    bind $w.$panel.$i.l <1> [list focus $w.$panel.$i]
    bind $w.$panel.$i <1> {focus %W}
}

# switches the panels
proc RE_Tab {panel} {
    global all

    trace vdelete all w RE_Upd

    # restore selected button to default state
    .rcedit.tab.d.$all(selected) config -relief raised -bg [.rcedit cget -bg]
    grid remove .rcedit.$all(selected)
    set all(selected) $panel

    # make selected button 'active'
    .rcedit.tab.d.$panel config -relief sunken -bg #fcbcbc
    grid .rcedit.$all(selected) -column 1 -row 0 -sticky nwe -padx 5 -pady 5

    # enable/disable Add, Remove and Edit Name buttons
    switch $panel {
	popup -
	fonts -
	colors {
	    set state normal
	}
	default {
	    set state disabled
	}
    }
    .rcedit.bot.add config -state $state
    .rcedit.bot.remove config -state $state
    .rcedit.bot.edit config -state $state

    trace variable all w RE_Upd
} 

proc RE_GetFSName {entry dirmode} {
    global xf env

    regsub {[^\.]*$} $entry "b" b
    set bg [lindex [$b config -bg] end]
    $b config -relief sunken -bg #fcbcbc
    if {$dirmode} {set m "dir"} {set m "load"}
    if {[string compare {} [$entry get]] == 0} {
	set dir $env(HOME)/
    } {
	set dir [GetParentDir [TildeSubst [$entry get]]]
    }
    #if {$dirmode == 1} {
	set new [FS "RE" $dir $m]
    #} {
	#set new [tk_getOpenFile -parent .rcedit -initialdir $dir -title "Select file"]
    #}
    $b config -relief raised -bg $bg
    if {[string compare "" $new] == 0 \
	|| [string compare [$entry get] $new] == 0} {
	return
    }
    $entry delete 0 end
    $entry insert 0 $new
    $entry xview moveto 1
    $entry icursor end
}
proc RE_GetFont {entry} {
    global xf

    regsub {[^\.]*$} $entry "b" b
    set bg [lindex [$b config -bg] end]
    $b config -relief sunken -bg #fcbcbc
    set new [SelectFont [$entry get]]
    $b config -relief raised -bg $bg
    if {[string compare [$entry get] $new] == 0} {
	return
    }
    $entry delete 0 end
    $entry insert 0 $new
    $entry xview moveto 1
    $entry icursor end
}
proc RE_GetGeom {entry} {
    global xf

    set new [wm geometry .]
    if {[string compare [$entry get] $new] == 0} {
	return
    }
    $entry delete 0 end
    $entry insert 0 $new
    $entry xview moveto 1
    $entry icursor end
}
proc RE_GetColor {entry} {
    global xf

    regsub {[^\.]*$} $entry "b" b
    regsub {[^\.]*$} $entry "cl" cl
    set bg [lindex [$b config -bg] end]
    $b config -relief sunken -bg #fcbcbc
    #set new [SelectColor [$entry get]]
    set new [tk_chooseColor -initialcolor [$entry get] -parent .rcedit -title "Select Color"]
    $b config -relief raised -bg $bg
    #if {[string compare [$entry get] $new] == 0} 
    if {[string compare $new {}] == 0} {
	return
    }
    $entry delete 0 end
    $entry insert 0 $new
    $entry xview moveto 1
    $entry icursor end
    $cl config -bg $new
}
proc RE_PopUp {W X Y} {
    global all
    focus $W
    catch {destroy $W.popup}
    regexp {.*\.(.*)\.(.*)$} $W g side ind
    set p [menu $W.popup -tearoff 0 -relief ridge -bd 4 -bg grey70 -disabledforeground #000000]
    $p add command -label "Edit comment..." -command [list RE_EditComment $ind]
    $p add separator
    foreach l $all($ind.comment) {
	$p add command -label $l -state disabled
    }
    tk_popup $p $X $Y
}
proc RE_EditComment {ind} {
    global all

    set tl [toplevel .rc_comment]
    wm geometry $tl +100+100
    wm title $tl "X-Files Resource Comment"
    frame $tl.tf
    text $tl.tf.text -width 50 -height 10
    frame $tl.bf
    button $tl.bf.ok -text OK -width 6 -command [list RE_CommentOK $ind]
    button $tl.bf.cancel -text Cancel -width 6 -command {destroy .rc_comment}
    pack $tl.tf -side top
    pack $tl.bf -side bottom -fill x -expand true
    pack $tl.bf.ok -side left
    pack $tl.bf.cancel -side right
    pack $tl.tf.text -side top
    $tl.tf.text delete 0.0 end
    foreach line $all($ind.comment) {
	$tl.tf.text insert end "$line\n"
    }
    focus $tl.bf.cancel
}
proc RE_CommentOK {ind} {
    global all RE_upd

    set text [split [string trim [.rc_comment.tf.text get 0.0 end]] \n]
    if {[string compare $text $all($ind.comment)] == 0} {
	return
    }
    set RE_upd 1
    set all($ind.comment) ""
    foreach l $text {
	lappend all($ind.comment) !![string trimleft $l !]
    }
    destroy .rc_comment
}
proc RE_Add {} {
    global all prompt

    if {[string compare popup $all(selected)] == 0} {
	set prefix *xfiles.
    } {
	set prefix *
    }
    set prompt(1.label) "Name:"
    set prompt(1.result) $prefix
    if {[DialogWin "Give the name of the new resource." -100 -150]} {
	if {[string match {\*xfiles*} $prompt(1.result)] && \
		![string match {*popup_user_item_*} $prompt(1.result)]} {
	    MessageBox "You cannot give an *xfiles option!!"
	    unset prompt
	    return
	}
	set i $all(size)
	set all($i.name) [string trimright $prompt(1.result) :]:
	set all($i.val) ""
	set all($i.comment) {}
	incr all(size)
	RE_PackOptions .rcedit $i
    }
    unset prompt
}
proc RE_Remove {} {
    global all RE_upd

    set w [focus]
    if {[string match *bot* $w]} {
	MessageBox "Select an option first!" {} -100 -150
	return
    }
    regexp {^\..*\..*\.([0-9]+)} $w gfg ind
    # COLORS tab has obligatory xfiles options, 
    # check that they are not removed
    if {[string match *xfiles* $all($ind.name)] && \
	    ![string match *popup_user* $all($ind.name)]} {
	MessageBox "You are not allowed to remove an *xfiles -option!" {} -100 -150
	return
    }
    if {[AskWin "Remove option: Are You sure?!" -100 -150] == 0} {
	return
    }
    set RE_upd 1
    grid forget $w
    unset all($ind.name)
    unset all($ind.val)
    unset all($ind.comment)
    .rcedit.bot.remove flash
}
proc RE_Edit {} {
    global all xf RE_upd prompt

    set w [focus]
    if {[string match *bot* $w]} {
	MessageBox "Select an option first!" {} -150 -150
	return
    }
    regexp {^\..*\..*\.([0-9]+)} $w gfg ind
    if {[string match *xfiles* $all($ind.name)] && \
	    ![string match *popup_user* $all($ind.name)]} {
	MessageBox "You are not allowed to edit an *xfiles -option name!" {} -150 -150
	return
    }
    set x [winfo pointerx .]
    set y [winfo pointery .]
    set prompt(1.label) "Name:"
    set prompt(1.result) [string trimright $all($ind.name) :]
    if {[DialogWin "Edit option\n" -150 -150 1 $x $y]} {
	if {[string compare {} $prompt(1.result)] == 0} {
	    MessageBox "Not a good name...''" {} -150 -150 {} $x $y
	    unset prompt
	    return
	}
	set res [string trimright $prompt(1.result) :]:
	foreach n [array names all *name] {
	    if {[string compare $res $all($n)] == 0} {
		MessageBox "An option with that name already exists!" {} -150 -150 {} $x $y
		unset prompt
		return
	    }
	}
	set RE_upd 1
	set all($ind.name) $res
	$w.l config -text $all($ind.name)
    }
    update idletasks
    unset prompt
}
proc RE_Save {} {
    global all xf RE_upd RE_saved

    MakeSaveDir
    set xf(rcfile) $xf(user_home)xfilesrc
    set out [open $xf(rcfile) w]
    foreach l $all(comment) {
	# update version info
	regsub {v.\..*$} $l "v$xf(A_VERSION)" l
	puts $out $l
    }
    puts $out ""
    for {set i 0} {$i < $all(size)} {incr i} {
	foreach x $all($i.comment) {
	    puts $out $x
	}
	puts $out "$all($i.name) $all($i.val)"
	puts $out ""
    }
    close $out
    set RE_upd 0
    set RE_saved 1
    trace variable RE_upd w RE_Upd
    .rcedit.bot.save flash
}
proc RE_Close {} {
    global all RE_upd RE_saved xf argc argv

    set x [winfo pointerx .]
    set y [winfo pointery .]

    if {$RE_upd} {
	set ret [AskWin "You have made changes! Close the editor without saving?" -150 -150 "Save" $x $y]
	switch $ret {
	    0 {return}
	    1 {set RE_upd 0; set RE_saved 0}
	    2 {RE_Save}
	    default {}
	}
    } {
	set RE_upd 0
    }
    if {$RE_upd || $RE_saved} {
	if {[AskWin "Do you wish to restart X-Files, so that the changes become effective now?" -150 -150 {} $x $y]} {
	    set home $xf(xf_home)
	    catch {
		after cancel MailChk
		after cancel AutoUD
		unset xf ee ea be all RE_upd
	    }
	    bind XF_Listbox <Configure> {}
	    foreach w [winfo children .] {
		destroy $w
	    }
	    set xf(xf_home) $home
	    uplevel #0 {MAIN $argc $argv}
	}
    }
    set xf(re_on) 0
    SetCnfMenuBg
    destroy .rcedit
    catch {unset all}
    catch {unset RE_upd}
}
