Author: manolo
Date: 2010-10-26 14:01:17 -0700 (Tue, 26 Oct 2010)
New Revision: 7759
Log:
Use Mac OS-defined character composition method. It allows to handle composed 
characters of many more languages than before (e.g., Polish, Greek).

Modified:
   branches/branch-1.3/FL/Fl_Input.H
   branches/branch-1.3/src/Fl_cocoa.mm
   branches/branch-1.3/src/Fl_compose.cxx

Modified: branches/branch-1.3/FL/Fl_Input.H
===================================================================
--- branches/branch-1.3/FL/Fl_Input.H   2010-10-26 20:43:03 UTC (rev 7758)
+++ branches/branch-1.3/FL/Fl_Input.H   2010-10-26 21:01:17 UTC (rev 7759)
@@ -37,10 +37,10 @@
   This is the FLTK text input widget. It displays a single line
   of text and lets the user edit it. Normally it is drawn with an
   inset box and a white background. The text may contain any
-  characters (even 0), and will correctly display anything, using
-  ^X notation for unprintable control characters and \\nnn notation
-  for unprintable characters with the high bit set. It assumes the
-  font can draw any characters in the ISO-8859-1 character set.</P>
+  characters (even 0), and will correctly display any UTF text, using
+  ^X notation for unprintable control characters. It assumes the
+ font can draw any characters of the used scripts, which is true
+ for standard fonts under MSWindows and Mac OS X.</P>
   
   <CENTER><TABLE border=1 WIDTH=90% summary="Fl_Input keyboard and mouse 
bindings.">
   
@@ -114,7 +114,10 @@
   also be able to type "dead key" prefix characters.  On X you will
   actually be able to see what dead key you typed, and if you then move
   the cursor without completing the sequence the accent will remain
-  inserted.</TD></TR>
+ inserted.
+ 
+ <p>Under Mac OS X, character composition is done as for any Mac application
+ using Mac OS-defined keystroke series.</TD></TR>
   </TABLE></CENTER>
   
   <!-- NEW PAGE -->

Modified: branches/branch-1.3/src/Fl_cocoa.mm
===================================================================
--- branches/branch-1.3/src/Fl_cocoa.mm 2010-10-26 20:43:03 UTC (rev 7758)
+++ branches/branch-1.3/src/Fl_cocoa.mm 2010-10-26 21:01:17 UTC (rev 7759)
@@ -875,141 +875,33 @@
 }
 
 
