--- 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 <X11/Xlocale.h>
 # endif
 #endif /* NO_XLOCALE */
+#ifdef USE_XIM
+# undef NO_XLOCALE
+#include <locale.h>
+#endif
 #ifdef USE_GETGRNAME
 # include <grp.h>
 #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 */
 /*
