changeset 27500:d33b4becc3ca

(x_display_cursor): Set XIC pre-edit area only if window is its frame's selected window. (xim_instantiate_callback): Likewise. (XTread_socket) [HAVE_X_I18N]: If event is for none of our frames, call XFilterEvent with 2nd parameter `None'. (XTread_socket) <KeyPress> [HAVE_X_I18N]: Handle XmbLookupString returning XBufferOverflow. (XTread_socket) <ConfigureNotify> [HAVE_X_I18N]: Set XIC status area. (x_display_cursor) [HAVE_X_I18N]: Set XIC pre-edit area. (x_new_fontset) [HAVE_X_I18N]: Create XIC status area fontset. (xim_destroy_callback, xim_open_dpy, xim_instantiate_callback) (xim_initialize, xim_close) [HAVE_X_I18N && HAVE_X11R6]: New functions. (x_destroy_window) [HAVE_X_I18N]: Call xic_destroy_frame. (x_term_init) [HAVE_X_I18N]: Call xim_initialize. (x_delete_display) [HAVE_X_I18N]: Call xim_close.
author Gerd Moellmann <gerd@gnu.org>
date Sat, 29 Jan 2000 23:16:55 +0000
parents 92903015c94c
children ea054e85f0e2
files src/xterm.c
diffstat 1 files changed, 245 insertions(+), 20 deletions(-) [+]
line wrap: on
line diff
--- a/src/xterm.c	Sat Jan 29 18:44:47 2000 +0000
+++ b/src/xterm.c	Sat Jan 29 23:16:55 2000 +0000
@@ -8818,9 +8818,6 @@
   struct frame *f;
   int event_found = 0;
   struct x_display_info *dpyinfo;
-#ifdef HAVE_X_I18N
-  Status status_return;
-#endif
 
   if (interrupt_input_blocked)
     {
@@ -8901,11 +8898,9 @@
 	       consumed the event.  We pass the frame's X window to
 	       XFilterEvent because that's the one for which the IC
 	       was created.  */
-	    struct frame *f1
-	      = x_any_window_to_frame (dpyinfo, event.xclient.window);
-	    if (f1
-		&& FRAME_XIC (f1)
-		&& XFilterEvent (&event, FRAME_X_WINDOW (f1)))
+	    struct frame *f1 = x_any_window_to_frame (dpyinfo,
+						      event.xclient.window);
+	    if (XFilterEvent (&event, f1 ? FRAME_X_WINDOW (f1) : None))
 	      break;
 	  }
 #endif
@@ -9338,10 +9333,24 @@
 #ifdef HAVE_X_I18N
 		  if (FRAME_XIC (f))
 		    {
+		      unsigned char *copy_bufptr = copy_buffer;
+		      int copy_bufsiz = sizeof (copy_buffer);
+		      Status status_return;
+
 		      nbytes = XmbLookupString (FRAME_XIC (f),
-						&event.xkey, copy_buffer,
-						80, &keysym,
+						&event.xkey, copy_bufptr,
+						copy_bufsiz, &keysym,
 						&status_return);
+		      if (status_return == XBufferOverflow)
+			{
+			  copy_bufsiz = nbytes + 1;
+			  copy_bufptr = (char *) alloca (copy_bufsiz);
+			  nbytes = XmbLookupString (FRAME_XIC (f),
+						    &event.xkey, copy_bufptr,
+						    copy_bufsiz, &keysym,
+						    &status_return);
+			}
+
 		      if (status_return == XLookupNone)
 			break;
 		      else if (status_return == XLookupChars)
@@ -9483,6 +9492,9 @@
 		}
 	      goto OTHER;
 
