#!/usr/local/wish -f

#
# A nice interface to "xset" to change X server settings
#
# History :
#   91/11/23 : pda@masi.ibp.fr, jt@ratp.fr : design
#

proc bind.entry args {
    foreach w $args {
	bind $w <Any-KeyPress> {%W insert cursor "%A"}
	bind $w <quotedbl> {%W insert cursor \"}
	bind $w <backslash> {%W insert cursor \\}
	bind $w <dollar> {%W insert cursor {$}}
	bind $w <space> {%W insert cursor " "}
	bind $w <2> {puts stdout "character [%W index @%x]"}
	bind $w <Delete> {bs %W}
	bind $w <BackSpace> {bs %W}
	bind $w <Control-h> {bs %W}
	bind $w <1> {%W cursor @%x; focus %W; %W select from @%x}
	bind $w <B1-Motion> {%W select to @%x}
	bind $w <Shift-1> {%W select adjust @%x}
	bind $w <Shift-B1-Motion> {%W select to @%x}
	bind $w <3> {%W scan mark %x}
	bind $w <B3-Motion> {%W scan dragto %x}
	bind $w <Control-d> {%W delete sel.first sel.last}
	bind $w <Control-v> {%W insert cursor [selection get]}
	bind $w <Control-u> {%W delete 0 end}
    }
}

proc bs win {
    set x [expr {[$win index cursor] - 1}]
    if {$x != -1} {$win delete $x}
}

proc bind.radiobutton args {
    foreach w $args {
	bind $w <Any-Enter> {}
	bind $w <Any-Leave> {}
	bind $w <ButtonPress-1> {}
	bind $w <ButtonRelease-1> {}
    }
}

proc labelentry {path text length} {
    frame $path
    label $path.lbl -text $text
    entry $path.entry -width $length -relief sunken
    bind.entry $path.entry
    pack append $path $path.lbl {left} $path.entry {right}
}

proc quit {} {
    destroy .
}

proc ok {} {
    writesettings
    quit
}

#
# Read current settings
#

# proc readsettings {} {
    global kbdrep ;	set kbdrep	"on"
    global kbdcli ;	set kbdcli	0
    global bellvol ;	set bellvol	100
    global bellpit ;	set bellpit	440
    global belldur ;	set belldur	100
    global mouseacc ;	set mouseacc	"3/1"
    global mousethr ;	set mousethr	4
    global screenbla ;	set screenbla	"yes"
    global screentim ;	set screentim	600
    global screencyc ;	set screencyc	600

    set tmp		"/tmp/xset.tmp"

    exec xset q > $tmp
    set xfd [open /tmp/xset.tmp]
    gets $xfd line
    while {[expr ![eof $xfd]]} {
	set kbd1 [lindex $line 0]
	set kbd2 [lindex $line 1]

	if {[expr "{$kbd1} == {auto} && {$kbd2} == {repeat:}"]} then {
	    set kbdrep [lindex $line 2]
	    set kbdcli [lindex $line 6]
	}
	if {[expr "{$kbd1} == {bell}"]} then {
	    set bellvol [lindex $line 2]
	    set bellpit [lindex $line 5]
	    set belldur [lindex $line 8]
	}
	if {[expr "{$kbd1} == {acceleration:}"]} then {
	    set mouseacc [lindex $line 1]
	    set mousethr [lindex $line 3]
	}
	if {[expr "{$kbd1} == {prefer}"]} then {
	    set screenbla [lindex $line 2]
	}
	if {[expr "{$kbd1} == {timeout:}"]} then {
	    set screentim [lindex $line 1]
	    set screencyc [lindex $line 3]
	}

	gets $xfd line
    }
    close $xfd
    exec rm $tmp

    # puts stdout [format "Key REPEAT = %s\n" $kbdrep]
    # puts stdout [format "Key CLICK  = %s\n" $kbdcli]
    # puts stdout [format "Bell VOLUME = %s\n" $bellvol]
    # puts stdout [format "Bell PITCH = %s\n" $bellpit]
    # puts stdout [format "Bell DURATION = %s\n" $belldur]
    # puts stdout [format "Mouse ACCELERATION = %s\n" $mouseacc]
    # puts stdout [format "Mouse THRESHOLD = %s\n" $mousethr]
    # puts stdout [format "Screen BLANCK = %s\n" $screenbla]
    # puts stdout [format "Screen TIMEOUT = %s\n" $screentim]
    # puts stdout [format "Screen CYCLE = %s\n" $screencyc]
# }

proc writesettings {} {
    global kbdrep
    global kbdcli
    global bellvol
    global bellpit
    global belldur
    global mouseacc
    global mousethr
    global screenbla
    global screentim
    global screencyc

    global bellpath kbdpath mousepath screenpath

    set bellvol		[$bellpath.vol get]
    set bellpit		[$bellpath.val.pit.entry get]
    set belldur		[$bellpath.val.dur.entry get]

    set kbdcli		[$kbdpath.val.cli get]

    set mouseacc	[$mousepath.hor.acc.entry get]
    set mousethr	[$mousepath.hor.thr.entry get]

    set screentim	[$screenpath.val.le.tim.entry get]
    set screencyc	[$screenpath.val.le.cyc.entry get]

    exec xset \
	b $bellvol $bellpit $belldur \
	c $kbdcli \
	r $kbdrep \
	m $mouseacc $mousethr \
	s $screentim $screencyc
}

# readsettings

#
# Buttons
#

frame .buttons
button .buttons.ok	-command "ok"			-text "Ok"
button .buttons.apply	-command "writesettings"	-text "Apply"
button .buttons.quit	-command "quit"			-text "Quit"

pack append .buttons \
    .buttons.ok		{left expand pady 10} \
    .buttons.apply	{left expand pady 10} \
    .buttons.quit	{left expand pady 10}

#
# Bell settings
#

set bellpath .bell

frame $bellpath -relief raised -borderwidth 2

label $bellpath.lbl -text "Bell Settings"
scale $bellpath.vol \
    -from 0 -to 100 -label "Volume (%)" -orient horizontal \
    -length 200 -activeforeground Gray -tickinterval 20 \
    -bg Bisque1
$bellpath.vol set $bellvol

frame $bellpath.val
labelentry $bellpath.val.pit "Pitch (Hz)" 6
$bellpath.val.pit.entry insert 0 $bellpit
labelentry $bellpath.val.dur "Duration (ms)" 6
$bellpath.val.dur.entry insert 0 $belldur
pack append $bellpath.val \
    $bellpath.val.pit {left} \
    $bellpath.val.dur {right}

pack append $bellpath \
    $bellpath.lbl {top} \
    $bellpath.vol {top} \
    $bellpath.val {top}

#
# Keyboard settings
#

set kbdpath .kbd

frame $kbdpath -relief raised -borderwidth 2

label $kbdpath.lbl -text "Keyboard Repeat Settings"

frame $kbdpath.val

checkbutton $kbdpath.val.onoff \
    -text "On" \
    -onvalue "on" -offvalue "off" -variable kbdrep \
    -relief flat
if {[expr "{$kbdrep} == {on}"]} then {$kbdpath.val.onoff select}
scale $kbdpath.val.cli \
    -from 0 -to 100 -label "Click Volume (%)" -orient horizontal \
    -length 200 -activeforeground Gray -tickinterval 20 \
    -bg Bisque1
$kbdpath.val.cli set $kbdcli
pack append $kbdpath.val \
    $kbdpath.val.onoff {left} \
    $kbdpath.val.cli {right}

pack append $kbdpath \
    $kbdpath.lbl {top} \
    $kbdpath.val {top pady 4}

#
# Mouse settings
#

set mousepath .mouse

frame $mousepath -relief raised -borderwidth 2

label $mousepath.lbl -text "Mouse Settings"
frame $mousepath.hor
labelentry $mousepath.hor.acc "Acceleration" 3
$mousepath.hor.acc.entry insert 0 $mouseacc
labelentry $mousepath.hor.thr "Threshold (pixels)" 3
$mousepath.hor.thr.entry insert 0 $mousethr

pack append $mousepath.hor \
    $mousepath.hor.acc {left} \
    $mousepath.hor.thr {right}

pack append $mousepath \
    $mousepath.lbl {top} \
    $mousepath.hor {top}

#
# Screen Saver settings
#

set screenpath .screen

frame $screenpath -relief raised -borderwidth 2

label $screenpath.lbl -text "Screen-saver Settings"
frame $screenpath.val

frame $screenpath.val.rb
radiobutton $screenpath.val.rb.blank \
    -variable screenblank -text "Blank" -relief flat \
    -value "yes" -variable screenbla \
    -activebackground Bisque1
radiobutton $screenpath.val.rb.pat \
    -variable screenblank -text "Pattern" -relief flat \
    -value "no" -variable screenbla \
    -activebackground Bisque1
$screenpath.val.rb.blank [expr "{$screenbla} == {yes} ? {select} : {deselect}"]
$screenpath.val.rb.pat   [expr "{$screenbla} != {yes} ? {select} : {deselect}"]
pack append $screenpath.val.rb \
    $screenpath.val.rb.blank {top pady 4 frame w} \
    $screenpath.val.rb.pat {top pady 4 frame w}
frame $screenpath.val.le
labelentry $screenpath.val.le.tim "Timeout (s)" 5
$screenpath.val.le.tim.entry insert 0 $screentim
labelentry $screenpath.val.le.cyc "Cycle (s)" 5
$screenpath.val.le.cyc.entry insert 0 $screencyc
pack append $screenpath.val.le \
    $screenpath.val.le.tim {top pady 4 frame e} \
    $screenpath.val.le.cyc {top pady 4 frame e}

pack append $screenpath.val \
    $screenpath.val.rb {left} \
    $screenpath.val.le {left}

pack append $screenpath \
    $screenpath.lbl {top} \
    $screenpath.val {top}

#
# Main window
#

pack append . \
    .buttons	{top fill} \
    $bellpath	{top pady 10 fill} \
    $kbdpath	{top pady 10 fill} \
    $mousepath	{top pady 10 fill} \
    $screenpath	{top pady 10 fill}