-/*
- * 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,
- 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
-   
-   Ptr resource;
-   TextEncoding encoding;
-   static TextEncoding lastEncoding = kTextEncodingMacRoman;
-   int len = 0;
-   KeyboardLayoutRef currentLayout = NULL;
-   static KeyboardLayoutRef lastLayout = NULL;
-   SInt32 currentLayoutId = 0;
-   static SInt32 lastLayoutId;
-   int hasLayoutChanged = false;
-   static Ptr uchr = NULL;
-   static Ptr KCHR = NULL;
-   // ScriptCode currentKeyScript;
-   
-   KLGetCurrentKeyboardLayout(&currentLayout);
-    if (currentLayout) {
-     KLGetKeyboardLayoutProperty(currentLayout, kKLIdentifier, (const 
void**)&currentLayoutId);
-     if ( (lastLayout != currentLayout) || (lastLayoutId != currentLayoutId) ) 
{
-       lastLayout = currentLayout;
-       lastLayoutId = currentLayoutId;
-       uchr = NULL;
-       KCHR = NULL;
-       if ((KLGetKeyboardLayoutProperty(currentLayout, kKLuchrData, (const 
void**)&uchr) == noErr) && (uchr != NULL)) {
-        // done
-       } else if ((KLGetKeyboardLayoutProperty(currentLayout, kKLKCHRData, 
(const void**)&KCHR) == noErr) && (KCHR != NULL)) {
-        // done
-       }
-       // FIXME No Layout property found. Now we have a problem. 
-     }
-   }
-   if (hasLayoutChanged) {
-     // deadKeyStateUp = deadKeyStateDown = 0;
-     if (KCHR != NULL) {
-       // FIXME this must not happen
-     } else if (uchr == NULL) {
-       KCHR = (Ptr) GetScriptManagerVariable(smKCHRCache);
-     }
-   }
-   if (uchr != NULL) {
-     // this is what I expect
-     resource = uchr;
-   } else {
-     resource = KCHR;
-     encoding = lastEncoding;
-     // this is actually not supported by the following code and will likely 
crash
-   }
-   
-   // now apply that keyboard mapping to our keycode
-   
-   int action;
-   //OptionBits options = 0;
-   // not used yet: OptionBits options = kUCKeyTranslateNoDeadKeysMask;
-   unsigned long keyboardType;
-   keycode &= 0xFF;
-   modifiers = (modifiers >> 8) & 0xFF;
-   keyboardType = LMGetKbdType();
-   OSStatus status;
-   UniCharCount actuallength;
-   UniChar utext[10];
-   
-   switch(eKind) {     
-     case kEventRawKeyDown:    action = kUCKeyActionDown; break;
-     case kEventRawKeyUp:      action = kUCKeyActionUp; break;
-     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,
-                          0, deadKeyStatePtr,
-                          10, &actuallength, utext);
-   
-   if (noErr != 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 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)
+static void calc_e_text(CFStringRef s, char *buffer, size_t len, unsigned sym)
 {
-  if ( (sym >= FL_KP && sym <= FL_KP_Last) || !(sym & 0xff00) ||
-        sym == FL_Tab || sym == FL_Enter) {
-    buffer[0] = key;
-    return 1;
-  } else {
+  int i, no_text_key = false;
+  static unsigned notext[] = { // keys that don't emit text
+    FL_BackSpace, FL_Print, FL_Scroll_Lock, FL_Pause,
+    FL_Insert, FL_Home, FL_Page_Up, FL_Delete, FL_End, FL_Page_Down,
+    FL_Left, FL_Up, FL_Right, FL_Down, 
+    FL_Menu, FL_Num_Lock, FL_Help 
+  };
+  int count = sizeof(notext)/sizeof(int);
+  
+  if (sym > FL_F && sym <= FL_F_Last) no_text_key = true;
+  else for (i=0; i < count; i++) {
+    if(notext[i] == sym) {
+      no_text_key = true;
+      break;
+      }
+  }
+  
+  if ( no_text_key) {
     buffer[0] = 0;
-    return 0;
+  } else {
+    CFStringGetCString(s, buffer, len, kCFStringEncodingUTF8);
   }
-} /* 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;
 
-
-// EXPERIMENTAL!
 // this gets called by CJK character palette input
 OSStatus carbonTextHandler( EventHandlerCallRef nextHandler, EventRef event, 
void *unused )
 {
@@ -1047,45 +939,7 @@
   return noErr;
 }
 
-static void processCompositionSequence(CFStringRef s, Fl_Window *window)
-// composed character sequences are sent here
-// they contain 2 unichars, the first comes from the deadkey and can be non 
ascii (e.g., diaeresis),
-// the second is the character to be modified (e.g., e to be accented)
-{
-  // unicodes: non-ascii unicode chars produced by deadkeys
-  // asciis: corresponding ascii chars expected by Fl::compose()
-  //                           diaeresis acute-accent circumflex tilde 
ring-above 
-  static UniChar unicodes[] = {0xA8,      0xB4,      0x2C6,     0x2DC, 0x2DA };
-  static char asciis[] = {     ':',        '\'',      '^',       '~',    '*' };
-  if (CFStringGetLength(s) == 0) return;
-  char text[10];
-  char buffer[10];
-  UniChar unis[2];
-  CFStringGetCharacters(s, CFRangeMake(0, 2), unis);
-  for(unsigned int i = 0; i < sizeof(asciis)/sizeof(char); i++) {
-    if (unis[0] == unicodes[i]) {
-      // replace the non-ascii unicode by the corresponding ascii value
-      unis[0] = (UniChar)asciis[i];
-      break;
-    }
-  }
-  CFStringRef smod = CFStringCreateWithCharacters(kCFAllocatorDefault, unis, 
2);
-  CFStringGetCString(smod, buffer, sizeof(buffer), kCFStringEncodingUTF8);
-  CFRelease(smod);
-  Fl::e_keysym = 0;
-  Fl::e_state = 0;
-  Fl::e_length = 1;
-  Fl::e_text = text;
-  Fl::e_text[0] = buffer[0];
-  Fl::handle(FL_KEYBOARD, window);
-  Fl::e_keysym = 0;
-  Fl::e_state = 0;
-  Fl::e_length = 1;
-  Fl::e_text[0] = buffer[1];
-  Fl::handle(FL_KEYBOARD, window);
-}
 
-
 /*
  * handle cocoa keyboard events
  */
