9fcb0f8
Return-Path: a-higuti@math.sci.hokudai.ac.jp
9fcb0f8
Delivery-Date: Thu Sep 23 14:52:43 1999
9fcb0f8
Return-Path: <a-higuti@math.sci.hokudai.ac.jp>
9fcb0f8
Received: from localhost (IDENT:otaylor@localhost [127.0.0.1])
9fcb0f8
	by fresnel.labs.redhat.com (8.9.3/8.9.3) with ESMTP id OAA00891
9fcb0f8
	for <otaylor@localhost>; Thu, 23 Sep 1999 14:52:41 -0400
9fcb0f8
Received: from lacrosse.redhat.com
9fcb0f8
	by localhost with POP3 (fetchmail-5.0.0)
9fcb0f8
	for otaylor@localhost (single-drop); Thu, 23 Sep 1999 14:52:42 -0400 (EDT)
9fcb0f8
Received: from mail.redhat.com (mail.redhat.com [199.183.24.239])
9fcb0f8
	by lacrosse.corp.redhat.com (8.9.3/8.9.3) with ESMTP id OAA19205
9fcb0f8
	for <otaylor@lacrosse.redhat.com>; Thu, 23 Sep 1999 14:01:27 -0400
9fcb0f8
Received: from math.sci.hokudai.ac.jp (seki.math.sci.hokudai.ac.jp [133.50.152.8])
9fcb0f8
	by mail.redhat.com (8.8.7/8.8.7) with ESMTP id OAA13383
9fcb0f8
	for <otaylor@redhat.com>; Thu, 23 Sep 1999 14:01:49 -0400
9fcb0f8
Received: from heathcliff (a-higuti@hilbert.math.sci.hokudai.ac.jp [133.50.152.11])
9fcb0f8
	by math.sci.hokudai.ac.jp (8.8.8/3.6W01/06/98) with SMTP id DAA23889
9fcb0f8
	for <otaylor@redhat.com>; Fri, 24 Sep 1999 03:01:10 +0900 (JST)
