DO NOT REPLY TO THIS MESSAGE. INSTEAD, POST ANY RESPONSES TO THE LINK BELOW.
[STR New]
Link: http://www.fltk.org/str.php?L2599
Version: 1.3-feature
Attached file "fltk-1.3r8628-dead-chars-x11win32.patch"...
Link: http://www.fltk.org/str.php?L2599
Version: 1.3-feature
Index: src/Fl_x.cxx
===================================================================
--- src/Fl_x.cxx (revision 8625)
+++ src/Fl_x.cxx (working copy)
@@ -922,9 +922,6 @@
#endif
}
- if ( XFilterEvent((XEvent *)&xevent, 0) )
- return(1);
-
switch (xevent.type) {
case KeymapNotify:
@@ -1219,9 +1216,11 @@
case KeyRelease: {
KEYPRESS:
int keycode = xevent.xkey.keycode;
+ static int real_keycode;
fl_key_vector[keycode/8] |= (1 << (keycode%8));
static char *buffer = NULL;
static int buffer_len = 0;
+ static char *compose_buffer = NULL;
int len;
KeySym keysym;
if (buffer_len == 0) {
@@ -1232,6 +1231,12 @@
event = FL_KEYDOWN;
int len = 0;
+ // keycode 0 is a fake key, so looking that up is pointless,
+ // instead we rely on the fact that the preceding event was the
+ // real key
+ if (keycode != 0)
+ real_keycode = keycode;
+
if (fl_xim_ic) {
Status status;
len = XUtf8LookupString(fl_xim_ic, (XKeyPressedEvent *)&xevent.xkey,
@@ -1243,7 +1248,113 @@
len = XUtf8LookupString(fl_xim_ic, (XKeyPressedEvent *)&xevent.xkey,
buffer, buffer_len, &keysym, &status);
}
- keysym = XKeycodeToKeysym(fl_display, keycode, 0);
+
+ // if this returns true, then Xlib has done some compose processing
+ if (XFilterEvent((XEvent *)&xevent, 0)) {
+ XEvent peekevent;
+
+ // store a copy of the current symbol as it'll get
+ // overwritten with the composed character in the next
+ // iteration
+ if (len) {
+ if (compose_buffer)
+ free(compose_buffer);
+ compose_buffer = strdup(buffer);
+
+ Fl::e_compose_symbol = compose_buffer;
+ } else {
+ // Xutf8LookupString() doesn't give us anything for dead
+ // symbols though, so we need to figure out the symbol
+ // ourselves using the keysym
+ switch (keysym) {
+ case XK_dead_grave:
+ Fl::e_compose_symbol = "\314\200"; // U+0300 COMBINING GRAVE
ACCENT
+ break;
+ case XK_dead_acute:
+ Fl::e_compose_symbol = "\314\201"; // U+0301 COMBINING ACUTE
ACCENT
+ break;
+ case XK_dead_circumflex:
+ Fl::e_compose_symbol = "\314\202"; // U+0302 COMBINING
CIRCUMFLEX ACCENT
+ break;
+ case XK_dead_tilde:
+ Fl::e_compose_symbol = "\314\203"; // U+0303 COMBINING TILDE
+ break;
+ case XK_dead_macron:
+ Fl::e_compose_symbol = "\314\204"; // U+0304 COMBINING MACRON
+ break;
+ case XK_dead_breve:
+ Fl::e_compose_symbol = "\314\206"; // U+0306 COMBINING BREVE
+ break;
+ case XK_dead_abovedot:
+ Fl::e_compose_symbol = "\314\207"; // U+0307 COMBINING DOT ABOVE
+ break;
+ case XK_dead_diaeresis:
+ Fl::e_compose_symbol = "\314\210"; // U+0308 COMBINING DIAERESIS
+ break;
+ case XK_dead_abovering:
+ Fl::e_compose_symbol = "\314\212"; // U+030A COMBINING RING
ABOVE
+ break;
+ case XK_dead_doubleacute:
+ Fl::e_compose_symbol = "\314\213"; // U+030B COMBINING DOUBLE
ACUTE ACCENT
+ break;
+ case XK_dead_caron:
+ Fl::e_compose_symbol = "\314\214"; // U+030C COMBINING CARON
+ break;
+ case XK_dead_cedilla:
+ Fl::e_compose_symbol = "\314\247"; // U+0327 COMBINING CEDILLA
+ break;
+ case XK_dead_ogonek:
+ Fl::e_compose_symbol = "\314\250"; // U+0328 COMBINING OGONEK
+ break;
+ case XK_dead_iota:
+ Fl::e_compose_symbol = "\341\266\245"; // U+1DA5 MODIFIER
LETTER SMALL IOTA
+ break;
+ case XK_dead_voiced_sound:
+ Fl::e_compose_symbol = "\343\202\231"; // U+3099 COMBINING
KATAKANA-HIRAGANA VOICED SOUND MARK
+ break;
+ case XK_dead_semivoiced_sound:
+ Fl::e_compose_symbol = "\343\202\232"; // U+309A COMBINING
KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK
+ break;
+ case XK_dead_belowdot:
+ Fl::e_compose_symbol = "\314\243"; // U+0323 COMBINING DOT BELOW
+ break;
+ default:
+ // this is some unknown compose character
+ Fl::e_compose_symbol = "";
+ }
+ }
+ // We don't want to display anything for intermediate stages, so
+ // clear out the event text
+ len = 0;
+
+ // if a new character was produced then Xlib has put back an event
+ // on the queue with keycode 0
+ if (XPending(fl_display)) {
+ XPeekEvent(fl_display, &peekevent);
+ if ( (peekevent.type == KeyPress) // must be a KeyPress event
+ && (peekevent.xkey.keycode == 0) // must be keycode 0
+ && (peekevent.xkey.time == xevent.xkey.time) // must be sent
at the exact same time
+ ) {
+ XNextEvent(fl_display, &xevent);
+
+ // Something went wrong fetching the current symbol...
+ if (Fl::e_compose_symbol[0] == '\0')
+ Fl::e_compose_state = FL_COMPOSE_UNKNOWN;
+ else
+ Fl::e_compose_state = FL_COMPOSE_FINAL;
+
+ // Process things again to get the composed symbol
+ goto KEYPRESS;
+ }
+ }
+ Fl::e_compose_state = FL_COMPOSE_INTERMEDIATE;
+ } else {
+ // if the keycode is 0 then state was set earlier
+ if (keycode != 0)
+ Fl::e_compose_state = FL_COMPOSE_NONE;
+ }
+
+ keysym = XKeycodeToKeysym(fl_display, real_keycode, 0);
} else {
//static XComposeStatus compose;
len = XLookupString((XKeyEvent*)&(xevent.xkey),
Index: FL/Enumerations.H
===================================================================
--- FL/Enumerations.H (revision 8623)
+++ FL/Enumerations.H (working copy)
@@ -423,6 +423,25 @@
/*@}*/ // group: Event States
+/** \name Compose States
+
+ These constants define the state of character composition for the
+ current keyboard event.
+
+ \sa Fl::event_compose_state(), Fl::event_compose_symbol()
+*/
+
+/*@{*/
+
+enum Fl_Compose {
+ FL_COMPOSE_UNKNOWN = 0, ///< current compose status cannot be determined
+ FL_COMPOSE_NONE, ///< no composition active for this event
+ FL_COMPOSE_INTERMEDIATE, ///< the current event is part of a composition
but does not end it
+ FL_COMPOSE_FINAL, ///< a composed character has successfully been
constructed
+};
+
+/*@}*/ // group: Compose States
+
/** \name Box Types
\brief FLTK standard box types
Index: FL/Fl.H
===================================================================
--- FL/Fl.H (revision 8548)
+++ FL/Fl.H (working copy)
@@ -133,6 +133,8 @@
static int e_keysym;
static char* e_text;
static int e_length;
+ static int e_compose_state;
+ static const char* e_compose_symbol;
static Fl_Event_Dispatch e_dispatch;
static Fl_Widget* belowmouse_;
static Fl_Widget* pushed_;
@@ -685,6 +687,9 @@
*/
static int event_length() {return e_length;}
+ static int event_compose_state();
+ static const char* event_compose_symbol();
+
static int compose(int &del);
static void compose_reset();
static int event_inside(int,int,int,int);
Index: src/Fl_compose.cxx
===================================================================
--- src/Fl_compose.cxx (revision 8626)
+++ src/Fl_compose.cxx (working copy)
@@ -30,6 +30,8 @@
#ifndef FL_DOXYGEN
int Fl::compose_state = 0;
+int Fl::e_compose_state = FL_COMPOSE_UNKNOWN;
+const char* Fl::e_compose_symbol = "";
#endif
#if !defined(WIN32) && !defined(__APPLE__)
@@ -96,6 +98,31 @@
#endif
}
+/**
+ Returns what role the current key press plays in constructing a composed
+ character.
+ \see Fl_Compose
+ */
+int Fl::event_compose_state()
+{
+ return e_compose_state;
+}
+
+/**
+ Returns the raw symbol associated with the current event. This will be
+ the same as what Fl::event_text() returns except when the compose state
+ is FL_COMPOSE_INTERMEDIATE or FL_COMPOSE_FINAL.
+ \see Fl_Compose
+ */
+const char* Fl::event_compose_symbol()
+{
+ if ((e_compose_state == FL_COMPOSE_INTERMEDIATE) ||
+ (e_compose_state == FL_COMPOSE_FINAL))
+ return e_compose_symbol;
+
+ return Fl::event_text();
+}
+
//
// End of "$Id$"
//
Index: src/Fl_win32.cxx
===================================================================
--- src/Fl_win32.cxx (revision 8623)
+++ src/Fl_win32.cxx (working copy)
@@ -778,6 +778,27 @@
return extended ? extendedlut[vk] : vklut[vk];
}
+static xchar msdead2fltk(xchar in)
+{
+ switch (in) {
+ case 0x0060: // GRAVE ACCENT
+ return 0x0300; // COMBINING GRAVE ACCENT
+ case 0x00b4: // ACUTE ACCENT
+ return 0x0301; // COMBINING ACUTE ACCENT
+ case 0x005e: // CIRCUMFLEX ACCENT
+ return 0x0302; // COMBINING CIRCUMFLEX ACCENT
+ case 0x007e: // TILDE
+ return 0x0303; // COMBINING TILDE
+ case 0x00a8: // DIAERESIS
+ return 0x0308; // COMBINING DIAERESIS
+ // FIXME: Windows dead key behaviour isn't documented and I don't have
+ // any more keyboards to test with...
+ }
+
+ // hope that Windows gave us something proper to begin with
+ return in;
+}
+
#if USE_COLORMAP
extern HPALETTE fl_select_palette(void); // in fl_color_win32.cxx
#endif
@@ -839,6 +860,8 @@
//fl_msg.pt = ???
//fl_msg.lPrivate = ???
+ MSG fl_orig_msg = fl_msg;
+
Fl_Window *window = fl_find(hWnd);
if (window) switch (uMsg) {
@@ -1018,6 +1041,7 @@
if (GetKeyState(VK_SCROLL)) state |= FL_SCROLL_LOCK;
Fl::e_state = state;
static char buffer[1024];
+ static char compose_buffer[1024];
if (uMsg == WM_CHAR || uMsg == WM_SYSCHAR) {
xchar u = (xchar) wParam;
@@ -1025,7 +1049,67 @@
Fl::e_length = fl_utf8fromwc(buffer, 1024, &u, 1);
buffer[Fl::e_length] = 0;
+ if (Fl::e_compose_state == FL_COMPOSE_INTERMEDIATE) {
+ // if you enter an invalid compose sequence Windows will spit
+ // out the entire thing in back-to-back messages
+ while (PeekMessageW(&fl_msg, hWnd, WM_CHAR, WM_SYSDEADCHAR,
PM_REMOVE)) {
+ uMsg = fl_msg.message;
+ wParam = fl_msg.wParam;
+ lParam = fl_msg.lParam;
+ u = (xchar) wParam;
+ Fl::e_length += fl_utf8fromwc(&buffer[Fl::e_length],
1024-Fl::e_length, &u, 1);
+ buffer[Fl::e_length] = 0;
+
+ // update the compose symbol so that it will end up pointing at
+ // the last symbol in the sequence
+ u = msdead2fltk(u);
+ int length = fl_utf8fromwc(compose_buffer, 1024, &u, 1);
+ compose_buffer[length] = '\0';
+
+ Fl::e_compose_symbol = compose_buffer;
+ Fl::e_compose_state = FL_COMPOSE_FINAL;
+ }
+
+ if (Fl::e_compose_state != FL_COMPOSE_FINAL) {
+ MSG extra_msg;
+
+ // Windows doesn't expose the raw symbol (AFAIK), so we have to
+ // get a bit creative. Resend the last message to TranslateMessage()
+ // without all the inital dead characters, and we should get the
+ // raw symbol.
+ TranslateMessage(&fl_orig_msg);
+
+ if (PeekMessageW(&extra_msg, hWnd, WM_CHAR, WM_SYSDEADCHAR,
PM_REMOVE)) {
+ u = (xchar) extra_msg.wParam;
+ int length = fl_utf8fromwc(compose_buffer, 1024, &u, 1);
+ compose_buffer[length] = '\0';
+
+ Fl::e_compose_symbol = compose_buffer;
+ Fl::e_compose_state = FL_COMPOSE_FINAL;
+ } else {
+ // something went wrong, just provide the composed symbol
+ Fl::e_compose_symbol = buffer;
+ Fl::e_compose_state = FL_COMPOSE_FINAL;
+ }
+ }
+ } else {
+ Fl::e_compose_state = FL_COMPOSE_NONE;
+ }
+ } else if (uMsg == WM_DEADCHAR || uMsg == WM_SYSDEADCHAR) {
+ xchar u = (xchar) wParam;
+ int length;
+
+ u = msdead2fltk(u);
+
+ length = fl_utf8fromwc(compose_buffer, 1024, &u, 1);
+ compose_buffer[length] = '\0';
+
+ Fl::e_compose_state = FL_COMPOSE_INTERMEDIATE;
+ Fl::e_compose_symbol = compose_buffer;
+
+ buffer[0] = '\0';
+ Fl::e_length = 0;
} else if (Fl::e_keysym >= FL_KP && Fl::e_keysym <= FL_KP_Last) {
if (state & FL_NUM_LOCK) {
// Convert to regular keypress...
@@ -1076,19 +1160,8 @@
}
}
} else if ((lParam & (1<<31))==0) {
-#ifdef FLTK_PREVIEW_DEAD_KEYS
- if ((lParam & (1<<24))==0) { // clear if dead key (always?)
- xchar u = (xchar) wParam;
- Fl::e_length = fl_utf8fromwc(buffer, 1024, &u, 1);
- buffer[Fl::e_length] = 0;
- } else { // set if "extended key" (never printable?)
- buffer[0] = 0;
- Fl::e_length = 0;
- }
-#else
buffer[0] = 0;
Fl::e_length = 0;
-#endif
}
Fl::e_text = buffer;
if (lParam & (1<<31)) { // key up events.
_______________________________________________
fltk-bugs mailing list
[email protected]
http://lists.easysw.com/mailman/listinfo/fltk-bugs