--- src/command.c.orig Sat Apr 24 05:56:49 1999 +++ src/command.c Mon May 3 03:05:33 1999 @@ -91,6 +91,10 @@ # include # endif #endif /* NO_XLOCALE */ +#ifdef USE_XIM +# undef NO_XLOCALE +#include +#endif #ifdef USE_GETGRNAME # include #endif @@ -299,7 +303,7 @@ /* defines: */ -#define KBUFSZ 8 /* size of keyboard mapping buffer */ +#define KBUFSZ 512 /* size of keyboard mapping buffer */ #define STRING_MAX 512 /* max string size for process_xterm_seq() */ #define ESC_ARGS 32 /* max # of args for esc sequences */ @@ -584,12 +588,11 @@ #endif /* OFFIX_DND */ -#ifndef NO_XLOCALE -static char *rs_inputMethod = ""; /* XtNinputMethod */ -static char *rs_preeditType = NULL; /* XtNpreeditType */ +#ifdef USE_XIM +extern char *rs_inputMethod; /* XtNinputMethod */ +extern char *rs_preeditType; /* XtNpreeditType */ static XIC Input_Context; /* input context */ - -#endif /* NO_XLOCALE */ +#endif /* USE_XIM */ /* command input buffering */ @@ -647,6 +650,16 @@ #else # define init_xlocale() ((void)0) #endif +#ifdef USE_XIM +void IMInstantiateCallback(Display *display, XPointer client_data, XPointer call_data); +void IMDestroyCallback(XIM xim, XPointer client_data, XPointer call_data); +void IMSetStatusPosition(void); +void setTermFontSet(void); +void IMSendSpot(void); +void setColor(unsigned long *fg, unsigned long *bg); +void setSize(XRectangle *size); +extern void setPosition(XPoint *pos); +#endif /*for Big Paste Handling */ static int v_doPending(void); @@ -2425,8 +2438,6 @@ DndSelection = XInternAtom(Xdisplay, "DndSelection", False); #endif /* OFFIX_DND */ - init_xlocale(); - /* get number of available file descriptors */ #ifdef _POSIX_VERSION num_fds = sysconf(_SC_OPEN_MAX); @@ -2489,135 +2500,20 @@ void init_xlocale(void) { + char *locale; - char *p, *s, buf[32], tmp[1024]; - XIM xim = NULL; - XIMStyle input_style; - XIMStyles *xim_styles = NULL; - int found, i, mc; - XFontSet fontset = 0; - char *fontname, **ml, *ds; - XVaNestedList list; - const char fs_base[] = ",-misc-fixed-*-r-*-*-*-120-*-*-*-*-*-*"; - - D_X11(("Initializing X locale and Input Method...\n")); - Input_Context = NULL; - if (rs_inputMethod && strlen(rs_inputMethod) >= sizeof(tmp)) { - print_error("Input Method too long, ignoring."); - rs_inputMethod = NULL; - } -# ifdef KANJI - setlocale(LC_CTYPE, ""); -# else - if (rs_inputMethod && !*rs_inputMethod) { - rs_inputMethod = NULL; - } -# endif - - if (rs_inputMethod == NULL) { - if ((p = XSetLocaleModifiers("@im=none")) != NULL && *p) { - xim = XOpenIM(Xdisplay, NULL, NULL, NULL); - } - } else { - strcpy(tmp, rs_inputMethod); - for (s = tmp; *s; /*nil */ ) { - - char *end, *next_s; - - for (; *s && isspace(*s); s++); - if (!*s) - break; - end = s; - for (; *end && (*end != ','); end++); - next_s = end--; - for (; (end >= s) && isspace(*end); end--); - *(end + 1) = '\0'; - - if (*s) { - snprintf(buf, sizeof(buf), "@im=%s", s); - if ((p = XSetLocaleModifiers(buf)) != NULL && *p && (xim = XOpenIM(Xdisplay, NULL, NULL, NULL)) != NULL) { - break; - } +#ifdef USE_XIM + locale = setlocale(LC_CTYPE, ""); + if (locale == NULL) { + print_error("Setting locale failed."); + } else { + if (strcmp(locale, "C") != 0) { + setTermFontSet(); + XRegisterIMInstantiateCallback(Xdisplay, NULL, NULL, NULL, IMInstantiateCallback, NULL); } - if (!*next_s) - break; - s = (next_s + 1); - } - } - - if (xim == NULL && (p = XSetLocaleModifiers("")) != NULL && *p) { - xim = XOpenIM(Xdisplay, NULL, NULL, NULL); - } - if (xim == NULL) { - D_X11(("Error: Failed to open Input Method\n")); - return; - } else { - D_X11(("Opened X Input Method. xim == 0x%08x\n", xim)); - } - - if (XGetIMValues(xim, XNQueryInputStyle, &xim_styles, NULL) || !xim_styles) { - D_X11(("Error: Input Method doesn't support any style\n")); - XCloseIM(xim); - return; - } else { - D_X11((" -> Input Method supports %d styles.\n", xim_styles->count_styles)); - } - - /* We only support the Root preedit type */ - input_style = (XIMPreeditNothing | XIMStatusNothing); - D_X11((" -> input_style == 0x%08x\n", input_style)); - - for (i = 0, found = 0; i < xim_styles->count_styles; i++) { - D_X11((" -> Supported style flags: 0x%08x %s\n", xim_styles->supported_styles[i], get_input_style_flags(xim_styles->supported_styles[i]))); - D_X11((" -> 0x%08x %s\n", xim_styles->supported_styles[i] & input_style, - get_input_style_flags(xim_styles->supported_styles[i] & input_style))); - if ((xim_styles->supported_styles[i] & input_style) == (xim_styles->supported_styles[i])) { - input_style = xim_styles->supported_styles[i]; - found = 1; - break; } - } - XFree(xim_styles); - - if (!found) { - D_X11(("Error: " APL_NAME " " VERSION " only supports the \"Root\" preedit type, which the Input Method does not support.\n")); - XCloseIM(xim); - return; - } - /* Create Font Set */ +#endif -#ifdef KANJI - fontname = MALLOC(strlen(rs_font[0]) + strlen(rs_kfont[0]) + sizeof(fs_base) + 2); - if (fontname) { - strcpy(fontname, rs_font[0]); - strcat(fontname, fs_base); - strcat(fontname, ","); - strcat(fontname, rs_kfont[0]); - } -#else - fontname = MALLOC(strlen(rs_font[0]) + sizeof(fs_base) + 1); - if (fontname) { - strcpy(fontname, rs_font[0]); - strcat(fontname, fs_base); - } -#endif - if (fontname) { - setlocale(LC_ALL, ""); - fontset = XCreateFontSet(Xdisplay, fontname, &ml, &mc, &ds); - FREE(fontname); - if (mc) { - XFreeStringList(ml); - fontset = 0; - return; - } - } - list = XVaCreateNestedList(0, XNFontSet, fontset, NULL); - Input_Context = XCreateIC(xim, XNInputStyle, input_style, XNClientWindow, TermWin.parent, XNFocusWindow, TermWin.parent, - XNPreeditAttributes, list, XNStatusAttributes, list, NULL); - if (Input_Context == NULL) { - D_X11(("Error: Unable to create Input Context\n")); - XCloseIM(xim); - } } #endif /* NO_XLOCALE */ @@ -3160,6 +3056,9 @@ if (greek_mode) len = greek_xlat(kbuf, len); #endif +#ifdef USE_XIM + IMSendSpot(); +#endif } if (len <= 0) @@ -3344,6 +3243,7 @@ #else scr_refresh(refresh_type); #endif + IMSendSpot(); } /* characters already read in */ if (CHARS_READ()) { @@ -3444,6 +3344,9 @@ scr_refresh(refresh_type); if (scrollbar_visible()) scrollbar_show(1); +#ifdef USE_XIM + IMSendSpot(); +#endif } } } @@ -4157,6 +4060,9 @@ refresh_count = refresh_limit = 0; scr_refresh(refresh_type); scrollbar_show(mouseoffset); +#ifdef USE_XIM + IMSendSpot(); +#endif #endif } else if ((ev->xany.window == scrollBar.win) && scrollbar_isMotion()) { Window unused_root, unused_child; @@ -4174,6 +4080,9 @@ refresh_count = refresh_limit = 0; scr_refresh(refresh_type); scrollbar_show(mouseoffset); +#ifdef USE_XIM + IMSendSpot(); +#endif } #ifdef PROFILE_X_EVENTS P_SETTIMEVAL(motion_stop); @@ -5065,6 +4974,9 @@ } } Gr_do_graphics(cmd, nargs, args, text); +#ifdef USE_XIM + IMSendSpot(); +#endif #endif } @@ -6311,6 +6223,9 @@ /* parent already resized */ resize_window1(width, height); +#ifdef USE_XIM + IMSetStatusPosition(); +#endif } /* xterm sequences - title, iconName, color (exptl) */ @@ -6893,6 +6808,328 @@ free(orig_tnstr); #endif } + +#ifdef USE_XIM +void +setSize(XRectangle *size) +{ + size->x = TermWin.internalBorder; + size->y = TermWin.internalBorder; + size->width = Width2Pixel(TermWin.ncol); + size->height = Height2Pixel(TermWin.nrow); +} + +void +setColor(unsigned long *fg, unsigned long *bg) +{ + *fg = PixColors[fgColor]; + *bg = PixColors[bgColor]; +} + +void +IMSendSpot(void) +{ + XPoint spot; + XVaNestedList preedit_attr; + XIMStyle input_style; + + if (Input_Context == NULL) + return; + else { + XGetICValues(Input_Context, XNInputStyle, &input_style, NULL); + if (!(input_style & XIMPreeditPosition)) + return; + } + setPosition(&spot) ; + + preedit_attr = XVaCreateNestedList( 0, XNSpotLocation, &spot, NULL ) ; + XSetICValues( Input_Context, XNPreeditAttributes, preedit_attr, NULL ) ; + XFree( preedit_attr ) ; +} + +void +setTermFontSet(void) +{ + char *string; + long length, i; + + if (TermWin.fontset != NULL){ + XFreeFontSet(Xdisplay, TermWin.fontset); + TermWin.fontset = NULL; + } + + length = 0; + for (i = 0; i < NFONTS; i++) { + if (rs_font[i]) + length += strlen(rs_font[i]) + 1; +# ifdef KANJI + if (rs_kfont[i]) + length += strlen(rs_kfont[i]) + 1; +# endif + } + if ((string = malloc( length )) != NULL) { + char **missing_charsetlist, *def_string; + int missing_charsetcount; + + string[0] = '\0'; + for (i = 0; i < NFONTS; i++) { + if (rs_font[i]){ + strcat(string, rs_font[i]); + strcat(string, ","); + } +# ifdef KANJI + if(rs_kfont[i]){ + strcat(string, rs_kfont[i]); + strcat(string, ","); + } +# endif + } + length = strlen(string); + if (length > 0 && string[ length - 1 ] == ',') { + string[length - 1] = '\0'; + length--; + } + if (length > 0) { + TermWin.fontset = XCreateFontSet(Xdisplay, string, + &missing_charsetlist, &missing_charsetcount, + &def_string); + } + free(string); + } else { + TermWin.fontset = NULL; + } +} + +void +IMInstantiateCallback(Display *display, XPointer client_data, XPointer call_data) +{ + char *p, *s, buf[32], tmp[1024]; + XIM xim = NULL; + XIMStyle input_style = 0; + XIMStyles *xim_styles = NULL; + int found; + XPoint spot; + XRectangle rect, status_rect, *needed_rect; + unsigned long fg, bg; + XVaNestedList preedit_attr = NULL; + XVaNestedList status_attr = NULL; + XIMCallback ximcallback; + + if (Input_Context) return; + + Input_Context = NULL; + if (rs_inputMethod == NULL +# ifndef KANJI + || !*rs_inputMethod /* required ? */ +# endif + ) { + if ((p = XSetLocaleModifiers("")) != NULL && *p) + xim = XOpenIM(Xdisplay, NULL, NULL, NULL); + } else { + strcpy(tmp, rs_inputMethod); + for (s = tmp; *s; /*nil*/) { + + char *end, *next_s; + + for (; *s && isspace(*s); s++); + if (!*s) break; + end = s; + for (; *end && (*end != ','); end++); + next_s = end--; + for (; (end >= s) && isspace(*end); end--); + *(end + 1) = '\0'; + + if (*s) { + strcpy(buf, "@im="); + strcat(buf, s); + if ((p = XSetLocaleModifiers(buf)) != NULL && *p + && (xim = XOpenIM(Xdisplay, NULL, NULL, NULL)) != NULL) + break; + } + if (!*next_s) break; + s = (next_s + 1); + } + } + + if (xim == NULL && (p = XSetLocaleModifiers("")) != NULL && *p) + xim = XOpenIM(Xdisplay, NULL, NULL, NULL); + + if (xim == NULL) { +# ifdef DEBUG_X11 + print_error("Failed to open input method"); +# endif + return; + } + + XSetIMValues(xim, XNDestroyCallback, &ximcallback, NULL); + + if (XGetIMValues(xim, XNQueryInputStyle, &xim_styles, NULL) || !xim_styles) { +# ifdef DEBUG_X11 + print_error("input method doesn't support any style"); +# endif + XCloseIM(xim); + return; + } + + strcpy(tmp, (rs_preeditType ? rs_preeditType : "OverTheSpot")); + for (found = 0, s = tmp; *s && !found; /*nil*/) { + + unsigned short i; + char *end, *next_s; + + while (*s && isspace(*s)) s++; + if (!*s) break; + end = s; + while (*end && (*end != ',')) end++; + next_s = end--; + while ((end >= s) && isspace(*end)) *end-- = 0; + + if (!strcmp(s, "OverTheSpot")) + input_style = (XIMPreeditPosition | XIMStatusNothing); + else + if (!strcmp(s, "OffTheSpot")) + input_style = (XIMPreeditArea | XIMStatusArea); + else + if (!strcmp(s, "Root")) + input_style = (XIMPreeditNothing | XIMStatusNothing); + + for (i = 0; i < xim_styles->count_styles; i++) { + if (input_style == xim_styles->supported_styles[i]) { + found = 1; + break; + } + } + s = next_s; + } + XFree(xim_styles); + + if (found == 0) { +# ifdef DEBUG_X11 + print_error ("input method doesn't support my preedit type"); +# endif + XCloseIM(xim); + return; + } + + /* + * This program only understands the Root preedit_style yet + * Then misc.preedit_type should default to: + * "OverTheSpot,OffTheSpot,Root" + * /MaF + */ + if ((input_style != (XIMPreeditPosition | XIMStatusNothing)) && + (input_style != (XIMPreeditArea | XIMStatusArea)) && + (input_style != (XIMPreeditNothing | XIMStatusNothing))) { +# ifdef DEBUG_X11 + print_error ("This program only supports the preedit type"); +# endif + XCloseIM(xim); + return; + } + + if (input_style & XIMPreeditPosition) { + setSize(&rect); + setPosition(&spot); + setColor(&fg, &bg); + + preedit_attr = XVaCreateNestedList(0, + XNArea, &rect, + XNSpotLocation, &spot, + XNForeground, fg, + XNBackground, bg, + XNFontSet, TermWin.fontset, + NULL); + } else if (input_style & XIMPreeditArea) { + setColor(&fg, &bg); + + preedit_attr = XVaCreateNestedList(0, + XNForeground, fg, + XNBackground, bg, + XNFontSet, TermWin.fontset, + NULL); + + status_attr = XVaCreateNestedList(0, + XNForeground, fg, + XNBackground, bg, + XNFontSet, TermWin.fontset, + NULL); + } + + ximcallback.callback = IMDestroyCallback; + ximcallback.client_data = NULL; + + Input_Context = XCreateIC(xim, XNInputStyle, input_style, + XNClientWindow, TermWin.parent, + XNFocusWindow, TermWin.parent, + XNDestroyCallback, &ximcallback, + preedit_attr ? XNPreeditAttributes : NULL, preedit_attr, + status_attr ? XNStatusAttributes : NULL, status_attr, + NULL); + XFree(preedit_attr); + XFree(status_attr); + if (Input_Context == NULL) { +# ifdef DEBUG_X11 + print_error("Failed to create input context"); +# endif + XCloseIM(xim); + } + + if (input_style & XIMPreeditArea) { + IMSetStatusPosition(); + } +} + +void +IMSetStatusPosition(void) +{ + XIMStyle input_style; + XRectangle rect, status_rect, *needed_rect; + XVaNestedList preedit_attr, status_attr; + + if (Input_Context == NULL) + return; + + XGetICValues(Input_Context, XNInputStyle, &input_style, NULL); + + if (input_style & XIMPreeditArea) { + status_attr = XVaCreateNestedList(0, XNAreaNeeded, &needed_rect, NULL); + XGetICValues(Input_Context, XNStatusAttributes, status_attr, NULL); + XFree(status_attr); + + rect.x = needed_rect->width; + if (menuBar.state == 1) { + rect.y = Height2Pixel(TermWin.nrow) + menuBar_TotalHeight() - TermWin.internalBorder; + } else { + rect.y = Height2Pixel(TermWin.nrow) - TermWin.internalBorder; + } + rect.width = Width2Pixel(TermWin.ncol + 1) - needed_rect->width; + rect.height = needed_rect->height; + preedit_attr = XVaCreateNestedList(0, XNArea, &rect, NULL); + + status_rect.x = 0; + if (menuBar.state == 1) { + status_rect.y = Height2Pixel(TermWin.nrow) + menuBar_TotalHeight() - TermWin.internalBorder; + } else { + status_rect.y = Height2Pixel(TermWin.nrow) - TermWin.internalBorder; + } + status_rect.width = needed_rect->width; + status_rect.height = needed_rect->height; + status_attr = XVaCreateNestedList(0, XNArea, &status_rect, NULL); + XSetICValues(Input_Context, + XNPreeditAttributes, preedit_attr, + XNStatusAttributes, status_attr, NULL); + XFree(preedit_attr); + XFree(status_attr); + } +} + +void +IMDestroyCallback(XIM xim, XPointer client_data, XPointer call_data) +{ + Input_Context = NULL; + XRegisterIMInstantiateCallback(Xdisplay, NULL, NULL, NULL, IMInstantiateCallback, NULL); +} +#endif /* USE_XIM */ /* change_font() - Switch to a new font */ /*