This is the third and final mail in my renewed contact Blitz. I hope that you
still ahve the energy to peruse it ;-)
The attached patch is pretty monstrous but is the necessary first step to
enabling the display and input of Far Eastern characters by xforms. I
actually regard it as a clean-up of some obfuscated code and it has worked
perfectly for me for months.
However, it does change the information passed by xforms to its widgets and
may therefore break any home made widgets that relied on the old, obfuscated
form of the data passed to them. I submit it therefore as a discussion
document.
If it turns out to be too much to consider in one go, then I can try and break
it up into smaller parts...
I have also provided some detailed explanations of what the patch does
(below). Please bear with me ;-)
What it does:
1. xforms passes both FL_KEYPRESS and FL_KEYRELEASE events to do_keyboard and
thence to fl_handle_object. However, the FL_KEYRELEASE event is then silently
dropped. xforms has no right to do such a thing (who knows what widgets out
there might want a KEYRELEASE event) and this patch therefore
passes the FL_KEYRELEASE event to fl_keyboard and thence to the widgets.
This, of itself, requires changes in a couple of places
a. do_keyboard extracts information about the keyboard event using both
XLookupString and XmbLookupString. However, XmbLookupString is undefined on a
KeyRelease event so we store the keysym of the previous FL_KEYPRESS event
and dispatch that on a FL_KEYRELEASE event.
b. Given that XmbLookupString is undefined on a KeyRelease event, it is
safest to bail out of fl_XLookupString in such a situation (although I
emphasise that the routine should not be, and is not, called from do_keyboard
on a KeyRelease event).
2. Without beating about the bush, forms.c's do_keyboard is designed to
confuse with no other real benefit ;-) This patch makes it 'do the right
thing' at the expense of a changed behaviour that may break any home made
widgets that relied on the old behaviour.
Let me explain further.
do_keyboard exists to extract the keysym from the XEvent and to dispatch this
keysym to fl_handle_form. The important code is:
KeySym keysym = 0;
unsigned char keybuf[227];
kbuflen = fl_XLookupString((XKeyEvent *) xev, (char *) keybuf,
sizeof(keybuf), &keysym);
It _should_ then pass this keysym to fl_handle_form, so:
fl_handle_form(keyform, formevent, keysym, xev);
but in a misguided attempt to be nice to mulitbyte languages, it actually does
this:
if (IsTab(keysym)) {
fl_handle_form(keyform, formevent, 9, xev);
else if (IsCursorKey(keysym) || kbuflen == 0)
fl_handle_form(keyform, formevent, keysym, xev);
else {
unsigned char *ch;
/* all regular keys, including mapped strings */
for (ch = keybuf; ch < (keybuf + kbuflen) && keyform; ch++)
fl_handle_form(keyform, formevent, *ch, xev);
}
Changing the code to just pass the keysym results in changes elsewhere in the
source such as:
-#define Control(c) ((c) - 'a' + 1)
+#define Control(c) ((c) | FL_CONTROL_MASK)
and
else if (str[i] == '[')
- sc[j++] = 27 + offset;
+ sc[j++] = XK_Escape + offset;
I contend that this immediately makes the source more understandable. However,
as I have already stated, it will break any home made widgets that relied on
this behaviour. Your call.
I said above that the code is written as it is in a misguided attempt to be
nice to mulitbyte languages. What was meant to happen was that the receiving
widget could check the timestamp of the XEvent passed with each call of
for (ch = keybuf; ch < (keybuf + kbuflen) && keyform; ch++)
fl_handle_form(keyform, formevent, *ch, xev);
XEvents with the same timestamps are the same and therefore the widget was
meant to piece together the multibyte info needed to create a Chinese
character (for example).
Having spent a great deal of time with CG Han actually getting xforms to
display and input Chinese, Korean and Japanese (CJK) characters, I can
definitively say that this approach sucks ;-) (Incidentally this patch does
_not_ enable CJK support but it is a necessary precursor to it.)
Instead, the keybuf and kbuflen data that are initialised at the same time as
keysym by fl_XLookupString should be made available to any widget that
desires them. This we do by providing the following new accessor function:
/* These vars are initialised in do_keyboard.
* They are global vars so that we can make them accessible to the outside
* world. CJK users will find them useful.
*/
static int kbuflen;
static char keybuf[256];
void fl_get_composed_string(int * ptr_kbuflen, char const ** ptr_keybuf)
{
if (!ptr_kbuflen) return;
*ptr_kbuflen = kbuflen;
*ptr_keybuf = keybuf;
}
it is not used internally by xforms in this patch but is used by input.c in CG
Han's CJK patch being used successfully as we speak in CJK-LyX 1.3.0 released
on February 26. FWIW, you can read his announcement here:
http://www.lyx.org/announce/1_3_0cjk.txt.
3. As a result of getting xforms to work with CJK characters, the large
ifthenelse block in input.c's handle_key routine was split out into a
separate draw_char function. CJK input calls this routine multiple times per
XEvent, once for each char of the keybuf (above). For the sake of overall
simplicity this change is included in the present patch.
I hope that this long explanation proves useful when you come to look at the
patch and enables us to start a discussion about it.
Best regards,
Angus
_________________________________________________
To unsubscribe, send the message "unsubscribe" to
xforms-request@bob.usuhs.mil or see
http://bob.usuhs.mil/mailserv/xforms.html
XForms Home Page: http://world.std.com/~xforms
List Archive: http://bob.usuhs.mil/mailserv/list-archives/
This archive was generated by hypermail 2b29 : Thu Mar 27 2003 - 13:06:37 EST