@@ -1106,36 +960,41 @@
   
   // get the key code only for key events
   UInt32 keyCode = 0, maskedKeyCode = 0;
-  unichar key = 0;
-  unsigned char keychar = 0;
   unsigned short sym = 0;
   keyCode = [theEvent keyCode];
   NSString *s = [theEvent characters];
   static BOOL compose = NO;
   static NSText *edit;
   static int countevents;
-  static CFMutableStringRef sequence;  // will contain the two characters of 
the composition sequence
   if ( (mods & NSShiftKeyMask) && (mods & NSCommandKeyMask) ) {
     s = [s uppercaseString]; // US keyboards return lowercase letter in s if 
cmd-shift-key is hit
   }
   if (compose) {       // we are in a composition sequence
-    // the only benefit of sending events to the NSText object edit is that 
the deadkey becomes visible
-    // at its keyUp event; without this, the deadkey remains invisible
     if ([s length] == 0) {     // occurs if 2 deadkeys are typed successively 
by error
       compose = NO;
       [edit setString:@""];
-      CFRelease(sequence);
       fl_unlock_function();
       return noErr;
     }
-    [edit interpretKeyEvents:[NSArray arrayWithObject:theEvent]];
+    mods_to_e_state( mods ); // process modifier keys
+    Fl::e_keysym = Fl::e_original_keysym = macKeyLookUp[keyCode];
+    if([theEvent type] == NSKeyDown) { // keydown of the 2nd key of the 
compose sequence
+      [edit interpretKeyEvents:[NSArray arrayWithObject:theEvent]];
+      }
+    else { // keyup of the dead key: there's text in s: display it temporarily
+      CFStringGetCString((CFStringRef)s, buffer, sizeof(buffer), 
kCFStringEncodingUTF8);
+      Fl::e_length = strlen(buffer);
+      Fl::e_text = buffer;
+      Fl::handle(FL_KEYBOARD, window);    
+    }
     countevents++;
-    UniChar deadkey;
-    CFStringGetCharacters((CFStringRef)s, CFRangeMake(0, 1), &deadkey);
-    CFStringAppendCharacters(sequence, &deadkey, 1);// done for keyUp of 
deadkey and keyDown of next key
     if (countevents >= 3) {    // end of composition sequence
-      processCompositionSequence( sequence, window );
-      CFRelease(sequence);
+      // the composed char is now in s, handle it
+      CFStringGetCString((CFStringRef)s, buffer, sizeof(buffer), 
kCFStringEncodingUTF8);
+      Fl::e_length = strlen(buffer);
+      Fl::e_text = buffer;
+      Fl::compose_state = 1; // signals the end of a composition sequence
+      Fl::handle(FL_KEYBOARD, window);
       [edit setString:@""];    // clear the content of the edit object
       compose=NO;              // character composition is now complete
     }
@@ -1144,23 +1003,13 @@
   }
   if ([s length] == 0) {       // this is a dead key that must be combined 
with the next key to be pressed
     while (window->parent()) window = window->window();
-    Fl::e_keysym = FL_Control_R; // first simulate pressing of the compose key 
(FL_Control_R)
-    Fl::e_text = (char*)"";
-    Fl::e_length = 0;
-    Fl::handle(FL_KEYBOARD, window); 
     compose=YES;
-    // then send remaining events to an object of type NSText that helps 
handle character composition sequences
+    // send remaining keydown events to an object of type NSText that handles 
character composition sequences
     edit = [[theEvent window]  fieldEditor:YES forObject:nil];
-    [edit interpretKeyEvents:[NSArray arrayWithObject:theEvent]];
+    [edit interpretKeyEvents:[NSArray arrayWithObject:theEvent]];    
     countevents = 1;
-    sequence = CFStringCreateMutable(NULL, 2);
     fl_unlock_function();
     return noErr;
-  } else {
-    char buff[10];
-    CFStringGetCString((CFStringRef)s, buff, sizeof(buff), 
kCFStringEncodingUnicode);
-    key = *(unichar*)buff;
-    keychar = buff[0];
   }
   // extended keyboards can also send sequences on key-up to generate Kanji 
