diff --git a/CHANGES b/CHANGES
index b24d6b6cf..d7ff4a44c 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,5 +1,6 @@
 CHANGES IN FLTK 1.3.0
 
+	- Improved handling of composed keys in OS X 10.5 and up
 	- Updated the bundled libpng to v1.2.33.
 	- Fixed callback would not be called when shortcut was used with
           radio and toggle buttons in default FL_RELEASE mode.
diff --git a/src/Fl_mac.cxx b/src/Fl_mac.cxx
index 7edb07bea..7db76cbdf 100644
--- a/src/Fl_mac.cxx
+++ b/src/Fl_mac.cxx
@@ -1096,13 +1096,15 @@ static unsigned short keycode_to_sym( UInt32 keyCode, UInt32 mods, unsigned shor
 }
 
 /*
- *
+ * keycode_function for post-10.5 systems, allows more sophisticated decoding of keys
  */
 static int keycodeToUnicode(
                 char * uniChars, int maxChars,
                 EventKind eKind,
                 UInt32 keycode, UInt32 modifiers,
-                UInt32 * deadKeyStatePtr)
+                UInt32 * deadKeyStatePtr,
+                unsigned char,  // not used in this function
+                unsigned short) // not used in this function
 {
   // first get the keyboard mapping in a post 10.2 way
   
@@ -1171,37 +1173,59 @@ static int keycodeToUnicode(
     case kEventRawKeyRepeat:  action = kUCKeyActionAutoKey; break;
     default: return 0;
   }
-  
+
+  UInt32 deadKeyState = *deadKeyStatePtr;
+  if ((action==kUCKeyActionUp)&&(*deadKeyStatePtr))
+    deadKeyStatePtr = &deadKeyState;
+
   status = UCKeyTranslate(
                           (const UCKeyboardLayout *) uchr,
                           keycode, action, modifiers, keyboardType,
-                          options, deadKeyStatePtr,
+                          0, deadKeyStatePtr,
                           10, &actuallength, utext);
-  
-  if ((0 == actuallength) && (0 != *deadKeyStatePtr)) {
-    /*
-     * More data later
-     */
-    
-    return 0; 
-  }
-  
-  *deadKeyStatePtr = 0; 
-  
+
   if (noErr != status) {
-    fprintf(stderr,"UCKeyTranslate failed: %d", (int) status);
+    fprintf(stderr,"UCKeyTranslate failed: %d\n", (int) status);
     actuallength = 0;
   }
+
+  // convert the list of unicode chars into utf8
   // FIXME no bounds check (see maxchars)
   unsigned i;
   for (i=0; i<actuallength; ++i) {
     len += fl_utf8encode(utext[i], uniChars+len);
   }
   uniChars[len] = 0;
-  
-  return actuallength;
+  return len;
 }
 
+/*
+ * keycode_function for pre-10.5 systems, this is the "historic" fltk Mac key handling
+ */
+static int keycode_wrap_old(
+                char * buffer,
+                int, EventKind, UInt32, // not used in this function
+                UInt32, UInt32 *,       // not used in this function
+                unsigned char key,
+                unsigned short sym)
+{
+  if ( (sym >= FL_KP && sym <= FL_KP_Last) || !(sym & 0xff00) ||
+        sym == FL_Tab || sym == FL_Enter) {
+    buffer[0] = key;
+    return 1;
+  } else {
+    buffer[0] = 0;
+    return 0;
+  }
+} /* keycode_wrap_old */
+/* 
+ * Stub pointer to select appropriate keycode_function per operating system version. This function pointer
+ * is initialised in fl_open_display, based on the runtime identification of the host OS version. This is
+ * intended to allow us to utilise 10.5 services dynamically to improve Unicode handling, whilst still 
+ * allowing code to run satisfactorily on older systems.
+ */
+static int (*keycode_function)(char*, int, EventKind, UInt32, UInt32, UInt32*, unsigned char, unsigned short) = keycode_wrap_old;
+
 
 /**
  * handle carbon keyboard events
@@ -1234,7 +1258,7 @@ pascal OSStatus carbonKeyboardHandler(
     GetEventParameter( event, kEventParamKeyMacCharCodes, typeChar, 
                        NULL, sizeof(char), NULL, &key );
   }
-  /* output a human readbale event identifier for debugging
+  /* output a human readable event identifier for debugging
   const char *ev = "";
   switch (kind) {
     case kEventRawKeyDown: ev = "kEventRawKeyDown"; break;
@@ -1249,6 +1273,8 @@ pascal OSStatus carbonKeyboardHandler(
   {
   case kEventRawKeyDown:
   case kEventRawKeyRepeat:
+/*
+    // FIXME Matt: For 10.5, the keycode_function will handle all this. This is untested for ealier versions of OS X.
     // When the user presses a "dead key", no information is send about
     // which dead key symbol was created. So we need to trick Carbon into
     // giving us the code by sending a "space" after the "dead key".
@@ -1263,6 +1289,7 @@ pascal OSStatus carbonKeyboardHandler(
     } else {
       Fl::e_state &= 0xbfffffff; // clear the deadkey flag
     }
+*/
     sendEvent = FL_KEYBOARD;
     // fall through
   case kEventRawKeyUp:
