Hello, Angus; my mail failed to reach you yesterday. The internet mail delivery system seems unstable recently.
On Tue, 18 Feb 2003, Angus Leeming wrote: > > > (a) the first widget in both windows overwrite the 'X' or > > > (b) only the first widget of the first dialog? > > > > > > I ask because if you get result (a), then that suggests that the problem > > > lies with the initialisation of the XIC. If you get result (b), then the > > > problem must lie with some static variable in the xforms library. > > I found that ONLY 'Edit->Find&Search' widget has the problem. Your genuine xforms-widget(trial.C) does not have the problem. So I think the problem lies not on the xforms, but on the source code of the widget. Where is the source code of the 'Edit->...' widget? That's a good questiion which you may know the answer to, no? So I cleaned up a little bit and made the patch against clean xforms-1.0, which I attached on this mail. I hope you lok at the patch and polish it as much as possible, and then send it back to me as soon as possible. Because the CJK-LyX-1.3.0 critically depends on the patched xforms, I have to make both of them(CJK-LyX-1.3.0 and the patched xforms-lib) available at the time of the announcement of CJK-LyX-1.3.0. For the i18n of xforms, I also have attached a slightly modified trial.C to this mail. If you look at the file, you will find the modified function, 'XNextEvents' is added to it. Without this function added, I cannot input CJK-chars on your 'trial' widget. This means to make the xforms-lib i18n, this modified 'XNextEvents' must be added to the lib, which I hope you can give a hand. The job is not urgent, though, forthis 'XNextEvents' function is a part of lyxim.C, and thus without this function added to the lib, CJK-LyX will have no problem. Regards, cghan
diff -urdN xforms-1.0-release/Imakefile xforms-1.0-i18n/Imakefile --- xforms-1.0-release/Imakefile 2002-12-04 02:25:43.000000000 +0900 +++ xforms-1.0-i18n/Imakefile 2003-02-20 21:42:27.000000000 +0900 @@ -100,7 +100,7 @@ image \ $(GL) \ fdesign \ - fd2ps \ + fd2ps \ $(DEMOS) IMAKE_DEFINES = \ diff -urdN xforms-1.0-release/X11/X11/forms.h xforms-1.0-i18n/X11/X11/forms.h --- xforms-1.0-release/X11/X11/forms.h 2002-06-07 04:05:48.000000000 +0900 +++ xforms-1.0-i18n/X11/X11/forms.h 2003-02-20 21:42:27.000000000 +0900 @@ -729,6 +729,11 @@ void (*pre_attach)(struct forms_ *); void *attach_data; int no_tooltip; +#ifdef XlibSpecificationRelease + XIC xic ; /* input context */ +#else + void *xic; +#endif int reserved[10]; /* future use */ } FL_FORM; @@ -987,6 +992,10 @@ FL_FORMCALLBACKPTR callback, void *d ); +FL_EXPORT void fl_get_composed_string( + int * ptr_kbuflen, + char const ** ptr_keybuf + ); #define fl_set_form_call_back fl_set_form_callback @@ -1409,7 +1418,6 @@ int *height ); - #define fl_get_string_size fl_get_string_dimension FL_EXPORT void fl_get_align_xy( @@ -5518,6 +5526,11 @@ FL_OBJECT *ob ); +FL_EXPORT void fl_get_CJK_offset( + FL_OBJECT *ob, + int * x, + int * y + ); FL_EXPORT int fl_get_menu( FL_OBJECT *ob diff -urdN xforms-1.0-release/exports/include/X11/forms.h xforms-1.0-i18n/exports/include/X11/forms.h --- xforms-1.0-release/exports/include/X11/forms.h 2002-06-07 04:05:48.000000000 +0900 +++ xforms-1.0-i18n/exports/include/X11/forms.h 2003-02-20 21:42:27.000000000 +0900 @@ -729,6 +729,11 @@ void (*pre_attach)(struct forms_ *); void *attach_data; int no_tooltip; +#ifdef XlibSpecificationRelease + XIC xic ; /* input context */ +#else + void *xic; +#endif int reserved[10]; /* future use */ } FL_FORM; @@ -987,6 +992,10 @@ FL_FORMCALLBACKPTR callback, void *d ); +FL_EXPORT void fl_get_composed_string( + int * ptr_kbuflen, + char const ** ptr_keybuf + ); #define fl_set_form_call_back fl_set_form_callback @@ -1409,7 +1418,6 @@ int *height ); - #define fl_get_string_size fl_get_string_dimension FL_EXPORT void fl_get_align_xy( @@ -5518,6 +5526,11 @@ FL_OBJECT *ob ); +FL_EXPORT void fl_get_CJK_offset( + FL_OBJECT *ob, + int * x, + int * y + ); FL_EXPORT int fl_get_menu( FL_OBJECT *ob diff -urdN xforms-1.0-release/lib/X11/X11/forms.h xforms-1.0-i18n/lib/X11/X11/forms.h --- xforms-1.0-release/lib/X11/X11/forms.h 2002-06-07 04:05:48.000000000 +0900 +++ xforms-1.0-i18n/lib/X11/X11/forms.h 2003-02-20 21:42:27.000000000 +0900 @@ -729,6 +729,11 @@ void (*pre_attach)(struct forms_ *); void *attach_data; int no_tooltip; +#ifdef XlibSpecificationRelease + XIC xic ; /* input context */ +#else + void *xic; +#endif int reserved[10]; /* future use */ } FL_FORM; @@ -987,6 +992,10 @@ FL_FORMCALLBACKPTR callback, void *d ); +FL_EXPORT void fl_get_composed_string( + int * ptr_kbuflen, + char const ** ptr_keybuf + ); #define fl_set_form_call_back fl_set_form_callback @@ -1409,7 +1418,6 @@ int *height ); - #define fl_get_string_size fl_get_string_dimension FL_EXPORT void fl_get_align_xy( @@ -5518,6 +5526,11 @@ FL_OBJECT *ob ); +FL_EXPORT void fl_get_CJK_offset( + FL_OBJECT *ob, + int * x, + int * y + ); FL_EXPORT int fl_get_menu( FL_OBJECT *ob diff -urdN xforms-1.0-release/lib/exports/include/X11/forms.h xforms-1.0-i18n/lib/exports/include/X11/forms.h --- xforms-1.0-release/lib/exports/include/X11/forms.h 2002-06-07 04:05:48.000000000 +0900 +++ xforms-1.0-i18n/lib/exports/include/X11/forms.h 2003-02-20 21:42:27.000000000 ++0900 @@ -729,6 +729,11 @@ void (*pre_attach)(struct forms_ *); void *attach_data; int no_tooltip; +#ifdef XlibSpecificationRelease + XIC xic ; /* input context */ +#else + void *xic; +#endif int reserved[10]; /* future use */ } FL_FORM; @@ -987,6 +992,10 @@ FL_FORMCALLBACKPTR callback, void *d ); +FL_EXPORT void fl_get_composed_string( + int * ptr_kbuflen, + char const ** ptr_keybuf + ); #define fl_set_form_call_back fl_set_form_callback @@ -1409,7 +1418,6 @@ int *height ); - #define fl_get_string_size fl_get_string_dimension FL_EXPORT void fl_get_align_xy( @@ -5518,6 +5526,11 @@ FL_OBJECT *ob ); +FL_EXPORT void fl_get_CJK_offset( + FL_OBJECT *ob, + int * x, + int * y + ); FL_EXPORT int fl_get_menu( FL_OBJECT *ob diff -urdN xforms-1.0-release/lib/flinternal.h xforms-1.0-i18n/lib/flinternal.h --- xforms-1.0-release/lib/flinternal.h 2002-05-21 04:38:39.000000000 +0900 +++ xforms-1.0-i18n/lib/flinternal.h 2003-02-20 21:42:27.000000000 +0900 @@ -411,10 +411,10 @@ int tooltip_time; #ifdef XlibSpecificationRelease XIM xim ; /* input method */ - XIC xic ; /* input context */ +// XIC xic ; /* input context */ #else void *xim; - void *xic; +// void *xic; #endif unsigned int navigate_mask; /* input field */ long reserverd[6]; @@ -490,6 +490,7 @@ #define IsEnd(k) (k==XK_End || k==XK_KP_End) #define IsPageDown(k) (k==XK_Next || k==XK_Page_Down || k==XK_KP_Page_Down) #define IsPageUp(k) (k==XK_Prior || k==XK_Page_Up || k==XK_KP_Page_Up) +#define IsReturn(k) (k==XK_Return || k==XK_KP_Enter) #else #define IsHome(k) (k==XK_Home || k== XK_Begin) #define IsLeft(k) (k==XK_Left) @@ -499,6 +500,7 @@ #define IsEnd(k) (k==XK_End) #define IsPageDown(k) (k==XK_Next) #define IsPageUp(k) (k==XK_Prior) +#define IsReturn(k) (k==XK_Return) #endif #define FL_HALFPAGE_UP 0x10000000 @@ -514,6 +516,15 @@ #define Is1LineUp(k) ((k)==FL_1LINE_UP) #define Is1LineDown(k) ((k)==FL_1LINE_DOWN) +#define IsFLCursorKey(k) (IsHome(k) || IsLeft(k) || \ + IsRight(k) || IsUp(k) || \ + IsDown(k) || IsEnd(k) || \ + IsPageDown(k) || IsPageUp(k) || \ + IsReturn(k) || IsHalfPageUp(k) || \ + IsHalfPageDown(k) || IsNLinesUp(k) || \ + IsNLinesDown(k) || Is1LineUp(k) || \ + Is1LineDown(k)) + extern int fl_convert_shortcut(const char *, long *); extern int fl_get_underline_pos(const char *, const char *); diff -urdN xforms-1.0-release/lib/flresource.c xforms-1.0-i18n/lib/flresource.c --- xforms-1.0-release/lib/flresource.c 2002-06-02 07:09:37.000000000 +0900 +++ xforms-1.0-i18n/lib/flresource.c 2003-02-20 21:42:27.000000000 +0900 @@ -952,15 +952,7 @@ { XSetLocaleModifiers(""); /* use the same input method throughout xforms */ - fl_context->xim = XOpenIM(fl_display, 0, 0, 0); - /* also use the same input context */ - if (fl_context->xim) - { - int style = XIMPreeditNothing|XIMStatusNothing; - fl_context->xic = XCreateIC(fl_context->xim, - XNInputStyle, style, - 0); - } + fl_context->xim = XOpenIM(fl_display, 0, 0, 0); } #endif fl_default_xswa(); diff -urdN xforms-1.0-release/lib/forms.c xforms-1.0-i18n/lib/forms.c --- xforms-1.0-release/lib/forms.c 2002-11-20 06:06:43.000000000 +0900 +++ xforms-1.0-i18n/lib/forms.c 2003-02-20 21:48:04.000000000 +0900 @@ -53,6 +53,7 @@ #define SHORT_PAUSE 10 /* check_form wait */ +#define DEFAULT_FONT_NAME "-*-*-medium-r-normal--14-*-*-*-*-*-*-*" void fl_set_no_connection(int yes) @@ -531,6 +532,113 @@ fl_wintitle(form->window, form->label); } +void +fl_create_xic(FL_FORM * form) +{ + char **missing_list; + int missing_count; + char *def_string; + XRectangle pre_area; + XPoint location; + XVaNestedList status_list; + XVaNestedList preedit_list; + XIMStyle preedit[]={XIMPreeditPosition,XIMPreeditNothing,0}; + XIMStyle status[]={XIMStatusArea,XIMStatusNothing,0}; + XIMStyles *xim_styles = 0; + XIMStyle input_style; + + + if ( XGetIMValues(fl_context->xim, XNQueryInputStyle, &xim_styles, (char *) +0, (char *) 0) || !xim_styles) { + printf("input method doesn't support any style"); + XCloseIM(fl_context->xim); + return; + } + + int k, i = 0; + int found = 0; + while ((preedit[i]!=0)&& (found != 1)) + { + int j = 0; + while((status[j]!=0)&& (found != 1)) + { + for (k = 0;k < xim_styles->count_styles;k++) + { + if ((preedit[i] | status[j])==xim_styles->supported_styles[k]) + { + input_style=xim_styles->supported_styles[k]; + found = 1; + break; + } + } + j++; + } + i++; + } + XFree( (char *)xim_styles ); + + + + XFontSet fontset = XCreateFontSet(fl_display, DEFAULT_FONT_NAME, +&missing_list, + &missing_count, &def_string); + + + pre_area.x = 0; + pre_area.y = 0; + pre_area.width = form->w; + pre_area.height = form->h; + + location.x = form->x; + location.y = form->y; + + status_list = XVaCreateNestedList( 0, + XNFontSet, fontset, + 0); + + preedit_list = XVaCreateNestedList( 0, + XNSpotLocation, &location, + XNFontSet, fontset, + XNArea, &pre_area, + 0); + + if(preedit_list){ + form->xic = XCreateIC(fl_context->xim, + XNInputStyle, input_style, + XNClientWindow, form->window, + XNFocusWindow, form->window, + XNPreeditAttributes, preedit_list, + XNStatusAttributes, status_list, + 0); + + XFree(preedit_list); + XFree(status_list); + }else + form->xic = XCreateIC(fl_context->xim, + XNInputStyle, input_style, + XNClientWindow, form->window, + 0); + if(!form->xic){ + M_err("fl_initialize", "Could not create an input context"); + XCloseIM (fl_context->xim); + return; + } + + if(form->focusobj){ + int imx, imy; + fl_get_CJK_offset(form->focusobj, &imx, &imy); + location.x = imx; + location.y = imy; + } + else { + location.x = 0; + location.y = 0; + } + preedit_list = XVaCreateNestedList( 0, + XNSpotLocation, &location, + 0); + XSetICValues(form->xic, XNPreeditAttributes, preedit_list, (char *) 0); + XFree(preedit_list); + } + /* Displays a particular form. Returns window handle. */ static int has_initial; @@ -543,6 +651,7 @@ long screenw, screenh; int itx = 0, ity = 0, dont_fix_size = 0; FL_Coord mx, my, nmx, nmy; + XSetWindowAttributes st_xswa; if (border == 0) border = FL_FULLBORDER; @@ -734,6 +843,10 @@ if (border == FL_FULLBORDER || (form->prop & FL_COMMAND_PROP)) fl_set_form_property(form, FL_COMMAND_PROP); + + if (fl_context->xim) + fl_create_xic(form); + return form->window; } @@ -793,6 +906,8 @@ else fl_XPutBackEvent(&xev); + +// XDestroyIC(form->xic); } #else /* suspend timeout and IO stuff. need to complete hide_form without @@ -1161,7 +1276,8 @@ } } - M_info("Shortcut", "win=%lu key=%d %d %d", form->window, key, key1, key2); + M_info("Shortcut", "win=%lu key=%d %d %d %d", + form->window, key, key1, key2); /* Check whether an object has this as shortcut. */ for (i = -1; obj1; obj1 = obj1->next, i = -1) @@ -1218,7 +1334,8 @@ } static void -fl_keyboard(FL_FORM * form, int key, FL_Coord x, FL_Coord y, void *xev) +fl_keyboard(int event, + FL_FORM * form, int key, FL_Coord x, FL_Coord y, void *xev) { FL_OBJECT *obj, *obj1, *special; @@ -1228,7 +1345,7 @@ /* focus policy is done as follows: Input object has the highiest priority. Next is the object that wants special keys which is followed - by mouseobj that has the lowest. Focusobj == FL_INPUT OBJ */ + by mouseobj that has the lowest. */ special = fl_find_first(form, FL_FIND_KEYSPECIAL, 0, 0); obj1 = special ? fl_find_object(special->next, FL_FIND_KEYSPECIAL, 0, 0) : 0; @@ -1239,33 +1356,30 @@ if (obj1 && obj1 != special) special = fl_mouseobj; - if (form->focusobj) + /* Focusobj == FL_INPUT OBJ */ + if (event == FL_KEYPRESS && form->focusobj) { FL_OBJECT *focusobj = form->focusobj; + int special_key = 0; - /* handle special keys first */ - if (key > 255) - { - if (IsLeft(key) || IsRight(key) || IsHome(key) || IsEnd(key)) - fl_handle_object(focusobj, FL_KEYBOARD, x, y, key, xev); - else if ((IsUp(key) || IsDown(key) || - IsPageUp(key) || IsPageDown(key)) && - (focusobj->wantkey & FL_KEY_TAB)) - fl_handle_object(focusobj, FL_KEYBOARD, x, y, key, xev); - else if (special && (special->wantkey & FL_KEY_SPECIAL)) - { - /* moving the cursor in input field that does not have focus - looks weird */ - if (special->objclass != FL_INPUT) - fl_handle_object(special, FL_KEYBOARD, x, y, key, xev); + /* Handle positioning keys first. + Let the FL_OBJECT tell us whether it has done anything. */ + if (IsFLCursorKey(key)) { + if (fl_handle_object_direct(focusobj, event, x, y, key, xev)) { + fl_object_qenter(focusobj); + return; + } + + if (special && (special->wantkey & FL_KEY_SPECIAL) && + special->objclass != FL_INPUT && + fl_handle_object_direct(special, event, x, y, key, xev)) { + fl_object_qenter(special); + return; } - else if (key == XK_BackSpace || key == XK_Delete) - fl_handle_object(focusobj, FL_KEYBOARD, x, y, key, xev); - return; } - /* dispatch tab & return switches focus if not FL_KEY_TAB */ - if ((key == 9 || key == 13) && !(focusobj->wantkey & FL_KEY_TAB)) + /* Dispatch tab & return switches focus if not FL_KEY_TAB */ + if ((IsTab(key) || IsReturn(key)) && !(focusobj->wantkey & FL_KEY_TAB)) { if ((((XKeyEvent *) xev)->state & fl_context->navigate_mask)) { @@ -1284,7 +1398,7 @@ fl_handle_object(obj, FL_FOCUS, x, y, 0, xev); } else if (focusobj->wantkey != FL_KEY_SPECIAL) - fl_handle_object(focusobj, FL_KEYBOARD, x, y, key, xev); + fl_handle_object(focusobj, event, x, y, key, xev); return; } @@ -1294,11 +1408,11 @@ /* space is an exception for browser */ if ((key > 255 || key == ' ') && (special->wantkey & FL_KEY_SPECIAL)) - fl_handle_object(special, FL_KEYBOARD, x, y, key, xev); + fl_handle_object(special, event, x, y, key, xev); else if (key < 255 && (special->wantkey & FL_KEY_NORMAL)) - fl_handle_object(special, FL_KEYBOARD, x, y, key, xev); + fl_handle_object(special, event, x, y, key, xev); else if (special->wantkey == FL_KEY_ALL) - fl_handle_object(special, FL_KEYBOARD, x, y, key, xev); + fl_handle_object(special, event, x, y, key, xev); #if FL_DEBUG >= ML_INFO M_info("KeyBoard", "(%d %d)pushing %d to %s\n", x, y, key, special->label); @@ -1424,8 +1538,9 @@ fl_pushobj = NULL; fl_handle_object(obj, FL_RELEASE, xx, yy, key, xev); break; - case FL_KEYBOARD: /* A key was pressed */ - fl_keyboard(form, key, xx, yy, xev); + case FL_KEYPRESS: /* A key was pressed */ + case FL_KEYRELEASE: /* A key was released */ + fl_keyboard(event, form, key, xx, yy, xev); break; case FL_STEP: /* A simple step */ obj1 = fl_find_first(form, FL_FIND_AUTOMATIC, 0, 0); @@ -1506,23 +1621,40 @@ #endif /* } */ +/* 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; + +} + /* formevent is either FL_KEYPRESS or FL_KEYRELEASE */ static void do_keyboard(XEvent * xev, int formevent) { - Window win; - int kbuflen; + KeySym keysym = 0; + static KeySym last_pressed_keysym; + unsigned char * ch; - /* before doing anything, save the current modifier key for the handlers */ + /* Before doing anything, save the current modifier key for the handlers. */ win = xev->xkey.window; fl_keymask = xev->xkey.state; if (win && (!keyform || !fl_is_good_form(keyform))) keyform = fl_win_to_form(win); - /* switch keyboard input only if different top-level form */ + /* Switch keyboard input only if different top-level form. */ if (keyform && keyform->window != win) { M_warn("KeyEvent", "pointer/keybd focus differ"); @@ -1533,67 +1665,51 @@ keyform = fl_win_to_form(win); } - if ( keyform ) { - - KeySym keysym = 0; - unsigned char keybuf[227]; + if (!keyform) + return; - kbuflen = fl_XLookupString((XKeyEvent *) xev, (char *) keybuf, - sizeof(keybuf), &keysym); - - if (kbuflen < 0) { - - if ( kbuflen != INT_MIN ) { - - /* buffer overflow, should not happen */ - M_err("DoKeyBoard", "keyboad buffer overflow ?"); - - } else { + /* Note that the behaviour of XmbLookupString is undefined on a KeyRelease + event, so we do not attempt to call fl_XLookupString. + Rather, we store the keysym of the previous FL_KEYPRESS event + and dispatch that. */ + if (formevent == FL_KEYRELEASE) { + fl_handle_form(keyform, FL_KEYRELEASE, last_pressed_keysym, xev); + return; + } - M_err("DoKeyBoard", "fl_XLookupString failed ?"); - - } + memset(keybuf, '\0', sizeof(keybuf)); + + kbuflen = fl_XLookupString((XKeyEvent *) xev, (char *) keybuf, + sizeof(keybuf), &keysym); + if (kbuflen < 0) { + if ( kbuflen != INT_MIN ) { + /* buffer overflow, should not happen */ + M_err("DoKeyBoard", "keyboad buffer overflow ?"); } else { - - /* ignore modifier keys as they don't cause action and are - taken care of by the lookupstring routine */ - - if (IsModifierKey(keysym)) - ; - else if (IsTab(keysym)) { - - /* fake a tab key. */ - /* some system shift+tab does not generate tab */ - - fl_handle_form(keyform, formevent, 9, xev); - - } -#if (FL_DEBUG >= ML_DEBUG ) - else if (keysym == XK_F10) /* && controlkey_down(fl_keymask)) */ - hack_test(); -#endif - - /* pass all keys to the handler */ - 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); - - } - + M_err("DoKeyBoard", "fl_XLookupString failed ?"); } - + return; } + /* keysym == NoSymbol during multi-byte char composition. + Eg, I've typed Multi_key-a but not yet ' to give ? + Silently swallow these partial-compositions. */ + if (keysym == NoSymbol && kbuflen == 0) + return; + + /* Ignore modifier keys as they don't cause action and are + taken care of by the LookupString routine. */ + if (IsModifierKey(keysym)) + return; + + /* Dispatch the key event */ + fl_handle_form(keyform, formevent, keysym, xev); + /* Record the keysym for the next KEYRELEASE event. */ + last_pressed_keysym = keysym; } + FL_FORM_ATCLOSE fl_set_form_atclose(FL_FORM * form, FL_FORM_ATCLOSE fmclose, void *data) { @@ -1860,14 +1976,14 @@ return; case FocusIn: - if (fl_context->xic) +/* if (evform->xic) { M_info("Focus", "Setting focus window for IC"); - XSetICValues(fl_context->xic, + XSetICValues(evform->xic, XNFocusWindow, st_xev.xfocus.window, XNClientWindow, st_xev.xfocus.window, 0); - } + } */ break; case KeyPress: @@ -2785,8 +2901,16 @@ fl_XLookupString(XKeyEvent * xkey, char *buf, int buflen, KeySym * ks) { int len = INT_MIN; + FL_FORM * f; - if (!fl_context->xic) + f = fl_win_to_form(xkey->window); + + /* Note that the behaviour of XmbLookupString is undefined on a KeyRelease + event. Safest therefore to bail out in such a situation. */ +/* if (xkey->type != KeyPress) + return 0; */ + + if (!f->xic) { len = XLookupString(xkey, buf, buflen, ks, 0); } @@ -2800,14 +2924,26 @@ return 0; } - len = - XmbLookupString(fl_context->xic, xkey, buf, buflen, ks, &status); + len = XmbLookupString(f->xic, xkey, buf, buflen, ks, &status); switch (status) { case XBufferOverflow: - len = -len; +// len = -len; break; + case XLookupBoth: + break; + case XLookupChars: + *ks = NoSymbol; + break; + case XLookupKeySym: + len = 0; + break; + case XLookupNone: + *ks = NoSymbol; + len = 0; + break; + default: break; } diff -urdN xforms-1.0-release/lib/forms.h xforms-1.0-i18n/lib/forms.h --- xforms-1.0-release/lib/forms.h 2002-06-07 04:05:48.000000000 +0900 +++ xforms-1.0-i18n/lib/forms.h 2003-02-20 21:42:27.000000000 +0900 @@ -729,6 +729,11 @@ void (*pre_attach)(struct forms_ *); void *attach_data; int no_tooltip; +#ifdef XlibSpecificationRelease + XIC xic ; /* input context */ +#else + void *xic; +#endif int reserved[10]; /* future use */ } FL_FORM; @@ -987,6 +992,10 @@ FL_FORMCALLBACKPTR callback, void *d ); +FL_EXPORT void fl_get_composed_string( + int * ptr_kbuflen, + char const ** ptr_keybuf + ); #define fl_set_form_call_back fl_set_form_callback @@ -1409,7 +1418,6 @@ int *height ); - #define fl_get_string_size fl_get_string_dimension FL_EXPORT void fl_get_align_xy( @@ -5518,6 +5526,11 @@ FL_OBJECT *ob ); +FL_EXPORT void fl_get_CJK_offset( + FL_OBJECT *ob, + int * x, + int * y + ); FL_EXPORT int fl_get_menu( FL_OBJECT *ob diff -urdN xforms-1.0-release/lib/input.c xforms-1.0-i18n/lib/input.c --- xforms-1.0-release/lib/input.c 2002-06-04 02:57:29.000000000 +0900 +++ xforms-1.0-i18n/lib/input.c 2003-02-20 21:45:05.000000000 +0900 @@ -52,6 +52,8 @@ #define FL_VALIDATE FL_INPUTVALIDATOR #define NL '\n' +#define CURSOR_SIZE 12 + enum { COMPLETE, @@ -107,6 +109,7 @@ int dead_area, attrib; int no_cursor; int field_char; + int CJK_composing; } SPEC; @@ -240,6 +243,40 @@ } } +void fl_get_CJK_offset(FL_OBJECT * ob, int * x, int * y) +{ + *x = 0; + *y = 0; + if (ob && ob->objclass == FL_INPUT) { + FL_Coord xmargin, ymargin; + FL_Coord bw = FL_abs(ob->bw); + SPEC * sp = ob->spec; + GetMargin(ob->boxtype, bw, &xmargin, &ymargin); + + *x = ob->x + sp->max_pixels + xmargin; + *y = ob->y + ob->h/2 + CURSOR_SIZE/2; + } +} + +static void activate_CJK_composition(FL_OBJECT * ob) +{ + XPoint location; + XVaNestedList preedit_list; + int x, y; + + fl_get_CJK_offset(ob, &x, &y); + + location.x = x; + location.y = y; + preedit_list = XVaCreateNestedList( 0, + XNSpotLocation, &location, + 0); + + XSetICValues(ob->form->xic, XNPreeditAttributes, preedit_list, (char *) 0); + + XFree(preedit_list); + +} static void draw_input(FL_OBJECT * ob) @@ -705,7 +742,7 @@ int ret = 1, i, j; int prev = 1; - if (key == kmap.del_prev_char || key == kmap.backspace) + if (key == XK_BackSpace) { prev = -1; if (sp->endrange >= 0) @@ -717,7 +754,7 @@ else ret = 0; } - else if (key == kmap.del_next_char) + else if (key == XK_Delete) { if (sp->endrange >= 0) delete_piece(ob, sp->beginrange, sp->endrange - 1); @@ -815,6 +852,77 @@ return ret; } +static int +draw_char(FL_OBJECT * ob, int key, int startpos) +{ + int ok = FL_VALID; + char * tmpbuf = 0; + int i = 0; + int tmppos = 0; + int tmpxoffset = 0; + SPEC *sp = ob->spec; + int slen = strlen(sp->str); + if (sp->endrange >= 0) + { + delete_piece(ob, sp->beginrange, sp->endrange - 1); + slen = strlen(sp->str); + } + + if (sp->maxchars > 0 && slen >= sp->maxchars) + { + ringbell(); + return 0; + } + + if (sp->validate) + { + tmpbuf = fl_strdup(sp->str); + tmppos = sp->position; + tmpxoffset = sp->xoffset; + } + + /* merge the new character */ + for (i = slen + 1; i > sp->position; i--) + sp->str[i] = sp->str[i - 1]; + sp->str[sp->position] = key; + sp->position++; + + if (key == '\n') + { + sp->lines++; + sp->ypos++; + sp->xoffset = 0; + } + else + { + int tmp = get_substring_width(ob, startpos, sp->position); + if (tmp - sp->xoffset > sp->w) + sp->xoffset = tmp - sp->w + H_PAD; + } + + if (sp->validate) + { + ok = sp->validate(ob, tmpbuf, sp->str, key); + + if ((ok & ~FL_RINGBELL) != FL_VALID) + { + strcpy(sp->str, tmpbuf); + sp->position = tmppos; + sp->xoffset = tmpxoffset; + if (key == '\n') + { + sp->lines--; + sp->ypos--; + } + } + + if ((ok & FL_RINGBELL)) + ringbell(); + fl_free(tmpbuf); + } + return 1; +} + /* Handles a key press, returns whether something has changed */ static int handle_key(FL_OBJECT * ob, int key, unsigned kmask) @@ -828,6 +936,12 @@ int oldx = sp->xoffset; int oldmax = sp->max_pixels; + if ((ob->type != FL_MULTILINE_INPUT) && + (IsUp(key) || IsDown(key) || IsPageUp(key) || IsPageDown(key))) { + /* Don't want to handle this key. */ + return 0; + } + /* Extend field size if required */ slen = strlen(sp->str); if (sp->size == slen + 1) @@ -836,7 +950,7 @@ sp->str = (char *) fl_realloc(sp->str, sp->size); } - if (ob->type == FL_MULTILINE_INPUT && key == 13) + if (ob->type == FL_MULTILINE_INPUT && IsReturn(key)) key = NL; /* Compute starting position of current line */ @@ -844,7 +958,7 @@ while (startpos > 0 && sp->str[startpos - 1] != NL) startpos--; - if (controlkey_down(kmask) && key > 255) + if (controlkey_down(kmask)) key |= FL_CONTROL_MASK; if (metakey_down(kmask)) @@ -878,71 +992,37 @@ else if (key == kmap.moveto_prev_page) key = XK_PageUp; - if (IsRegular(key)) /* Normal keys or NL */ - { - int ok = FL_VALID; - char *tmpbuf = 0; - int tmppos = 0, tmpxoffset = 0; - - if (sp->endrange >= 0) - { - delete_piece(ob, sp->beginrange, sp->endrange - 1); - slen = strlen(sp->str); - } - - if (sp->maxchars > 0 && slen >= sp->maxchars) - { - ringbell(); - return 0; - } - - if (sp->validate) - { - tmpbuf = fl_strdup(sp->str); - tmppos = sp->position; - tmpxoffset = sp->xoffset; - } - - /* merge the new character */ - for (i = slen + 1; i > sp->position; i--) - sp->str[i] = sp->str[i - 1]; - sp->str[sp->position] = key; - sp->position++; + /* ditto for the delete keys */ + if (key == kmap.del_prev_char || key == kmap.backspace) + key == XK_BackSpace; + else if (key == kmap.del_next_char) + key == XK_Delete; - if (key == '\n') - { - sp->lines++; - sp->ypos++; - sp->xoffset = 0; - } - else - { - int tmp = get_substring_width(ob, startpos, sp->position); - if (tmp - sp->xoffset > sp->w) - sp->xoffset = tmp - sp->w + H_PAD; - } - if (sp->validate) - { - ok = sp->validate(ob, tmpbuf, sp->str, key); - - if ((ok & ~FL_RINGBELL) != FL_VALID) - { - strcpy(sp->str, tmpbuf); - sp->position = tmppos; - sp->xoffset = tmpxoffset; - if (key == '\n') - { - sp->lines--; - sp->ypos--; - } - } + int kbuflen; + char const * keybuf; + fl_get_composed_string(&kbuflen, &keybuf); - if ((ok & FL_RINGBELL)) - ringbell(); - fl_free(tmpbuf); - } + if(kbuflen > 1) + { + for (i=0; i<kbuflen; ++i) { + if (!draw_char(ob, keybuf[i], startpos)) + return 0; + } + } + else if (IsRegular(key)) /* Normal keys or NL */ + { + if (!draw_char(ob, key, startpos)) + return 0; + } + else if(key == XK_BackSpace || key == XK_Delete || + key == kmap.del_next_word || key == kmap.del_prev_word || + key == kmap.clear_field || key == kmap.del_to_eol || + key == kmap.paste || key == kmap.transpose ) + { + ret = handle_edit(ob, key, slen, startpos, kmask); } + else if (IsCursorKey(key) || key == kmap.moveto_eol || key == kmap.moveto_bol || key == kmap.moveto_prev_word || key == kmap.moveto_next_word || @@ -951,10 +1031,7 @@ { ret = handle_movement(ob, key, slen, startpos, kmask); } - else - { - ret = handle_edit(ob, key, slen, startpos, kmask); - } + sp->endrange = -1; @@ -984,6 +1061,8 @@ fl_redraw_object(sp->input); fl_unfreeze_form(ob->form); + + activate_CJK_composition(ob); return ret; } @@ -1205,6 +1284,9 @@ } else if (handle_select(mx, my, ob, 0, NORMAL_SELECT)) fl_redraw_object(sp->input); + + activate_CJK_composition(ob); + break; case FL_DBLCLICK: case FL_TRPLCLICK: @@ -1224,6 +1306,7 @@ ret = (sp->how_return == FL_RETURN_ALWAYS || sp->how_return == FL_RETURN_CHANGED); } + activate_CJK_composition(ob); break; case FL_FREEMEM: fl_free(((SPEC *) (ob->spec))->str); @@ -1352,8 +1435,9 @@ sp->dummy->spec = sp; sp->input = ob; sp->field_char = ' '; + sp->CJK_composing = 0; - /* can't remember why validated input return is set to RETURN_END + /* can't remember why validated input return is set to RETURN_END but probably with some reason. Wait until 1.0 to reset it */ if (ob->type == FL_FLOAT_INPUT || ob->type == FL_INT_INPUT) @@ -1713,7 +1797,7 @@ } -#define Control(c) ((c) - 'a' + 1) +#define Control(c) ((c) | FL_CONTROL_MASK) #define Meta(c) ((c) | METAMASK) #define Dump(a) fprintf(stderr,"\t%s: %ld(0x%lx)\n",#a,kmap.a,kmap.a) @@ -2240,3 +2324,4 @@ return (obj && (obj->objclass == FL_INPUT)) ? ((SPEC*)(obj->spec))->changed:0; } + diff -urdN xforms-1.0-release/lib/objects.c xforms-1.0-i18n/lib/objects.c --- xforms-1.0-release/lib/objects.c 2002-06-04 02:58:23.000000000 +0900 +++ xforms-1.0-i18n/lib/objects.c 2003-02-20 21:42:27.000000000 +0900 @@ -1004,7 +1004,7 @@ else if (str[i] >= 'a' && str[i] <= 'z') sc[j++] = str[i] - 'a' + 1 + offset; else if (str[i] == '[') - sc[j++] = 27 + offset; + sc[j++] = XK_Escape + offset; else sc[j++] = str[i] + offset; offset = 0; @@ -1420,17 +1420,56 @@ } /* handle tooltips */ -static void -tooltip_handler(int ID, void *data) +static +FL_OBJECT * get_parent(FL_OBJECT * obj) { - FL_OBJECT *obj = data; + if (obj) { + while (obj->parent && obj->parent != obj) + obj = obj->parent; + } + return obj; +} - if (obj->tooltip && *(obj->tooltip)) - fl_show_tooltip(obj->tooltip, obj->form->x + obj->x, +static +void tooltip_handler(int ID, void *data) +{ + FL_OBJECT * const obj = get_parent(data); + char const * const tooltip = obj->tooltip; + + if (tooltip && *(tooltip)) + fl_show_tooltip(tooltip, obj->form->x + obj->x, obj->form->y + obj->y + obj->h + 1); obj->tipID = 0; } +static +void hide_tooltip(FL_OBJECT * obj, XEvent * xev) +{ + FL_OBJECT * const parent = get_parent(obj); + char const * const tooltip = parent->tooltip; + if (tooltip && *(tooltip)) { + /* If obj is part of a composite widget, it may well be that we're + leaving a child widget but are still within the parent. + If that is the case, we don't want to hide the tooltip at all. */ + int outside_parent = 1; + if (parent != obj && xev) { + int const pointer_x = xev->xmotion.x; + int const pointer_y = xev->xmotion.y; + if (pointer_x >= parent->x && pointer_x <= parent->x + parent->w && + pointer_y >= parent->y && pointer_y <= parent->y + parent->h) + outside_parent = 0; + } + if (outside_parent) { + fl_hide_tooltip(); + if (parent->tipID) { + fl_remove_timeout(parent->tipID); + parent->tipID = 0; + } + } + } +} + + /* handles an event for an object */ static int fl_handle_it(FL_OBJECT * obj, int event, FL_Coord mx, FL_Coord my, int key, @@ -1463,31 +1502,30 @@ switch (event) { case FL_ENTER: - if (obj->tooltip && *(obj->tooltip) && !obj->form->no_tooltip) - obj->tipID = fl_add_timeout(fl_context->tooltip_time, - tooltip_handler, obj); + { + /* We assign the timer to the parent widget in the case of a + composite object as that's the thing that's actually got the tip. */ + FL_OBJECT * const parent = get_parent(obj); + if (!parent->tipID) { + char const * const tooltip = parent->tooltip; + if (tooltip && *(tooltip) && !parent->form->no_tooltip) + parent->tipID = fl_add_timeout(fl_context->tooltip_time, + tooltip_handler, parent); + } obj->belowmouse = 1; break; + } case FL_LEAVE: - if (obj->tooltip && *(obj->tooltip)) - { - fl_hide_tooltip(); - if (obj->tipID) - fl_remove_timeout(obj->tipID); - obj->tipID = 0; - } + hide_tooltip(obj, xev); obj->belowmouse = 0; break; case FL_PUSH: - if (obj->tooltip && *(obj->tooltip)) - { - fl_hide_tooltip(); - if (obj->tipID) - fl_remove_timeout(obj->tipID); - obj->tipID = 0; - } + hide_tooltip(obj, xev); obj->pushed = 1; break; + case FL_KEYPRESS: + hide_tooltip(obj, xev); + break; case FL_RELEASE: if (!obj->radio) obj->pushed = 0; diff -urdN xforms-1.0-release/lib/slider.c xforms-1.0-i18n/lib/slider.c --- xforms-1.0-release/lib/slider.c 2002-05-31 01:28:07.000000000 +0900 +++ xforms-1.0-i18n/lib/slider.c 2003-02-20 21:42:27.000000000 +0900 @@ -293,6 +293,7 @@ } static int timdel; +static int max_timdel = 11; static int mpos; /* < 0 below knob, 0 on knob, > 0 above knob */ /* Handle a mouse position change */ @@ -305,7 +306,7 @@ /* mouse on trough */ if (mpos && (sp->rdelta + sp->ldelta) > 0.0f) { - if (timdel++ == 0 || (timdel > 11 && (timdel & 1) == 0)) + if (timdel++ == 0) { if (key == FL_LEFT_MOUSE) newval = sp->val + mpos * sp->ldelta; @@ -313,7 +314,11 @@ newval = sp->val + mpos * sp->rdelta; } else + { + if (timdel > max_timdel) + timdel = 0; return 0; + } } else newval = get_newvalue(ob, mx, my); diff -urdN xforms-1.0-release/lib/textbox.c xforms-1.0-i18n/lib/textbox.c --- xforms-1.0-release/lib/textbox.c 2002-05-20 23:35:56.000000000 +0900 +++ xforms-1.0-i18n/lib/textbox.c 2003-02-20 21:42:27.000000000 +0900 @@ -1148,7 +1148,7 @@ return 1; } break; - case FL_KEYBOARD: + case FL_KEYPRESS: return handle_keyboard(ob, key, xev); case FL_RELEASE: sp->lastmy = -1; @@ -1799,7 +1799,7 @@ if (*ev == FL_RELEASE && (*key > FL_MBUTTON3)) { - *ev = FL_KEYBOARD; + *ev = FL_KEYPRESS; if (xev && shiftkey_down((((XButtonEvent *) xev)->state))) { ((XButtonEvent *) xev)->state &= ~ShiftMask; diff -urdN xforms-1.0-release/lib/thumbwheel.c xforms-1.0-i18n/lib/thumbwheel.c --- xforms-1.0-release/lib/thumbwheel.c 2002-05-20 23:36:01.000000000 +0900 +++ xforms-1.0-i18n/lib/thumbwheel.c 2003-02-20 21:42:27.000000000 +0900 @@ -222,7 +222,7 @@ sp->oldmx = mx; sp->oldmy = my; return fl_valuator_handle_drag(ob, value); - case FL_KEYBOARD: + case FL_KEYPRESS: value = sp->val; if (IsHome(key)) value = 0.5f * (sp->min + sp->max); diff -urdN xforms-1.0-release/lib/util.c xforms-1.0-i18n/lib/util.c --- xforms-1.0-release/lib/util.c 2002-05-20 23:35:57.000000000 +0900 +++ xforms-1.0-i18n/lib/util.c 2003-02-20 21:42:27.000000000 +0900 @@ -84,7 +84,7 @@ { VN(FL_ENTER), VN(FL_LEAVE), VN(FL_PUSH), VN(FL_RELEASE), VN(FL_STEP), VN(FL_SHORTCUT), VN(FL_MOUSE), VN(FL_MOTION), - VN(FL_KEYBOARD), VN(FL_DRAW), VN(FL_FOCUS), VN(FL_UNFOCUS), + VN(FL_KEYPRESS), VN(FL_DRAW), VN(FL_FOCUS), VN(FL_UNFOCUS), VN(FL_FREEMEM), VN(FL_DRAWLABEL), VN(FL_DBLCLICK), VN(FL_OTHER), VN(FL_ATTRIB), VN(-1) diff -urdN xforms-1.0-release/lib/win.c xforms-1.0-i18n/lib/win.c --- xforms-1.0-release/lib/win.c 2002-06-04 05:25:35.000000000 +0900 +++ xforms-1.0-i18n/lib/win.c 2003-02-20 21:42:27.000000000 +0900 @@ -76,7 +76,7 @@ /* for input method */ - if(fl_context->xic) +// if(fl_context->xic) st_xswa.event_mask |= FocusChangeMask; st_xswa.backing_store = fl_cntl.backingStore; diff -urdN xforms-1.0-release/lib/xpopup.c xforms-1.0-i18n/lib/xpopup.c --- xforms-1.0-release/lib/xpopup.c 2002-06-04 05:25:18.000000000 +0900 +++ xforms-1.0-i18n/lib/xpopup.c 2003-02-20 21:42:27.000000000 +0900 @@ -1484,16 +1484,34 @@ #else fl_set_font(tfstyle, tfsize); fl_textcolor(puptcolor); - XDrawString(d, w, flx->textgc, x - 1, y - 1, s, n); - XDrawString(d, w, flx->textgc, x, y - 1, s, n); - XDrawString(d, w, flx->textgc, x + 1, y - 1, s, n); - XDrawString(d, w, flx->textgc, x - 1, y, s, n); - XDrawString(d, w, flx->textgc, x + 1, y, s, n); - XDrawString(d, w, flx->textgc, x - 1, y + 1, s, n); - XDrawString(d, w, flx->textgc, x, y + 1, s, n); - XDrawString(d, w, flx->textgc, x + 1, y + 1, s, n); + static XFontSet fset = 0; + static int junk; + char **missing_charset; + int num_missing; + static char *dd; + + if(fset == 0) + { + fset = XCreateFontSet(flx->display, + "-*-*-medium-r-normal--14-*-*-*-*-*-*-*", + &missing_charset, &num_missing, &dd); + } + if(fset == 0) + { + M_err("DrawString","Bad fontset"); + exit(0); + } + + XmbDrawString(d, w, fset, flx->textgc, x - 1, y - 1, s, n); + XmbDrawString(d, w, fset, flx->textgc, x, y - 1, s, n); + XmbDrawString(d, w, fset, flx->textgc, x + 1, y - 1, s, n); + XmbDrawString(d, w, fset, flx->textgc, x - 1, y, s, n); + XmbDrawString(d, w, fset, flx->textgc, x + 1, y, s, n); + XmbDrawString(d, w, fset, flx->textgc, x - 1, y + 1, s, n); + XmbDrawString(d, w, fset, flx->textgc, x, y + 1, s, n); + XmbDrawString(d, w, fset, flx->textgc, x + 1, y + 1, s, n); fl_textcolor(FL_WHITE); - XDrawString(d, w, flx->textgc, x, y, s, n); + XmbDrawString(d, w, fset, flx->textgc, x, y, s, n); #endif } diff -urdN xforms-1.0-release/lib/xtext.c xforms-1.0-i18n/lib/xtext.c --- xforms-1.0-release/lib/xtext.c 2002-05-20 23:35:58.000000000 +0900 +++ xforms-1.0-i18n/lib/xtext.c 2003-02-20 21:42:27.000000000 +0900 @@ -51,6 +51,8 @@ #define NL 10 #define LINES 1024 +#define DEFAULT_FONT_NAME "-*-*-medium-r-normal--14-*-*-*-*-*-*-*" + static char **lines; static int *start; /* start position of these lines */ static int *startx; /* start x-FL_coordinate of these lines */ @@ -59,6 +61,11 @@ static int nlines = LINES; static int max_pixelline; +static XFontStruct **fs_list; +static char **missing_charset; +static int num_missing; +static char *dd; + static void extend_workmem(int nl) { @@ -89,7 +96,7 @@ /* wrong, but looks nicer */ #define CDELTA (flx->fdesc/3) -typedef int (*DrawString) (Display *, Drawable, GC, int, int, const char *, int); +typedef int (*DrawString) (Display *, Drawable, XFontSet, GC, int, int, const char *, +int); /* Major text drawing routine * clip == 0: no clipping @@ -116,6 +123,10 @@ int max_pixels = 0; int cdelta; DrawString XdrawString; + XFontSet fset = XCreateFontSet(flx->display, + DEFAULT_FONT_NAME, &missing_charset, &num_missing, &dd); + XFontsOfFontSet(fset,&fs_list,&missing_charset); + flx->fs = fs_list[0]; if (!startx) extend_workmem(nlines = LINES); @@ -124,7 +135,7 @@ if (curspos != 0 && (str == NULL || str[0] == '\0')) return max_pixels; - XdrawString = (DrawString) (img ? XDrawImageString : XDrawString); + XdrawString = (DrawString) (img ? XmbDrawImageString : XmbDrawString); fl_set_font(style, size); @@ -179,7 +190,7 @@ cdelta = CDELTA; for (i = topline; i < endline; i++) { - width = XTextWidth(flx->fs, lines[i], slen[i]); + width = XmbTextEscapement(fset, lines[i], slen[i]); if (width > max_pixels) { max_pixels = width; @@ -231,40 +242,21 @@ #endif lines[i] = newlabel; slen[i] = strlen(lines[i]); - startx[i] += XTextWidth(flx->fs, fl_ul_magic_char, 1) / 2; + startx[i] += XmbTextEscapement(fset, fl_ul_magic_char, 1) / 2; } /* Draw it */ fl_textcolor(forecol); -#if 2 +#if 0 XdrawString(flx->display, flx->win, flx->textgc, (int) startx[i], (int) starty[i], lines[i], slen[i]); -#else - { - static XFontSet fset = 0; - static int junk; - char **missing_charset; - int num_missing; - static char *dd; - - if(fset == 0) - { - fset = XCreateFontSet(flx->display, - "-adobe-helvetica-*-r-*--*-100-*-*-*-*-*-1", - &missing_charset, &num_missing, &dd); - } - if(fset == 0) - { - M_err("DrawString","Bad fontset"); - exit(0); - } +#else - XmbDrawString(flx->display, flx->win, fset, flx->textgc, + XdrawString(flx->display, flx->win, fset, flx->textgc, (int) startx[i], (int) starty[i], lines[i], slen[i]); - } #endif /* setup correct underline color in proper GC */ @@ -295,17 +287,21 @@ slend = selend; xsel = startx[i] + - XTextWidth(flx->fs, lines[i], slstart - start[i]); + XmbTextEscapement(fset, lines[i], slstart - start[i]); len = slend - slstart; - wsel = XTextWidth(flx->fs, str + slstart, len); + wsel = XmbTextEscapement(fset, str + slstart, len); if (wsel > w) wsel = w + 1; fl_rectf(xsel, starty[i] - height, wsel, flx->fheight, forecol); fl_textcolor(backcol); - +#if 0 XdrawString(flx->display, flx->win, flx->textgc, xsel, starty[i], str + slstart, len); +#else + XdrawString(flx->display, flx->win, fset, flx->textgc, + xsel, starty[i], str +slstart, len); +#endif } } @@ -318,7 +314,7 @@ ; i--; - tt = XTextWidth(flx->fs, lines[i], curspos - start[i]); + tt = XmbTextEscapement(fset, lines[i], curspos - start[i]); fl_set_clipping(x, y, w - 2, h); fl_rectf(startx[i] + tt, starty[i] - height, (FL_Coord) 2, flx->fheight, curscol); @@ -355,6 +351,11 @@ int xstart; /* start x-FL_coordinate of this line */ float toppos; /* y-FL_coord of the top line */ + XFontSet fset = XCreateFontSet(flx->display, + DEFAULT_FONT_NAME, &missing_charset, &num_missing, &dd); + XFontsOfFontSet(fset,&fs_list,&missing_charset); + flx->fs = fs_list[0]; + /* Check whether anything has to be done */ if (!str || !*str) return 0; @@ -400,7 +401,7 @@ /* Calculate start FL_coordinate of the line */ - width = XTextWidth(flx->fs, (char *) line, + width = XmbTextEscapement(fset, (char *) line, start[theline + 1] - start[theline]); if (horalign == FL_ALIGN_LEFT) xstart = x; @@ -420,7 +421,7 @@ len = start[theline + 1] - start[theline]; for (i = i0; i < len; i++) { - if (XTextWidth(flx->fs, line, i) > xpos) + if (XmbTextEscapement(fset, line, i) > xpos) { *xp = i - 1; return start[theline] + i - 1; @@ -656,6 +657,11 @@ int ch = *(str + n); int pre; /* stuff in front of the string, such as ^H */ + XFontSet fset = XCreateFontSet(flx->display, + DEFAULT_FONT_NAME, &missing_charset, &num_missing, &dd); + XFontsOfFontSet(fset,&fs_list,&missing_charset); + flx->fs = fs_list[0]; + if (UL_thickness < 0) XGetFontProperty(flx->fs, XA_UNDERLINE_THICKNESS, &ul_thickness); else @@ -671,8 +677,8 @@ of D. Of course, if UL_width == proportional, this really does not matter */ - ul_width = XTextWidth(fs, NARROW(ch) ? "h" : "D", 1); - ul_rwidth = XTextWidth(fs, str + n, 1); + ul_width = XmbTextEscapement(fset, NARROW(ch) ? "h" : "D", 1); + ul_rwidth = XmbTextEscapement(fset, str + n, 1); pre = (str[0] == *fl_ul_magic_char); @@ -715,6 +721,11 @@ unsigned long ul_pos, ul_thickness = 0; char *str = (char *) cstr; + XFontSet fset = XCreateFontSet(flx->display, + DEFAULT_FONT_NAME, &missing_charset, &num_missing, &dd); + XFontsOfFontSet(fset,&fs_list,&missing_charset); + flx->fs = fs_list[0]; + if (UL_thickness < 0) XGetFontProperty(flx->fs, XA_UNDERLINE_THICKNESS, &ul_thickness); else @@ -726,7 +737,7 @@ if (!XGetFontProperty(flx->fs, XA_UNDERLINE_POSITION, &ul_pos)) ul_pos = has_desc(str) ? (1 + flx->fdesc) : 1; - ul_width = XTextWidth(flx->fs, str, n); + ul_width = XmbTextEscapement(fset, str, n); /* do it */ XFillRectangle(flx->display, flx->win, flx->gc, x, (int) (y + ul_pos), @@ -741,22 +752,26 @@ { int w, tab; const char *p, *q; + XFontSet fset = XCreateFontSet(flx->display, + DEFAULT_FONT_NAME,&missing_charset, &num_missing, &dd); + XFontsOfFontSet(fset,&fs_list,&missing_charset); XFontStruct *fs = fl_get_font_struct(style, size); + fs = fs_list[0]; DrawString XdrawString; tab = fl_get_tabpixels(fs); - XdrawString = (DrawString) (img ? XDrawImageString : XDrawString); + XdrawString = (DrawString) (img ? XmbDrawImageString : XmbDrawString); XSetFont(flx->display, gc, fs->fid); for (w = 0, q = s; *q && (p = strchr(q, '\t')) && (p - s) < len; q = p + 1) { - XdrawString(flx->display, win, gc, x + w, y, (char *) q, p - q); - w += XTextWidth(fs, q, p - q); + XdrawString(flx->display, win, fset, gc, x + w, y, (char *) q, p - q); + w += XmbTextEscapement(fset, q, p - q); w = ((w / tab) + 1) * tab; } - XdrawString(flx->display, win, gc, x + w, y, (char *) q, len - (q - s)); + XdrawString(flx->display, win, fset, gc, x + w, y, (char *) q, len - (q - s)); return 0; /* w + XTextWidth(fs, q, len - (q - s)); */ }
// Compiles with // g++ -W -o trial trial.C -L$HOME/xforms-1.0-release/lib -lforms-static \ // -L/usr/X11R6/lib -lX11 #include <X11/forms.h> #include <stdlib.h> #include <iostream> #define NEED_EVENTS extern "C" { #include <X11/Xlibint.h> } struct FD_test { FL_FORM * form; FL_OBJECT * input_1; FL_OBJECT * input_2; FL_OBJECT * button_close; }; extern "C" { void InputCB(FL_OBJECT *, long); void CloseCB(FL_OBJECT *, long); int WMHideCB(FL_FORM * form, void *); int XNextEvent (register Display *dpy, register XEvent *event); } FD_test * build_form(); class Dialog { public: Dialog(); ~Dialog(); void build(); void show(); void hide(); void input(FL_OBJECT *); static bool finished() { return finished_; } private: FD_test * dialog_; static int nvisible_; static bool finished_; }; int Dialog::nvisible_ = 0; bool Dialog::finished_ = false; Dialog::Dialog() : dialog_(0) {} Dialog::~Dialog() { if (!dialog_) return; hide(); fl_free_form(dialog_->form); delete dialog_; } void Dialog::build() { if (dialog_) return; dialog_ = build_form(); dialog_->form->u_vdata = this; fl_set_input_return(dialog_->input_1, FL_RETURN_CHANGED); fl_set_input_return(dialog_->input_2, FL_RETURN_CHANGED); fl_set_form_atclose(dialog_->form, WMHideCB, 0); } void Dialog::show() { if (!dialog_) return; if (!dialog_->form) return; if (dialog_->form->visible) return; fl_show_form(dialog_->form, FL_PLACE_MOUSE, FL_FULLBORDER, "trial"); nvisible_ += 1; } void Dialog::hide() { if (!dialog_) return; if (!dialog_->form) return; if (!dialog_->form->visible) return; fl_hide_form(dialog_->form); nvisible_ -= 1; if (nvisible_ == 0) finished_ = true; } void Dialog::input(FL_OBJECT * ob) { char const * const cstr = fl_get_input(ob); std::cerr << this << " " << ob->label << ": " << cstr << std::endl; } int main(int argc, char *argv[]) { fl_initialize(&argc, argv, 0, 0, 0); Dialog dlg1; Dialog dlg2; dlg1.build(); dlg2.build(); dlg1.show(); dlg2.show(); while (!Dialog::finished()) fl_check_forms(); return 0; } extern "C" { void InputCB(FL_OBJECT * ob, long) { if (!ob) return; if (!ob->form->u_vdata) return; Dialog * ptr = static_cast<Dialog *>(ob->form->u_vdata); ptr->input(ob); } void CloseCB(FL_OBJECT * ob, long) { std::cerr << "CloseCB()" << std::endl; if (!ob) return; if (!ob->form->u_vdata) return; Dialog * ptr = static_cast<Dialog *>(ob->form->u_vdata); ptr->hide(); } int WMHideCB(FL_FORM * form, void *) { if (!form) return FL_CANCEL; if (!form->u_vdata) return FL_CANCEL; Dialog * ptr = static_cast<Dialog *>(form->u_vdata); ptr->hide(); return FL_CANCEL; } int XNextEvent (register Display *dpy, register XEvent *event) { register _XQEvent *qelt; LockDisplay(dpy); if (dpy->head == 0) _XReadEvents(dpy); qelt = dpy->head; *event = qelt->event; _XDeq(dpy, 0, qelt); UnlockDisplay(dpy); if (event->type == ClientMessage && XFilterEvent(event, None)) return XNextEvent(dpy, event); return 0; } } // extern "C" //extern "C" { //} FD_test * build_form() { FL_OBJECT *obj; FD_test *fdui = new FD_test; fdui->form = fl_bgn_form(FL_NO_BOX, 300, 210); obj = fl_add_box(FL_UP_BOX,0,0,300,210,""); fdui->input_1 = obj = fl_add_input(FL_NORMAL_INPUT,50,10,240,30,"Input1"); fl_set_object_lsize(obj,FL_NORMAL_SIZE); fl_set_object_callback(obj,InputCB,0); fdui->input_2 = obj = fl_add_input(FL_NORMAL_INPUT,50,70,240,30,"Input2"); fl_set_object_lsize(obj,FL_NORMAL_SIZE); fl_set_object_callback(obj,InputCB,0); fdui->button_close = obj = fl_add_button(FL_NORMAL_BUTTON,210,170,80,30,"Close|^["); fl_set_object_lsize(obj,FL_NORMAL_SIZE); fl_set_object_callback(obj,CloseCB,0); fl_end_form(); fdui->form->fdui = fdui; return fdui; }