An example Tk application using Tk and BWidgets that shows a comparison between two binary files and shows the differences between them.
#! /bin/sh # bindiff.tcl - Copyright (C) 2003 Pat Thoyts <[email protected]> # # Show a side by side comparison of two binary files with the differences # highlighted # # This could probably use more work, but it does the job I required it for. # Differences are highlighted in red. # # usage: # bindiff fileA fileB # # 16 Jan 2004: Patch provided by Paul Kienzle for different length files. # # $Id: 8545,v 1.3 2005-11-23 07:01:17 jcw Exp $ # \ exec wish "$0" ${1+"$@"} package require Tk package require BWidget set filename0 {} set filename1 {} set txt {} set progress 0 set top {} set menu { "&File" {} {} 0 { { command "&Left..." {} "Select the left hand side file" {} -command Menu::left } { command "&Right..." {} "Select the right hand side file" {} -command Menu::right } { separator } { command "&Compare" {} "Show the differences in the view window" {} -command Menu::compare} { command "E&xit" {} "Exit the application" {} -command Menu::exitApplication } } "&Options" {} {} 0 { { command "&Font..." {} "Select a new font" {} -command Menu::fontSelect } { checkbutton "&Console" {} "Show console" {} -variable Menu::console -command Menu::toggleConsole} } "&Help" {} {} 0 { } } namespace eval Menu { variable console 0 proc toggleConsole {} { variable console if {$console} { console hide } else {console show } } proc exitApplication {} { destroy $::top } proc fontSelect {} { global txt top set font [SelectFont .sel] font configure fdiff -family [lindex $font 0] -size [lindex $font 1] -weight [lindex $font 2] } proc left {} { global txt top set name [tk_getOpenFile -parent $top -title "Select left hand file"] if {$name != {}} { set ::filename0 $name $txt delete 0.0 end } } proc right {} { global txt top set name [tk_getOpenFile -parent $top -title "Select right hand file"] if {$name != {}} { set ::filename1 $name $txt delete 0.0 end } } proc compare {} { if {[file exists $::filename0] && [file exists $::filename1]} { cmp $::filename0 $::filename1 } else { tk_messageBox -icon error -type ok -title "Cannot compare" -message "Select two files for comparison." } } } proc gui {dlg} { global txt top set top $dlg wm title $dlg "Binary diff" if {$dlg == "."} { set dlg ""} font create fdiff -family {Courier New} -size 8 -weight normal set mw [MainFrame $dlg.main -menu $::menu -progressvar ::progress -progressmax 100] $mw showstatusbar progression set f1 [frame $mw.f1] set l0 [label $f1.l0 -font fdiff -width 10 -text "Filename:"] set l1 [label $f1.l1 -font fdiff -width 49 -textvariable ::filename0] set l2 [label $f1.l2 -font fdiff -width 49 -textvariable ::filename1] set l3 [label $f1.l3 -font fdiff -width 34 -textvariable ::filename0] pack $l0 $l1 $l2 $l3 -side left pack $f1 -side top -fill x set txt [text $dlg.txt -font fdiff] $txt tag configure diff -background red set sw [ScrolledWindow $mw.view] $sw setwidget $txt pack $sw -side top -fill both -expand 1 -anchor n pack $mw -side top -fill both -expand 1 -anchor n return $dlg } proc cmp {file0 file1} { global txt top set taglist {} set dlg $top if {$dlg == "."} {set dlg ""} set cursors [list $txt [$txt cget -cursor] $top [$top cget -cursor]] #$txt configure -cursor wait #$top configure -cursor wait ${dlg}.main configure -progressmax [file size $file0] set ::progress 0 set f0 [open $file0 r] set f1 [open $file1 r] set ::filename0 $file0 set ::filename1 $file1 fconfigure $f0 -translation binary fconfigure $f1 -translation binary set off 0 set chunk 16 set linecount 1 while {![eof $f0] || ![eof $f1]} { set d0 [read $f0 $chunk] set d1 [read $f1 $chunk] binary scan $d0 c* c0 binary scan $d1 c* c1 set line "[format 0x%06x $off] " foreach v $c0 { append line [format { %02x} [expr {$v & 0xFF}]] } append line [string repeat " " [expr {$chunk-[string length $d0]}]] append line " " foreach v $c1 { append line [format { %02x} [expr {$v & 0xFF}]] } append line [string repeat " " [expr {$chunk-[string length $d1]}]] append line " " foreach v $c0 { set cv [expr {$v & 0xFF}] if {$cv < 32} { set cv 46 } append line [format { %c} $cv] } append line "\n" #set lineno [lindex [split [$txt index current] .] 0] #if {$lineno != $linecount} {puts ">> $lineno != $linecount"} $txt insert end $line set n 9 set diff 0 foreach v0 $c0 v1 $c1 { if {$diff == 0 && $v0 != $v1} { lappend taglist "$linecount.[expr {$n + 1}]" set diff 1 } elseif {$diff == 1 && $v0 == $v1} { lappend taglist "$linecount.$n" set diff 0 } incr n 3 } if {$diff == 1} { lappend taglist "$linecount.$n" } incr off $chunk if {$linecount % 50 == 0} { set ::progress $off if {[llength $taglist] > 0} { eval [list $txt tag add diff] $taglist set taglist {} } } incr linecount } close $f0 close $f1 if {[llength $taglist] > 0} { eval [list $txt tag add diff] $taglist set taglist {} } #foreach {w c} $cursors { $w configure -cursor $c } return $taglist } if {!$::tcl_interactive} { gui . if {[llength $argv] == 2} { eval [list cmp] $argv } tkwait window . }