etc. codes.
   // Some observed prefixes are 0x81 to 0x83, followed by an 8 bit keycode.
@@ -1187,15 +1036,10 @@
         sendEvent = FL_KEYUP;
         Fl::e_state &= 0xbfffffff; // clear the deadkey flag
       }
-      mods_to_e_state( mods ); // we process modifier keys at the same time
-      // if the user pressed alt/option, event_key should have the keycap, 
-      // but event_text should generate the international symbol
+      mods_to_e_state( mods ); // process modifier keys
       sym = macKeyLookUp[maskedKeyCode];
-      if ( isalpha(key) )
-        sym = tolower(key);
-      else if ( Fl::e_state&FL_CTRL && key<32 && sym<0xff00)
-        sym = key+96;
-      else if ( Fl::e_state&FL_ALT && sym<0xff00) {    // find the keycap of 
this key
+      if (sym < 0xff00) { // a "simple" key
+       // find the result of this key without modifier
        NSString *sim = [theEvent charactersIgnoringModifiers];
        UniChar one;
        CFStringGetCharacters((CFStringRef)sim, CFRangeMake(0, 1), &one);
@@ -1206,16 +1050,11 @@
       
       Fl::e_keysym = Fl::e_original_keysym = sym;
       // Handle FL_KP_Enter on regular keyboards and on Powerbooks
-      if ( maskedKeyCode==0x4c || maskedKeyCode==0x34) key=0x0d;    
-      static UInt32 deadKeyState = 0; // must be cleared when losing focus
-      int l =  (*keycode_function)(buffer, 31, kind, keyCode, mods, 
&deadKeyState, keychar, sym);
-      if (l > 0) {
-        CFStringGetCString((CFStringRef)s, buffer, sizeof(buffer), 
kCFStringEncodingUTF8);
-      }
+      if ( maskedKeyCode==0x4c || maskedKeyCode==0x34) s = @"\r";    
+      calc_e_text((CFStringRef)s, buffer, sizeof(buffer), sym);
       Fl::e_length = strlen(buffer);
       Fl::e_text = buffer;
-      buffer[Fl::e_length] = 0; // just in case...
-      }
+    }
       break;
     default:
       fl_unlock_function();
@@ -1232,7 +1071,6 @@
 }
 
 
-
 /*
  * Open callback function to call...
  */
@@ -1557,18 +1395,7 @@
         
         CFRelease(execUrl);
       }
