diff options
| author | Manolo Gouy <Manolo> | 2010-10-26 21:01:17 +0000 |
|---|---|---|
| committer | Manolo Gouy <Manolo> | 2010-10-26 21:01:17 +0000 |
| commit | 901bc31ec35c79ea245a2895ff7a80657d01cf8b (patch) | |
| tree | 488b52e672804a207ac229f912b55c6cae6f74c4 /src | |
| parent | cac2ff33395798abaf2fa8a3041dea3819e4a36e (diff) | |
Use Mac OS-defined character composition method. It allows to handle composed characters of many more languages than before (e.g., Polish, Greek).
git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3@7759 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
Diffstat (limited to 'src')
| -rw-r--r-- | src/Fl_cocoa.mm | 271 | ||||
| -rw-r--r-- | src/Fl_compose.cxx | 67 |
2 files changed, 75 insertions, 263 deletions
diff --git a/src/Fl_cocoa.mm b/src/Fl_cocoa.mm index ec4513150..e74b1a4db 100644 --- a/src/Fl_cocoa.mm +++ b/src/Fl_cocoa.mm @@ -875,141 +875,33 @@ static void cocoaMouseHandler(NSEvent *theEvent) } -/* - * 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(¤tLayout); - if (currentLayout) { - KLGetKeyboardLayoutProperty(currentLayout, kKLIdentifier, (const void**)¤tLayoutId); - 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) -{ - if ( (sym >= FL_KP && sym <= FL_KP_Last) || !(sym & 0xff00) || - sym == FL_Tab || sym == FL_Enter) { - buffer[0] = key; - return 1; - } else { +static void calc_e_text(CFStringRef s, char *buffer, size_t len, unsigned sym) +{ + 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,44 +939,6 @@ OSStatus carbonTextHandler( EventHandlerCallRef nextHandler, EventRef event, voi 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 @@ OSStatus cocoaKeyboardHandler(NSEvent *theEvent) // 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 @@ OSStatus cocoaKeyboardHandler(NSEvent *theEvent) } 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 @@ OSStatus cocoaKeyboardHandler(NSEvent *theEvent) 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 @@ OSStatus cocoaKeyboardHandler(NSEvent *theEvent) 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 @@ OSStatus cocoaKeyboardHandler(NSEvent *theEvent) } - /* * Open callback function to call... */ @@ -1557,18 +1395,7 @@ void fl_open_display() { 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 diff --git a/src/Fl_compose.cxx b/src/Fl_compose.cxx index 3f2ff0bae..1601c74dd 100644 --- a/src/Fl_compose.cxx +++ b/src/Fl_compose.cxx @@ -37,14 +37,7 @@ //#define OLD_DEAD_KEY_CODE -#ifdef __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 +#ifndef __APPLE__ static const char* const compose_pairs = "=E _'f _\"..+ ++^ %%^S< OE ^Z ^''^^\"\"^-*- --~ TM^s> oe ^z:Y" @@ -85,6 +78,26 @@ static char dead_keys[] = { 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 @@ int Fl::compose(int& del) { // // 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 @@ int Fl::compose(int& del) { ) 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 @@ int Fl::compose(int& del) { } 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 @@ int Fl::compose(int& del) { 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 @@ int Fl::compose(int& del) { return 0; } +#endif // __APPLE__ +// +// End of "$Id$" +// |
