[openi18n-im:01267] iiimxcf patch to fix off-the-spot for motif

Jens Petersen <[email protected]> Tue, 08 Mar 2005 18:12:04 +0900
Newsgroups gmane.comp.internationalization.input-methods
Message-ID <[email protected]>
Attached is a patch contributed by [email protected]
which should fix problems with off-the-spot on motif.

The patch is against r12.1. If people more familiar
with the iiimxcf code could take a look and perhaps either commit it
if appropriate or provide feedback that would be great.

Thanks, Jens
iiimxcf-offthespot.patch (text/x-patch, 7.7 KB)
diff -ur im-sdk-r12_1-svn2002.orig/iiimxcf/xiiimp.so/iiimp/guiIMPre.c im-sdk-r12_1-svn2002/iiimxcf/xiiimp.so/iiimp/guiIMPre.c
--- im-sdk-r12_1-svn2002.orig/iiimxcf/xiiimp.so/iiimp/guiIMPre.c	2005-01-27 13:35:26.000000000 +0900
+++ im-sdk-r12_1-svn2002/iiimxcf/xiiimp.so/iiimp/guiIMPre.c	2005-02-22 18:42:40.913270752 +0900
@@ -194,6 +194,10 @@
 
   /* Draw All Preedit Text */
   for (i = 0; i < preedit->active_areas; i++) {
+    if (ic->core.input_style & XIMPreeditArea) {
+      XClearArea(ic->core.im->core.display,
+		 preedit_area[i].window, 0, 0, 0, 0, False);
+    }
     if (preedit_area[i].active_lines == 0) {
       DrawPreeditString(ic,
 			ic->core.im->core.display,
@@ -330,8 +334,12 @@
   }
   if (start == 0 && len == 0) {
     UpdatePreeditAll(ic);
-  }
-  if (len > 0) {
+  } else if (ic->core.input_style & XIMPreeditArea &&
+	     (preedit_area[0].configured == True ||
+	      preedit_area[0].char_len !=
+	      preedit_area[0].char_len_backup)) {
+    UpdatePreeditAll(ic);
+  } else if (len > 0) {
     int x;
     unsigned int width;
     wchar_t *wcstr = preedit_chars->wchar;
diff -ur im-sdk-r12_1-svn2002.orig/iiimxcf/xiiimp.so/iiimp/guiIMPreArea.c im-sdk-r12_1-svn2002/iiimxcf/xiiimp.so/iiimp/guiIMPreArea.c
--- im-sdk-r12_1-svn2002.orig/iiimxcf/xiiimp.so/iiimp/guiIMPreArea.c	2003-04-24 19:24:26.000000000 +0900
+++ im-sdk-r12_1-svn2002/iiimxcf/xiiimp.so/iiimp/guiIMPreArea.c	2005-02-22 18:49:22.724186208 +0900
@@ -70,65 +70,150 @@
   PreeditArea preedit_area;
   CacheRec *preedit_cache;
   PreeditChars preedit_chars;
-  unsigned int width, height;
+  XRectangle *ic_preedit_area;
+  unsigned int width, height, max_width, max_height;
+  XFontSetExtents *fse;
 
   if (!preedit) {
     create(ic, NULL);
     preedit = (PreeditWin)(ic->gui_icpart->preedit);
     if (!preedit) return;
   }
-  preedit_area = (PreeditArea)(preedit->preedit_areas);
-
   if (!preedit->fontset) {
     SetPreeditFont(ic, NULL);
+    if (!preedit->fontset) return;
   }
 
   preedit_chars = (PreeditChars)&(preedit->preedit_chars);
-  if (preedit_area) {
-    preedit_area[0].x = 0;
-    preedit_area[0].char_offset = 0;
-    preedit_area[0].char_len = preedit_chars->wchar_len;
-  }
-
   if (preedit_chars->wchar_len == 0) return;
 
-  if (preedit->fontset) {
-    XFontSetExtents *fse;
-    fse = XExtentsOfFontSet(preedit->fontset);
-    width = XwcTextEscapement(preedit->fontset,
-			      preedit_chars->wchar,
-			      preedit_chars->wchar_len);
-    height = fse->max_logical_extent.height;
-    if (preedit_area) {
-      preedit_area[0].y = fse->max_ink_extent.height;
+  preedit_area = (PreeditArea)(preedit->preedit_areas);
+  if (preedit->active_areas != 1 || !preedit_area ||
+      !preedit_area[0].window) {
+    return;
+  }
+
+  fse = XExtentsOfFontSet(preedit->fontset);
+  width = XwcTextEscapement(preedit->fontset,
+			    preedit_chars->wchar,
+			    preedit_chars->wchar_len);
+  if (width == 0) width = 1;
+  height = fse->max_ink_extent.height;
+  if (height == 0) height = 1;
+
+  ic_preedit_area = &ic->core.preedit_attr.area;
+  max_width = (fse->max_ink_extent.width > ic_preedit_area->width) ?
+    fse->max_ink_extent.width : ic_preedit_area->width;
+  max_height = ic_preedit_area->height;
+
+  preedit_area[0].configured = False;
+  preedit_area[0].x = 0;
+  preedit_area[0].char_offset = 0;
+  preedit_area[0].char_len = preedit_chars->wchar_len;
+  if (max_height < fse->max_ink_extent.height) {
+    int height_diff;
+    height_diff =
+      (max_height - fse->max_ink_extent.height);
+    height_diff += (height_diff & 1);
+    preedit_area[0].y = (-fse->max_ink_extent.y) + (height_diff / 2);
+  }
+  else {
+    preedit_area[0].y = (-fse->max_ink_extent.y);
+  }
+
+  if (width <= max_width) {
+    preedit_area[0].active_lines = 0;
+  }
+  else if (max_height < fse->max_ink_extent.height) {
+    /* draw latest characters only */
+    preedit_area[0].active_lines = 0;
+    preedit_area[0].x = max_width - width;
+  }
+  else {
+    /* draw more than two lines */
+    int left;
+    wchar_t *wcstr;
+    int n, prev_y, line_spacing;
+    PreeditLine preedit_line;
+    
+    preedit_line = preedit_area[0].lines;
+    left = preedit_chars->wchar_len;
+    wcstr = preedit_chars->wchar;
+    n = 0;
+    line_spacing = (ic->core.preedit_attr.line_spacing > 0) ?
+      ic->core.preedit_attr.line_spacing : height;
+    prev_y = preedit_area[0].y - line_spacing;;
+    while (left) {
+      wchar_t *p = wcstr;
+      int cur_width = 0;
+      int i;
+      if (n == preedit_area[0].alloc_lines) {
+	preedit_area[0].alloc_lines += 10;
+	if (!preedit_area[0].lines) {
+	  preedit_area[0].lines =
+	    (PreeditLine)Xmalloc(sizeof(PreeditLineRec) *
+				 preedit_area[0].alloc_lines);
+	}
+	else {
+	  preedit_area[0].lines =
+	    (PreeditLine)Xrealloc(preedit_area[0].lines,
+				  sizeof(PreeditLineRec) *
+				  preedit_area[0].alloc_lines);
+	}
+	if (!preedit_area[0].lines) return;
+	preedit_line = preedit_area[0].lines;
+      }
+      for (i = 1; i <= left; i++) {
+	cur_width += XwcTextEscapement(preedit->fontset, p++, 1);
+	if (cur_width > max_width) break;
+      }
+      preedit_line[n].x = 0;
+      preedit_line[n].y = prev_y + line_spacing;
+      preedit_line[n].char_offset = wcstr - preedit_chars->wchar;
+      preedit_line[n].char_len = i - 1;
+      prev_y = preedit_line[n].y;
+      n++;
+      left -= (i - 1);
+      wcstr += i - 1;
     }
-  } else {
-    width = ic->core.preedit_attr.area.width;
-    height = ic->core.preedit_attr.area.height;
-    if (preedit_area) {
-      preedit_area[0].y = ic->core.preedit_attr.area.height;
+    preedit_area[0].active_lines = n;
+    height = line_spacing * n;
+    if (max_height < height) {
+      int i;
+      int height_diff = height - max_height;
+      for (i = 0; i < n; ++i) {
+	preedit_line[i].y -= height_diff;
+      }
     }
   }
-
+  if (max_width < width) width = max_width;
+  // Is window size changed?
+  if (preedit_area[0].win_config.x != ic_preedit_area->x ||
+      preedit_area[0].win_config.y != ic_preedit_area->y ||
+      preedit_area[0].win_config.width != ic_preedit_area->width ||
+      preedit_area[0].win_config.height != ic_preedit_area->height) {
+    XMoveResizeWindow(ic->core.im->core.display,
+		      preedit_area[0].window,
+		      ic_preedit_area->x, ic_preedit_area->y,
+		      ic_preedit_area->width, ic_preedit_area->height);
+    preedit_area[0].win_config.x = ic_preedit_area->x;
+    preedit_area[0].win_config.y = ic_preedit_area->y;
+    preedit_area[0].win_config.width = ic_preedit_area->width;
+    preedit_area[0].win_config.height = ic_preedit_area->height;
+    preedit_area[0].configured = True;
+  }
+  // Is preedit area not changed ?
   preedit_cache = (CacheRec*)&(preedit->preedit_cache);
-  if (preedit_cache->win_x == ic->core.preedit_attr.area.x &&
-      preedit_cache->win_y == ic->core.preedit_attr.area.y &&
+  if (preedit_cache->win_x == preedit_area[0].x &&
+      preedit_cache->win_y == preedit_area[0].y &&
       preedit_cache->win_width == width &&
-      preedit_cache->win_height == height &&
-      preedit_cache->font_set == preedit->fontset) {
+      preedit_cache->win_height == height) {
     return;
   }
-  if (preedit->active_areas == 1 && preedit_area &&
-      preedit_area[0].window) {
-    XMoveResizeWindow(ic->core.im->core.display,
-		      preedit_area[0].window,
-		      ic->core.preedit_attr.area.x,
-		      ic->core.preedit_attr.area.y,
-		      width, height);
-  }
+  preedit_area[0].configured = True;
   /* data cache */
-  preedit_cache->win_x = ic->core.preedit_attr.area.x;
-  preedit_cache->win_y = ic->core.preedit_attr.area.y;
+  preedit_cache->win_x = preedit_area[0].x;
+  preedit_cache->win_y = preedit_area[0].y;
   preedit_cache->win_width = width;
   preedit_cache->win_height = height;
   preedit_cache->font_set = preedit->fontset;