diff -urp --strip-trailing-cr ../drupal-6.x-dev/misc/tableheader.js ./misc/tableheader.js
--- ../drupal-6.x-dev/misc/tableheader.js	2007-10-02 09:09:51.000000000 +0200
+++ ./misc/tableheader.js	2008-01-05 14:02:01.000000000 +0100
@@ -9,12 +9,14 @@ Drupal.behaviors.tableHeader = function 
   // Keep track of all header cells.
   var cells = [];
 
-  var z = 0;
+  // Only first time: Clone all table headers and initialize data.
   $('table thead:not(.tableHeader-processed)', context).each(function () {
     // Find table height.
     var table = $(this).parent('table')[0];
     var height = $(table).addClass('sticky-table').height();
     var i = 0;
+    var z = 1;
+    table.maxCellHeight = 0;
 
     // Find all header cells.
     $('th', this).each(function () {
@@ -28,48 +30,141 @@ Drupal.behaviors.tableHeader = function 
         html = '<span>'+ html +'</span>';
       }
 
-      // Clone and wrap cell contents in sticky wrapper that overlaps the cell's padding.
-      $('<div class="sticky-header" style="position: fixed; visibility: hidden; top: 0px;">'+ html +'</div>').prependTo(this);
+      // Clone and wrap cell contents in sticky wrapper that overlaps the cell's padding,
+      // and duplicates its borders exactly.
+      $('<div class="sticky-header" style="position: fixed; visibility: hidden; top: 0px; margin: 0; padding: 0">'+ html +'</div>').prependTo(this);
       var div = $('div.sticky-header', this).css({
-        'marginLeft': '-'+ $(this).css('paddingLeft'),
-        'marginRight': '-'+ $(this).css('paddingRight'),
-        'paddingLeft': $(this).css('paddingLeft'),
-        'paddingTop': $(this).css('paddingTop'),
-        'paddingBottom': $(this).css('paddingBottom'),
+        'borderLeftWidth': $(this).css('borderLeftWidth'),
+        'borderLeftColor': $(this).css('borderLeftColor'),
+        'borderLeftStyle': $(this).css('borderLeftStyle'),
+        'borderRightWidth': $(this).css('borderRightWidth'),
+        'borderRightColor': $(this).css('borderRightColor'),
+        'borderRightStyle': $(this).css('borderRightStyle'),
+        'borderTopWidth': $(this).css('borderTopWidth'),
+        'borderTopColor': $(this).css('borderTopColor'),
+        'borderTopStyle': $(this).css('borderTopStyle'),
+        'borderBottomWidth': $(this).css('borderBottomWidth'),
+        'borderBottomColor': $(this).css('borderBottomColor'),
+        'borderBottomStyle': $(this).css('borderBottomStyle'),
         'z-index': ++z
       })[0];
       cells.push(div);
 
-      // Adjust width to fit cell/table.
-      var ref = this;
+      // Prepare various dimensions for the cell
+      var paddingL = parseInt($(this).css('paddingLeft'));
+      var paddingR = parseInt($(this).css('paddingRight'));
+      var paddingT = parseInt($(this).css('paddingTop'));
+      var paddingB = parseInt($(this).css('paddingBottom'));
+      var scrollH = document.documentElement.scrollLeft || document.body.scrollLeft;
+      div.addV = paddingB + paddingT + parseInt($(this).css('borderTopWidth')) + parseInt($(this).css('borderBottomWidth'));
+      if ($(this).css('borderCollapse') == 'collapse') {
+        div.addH = paddingL + paddingR + parseInt($(this).css('borderRightWidth'));
+        div.cellOffset = parseInt($(this).css('borderLeftWidth')) + parseInt($(table).css('borderLeftWidth'));
+      }
+      else {
+        div.addH = paddingL + paddingR;
+        div.cellOffset = parseInt($(this).css('borderLeftWidth'));
+      }
+
+      // Note that height() and width() are not used, because they sometimes
+      // return distorted values.
+      div.cellWidth = parseInt($(this).css('width')) + div.addH;
+      div.cellLeft = $(this).offset().left - div.cellOffset - scrollH;
+
+      // Keep track of biggest cell-height.
+      var cellHeight = parseInt($(this).css('height')) + div.addV;
+      if (table.maxCellHeight < cellHeight) {
+        table.maxCellHeight = cellHeight;
+      }
+
+      // Wrap the contents in another wrapper, to re-introduce its padding.
+      $(div).wrapInner('<div style="border: 0; margin: 0;"></div>');
+      $(div).children().css({
+        'paddingLeft': paddingL +'px',
+        'paddingRight': paddingR +'px',
+        'paddingTop': paddingT +'px',
+        'paddingBottom': paddingB +'px'
+      })[0];
+
+      // Remember first/last cell.
       if (!i++) {
-        // The first cell is as wide as the table to prevent gaps.
-        ref = table;
-        div.wide = true;
+        table.first = div;
       }
-      $(div).width(Math.max(0, $(ref).width() - parseInt($(div).css('paddingLeft'))));
+      table.last = div;
 
-      // Get position and store.
+      // Store data for later updates.
       div.cell = this;
       div.table = table;
       div.stickyMax = height;
       div.stickyPosition = $(this).offset().top;
+      div.savedScrollH = scrollH;
+    });
+
+    $('div.sticky-header', this).each(function () {
+      // Set position and size of the cloned cell.
+      $(this).css({
+        'left': this.cellLeft +'px',
+        'width': this.cellWidth +'px',
+        'height': table.maxCellHeight +'px'
+      })[0];
     });
+
+    // Adjust first/last cell order for RTL.
+    if ($(table).css('direction') == 'rtl') {
+      var temp = table.first;
+      table.first = table.last;
+      table.last = temp;
+    }
+
+    // Wrap the contents of leftmost cell into yet another sticky wrapper, to
+    // ensure correct position and alignment, and make the outer wrapper as
+    // wide as the table, to serve as background, masking any gaps between
+    // cloned cells. Recreate the right border of original cell on the inner
+    // wrapper.
+    table.first.innerOffset = parseInt($(table.first).css('borderLeftWidth'));
+    $(table.first).wrapInner('<div style="position: fixed; margin: 0; padding: 0; border-top: 0; border-bottom: 0; border-left: 0;"></div>');
+    $(table.first).children('div').css({
+      'z-index': parseInt($(table.first).css('z-index')),
+      'borderRightWidth': $(table.first).css('borderRightWidth'),
+      'borderRightStyle': $(table.first).css('borderRightStyle'),
+      'borderRightColor': $(table.first).css('borderRightColor'),
+      'top': parseInt($(table.first).css('borderTopWidth')) +'px',
+      'left': (table.first.cellLeft + table.first.innerOffset) +'px',
+      'width': table.first.cellWidth +'px',
+      'height': table.maxCellHeight +'px'
+    })[0];
+
+    $(table.first).css({
+      'z-index': 1,
+      'width': (table.last.cellLeft - table.first.cellLeft + table.last.cellWidth) +'px'
+    })[0];
+    table.first.wide = true;
+
     $(this).addClass('tableHeader-processed');
   });
 
   // Track scrolling.
   var scroll = function() {
     $(cells).each(function () {
-      // Fetch scrolling position.
+      // Vertical.
       var scroll = document.documentElement.scrollTop || document.body.scrollTop;
       var offset = scroll - this.stickyPosition - 4;
-      if (offset > 0 && offset < this.stickyMax - 100) {
+      if (offset > 0 && offset < this.stickyMax - 50) {
         $(this).css('visibility', 'visible');
       }
       else {
         $(this).css('visibility', 'hidden');
       }
+      // Horizontal.
+      var scrollH = document.documentElement.scrollLeft || document.body.scrollLeft;
+      if (this.savedScrollH != scrollH) {
+        this.savedScrollH = scrollH;
+        var cellLeft = $(this.cell).offset().left - this.cellOffset - scrollH;
+        if (this.wide) {
+          $(this).children('div').css('left', (cellLeft + this.innerOffset) +'px');
+        }
+        $(this).css('left', cellLeft +'px');
+      }
     });
   };
   $(window).scroll(scroll);
@@ -84,25 +179,50 @@ Drupal.behaviors.tableHeader = function 
     }
     time = setTimeout(function () {
 
-      // Precalculate table heights
+      // Precalculate table heights.
       $('table.sticky-table').each(function () {
         this.savedHeight = $(this).height();
-      });
-
-      $('table.sticky-table div.sticky-header').each(function () {
-        // Get position.
-        this.stickyPosition = $(this.cell).offset().top;
-        this.stickyMax = this.table.savedHeight;
 
-        // Reflow the cell.
-        var ref = this.cell;
-        if (this.wide) {
-          // Resize the first cell to fit the table.
-          ref = this.table;
-        }
-        $(this).width(Math.max(0, $(ref).width() - parseInt($(this).css('paddingLeft'))));
+        // Find the biggest cell-height.
+        this.maxCellHeight = 0;
+        $('div.sticky-header', this).each(function () {
+          var cellHeight = parseInt($(this.cell).css('height')) + this.addV;
+          if (this.table.maxCellHeight < cellHeight) {
+            this.table.maxCellHeight = cellHeight;
+          }
+        });
+
+        $('div.sticky-header', this).each(function () {
+          // Get position.
+          this.stickyPosition = $(this.cell).offset().top;
+          this.stickyMax = this.table.savedHeight;
+          var scrollH = document.documentElement.scrollLeft || document.body.scrollLeft;
+          this.cellWidth = parseInt($(this.cell).css('width')) + this.addH;
+          this.cellLeft = $(this.cell).offset().left - this.cellOffset - scrollH;
+
+          // Reflow the cell.
+          $(this).css({
+            'left': this.cellLeft +'px',
+            'width': this.cellWidth +'px',
+            'height': this.table.maxCellHeight +'px'
+          })[0];
+        });
+
+        // Update the special leftmost cell.
+        $(this.first).children('div').css({
+          'left': (this.first.cellLeft + this.first.innerOffset) +'px',
+          'width': this.first.cellWidth +'px',
+          'height': this.maxCellHeight +'px'
+        })[0];
+
+        $(this.first).css({
+          'width': (this.last.cellLeft - this.first.cellLeft + this.last.cellWidth) +'px'
+        })[0];
       });
 
+      // Resizing may change position of the tables, so update visibility.
+      $(scroll);
+
       // Reset timer
       time = null;
     }, 250);