9fcb0f8
Date: Fri, 24 Sep 1999 03:01:10 +0900 (JST)
9fcb0f8
Message-Id: <199909231801.DAA23889@math.sci.hokudai.ac.jp>
9fcb0f8
From: a-higuti@math.sci.hokudai.ac.jp (Akira Higuchi)
9fcb0f8
To: otaylor@redhat.com
9fcb0f8
Subject: Adding more gdk_isw* macros
9fcb0f8
Mime-Version: 1.0
9fcb0f8
Content-Type: text/plain; charset=US-ASCII
9fcb0f8
Status:  O
9fcb0f8
Lines: 528
9fcb0f8
Xref: fresnel.labs.redhat.com prog-gtk:648
9fcb0f8
9fcb0f8
Hello Owen,
9fcb0f8
9fcb0f8
I'm working on adding CJK support to gnome apps, and I need your advice.
9fcb0f8
9fcb0f8
As you know, gtk+-1.2 has some support for CJK. It's sufficient for most
9fcb0f8
gnome apps to be internationalized, but some problems remain. The most
9fcb0f8
problem is that there is no way of doing word wrapping for CJK strings.
9fcb0f8
9fcb0f8
For example, gtk-xmhtml shows Japanese text very uglily, because Japanese
9fcb0f8
sentences are recognized as very long words. (a Japanese sentence 
9fcb0f8
contain any spaces in most cases.) The same problem is in gtk+ itself, too;
9fcb0f8
Word wrapping in GtkLabel and GtkText doesn't work correctly for CJK text,
9fcb0f8
because of the same reason as above.
9fcb0f8
9fcb0f8
In order to fix it, we need more gdk_isw* functions than we already have
9fcb0f8
in gdki18n.h. (I regret I didn't add them before gtk+-1.2 was released.)
9fcb0f8
I attach herewith a patch which fixes it, but I think it's not acceptable
9fcb0f8
to adding a new macro to a stable version of gtk+. (is it?)
9fcb0f8
9fcb0f8
The question I want to ask you is: what's the best way of fixing the
9fcb0f8
problem without adding these macros to gdki18n.h? A solution is to add
9fcb0f8
these macros to each *.c files (in GtkLabel, GtkText, and gtkxmhtml etc.)
9fcb0f8
rather than gtki18n.h, but it's very ugly I think. 
9fcb0f8
9fcb0f8
Please don't say "wait until gscript is completed" ;-(  I don't want to
9fcb0f8
wait for a long time. (Please let me know if I can help you with gscript
9fcb0f8
BTW. I've not hacked gscript yet, because it seems to be too early to be
9fcb0f8
hacked by other than you.)
9fcb0f8
9fcb0f8
Thanks,
9fcb0f8
Akira Higuchi
9fcb0f8
---------------- x8 ---------------- x8 ---------------- x8 ----------------
ef8f582
diff -up gtk+-1.2.10/gdk/gdki18n.h.ahiguti gtk+-1.2.10/gdk/gdki18n.h
ef8f582
--- gtk+-1.2.10/gdk/gdki18n.h.ahiguti	2000-01-24 03:58:21.000000000 +0100
ef8f582
+++ gtk+-1.2.10/gdk/gdki18n.h	2008-10-02 10:43:26.000000000 +0200
ef8f582
@@ -51,4 +51,32 @@
9fcb0f8
 #  define gdk_iswspace(c) ((wchar_t)(c) <= 0xFF && isspace(c))
9fcb0f8
 #endif
9fcb0f8
 
9fcb0f8
+/* The following 9 macros are added in gtk+ 1.2.X. Don't use them without
9fcb0f8
+ * checking GTK_CHECK_VERSION. For example,
9fcb0f8
+ *	#if GTK_CHECK_VERSION (1,2,X)
9fcb0f8
+ *	    ... code which uses gdk_iswalpha(), gdk_iswcntrl(), etc. ...
9fcb0f8
+ *      #endif
9fcb0f8
+ */
9fcb0f8
+#if !defined(G_HAVE_BROKEN_WCTYPE) && (defined(G_HAVE_WCTYPE_H) || defined(G_HAVE_WCHAR_H)) && !defined(X_LOCALE)
9fcb0f8
+#  define gdk_iswalpha(c)  iswalpha(c)
9fcb0f8
+#  define gdk_iswcntrl(c)  iswcntrl(c)
9fcb0f8
+#  define gdk_iswdigit(c)  iswdigit(c)
9fcb0f8
+#  define gdk_iswlower(c)  iswlower(c)
9fcb0f8
+#  define gdk_iswgraph(c)  iswgraph(c)
9fcb0f8
+#  define gdk_iswprint(c)  iswprint(c)
9fcb0f8
+#  define gdk_iswpunct(c)  iswpunct(c)
9fcb0f8
+#  define gdk_iswupper(c)  iswupper(c)
9fcb0f8
+#  define gdk_iswxdigit(c) iswxdigit(c)
9fcb0f8
+#else
9fcb0f8
+#  define gdk_iswalpha(c)  ((wchar_t)(c) <= 0xFF && isalpha(c))
9fcb0f8
+#  define gdk_iswcntrl(c)  ((wchar_t)(c) <= 0xFF && iscntrl(c))
9fcb0f8
+#  define gdk_iswdigit(c)  ((wchar_t)(c) <= 0xFF && isdigit(c))
9fcb0f8
+#  define gdk_iswlower(c)  ((wchar_t)(c) <= 0xFF && islower(c))
9fcb0f8
+#  define gdk_iswgraph(c)  ((wchar_t)(c) >  0xFF || isgraph(c))
9fcb0f8
+#  define gdk_iswprint(c)  ((wchar_t)(c) >  0xFF || isprint(c))
9fcb0f8
+#  define gdk_iswpunct(c)  ((wchar_t)(c) <= 0xFF && ispunct(c))
9fcb0f8
+#  define gdk_iswupper(c)  ((wchar_t)(c) <= 0xFF && isupper(c))
9fcb0f8
+#  define gdk_iswxdigit(c) ((wchar_t)(c) <= 0xFF && isxdigit(c))
9fcb0f8
+#endif
9fcb0f8
+
9fcb0f8
 #endif /* __GDK_I18N_H__ */
ef8f582
diff -up gtk+-1.2.10/gtk/gtkentry.c.ahiguti gtk+-1.2.10/gtk/gtkentry.c
ef8f582
--- gtk+-1.2.10/gtk/gtkentry.c.ahiguti	2001-04-02 04:14:54.000000000 +0200
ef8f582
+++ gtk+-1.2.10/gtk/gtkentry.c	2008-10-02 10:43:26.000000000 +0200
ef8f582
@@ -2036,11 +2036,21 @@ gtk_entry_move_word (GtkEditable *editab
ef8f582
     }
9fcb0f8
 }
9fcb0f8
 