@@ -1287,22 +1314,14 @@ pascal OSStatus carbonKeyboardHandler(
     // Matt: to Carbon. The kEventKeyModifierNumLockMask is only set when
     // Matt: a numeric keypad key is pressed and does not correspond with
     // Matt: the NumLock light in PowerBook keyboards.
-#if 1
-    if ( (sym >= FL_KP && sym <= FL_KP_Last) || !(sym & 0xff00) ||
-            sym == FL_Tab || sym == FL_Enter) {
-      buffer[0] = key;
-      Fl::e_length = 1;
-    } else {
-      buffer[0] = 0;
-      Fl::e_length = 0;
-    }
-#else
-    // Matt: attempt to get the correct Unicode character(S) from our keycode
+
+    // Matt: attempt to get the correct Unicode character(s) from our keycode
+    // imm:  keycode_function function pointer added to allow us to use different functions
+    // imm:  depending on which OS version we are running on (tested and set in fl_open_display)
     static UInt32 deadKeyState = 0; // must be cleared when losing focus
-    Fl::e_length = keycodeToUnicode(buffer, 31, kind, keyCode, mods, &deadKeyState);
-#endif
+    Fl::e_length = (*keycode_function)(buffer, 31, kind, keyCode, mods, &deadKeyState, key, sym);
     Fl::e_text = buffer;
-    // insert UnicodeHandling here!
+    buffer[Fl::e_length] = 0; // just in case...
     break;
   case kEventRawKeyModifiersChanged: {
     UInt32 tMods = prevMods ^ mods;
@@ -1467,12 +1486,31 @@ void fl_open_display() {
         CFRelease(execUrl);
       }
 
+    // imm: keycode handler stub setting - use Gestalt to determine the running system version,
+    // then set the keycode_function pointer accordingly
+    SInt32 MacVersion;
+    if (Gestalt(gestaltSystemVersion, &MacVersion) == noErr)
+    {
+//      SInt32 maj, min, fix;
+//      Gestalt(gestaltSystemVersionMajor, &maj);   // e.g. 10
+//      Gestalt(gestaltSystemVersionMinor, &min);   // e.g.  4
+//      Gestalt(gestaltSystemVersionBugFix, &fix);  // e.g. 11
+      if(MacVersion >= 0x1050) { // 10.5.0 or later
+        keycode_function = keycodeToUnicode;
+      }
+      else {
+        keycode_function = keycode_wrap_old; // pre-10.5 mechanism
+      }
+    }
+    // else our default handler will be used (keycode_wrap_old)
+
+
       if( !bundle )
       {
         // Earlier versions of this code tried to use weak linking, however it
-	// appears that this does not work on 10.2.  Since 10.3 and higher provide
-	// both TransformProcessType and CPSEnableForegroundOperation, the following
-	// conditional code compiled on 10.2 will still work on newer releases...
+        // appears that this does not work on 10.2.  Since 10.3 and higher provide
+        // both TransformProcessType and CPSEnableForegroundOperation, the following
+        // conditional code compiled on 10.2 will still work on newer releases...
         OSErr err;
 
 #if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_2