#
 # Returns an opaque handle which should be passed to nbdpoll.
 proc nbdcanvas { canvas logfile size blocksize width scale } {
-    canvas $canvas -bg white
     set height [expr {$size / $blocksize / $width}]
 
+    # Width and height of the canvas.
+    set w_scaled [expr {$width*$scale}]
+    set h_scaled [expr {$height*$scale}]
+    canvas $canvas -bg white -width $w_scaled -height $h_scaled
+
     # Because Tk's canvas cannot scale images, we use a very
     # inefficient double buffering here where we have $img which
     # contains the raw data but is not displayed, and $dispimg which
     # $img changes.
     set img [image create photo -width $width -height $height]
     $img put "white" -to 0 0 $width $height
-    set dispimg [image create photo -width [expr {$width*$scale}] \
-                     -height [expr {$height*$scale}]]
-    $canvas create image 0 0 -anchor nw -image $dispimg
+    set dispimg [image create photo -width $w_scaled -height $h_scaled]
+    # -borderwidth somehow counts towards the canvas area?!  So we have
+    # to offset the image by 4, 4 here to make it fully visible.
+    $canvas create image 4 4 -anchor nw -image $dispimg
 
     # Open the log file.
     set fp [open $logfile "r"]
     return [dict get $h height]
 }
 
-# Blit $img to $dispimg, with scaling.
-proc update_dispimg { h } {
-    set img [dict get $h img]
+# Blit $img to $dispimg, with scaling.  If the optional img parameter
+# is given, blit that image to $dispimg instead, else use the normal
+# img stored in the handle.
+proc update_dispimg { h { img - } } {
+    if { "$img" eq "-" } {
+        set img [dict get $h img]
+    }
     set dispimg [dict get $h dispimg]
-    set width [dict get $h width]
-    set height [dict get $h height]
     set scale [dict get $h scale]
     $dispimg copy $img -zoom $scale $scale
 }
 proc handle_read { h offset count } {
     set blocksize [dict get $h blocksize]
     set width [dict get $h width]
+    set height [dict get $h height]
     set img [dict get $h img]
 
+    # We only write into a temporary image here.
+    set tmpimg [image create photo -width $width -height $height]
+    $tmpimg copy $img
+
     while { $count > 0 } {
         set lba [expr {$offset/$blocksize}]
         set x [expr {$lba % $width}]
         set y [expr {$lba / $width}]
 
-        set oldcol [$img get $x $y]
-        set oldcol [format "#%02x%02x%02x" \
-                        [lindex $oldcol 0] \
-                        [lindex $oldcol 1] \
-                        [lindex $oldcol 2]]
-        # Flash the pixel to black.
-        $img put "black" -to $x $y [expr {$x+1}] [expr {$y+1}]
-        update_dispimg $h
-        update
-        # Restore old colour.
-        $img put $oldcol -to $x $y [expr {$x+1}] [expr {$y+1}]
-        update_dispimg $h
+        # Set the read pixel to black.
+        $tmpimg put "black" -to $x $y [expr {$x+1}] [expr {$y+1}]
 
         incr offset $blocksize
         incr count [expr {-$blocksize}]
     }
+
+    # Update the display buffer with the temporary image.
+    update_dispimg $h $tmpimg
+    update
+
+    # Discard the temporary copy.
+    image delete $tmpimg
+
+    # We don't actually update the display image again.  It will be
+    # restored next time something happens.
 }
 
 # Operation colours.
 array set colours {
-    # write => red
     w "#ff0000"
-    # trim => grey
-    t "#e0e0e0"
-    # zero => white
+    t "#e0e0f0"
     z "#ffffff"
 }
 
     # else just ignore any lines we don't understand
 }
 
+# If nothing happens in nbdpoll for a few iterations then we update
+# the displayed image.  This is so that black read bars don't appear
+# permanently if nothing else is happening.
+set pollcount 50
+
 # Poll the logfile and update the canvas.
-# This has to be called every so often.
+# This has to be called every so often from the main program.
 proc nbdpoll { h } {
+    global pollcount
+
     set fp [dict get $h fp]
 
     # Read as much as we can from the log file.
         foreach line $lines {
             handle $h $line
         }
+    } else {
+        # Nothing happening, did pollcount go to zero yet?
+        incr pollcount -1
+        if { $pollcount == 0 } {
+            update_dispimg $h
+            set pollcount 50
+        }
     }
 }
 
 
 set blocksize 4096
 set width 128
-set scale 2
+set scale 4
 
 # This is used to store the canvas handle.
 set h ""
 set logfile [lindex $argv 0]
 set size [lindex $argv 1]
 
-# Set up the window.
-wm title . "nbdview $logfile"
-
 # Menubar.
 option add *tearOff 0
 menu .menubar
 .menubar add cascade -menu .menubar.file -label File
 .menubar.file add command -label "Quit" -command { exit }
 
+# Frame.
+frame .f
+pack .f -anchor center -expand 1 -fill both -ipadx 10 -ipady 10
+
 # Canvas.
-set h [nbdcanvas .c $logfile $size $blocksize $width $scale]
-pack .c -in . -expand 1 -fill both
+set h [nbdcanvas .f.c $logfile $size $blocksize $width $scale]
+.f.c configure -borderwidth 4 -relief groove
+pack .f.c -anchor center -expand 0 -fill none
 
-# Set the width and height of the window.
-set h_ [expr {[nbdheight $h] * $scale + 40}]
-set w [expr {$width * $scale + 16}]
-wm geometry . "${w}x${h_}"
+# Set up the window.
+wm title . "nbdview $logfile"
 wm resizable . false false
 
 # Start polling the log file.