9fcb0f8
+static gboolean
9fcb0f8
+alnum_or_ideogram (GtkEntry *entry, guint index)
9fcb0f8
+{
9fcb0f8
+  GdkWChar ch;
9fcb0f8
+  ch = entry->text[index];
9fcb0f8
+  if (entry->use_wchar)
9fcb0f8
+    return !(gdk_iswpunct (ch) || gdk_iswcntrl (ch) || gdk_iswspace (ch));
9fcb0f8
+  else
9fcb0f8
+    return !(ispunct (ch) || iscntrl (ch) || isspace (ch));
9fcb0f8
+}
9fcb0f8
+
9fcb0f8
 static void
9fcb0f8
 gtk_move_forward_word (GtkEntry *entry)
9fcb0f8
 {
9fcb0f8
   GtkEditable *editable;
9fcb0f8
-  GdkWChar *text;
9fcb0f8
   gint i;
9fcb0f8
 
9fcb0f8
   editable = GTK_EDITABLE (entry);
ef8f582
@@ -2054,21 +2064,12 @@ gtk_move_forward_word (GtkEntry *entry)
9fcb0f8
 
9fcb0f8
   if (entry->text && (editable->current_pos < entry->text_length))
9fcb0f8
     {
9fcb0f8
-      text = entry->text;
9fcb0f8
-      i = editable->current_pos;
9fcb0f8
-	  
9fcb0f8
-      if ((entry->use_wchar) ? (!gdk_iswalnum (text[i])) : (!isalnum (text[i])))
9fcb0f8
-	for (; i < entry->text_length; i++)
9fcb0f8
-	  {
9fcb0f8
-	    if ((entry->use_wchar) ? gdk_iswalnum (text[i]) : isalnum (text[i]))
9fcb0f8
-	      break;
9fcb0f8
-	  }
9fcb0f8
-
9fcb0f8
+      for (i = editable->current_pos; i < entry->text_length; i++)
9fcb0f8
+	if (alnum_or_ideogram (entry, i))
9fcb0f8
+	  break;
9fcb0f8
       for (; i < entry->text_length; i++)
9fcb0f8
-	{
9fcb0f8
-	  if ((entry->use_wchar) ? (!gdk_iswalnum (text[i])) : (!isalnum (text[i])))
9fcb0f8
-	    break;
9fcb0f8
-	}
9fcb0f8
+	if (!alnum_or_ideogram (entry, i))
9fcb0f8
+	  break;
9fcb0f8
 
9fcb0f8
       editable->current_pos = i;
9fcb0f8
     }
ef8f582
@@ -2078,7 +2079,6 @@ static void
9fcb0f8
 gtk_move_backward_word (GtkEntry *entry)
9fcb0f8
 {
9fcb0f8
   GtkEditable *editable;
9fcb0f8
-  GdkWChar *text;
9fcb0f8
   gint i;
9fcb0f8
 
9fcb0f8
   editable = GTK_EDITABLE (entry);
ef8f582
@@ -2092,26 +2092,19 @@ gtk_move_backward_word (GtkEntry *entry)
9fcb0f8
 
9fcb0f8
   if (entry->text && editable->current_pos > 0)
9fcb0f8
     {
9fcb0f8
-      text = entry->text;
9fcb0f8
-      i = editable->current_pos - 1;
9fcb0f8
-      if ((entry->use_wchar) ? (!gdk_iswalnum (text[i])) : (!isalnum (text[i])))
9fcb0f8
-	for (; i >= 0; i--)
9fcb0f8
+      for (i = editable->current_pos - 1; i >= 0; i--)
9fcb0f8
+	if (alnum_or_ideogram (entry, i))
9fcb0f8
+	  break;
9fcb0f8
+      for (; i >= 0; i--)
9fcb0f8
+	if (!alnum_or_ideogram (entry, i))
9fcb0f8
 	  {
9fcb0f8
-	    if ((entry->use_wchar) ? gdk_iswalnum (text[i]) : isalnum (text[i]))
9fcb0f8
-	      break;
9fcb0f8
+	    i++;
9fcb0f8
+	    break;
9fcb0f8
 	  }
9fcb0f8
-      for (; i >= 0; i--)
9fcb0f8
-	{
9fcb0f8
-	  if ((entry->use_wchar) ? (!gdk_iswalnum (text[i])) : (!isalnum (text[i])))
9fcb0f8
-	    {
9fcb0f8
-	      i++;
9fcb0f8
-	      break;
9fcb0f8
-	    }
9fcb0f8
-	}
9fcb0f8
-	  
9fcb0f8
+
9fcb0f8
       if (i < 0)
9fcb0f8
 	i = 0;
9fcb0f8
-	  
9fcb0f8
+  
9fcb0f8
       editable->current_pos = i;
9fcb0f8
     }
9fcb0f8
 }
ef8f582
diff -up gtk+-1.2.10/gtk/gtklabel.c.ahiguti gtk+-1.2.10/gtk/gtklabel.c
ef8f582
--- gtk+-1.2.10/gtk/gtklabel.c.ahiguti	2001-04-02 05:12:38.000000000 +0200
ef8f582
+++ gtk+-1.2.10/gtk/gtklabel.c	2008-10-02 10:43:26.000000000 +0200
ef8f582
@@ -56,6 +56,7 @@ struct _GtkLabelWord
9fcb0f8
   GtkLabelWord *next;
9fcb0f8
   gint uline_y;
9fcb0f8
   GtkLabelULine *uline;
9fcb0f8
+  gboolean paragraph_break;
9fcb0f8
 };