-      
-      keycode_function = keycode_wrap_old; // under Cocoa we always use this 
one
-      /*  // imm: keycode handler stub setting - use Gestalt to determine the 
running system version,
-       *  // then set the keycode_function pointer accordingly
-       *  if (MACsystemVersion >= 0x1050) {      // 10.5.0 or later
-       *    keycode_function = keycodeToUnicode;
-       *  }
-       *  else {
-       *    keycode_function = keycode_wrap_old; // pre-10.5 mechanism
-       *  }
-       */
-      
+            
       if ( !bundle )
       {
         // Earlier versions of this code tried to use weak linking, however it

Modified: branches/branch-1.3/src/Fl_compose.cxx
===================================================================
--- branches/branch-1.3/src/Fl_compose.cxx      2010-10-26 20:43:03 UTC (rev 
7758)
+++ branches/branch-1.3/src/Fl_compose.cxx      2010-10-26 21:01:17 UTC (rev 
7759)
@@ -37,16 +37,9 @@
 //#define OLD_DEAD_KEY_CODE
 
 
-#ifdef __APPLE__
+#ifndef __APPLE__
 
 static const char* const compose_pairs =
-"  ! % # $ y=| & : c a <<~ - r _ * +-2 3 ' u p . , 1 o >>141234? "//00A0 ...
-"`A'A^A~A:A*AAE,C`E'E^E:E`I'I^I:I-D~N`O'O^O~O:Ox O/`U'U^U:U'YTHss" //00C0 ...
-"`a'a^a~a:a*aae,c`e'e^e:e`i'i^i:i-d~n`o'o^o~o:o-:o/`u'u^u:u'yth:y";//00E0 ...
-
-#else
-
-static const char* const compose_pairs =
 "=E  _'f _\"..+ ++^ %%^S< OE  ^Z    ^''^^\"\"^-*- --~ TM^s> oe  ^z:Y" 
 "  ! % # $ y=| & : c a <<~ - r _ * +-2 3 ' u p . , 1 o >>141234? "
 "`A'A^A~A:A*AAE,C`E'E^E:E`I'I^I:I-D~N`O'O^O~O:Ox O/`U'U^U:U'YTHss"
@@ -85,6 +78,26 @@
 int Fl::compose_state = 0;
 #endif
 
+#ifdef __APPLE__
+// under Mac OS X character composition is handled by the OS
+int Fl::compose(int& del) {
+  if(Fl::e_length == 0 || Fl::e_keysym == FL_Enter || Fl::e_keysym == 
FL_KP_Enter || 
+     Fl::e_keysym == FL_Tab || Fl::e_keysym == FL_Escape || 
Fl::e_state&FL_META || Fl::e_state&FL_CTRL) {
+    del = 0;
+    return 0;
+    }
+  if(Fl::compose_state) {
+    del = 1;
+    Fl::compose_state = 0;
+    }
+  else {
+    del = 0;
+    }
+  return 1;
+}
+
+#else
+
 /** Any text editing widget should call this for each FL_KEYBOARD event.
     Use of this function is very simple.
 
@@ -114,11 +127,7 @@
   //
   // OSX users sometimes need to hold down ALT for keys, so we only check
   // for META on OSX...
-#ifdef __APPLE__
-  if ((e_state & FL_META) && !(ascii & 128)) return 0;
-#else
   if ((e_state & (FL_ALT|FL_META)) && !(ascii & 128)) return 0;
-#endif // __APPLE__
 
   if (compose_state == 1) { // after the compose key
     if ( // do not get distracted by any modifier keys
@@ -134,15 +143,9 @@
       ) return 0;
 
     if (ascii == ' ') { // space turns into nbsp
-#ifdef __APPLE__
-      int len = fl_utf8encode(0xCA, e_text);
-      e_text[len] = '\0';
-      e_length = len;
- #else
       int len = fl_utf8encode(0xA0, e_text);
       e_text[len] = '\0';
       e_length = len;
-#endif
       compose_state = 0;
       return 1;
     } else if (ascii < ' ' || ascii == 127) {
@@ -171,19 +174,6 @@
   } else if (compose_state) { // second character of compose
 
     char c1 = char(compose_state); // retrieve first character
-#ifdef __APPLE__
-    if ( (c1==0x60 && ascii==0xab) || (c1==0x27 && ascii==0x60)) {
-      del = 1;
-      compose_state = '^';
-      e_text[0] = 0xf6;
-      return 1;
-    }
-    if (ascii==' ') {
-      del = 0;
-      compose_state = 0;
-      return 0;
-    }
-#endif
     // now search for the pair in either order:
     for (const char *p = compose_pairs; *p; p += 2) {
       if (p[0] == ascii && p[1] == c1 || p[1] == ascii && p[0] == c1) {
@@ -206,16 +196,7 @@
     return 1;
   }
 
-#ifdef WIN32
-#elif (defined __APPLE__)
-  if (e_state & 0x40000000) {
-    if (ascii<0x80)
-      compose_state = ascii;
-    else
-      compose_state = compose_pairs[(ascii-0x80)*2];
-    return 1;
-  }
-#else
+#ifndef WIN32
   // See if they typed a dead key.  This gets it into the same state as
   // typing prefix+accent:
   if (i >= 0xfe50 && i <= 0xfe5b) {
@@ -246,5 +227,9 @@
   return 0;
 }
 
+#endif // __APPLE__
 
+//
+// End of "$Id$"
+//
 

_______________________________________________
fltk-commit mailing list
[email protected]
http://lists.easysw.com/mailman/listinfo/fltk-commit

Reply via email to