cvs diff -u (in directory C:\CVS\drupalpatch)
cvs diff: Diffing .
cvs diff: Diffing database
cvs diff: Diffing includes
Index: includes/common.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/common.inc,v
retrieving revision 1.448
diff -u -r1.448 common.inc
--- includes/common.inc	25 May 2005 06:28:59 -0000	1.448
+++ includes/common.inc	26 May 2005 01:28:26 -0000
@@ -1070,6 +1070,61 @@
 }
 
 /**
+ * Return the HTML attribute for an access key
+ */
+function form_accesskey($label) {
+  $key = _form_get_accesskey($label);
+  return $key !== NULL ? ' accesskey="'. $key .'"' : '';
+}
+
+/**
+ * Return the access key for an item with the specified label.
+ */
+function _form_get_accesskey($label) {
+  static $keys = NULL;
+  static $map = NULL;
+
+  // Set up accesskeys for common commands to ensure they are always mapped to
+  // the same keys across Drupal.
+  if (!is_array($keys)) {
+    $keys = array();
+    $map = array();
+    _form_get_accesskey(t('Preview'));
+    _form_get_accesskey(t('Submit'));
+    _form_get_accesskey(t('Delete'));
+    _form_get_accesskey(t('Save configuration'));
+    _form_get_accesskey(t('Reset to defaults'));
+  }
+  
+  // Check for existing mapping.
+  if (isset($map[$label])) {
+    return $map[$label];
+  }
+  
+  // Find the first possible accesskey that is not taken
+  $pos = 0;
+  $len = strlen($label);
+  while ($pos < $len) {
+    // Take next character from label
+    $char = chop_utf8($label, 1, $pos);
+    $charlen = strlen($char);
+    $pos += $charlen;
+    // Restrict character set
+    if (ereg("[^\x80-\xF7[:alnum:]]", $char)) {
+      continue;
+    }
+    // We can only safely uppercase ASCII characters
+    if ($charlen == 1) $char = strtoupper($char);
+    // Check for existing mapping.
+    if (!isset($keys[$char])) {
+      $keys[$char] = true;
+      $map[$label] = $char;
+      return $char;
+    }
+  }
+}
+
+/**
  * Format a general form item.
  *
  * @param $title
@@ -1459,7 +1514,7 @@
  *   A themed HTML string representing the button.
  */
 function form_button($value, $name = 'op', $type = 'submit', $attributes = NULL) {
-  return '<input type="'. $type .'" class="form-'. $type .'" name="'. $name .'" value="'. check_plain($value) .'" '. drupal_attributes($attributes) ." />\n";
+  return '<button type="'. $type .'" class="form-'. $type .'" name="'. $name .'" value="'. check_plain($value) .'"'. drupal_attributes($attributes) . form_accesskey($value) .'>'. theme('label_key', check_plain($value)) .'</button>';
 }
 
 /**
@@ -1776,7 +1831,7 @@
 }
 
 /**
- * Truncate a UTF-8-encoded string safely.
+ * Truncate a UTF-8-encoded string to no more than $len bytes.
  *
  * If the end position is in the middle of a UTF-8 sequence, it scans backwards
  * until the beginning of the byte sequence.
@@ -1789,7 +1844,7 @@
  * @param $string
  *   The string to truncate.
  * @param $len
- *   An upper limit on the returned string length.
+ *   An upper limit on the returned string length in bytes.
  * @param $wordsafe
  *   Flag to truncate at nearest space. Defaults to FALSE.
  * @return
@@ -1811,6 +1866,35 @@
 }
 
 /**
+ * Chop off a piece of a UTF-8-encoded string, at least $len characters long.
+ *
+ * Use this function to get a certain amount of characters from the start of a
+ * string.
+ *
+ * @param $string
+ *   The string to chop from.
+ * @param $len
+ *   The amount of characters to return.
+ * @param $start
+ *   The byte index to start from in $string. Defaults to 0.
+ * @return
+ *   The truncated string.
+ */
+function chop_utf8($string, $len, $start = 0) {
+  $slen = strlen($string);
+  for ($chars = -1, $i = $start; $i < $slen; ++$i) {
+    $c = ord($string{$i});
+    if ($c < 0x80 || $c >= 0xC0) {
+      ++$chars;
+    }
+    if ($chars == $len) {
+      return substr($string, $start, $i - $start);
+    }
+  }
+  return $start ? substr($string, $start) : $string;
+}
+
+/**
  * Encodes MIME/HTTP header values that contain non-ASCII, UTF-8 encoded
  * characters.
  *
Index: includes/theme.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/theme.inc,v
retrieving revision 1.238
diff -u -r1.238 theme.inc
--- includes/theme.inc	25 May 2005 06:03:17 -0000	1.238
+++ includes/theme.inc	26 May 2005 01:28:29 -0000
@@ -598,10 +598,10 @@
 
   if ($title) {
     if ($id) {
-      $output .= ' <label for="'. form_clean_id($id) .'">'. $title .':</label>'. $required ."<br />\n";
+      $output .= ' <label for="'. form_clean_id($id) .'"'. form_accesskey($title) .'>'. theme('label_key', $title) .':</label>'. $required ."<br />\n";
     }
     else {
-      $output .= ' <label>'. $title .':</label>'. $required ."<br />\n";
+      $output .= ' <label '. form_accesskey($title) .'>'. theme('label_key', $title) .':</label>'. $required ."<br />\n";
     }
   }
 
@@ -616,6 +616,18 @@
   return $output;
 }
 
+/**
+ * Return a label themed with an access key.
+ */
+function theme_label_key($label) {
+  $key = _form_get_accesskey($label);
+  if ($key != NULL) {
+    return preg_replace('/'. preg_quote($key) .'/i', '<span class="accesskey">\0</span>', $label, 1);
+  }
+  else {
+    return $label;
+  }
+}
 
 /**
  * Return a themed submenu, typically displayed under the tabs.
cvs diff: Diffing misc
Index: misc/drupal.css
===================================================================
RCS file: /cvs/drupal/drupal/misc/drupal.css,v
retrieving revision 1.106
diff -u -r1.106 drupal.css
--- misc/drupal.css	25 May 2005 01:12:15 -0000	1.106
+++ misc/drupal.css	26 May 2005 01:28:29 -0000
@@ -84,6 +84,9 @@
 /*
 ** Other common styles
 */
+.accesskey {
+  text-decoration: underline;
+}
 .breadcrumb {
   padding-bottom: .5em
 }