9fcb0f8
 
9fcb0f8
 struct _GtkLabelULine
ef8f582
@@ -396,6 +397,7 @@ gtk_label_word_alloc (void)
9fcb0f8
   word->beginning = NULL;
9fcb0f8
   word->next = NULL;
9fcb0f8
   word->uline = NULL;
9fcb0f8
+  word->paragraph_break = FALSE;
9fcb0f8
 
9fcb0f8
   return word;
9fcb0f8
 }
ef8f582
@@ -441,6 +443,7 @@ gtk_label_split_text (GtkLabel *label)
9fcb0f8
       if (str == label->label_wc || str[-1] == '\n')
9fcb0f8
 	{
9fcb0f8
 	  /* Paragraph break */
9fcb0f8
+	  word->paragraph_break = TRUE;
9fcb0f8
 	  word->space = 0;
9fcb0f8
 	  
9fcb0f8
 	  max_line_width = MAX (line_width, max_line_width);
ef8f582
@@ -488,6 +491,7 @@ gtk_label_split_text (GtkLabel *label)
9fcb0f8
     {
9fcb0f8
       word = gtk_label_word_alloc ();
9fcb0f8
       
9fcb0f8
+      word->paragraph_break = TRUE;
9fcb0f8
       word->space = 0;
9fcb0f8
       word->beginning = str;
9fcb0f8
       word->length = 0;
ef8f582
@@ -500,6 +504,13 @@ gtk_label_split_text (GtkLabel *label)
9fcb0f8
   return MAX (line_width, max_line_width);
9fcb0f8
 }
9fcb0f8
 
9fcb0f8
+static gboolean
9fcb0f8
+is_ideogram (GdkWChar wc)
9fcb0f8
+{
9fcb0f8
+  return !(gdk_iswalnum (wc) || gdk_iswspace (wc) ||
9fcb0f8
+	   gdk_iswpunct (wc) || gdk_iswcntrl (wc));
9fcb0f8
+}
9fcb0f8
+
9fcb0f8
 /* this needs to handle white space better. */
9fcb0f8
 static gint
9fcb0f8
 gtk_label_split_text_wrapped (GtkLabel *label)
ef8f582
@@ -526,6 +537,7 @@ gtk_label_split_text_wrapped (GtkLabel *
9fcb0f8
       if (str == label->label_wc || str[-1] == '\n')
9fcb0f8
 	{
9fcb0f8
 	  /* Paragraph break */
9fcb0f8
+	  word->paragraph_break = TRUE;
9fcb0f8
 	  word->space = 0;
9fcb0f8
 	  
9fcb0f8
 	  max_line_width = MAX (line_width, max_line_width);
ef8f582
@@ -546,24 +558,30 @@ gtk_label_split_text_wrapped (GtkLabel *
9fcb0f8
 	  else
9fcb0f8
 	    word->space = space_width * nspaces;
9fcb0f8
 	}
9fcb0f8
-      else
9fcb0f8
+      else if (gdk_iswspace (str[-1]))
9fcb0f8
 	{
9fcb0f8
 	  /* Regular inter-word space */
9fcb0f8
 	  word->space = space_width;
9fcb0f8
 	}
9fcb0f8
+      else
9fcb0f8
+	{
9fcb0f8
+	  word->space = 0;
9fcb0f8
+	}
9fcb0f8
       
9fcb0f8
       word->beginning = str;
9fcb0f8
       word->length = 0;
9fcb0f8
       p = word->beginning;
9fcb0f8
       while (*p && !gdk_iswspace (*p))
9fcb0f8
 	{
9fcb0f8
+	  if (word->length > 0 && (is_ideogram (p[-1]) || is_ideogram (*p)))
9fcb0f8
+	    break;
9fcb0f8
 	  word->length++;
9fcb0f8
 	  p++;
9fcb0f8
 	}
9fcb0f8
       word->width = gdk_text_width_wc (GTK_WIDGET (label)->style->font, str, word->length);
9fcb0f8
       
9fcb0f8
       str += word->length;
9fcb0f8
-      if (*str)
9fcb0f8
+      if (*str && gdk_iswspace (*str))
9fcb0f8
 	str++;
9fcb0f8
       
9fcb0f8
       line_width += word->space + word->width;
ef8f582
@@ -600,7 +618,7 @@ gtk_label_pick_width (GtkLabel *label,
9fcb0f8
   width = 0;
9fcb0f8
   for (word = label->words; word; word = word->next)
9fcb0f8
     {
9fcb0f8
-      if (word->space == 0
9fcb0f8
+      if (word->paragraph_break
9fcb0f8
 	  || (line_width
9fcb0f8
 	      && (line_width >= min_width
9fcb0f8
 		  || line_width + word->width + word->space > max_width)))
ef8f582
@@ -716,7 +734,8 @@ gtk_label_finalize_lines_wrap (GtkLabel 
9fcb0f8
   GtkLabelWord *word, *line, *next_line;
9fcb0f8
   GtkWidget *widget;
9fcb0f8
   gchar *ptrn;
9fcb0f8
-  gint x, y, space, extra_width, add_space, baseline_skip;
9fcb0f8
+  gint x, y, space, num_words, extra_width, add_space, baseline_skip;
9fcb0f8
+  gboolean deliver_equivalently;
9fcb0f8
   
9fcb0f8
   g_return_if_fail (label->wrap);
9fcb0f8
   
ef8f582
@@ -724,20 +743,24 @@ gtk_label_finalize_lines_wrap (GtkLabel 
9fcb0f8
   y = 0;
9fcb0f8
   baseline_skip = (GTK_WIDGET (label)->style->font->ascent +
9fcb0f8
 		   GTK_WIDGET (label)->style->font->descent + 1);
9fcb0f8
+  deliver_equivalently = FALSE;
9fcb0f8
   
9fcb0f8
   for (line = label->words; line != 0; line = next_line)
9fcb0f8
     {
9fcb0f8
-      space = 0;
9fcb0f8
+      space = num_words = 0;
9fcb0f8
       extra_width = max_line_width - line->width;
9fcb0f8
       
9fcb0f8
       for (next_line = line->next; next_line; next_line = next_line->next)
9fcb0f8
 	{
9fcb0f8
-	  if (next_line->space == 0)
9fcb0f8
+	  if (next_line->paragraph_break)
9fcb0f8
 	    break;		/* New paragraph */
9fcb0f8
 	  if (next_line->space + next_line->width > extra_width)
9fcb0f8
 	    break;
9fcb0f8
+	  if (next_line->space == 0)
9fcb0f8
+	    deliver_equivalently = TRUE; /* An ideogram is found. */
9fcb0f8
 	  extra_width -= next_line->space + next_line->width;
9fcb0f8
 	  space += next_line->space;
9fcb0f8
+	  num_words++;
9fcb0f8
 	}
9fcb0f8
       
9fcb0f8
       line->x = 0;
ef8f582
@@ -747,14 +770,18 @@ gtk_label_finalize_lines_wrap (GtkLabel 
9fcb0f8
       
9fcb0f8
       for (word = line->next; word != next_line; word = word->next)
9fcb0f8
 	{
9fcb0f8
-	  if (next_line && next_line->space)
9fcb0f8
+	  if (next_line && !next_line->paragraph_break &&
9fcb0f8
+	      label->jtype == GTK_JUSTIFY_FILL &&
9fcb0f8
+	      (deliver_equivalently ? num_words : space) > 0)
9fcb0f8
 	    {
9fcb0f8
-	      /* Not last line of paragraph --- fill line if needed */
9fcb0f8
-	      if (label->jtype == GTK_JUSTIFY_FILL) {
9fcb0f8
+	      /* Not last line of paragraph --- fill line */
9fcb0f8
+	      if (deliver_equivalently)
9fcb0f8
+		add_space = (extra_width + num_words / 2) / num_words;
9fcb0f8
+	      else
9fcb0f8
 		add_space = (extra_width * word->space + space / 2) / space;
9fcb0f8
-		extra_width -= add_space;
9fcb0f8
-		space -= word->space;
9fcb0f8
-	      }
9fcb0f8
+	      extra_width -= add_space;
9fcb0f8
+	      space -= word->space;
9fcb0f8
+	      num_words--;
9fcb0f8
 	    }
9fcb0f8
 	  
9fcb0f8
 	  word->x = x + word->space + add_space;
ef8f582
@@ -925,7 +952,7 @@ gtk_label_expose (GtkWidget      *widget
9fcb0f8
 
9fcb0f8
       for (word = label->words; word; word = word->next)
9fcb0f8
 	{
9fcb0f8
-	  gchar save = word->beginning[word->length];
9fcb0f8
+	  GdkWChar save = word->beginning[word->length];
9fcb0f8
 	  word->beginning[word->length] = '\0';
9fcb0f8
 	  gtk_label_paint_word (label, x, y, word, &event->area);
9fcb0f8
 	  word->beginning[word->length] = save;
ef8f582
diff -up gtk+-1.2.10/gtk/gtktext.c.ahiguti gtk+-1.2.10/gtk/gtktext.c
ef8f582
--- gtk+-1.2.10/gtk/gtktext.c.ahiguti	2001-03-15 21:15:12.000000000 +0100
ef8f582
+++ gtk+-1.2.10/gtk/gtktext.c	2008-10-02 10:43:27.000000000 +0200
ef8f582
@@ -101,6 +101,13 @@ enum {
9fcb0f8
   ARG_WORD_WRAP
9fcb0f8
 };
9fcb0f8
 
9fcb0f8
+typedef enum {
9fcb0f8
+  CHAR_CLASS_SPACE,
9fcb0f8
+  CHAR_CLASS_ALNUM,
9fcb0f8
+  CHAR_CLASS_IDEOGRAM,
9fcb0f8
+  CHAR_CLASS_OTHERS     /* punct, cntrl */
9fcb0f8
+} CharClass;
9fcb0f8
+
9fcb0f8
 typedef struct _TextProperty          TextProperty;
9fcb0f8
 typedef struct _TabStopMark           TabStopMark;
9fcb0f8
 typedef struct _PrevTabCont           PrevTabCont;
ef8f582
@@ -300,6 +307,8 @@ static LineParams find_line_params (GtkT
9fcb0f8
 				    const GtkPropertyMark *mark,
9fcb0f8
 				    const PrevTabCont *tab_cont,
9fcb0f8
 				    PrevTabCont *next_cont);
9fcb0f8
+static void find_word_wrap_position (GtkText* text, LineParams *lp);
9fcb0f8
+static CharClass char_class (GtkText* text, guint index);
9fcb0f8
 static void recompute_geometry (GtkText* text);
9fcb0f8
 static void insert_expose (GtkText* text, guint old_pixels, gint nchars, guint new_line_count);
9fcb0f8
 static void delete_expose (GtkText* text,
ef8f582
@@ -4111,27 +4120,21 @@ gtk_text_move_forward_word (GtkText *tex
9fcb0f8
   
9fcb0f8
   undraw_cursor (text, FALSE);
9fcb0f8
   
9fcb0f8
-  if (text->use_wchar)
9fcb0f8
+  while (!LAST_INDEX (text, text->cursor_mark))
9fcb0f8
     {
9fcb0f8
-      while (!LAST_INDEX (text, text->cursor_mark) && 
9fcb0f8
-	     !gdk_iswalnum (GTK_TEXT_INDEX(text, text->cursor_mark.index)))
9fcb0f8
-	advance_mark (&text->cursor_mark);
9fcb0f8
-      
9fcb0f8
-      while (!LAST_INDEX (text, text->cursor_mark) && 
9fcb0f8
-	     gdk_iswalnum (GTK_TEXT_INDEX(text, text->cursor_mark.index)))
9fcb0f8
-	advance_mark (&text->cursor_mark);
9fcb0f8
+      CharClass cc = char_class (text, text->cursor_mark.index);
9fcb0f8
+      if (cc == CHAR_CLASS_ALNUM || cc == CHAR_CLASS_IDEOGRAM)
9fcb0f8
+	break;
9fcb0f8
+      advance_mark (&text->cursor_mark);
9fcb0f8
     }
9fcb0f8
-  else
9fcb0f8
+  while (!LAST_INDEX (text, text->cursor_mark))
9fcb0f8
     {
9fcb0f8
-      while (!LAST_INDEX (text, text->cursor_mark) && 
9fcb0f8
-	     !isalnum (GTK_TEXT_INDEX(text, text->cursor_mark.index)))
9fcb0f8
-	advance_mark (&text->cursor_mark);
9fcb0f8
-      
9fcb0f8
-      while (!LAST_INDEX (text, text->cursor_mark) && 
9fcb0f8
-	     isalnum (GTK_TEXT_INDEX(text, text->cursor_mark.index)))
9fcb0f8
-	advance_mark (&text->cursor_mark);
9fcb0f8
+      CharClass cc = char_class (text, text->cursor_mark.index);
9fcb0f8
+      if (cc != CHAR_CLASS_ALNUM && cc != CHAR_CLASS_IDEOGRAM)
9fcb0f8
+	break;
9fcb0f8
+      advance_mark (&text->cursor_mark);
9fcb0f8
     }
9fcb0f8
-  
9fcb0f8
+
9fcb0f8
   find_cursor (text, TRUE);
9fcb0f8
   draw_cursor (text, FALSE);
9fcb0f8
 }
ef8f582
@@ -4143,25 +4146,19 @@ gtk_text_move_backward_word (GtkText *te
9fcb0f8
   
9fcb0f8
   undraw_cursor (text, FALSE);
9fcb0f8
   
9fcb0f8
-  if (text->use_wchar)
9fcb0f8
+  while (text->cursor_mark.index > 0)
9fcb0f8
     {
9fcb0f8
-      while ((text->cursor_mark.index > 0) &&
9fcb0f8
-	     !gdk_iswalnum (GTK_TEXT_INDEX(text, text->cursor_mark.index-1)))
9fcb0f8
-	decrement_mark (&text->cursor_mark);
9fcb0f8
-      
9fcb0f8
-      while ((text->cursor_mark.index > 0) &&
9fcb0f8
-	     gdk_iswalnum (GTK_TEXT_INDEX(text, text->cursor_mark.index-1)))
9fcb0f8
-	decrement_mark (&text->cursor_mark);
9fcb0f8
+      CharClass cc = char_class (text, text->cursor_mark.index - 1);
9fcb0f8
+      if (cc == CHAR_CLASS_ALNUM || cc == CHAR_CLASS_IDEOGRAM)
9fcb0f8
+	break;
9fcb0f8
+      decrement_mark (&text->cursor_mark);
9fcb0f8
     }
9fcb0f8
-  else
9fcb0f8
+  while (text->cursor_mark.index > 0)
9fcb0f8
     {
9fcb0f8
-      while ((text->cursor_mark.index > 0) &&
9fcb0f8
-	     !isalnum (GTK_TEXT_INDEX(text, text->cursor_mark.index-1)))
9fcb0f8
-	decrement_mark (&text->cursor_mark);
9fcb0f8
-      
9fcb0f8
-      while ((text->cursor_mark.index > 0) &&
9fcb0f8
-	     isalnum (GTK_TEXT_INDEX(text, text->cursor_mark.index-1)))
9fcb0f8
-	decrement_mark (&text->cursor_mark);
9fcb0f8
+      CharClass cc = char_class (text, text->cursor_mark.index - 1);
9fcb0f8
+      if (cc != CHAR_CLASS_ALNUM && cc != CHAR_CLASS_IDEOGRAM)
9fcb0f8
+	break;
9fcb0f8
+      decrement_mark (&text->cursor_mark);
9fcb0f8
     }
9fcb0f8
   
9fcb0f8
   find_cursor (text, TRUE);
ef8f582
@@ -4782,27 +4779,8 @@ find_line_params (GtkText* text,
9fcb0f8
 		      GtkPropertyMark saved_mark = lp.end;
9fcb0f8
 		      guint saved_characters = lp.displayable_chars;
9fcb0f8
 		      
9fcb0f8
-		      lp.displayable_chars += 1;
9fcb0f8
-		      
9fcb0f8
-		      if (text->use_wchar)
9fcb0f8
-			{
9fcb0f8
-			  while (!gdk_iswspace (GTK_TEXT_INDEX (text, lp.end.index)) &&
9fcb0f8
-				 (lp.end.index > lp.start.index))
9fcb0f8
-			    {
9fcb0f8
-			      decrement_mark (&lp.end);
9fcb0f8
-			      lp.displayable_chars -= 1;
9fcb0f8
-			    }
9fcb0f8
-			}
9fcb0f8
-		      else
9fcb0f8
-			{
9fcb0f8
-			  while (!isspace(GTK_TEXT_INDEX (text, lp.end.index)) &&
9fcb0f8
-				 (lp.end.index > lp.start.index))
9fcb0f8
-			    {
9fcb0f8
-			      decrement_mark (&lp.end);
9fcb0f8
-			      lp.displayable_chars -= 1;
9fcb0f8
-			    }
9fcb0f8
-			}
9fcb0f8
-		      
9fcb0f8
+		      find_word_wrap_position (text, &lp);
9fcb0f8
+
9fcb0f8
 		      /* If whole line is one word, revert to char wrapping */
9fcb0f8
 		      if (lp.end.index == lp.start.index)
9fcb0f8
 			{
ef8f582
@@ -4850,6 +4828,54 @@ find_line_params (GtkText* text,
9fcb0f8
   return lp;
ef8f582
 }
ef8f582
 
9fcb0f8
+static CharClass
9fcb0f8
+char_class (GtkText* text, guint index)
9fcb0f8
+{
9fcb0f8
+  GdkWChar wc;
9fcb0f8
+  wc = GTK_TEXT_INDEX (text, index);
9fcb0f8
+  if (text->use_wchar)
9fcb0f8
+    {
9fcb0f8
+      if (gdk_iswspace (wc))
9fcb0f8
+	return CHAR_CLASS_SPACE;
9fcb0f8
+      else if (gdk_iswalnum (wc))
9fcb0f8
+	return CHAR_CLASS_ALNUM;
9fcb0f8
+      else if (gdk_iswpunct (wc) || gdk_iswcntrl (wc))
9fcb0f8
+	return CHAR_CLASS_OTHERS;
9fcb0f8
+      else
9fcb0f8
+	return CHAR_CLASS_IDEOGRAM;
9fcb0f8
+    }
9fcb0f8
+  else
9fcb0f8
+    {
9fcb0f8
+      if (isspace (wc))
9fcb0f8
+	return CHAR_CLASS_SPACE;
9fcb0f8
+      else if (isalnum (wc))
9fcb0f8
+	return CHAR_CLASS_ALNUM;
9fcb0f8
+      else if (ispunct (wc) || iscntrl (wc))
9fcb0f8
+	return CHAR_CLASS_OTHERS;
9fcb0f8
+      else
9fcb0f8
+	return CHAR_CLASS_IDEOGRAM;
9fcb0f8
+    }
9fcb0f8
+}
9fcb0f8
+
9fcb0f8
+static void
9fcb0f8
+find_word_wrap_position (GtkText* text, LineParams *lp)
9fcb0f8
+{
9fcb0f8
+  while (lp->end.index > lp->start.index &&
9fcb0f8
+	 char_class (text, lp->end.index) != CHAR_CLASS_SPACE &&
9fcb0f8
+	 char_class (text, lp->end.index) != CHAR_CLASS_IDEOGRAM &&
9fcb0f8
+	 char_class (text, lp->end.index - 1) != CHAR_CLASS_IDEOGRAM)
9fcb0f8
+    {
9fcb0f8
+      decrement_mark (&lp->end);
9fcb0f8
+      lp->displayable_chars -= 1;
9fcb0f8
+    }
9fcb0f8
+
9fcb0f8
+  /* lp->end.index points the position to be cut just now. If it's not a
9fcb0f8
+   * space, move it to the next display line. */
9fcb0f8
+  if (lp->end.index > lp->start.index &&
9fcb0f8
+      char_class (text, lp->end.index) != CHAR_CLASS_SPACE)
9fcb0f8
+    decrement_mark (&lp->end);
ef8f582
+}
ef8f582
+
9fcb0f8
 static void
ef8f582
 expand_scratch_buffer (GtkText* text, guint len)
ef8f582
 {
9fcb0f8
---------------- x8 ---------------- x8 ---------------- x8 ----------------
9fcb0f8
9fcb0f8
--------------------------------------
9fcb0f8
Akira Higuchi
9fcb0f8
Dept. of Mathematics, Hokkaido Univ.
9fcb0f8
Hokkaido, Japan
9fcb0f8
Email: a-higuti@math.sci.hokudai.ac.jp