+	    case KeyRelease:
+	      goto OTHER;
+
 	      /* Here's a possible interpretation of the whole
 		 FocusIn-EnterNotify FocusOut-LeaveNotify mess.  If
 		 you get a FocusIn event, you have to get a FocusOut
@@ -9712,6 +9724,11 @@
 		  x_real_positions (f, &f->output_data.x->left_pos,
 				    &f->output_data.x->top_pos);
 
+#ifdef HAVE_X_I18N
+		  if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMStatusArea))
+		    xic_set_statusarea (f);
+#endif
+
 		  if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
 		    {
 		      /* Since the WM decorations come below top_pos now,
@@ -10392,6 +10409,17 @@
 {
   BLOCK_INPUT;
   x_display_and_set_cursor (w, on, hpos, vpos, x, y);
+  
+#ifdef HAVE_X_I18N
+  {
+    struct frame *f = XFRAME (w->frame);
+
+    if (w == XWINDOW (f->selected_window))
+      if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMPreeditPosition))
+	xic_set_preeditarea (w, x, y);
+  }
+#endif
+  
   UNBLOCK_INPUT;
 }
 
@@ -10891,8 +10919,204 @@
   FS_LOAD_FONT (f, FRAME_X_FONT_TABLE (f),
 		CHARSET_ASCII, fontsetp->fontname[CHARSET_ASCII], fontset);
 
+#ifdef HAVE_X_I18N
+  if (FRAME_XIC (f)
+      && (FRAME_XIC_STYLE (f) & (XIMPreeditPosition | XIMStatusArea)))
+    xic_set_xfontset (f, fontsetp->fontname[CHARSET_ASCII]);
+#endif
+  
   return build_string (fontsetname);
 }
+
+
+/***********************************************************************
+			   X Input Methods
+ ***********************************************************************/
+
+#ifdef HAVE_X_I18N
+
+#ifdef HAVE_X11R6
+
+/* XIM destroy callback function, which is called whenever the
+   connection to input method XIM dies.  CLIENT_DATA contains a
+   pointer to the x_display_info structure corresponding to XIM.  */
+
+static void
+xim_destroy_callback (xim, client_data, call_data)
+     XIM xim;
+     XPointer client_data;
+     XPointer call_data;
+{
+  struct x_display_info *dpyinfo = (struct x_display_info *) client_data;
+  Lisp_Object frame, tail;
+  
+  BLOCK_INPUT;
+  
+  /* No need to call XDestroyIC.. */
+  FOR_EACH_FRAME (tail, frame)
+    {
+      struct frame *f = XFRAME (frame);
+      if (FRAME_X_DISPLAY_INFO (f) == dpyinfo)
+	{
+	  FRAME_XIC (f) = NULL;
+	  if (FRAME_XIC_FONTSET (f))
+	    {
+	      XFreeFontSet (FRAME_X_DISPLAY (f), FRAME_XIC_FONTSET (f));
+	      FRAME_XIC_FONTSET (f) = NULL;
+	    }
+	}
+    }
+  
+  /* No need to call XCloseIM.  */
+  dpyinfo->xim = NULL;
+  XFree (dpyinfo->xim_styles);
+  UNBLOCK_INPUT;
+}
+
+#endif /* HAVE_X11R6 */
+
+/* Open the connection to the XIM server on display DPYINFO.
+   RESOURCE_NAME is the resource name Emacs uses.  */
+
+static void
+xim_open_dpy (dpyinfo, resource_name)
+     struct x_display_info *dpyinfo;
+     char *resource_name;
+{
+  XIM xim;
+
+  xim = XOpenIM (dpyinfo->display, dpyinfo->xrdb, resource_name, EMACS_CLASS);
+  dpyinfo->xim = xim;
+
+  if (xim)
+    {
+      XIMValuesList *xim_values_list;
+#ifdef HAVE_X11R6
+      XIMCallback destroy;
+#endif
+      
+      /* Get supported styles and XIM values.  */
+      XGetIMValues (xim, XNQueryInputStyle, &dpyinfo->xim_styles, NULL);
+      
+#ifdef HAVE_X11R6
+      destroy.callback = xim_destroy_callback;
+      destroy.client_data = (XPointer)dpyinfo;
+      XSetIMValues (xim, XNDestroyCallback, &destroy, NULL);
+#endif
+    }
+}
+
+
+#ifdef HAVE_X11R6
+
+struct xim_inst_t
+{
+  struct x_display_info *dpyinfo;
+  char *resource_name;
+};
+
+/* XIM instantiate callback function, which is called whenever an XIM
+   server is available.  DISPLAY is teh display of the XIM.
+   CLIENT_DATA contains a pointer to an xim_inst_t structure created
+   when the callback was registered.  */
+
+static void
+xim_instantiate_callback (display, client_data, call_data)
+     Display *display;
+     XPointer client_data;
+     XPointer call_data;
+{
+  struct xim_inst_t *xim_inst = (struct xim_inst_t *) client_data;
+  struct x_display_info *dpyinfo = xim_inst->dpyinfo;
+
+  /* We don't support multiple XIM connections. */
+  if (dpyinfo->xim)
+    return;
+  
+  xim_open_dpy (dpyinfo, xim_inst->resource_name);
+
+  /* Create XIC for the existing frames on the same display, as long
+     as they have no XIC.  */
+  if (dpyinfo->xim && dpyinfo->reference_count > 0)
+    {
+      Lisp_Object tail, frame;
+
+      BLOCK_INPUT;
+      FOR_EACH_FRAME (tail, frame)
+	{
+	  struct frame *f = XFRAME (frame);
+	  
+	  if (FRAME_X_DISPLAY_INFO (f) == xim_inst->dpyinfo)
+	    if (FRAME_XIC (f) == NULL)
+	      {
+		create_frame_xic (f);
+		if (FRAME_XIC_STYLE (f) & XIMStatusArea)
+		  xic_set_statusarea (f);
+		if (FRAME_XIC_STYLE (f) & XIMPreeditPosition)
+		  {
+		    struct window *w = XWINDOW (f->selected_window);
+		    xic_set_preeditarea (w, w->cursor.x, w->cursor.y);
+		  }
+	      }
+	}
+      
+      UNBLOCK_INPUT;
+    }
+}
+
+#endif /* HAVE_X11R6 */
+
+
+/* Open a connection to the XIM server on display DPYINFO.
+   RESOURCE_NAME is the resource name for Emacs.  On X11R5, open the
+   connection only at the first time.  On X11R6, open the connection
+   in the XIM instantiate callback function.  */
+
+static void
+xim_initialize (dpyinfo, resource_name)
+     struct x_display_info *dpyinfo;
+     char *resource_name;
+{
+#ifdef HAVE_X11R6
+  struct xim_inst_t *xim_inst;
+  int len;
+  
+  dpyinfo->xim = NULL;
+  xim_inst = (struct xim_inst_t *) xmalloc (sizeof (struct xim_inst_t));
+  xim_inst->dpyinfo = dpyinfo;
+  len = strlen (resource_name);
+  xim_inst->resource_name = (char *) xmalloc (len + 1);
+  bcopy (resource_name, xim_inst->resource_name, len + 1);
+  XRegisterIMInstantiateCallback (dpyinfo->display, dpyinfo->xrdb,
+				  resource_name, EMACS_CLASS,
+				  xim_instantiate_callback,
+				  (XPointer)xim_inst);
+#else /* not HAVE_X11R6 */
+  dpyinfo->xim = NULL;
+  xim_open_dpy (dpyinfo, resource_name);
+#endif /* not HAVE_X11R6 */
+}
+
+
+/* Close the connection to the XIM server on display DPYINFO. */
+
+static void
+xim_close_dpy (dpyinfo)
+     struct x_display_info *dpyinfo;
+{
+#ifdef HAVE_X11R6
+  XUnregisterIMInstantiateCallback (dpyinfo->display, dpyinfo->xrdb,
+				    NULL, EMACS_CLASS,
+				    xim_instantiate_callback, NULL);
+#endif /* HAVE_X11R6 */
+  XCloseIM (dpyinfo->xim);
+  dpyinfo->xim = NULL;
+  XFree (dpyinfo->xim_styles);
+}
+
+#endif /* HAVE_X_I18N */
+
+
 
 /* Calculate the absolute position in frame F
    from its current recorded position values and gravity.  */
