# Simple GUI to choose what bits to set in a 32-bit hex value
# Run using "wish" as "wish hexy.tcl"
#

wm title . "Bit position to hex converter"
wm resizable . 0 0

label .prompt -text "Choose bits to include in the hex value:"
grid .prompt -row 0 -columnspan 32

for {set i 0} {$i < 32} {incr i} {
        set j [expr {31 - $i}]

        label .bit$j -text $j
        checkbutton .cb$j -command { manage_hexvalue } -variable cb$j -onvalue [expr {1 << $j}] -text {}
	if {$i < 16} {
        	grid .bit$j -row 1 -column $i
		grid .cb$j -row 2 -column $i
	} else {
        	grid .bit$j -row 3 -column [expr $i - 16]
		grid .cb$j -row 4 -column [expr $i - 16]
	}

}

entry .hex -textvariable hexvalue -takefocus 0 -width 20 -state disabled -justify center -bg white -fg black
grid .hex -row 5 -columnspan 32

proc manage_hexvalue {} {
	global hexvalue

	set result 0
	for {set i 0} {$i < 32} {incr i} {
		global cb$i
		set cbname cb$i
		set result [expr $result | [set $cbname]]
	}
        .hex configure -state normal
	set hexvalue [format "0x%08X" $result]
        .hex configure -state disabled
}

label .prompt2 -text "Enter hex value here to see which bits are set:"
grid .prompt2 -row 6 -columnspan 32

entry .hexentry -width 20 -justify center -bg white -fg black -textvariable hexentry -validate key -validatecommand { val_entry %P }
grid .hexentry -row 7 -columnspan 32

if {0} {
button .action -text "Determine bit positions" -command { eval_hex $hexentry }
grid .action -row 8 -columnspan 32
}

proc val_entry { ifvalidstr } {
	if {[string length $ifvalidstr] > 8 } { bell; return 0 }
	if {![string is xdigit $ifvalidstr]} { bell; return 0 }

	eval_hex $ifvalidstr
	return 1
}

proc eval_hex { hexentry } {

	if {![string length $hexentry]} { set hexentry 0 }

	set hexstr [binary format I* 0x$hexentry]
	binary scan $hexstr B* binstr

	for {set i 0} {$i < 32} {incr i} {
		set nextbit [string index $binstr end-$i]
		if {$nextbit} {
			.cb$i select
		} else {
			.cb$i deselect
		}
	}

	manage_hexvalue
}