@@ -11606,16 +11830,8 @@
       if (f->output_data.x->icon_desc != 0)
 	XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->icon_desc);
 #ifdef HAVE_X_I18N
-      if (FRAME_XIM (f))
-	{
-	  XDestroyIC (FRAME_XIC (f));
-#if ! defined (SOLARIS2) || defined (HAVE_X11R6)
-	  /* This line causes crashes on Solaris with Openwin,
-	     due to an apparent bug in XCloseIM.
-	     X11R6 seems not to have the bug.  */
-	  XCloseIM (FRAME_XIM (f));
-#endif
-	}
+      if (FRAME_XIC (f))
+	free_frame_xic (f);
 #endif
       XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->window_desc);
 #ifdef USE_X_TOOLKIT
@@ -12861,6 +13077,10 @@
 				     (unsigned long) 1, (unsigned long) 0, 1);
   }
 
+#ifdef HAVE_X_I18N
+  xim_initialize (dpyinfo, resource_name);
+#endif
+  
 #ifdef subprocesses
   /* This is only needed for distinguishing keyboard and process input.  */
   if (connection != 0)
@@ -12964,6 +13184,11 @@
   if (--dpyinfo->kboard->reference_count == 0)
     delete_kboard (dpyinfo->kboard);
 #endif
+#ifdef HAVE_X_I18N
+  if (dpyinfo->xim)
+    xim_close_dpy (dpyinfo);
+#endif
+  
   xfree (dpyinfo->font_table);
   xfree (dpyinfo->x_id_name);
   xfree (dpyinfo);