Index: XEmacs/lisp/ChangeLog
diff -u XEmacs/lisp/ChangeLog:1.1.3.13.2.14 XEmacs/lisp/ChangeLog:1.1.3.13.2.15
--- XEmacs/lisp/ChangeLog:1.1.3.13.2.14	Sun Jun 20 22:52:00 1999
+++ XEmacs/lisp/ChangeLog	Sun Jun 20 23:28:59 1999
@@ -1,3 +1,9 @@
+1999-06-20  MORIOKA Tomohiko  <tomo@etl.go.jp>
+
+	* mule/mule-category.el (word-combining-categories): Set up new
+	variable.
+	(word-separating-categories): Likewise.
+
 1999-06-04  MORIOKA Tomohiko  <tomo@etl.go.jp>
 
 	* files.el (insert-file-contents-literally): Treat file as binary;
Index: XEmacs/lisp/mule/mule-category.el
diff -u XEmacs/lisp/mule/mule-category.el:1.1.3.1 XEmacs/lisp/mule/mule-category.el:1.1.3.1.2.1
--- XEmacs/lisp/mule/mule-category.el:1.1.3.1	Thu Apr  1 21:44:49 1999
+++ XEmacs/lisp/mule/mule-category.el	Sun Jun 20 23:28:27 1999
@@ -1,6 +1,8 @@
 ;;; mule-category.el --- category functions for XEmacs/Mule.
 
 ;; Copyright (C) 1992,93,94,95 Free Software Foundation, Inc.
+;; Copyright (C) 1995, 1997, 1999 Electrotechnical Laboratory, JAPAN.
+;; Licensed to the Free Software Foundation.
 ;; Copyright (C) 1995 Amdahl Corporation.
 ;; Copyright (C) 1995 Sun Microsystems.
 
@@ -254,6 +256,23 @@
 	(define-category (nth 1 (car l)) (nth 2 (car l))))
     (modify-category-entry (car (car l)) (nth 1 (car l)))
     (setq l (cdr l))))
+
+;;; Setting word boundary.
+
+(setq word-combining-categories
+      '((?l . ?l)))
+
+(setq word-separating-categories	;  (2-byte character sets)
+      '((?A . ?K)			; Alpha numeric - Katakana
+	(?A . ?C)			; Alpha numeric - Chinese
+	(?H . ?A)			; Hiragana - Alpha numeric
+	(?H . ?K)			; Hiragana - Katakana
+	(?H . ?C)			; Hiragana - Chinese
+	(?K . ?A)			; Katakana - Alpha numeric
+	(?K . ?C)			; Katakana - Chinese
+	(?C . ?A)			; Chinese - Alpha numeric
+	(?C . ?K)			; Chinese - Katakana
+	))
 
 ;;; At the present, I know Japanese and Chinese text can
 ;;; break line at any point under a restriction of 'kinsoku'.
Index: XEmacs/src/ChangeLog
diff -u XEmacs/src/ChangeLog:1.1.3.13.2.12 XEmacs/src/ChangeLog:1.1.3.13.2.13
--- XEmacs/src/ChangeLog:1.1.3.13.2.12	Sun Jun 20 22:52:23 1999
+++ XEmacs/src/ChangeLog	Sun Jun 20 23:27:12 1999
@@ -1,3 +1,17 @@
+1999-06-20  MORIOKA Tomohiko  <tomo@etl.go.jp>
+
+	* syntax.c (word_constituent_p): Deleted.
+	(scan_words): Use `WORD_BOUNDARY_P'.
+
+	* chartab.c (Vword_combining_categories): New variable.
+	(Vword_separating_categories): Likewise.
+	(CATEGORYP): New macro.
+	(CATEGORY_SET): Likewise.
+	(CATEGORY_MEMBER): Likewise.
+	(word_boundary_p): New function.
+	(complex_vars_of_chartab): Set up new variable
+	`word-combining-categories' and `word-separating-categories'.
+
 1999-06-16  Norbert Koch  <n.koch@eai-delta.de>
 
 	* redisplay-msw.c: Run 'ccl_driver' with 'CCL_MODE_ENCODING' as in 
Index: XEmacs/src/chartab.c
diff -u XEmacs/src/chartab.c:1.1.3.3.2.2 XEmacs/src/chartab.c:1.1.3.3.2.3
--- XEmacs/src/chartab.c:1.1.3.3.2.2	Fri Jun  4 14:03:55 1999
+++ XEmacs/src/chartab.c	Sun Jun 20 23:23:29 1999
@@ -2,6 +2,8 @@
    Copyright (C) 1992, 1995 Free Software Foundation, Inc.
    Copyright (C) 1995 Sun Microsystems, Inc.
    Copyright (C) 1995, 1996 Ben Wing.
+   Copyright (C) 1995, 1997, 1999 Electrotechnical Laboratory, JAPAN.
+   Licensed to the Free Software Foundation.
 
 This file is part of XEmacs.
 
@@ -50,6 +52,9 @@
 Lisp_Object Qcategory_table_value_p;
 
 Lisp_Object Vstandard_category_table;
+
+/* Variables to determine word boundary.  */
+Lisp_Object Vword_combining_categories, Vword_separating_categories;
 #endif /* MULE */
 
 
@@ -1709,6 +1714,68 @@
   return CATEGORY_TABLE_VALUEP (obj) ? Qt : Qnil;
 }
 
+
+#define CATEGORYP(x) \
+  (CHARP ((x)) && XCHAR ((x)) >= 0x20 && XCHAR ((x)) <= 0x7E)
+
+#define CATEGORY_SET(c)						\
+  (get_char_table(c, XCHAR_TABLE(current_buffer->category_table)))
+
+/* Return 1 if CATEGORY_SET contains CATEGORY, else return 0.
+   The faster version of `!NILP (Faref (category_set, category))'.  */
+#define CATEGORY_MEMBER(category, category_set)		 	\
+  (bit_vector_bit(XBIT_VECTOR (category_set), category - 32))
+
+/* Return 1 if there is a word boundary between two word-constituent
+   characters C1 and C2 if they appear in this order, else return 0.
+   Use the macro WORD_BOUNDARY_P instead of calling this function
+   directly.  */
+
+int
+word_boundary_p (Emchar c1, Emchar c2)
+{
+  Lisp_Object category_set1, category_set2;
+  Lisp_Object tail;
+  int default_result;
+
+#if 0
+  if (COMPOSITE_CHAR_P (c1))
+    c1 = cmpchar_component (c1, 0, 1);
+  if (COMPOSITE_CHAR_P (c2))
+    c2 = cmpchar_component (c2, 0, 1);
+#endif
+
+  if (CHAR_CHARSET (c1) == CHAR_CHARSET (c2))
+    {
+      tail = Vword_separating_categories;
+      default_result = 0;
+    }
+  else
+    {
+      tail = Vword_combining_categories;
+      default_result = 1;
+    }
+
+  category_set1 = CATEGORY_SET (c1);
+  if (NILP (category_set1))
+    return default_result;
+  category_set2 = CATEGORY_SET (c2);
+  if (NILP (category_set2))
+    return default_result;
+
+  for (; CONSP (tail); tail = XCONS (tail)->cdr)
+    {
+      Lisp_Object elt = XCONS(tail)->car;
+
+      if (CONSP (elt)
+	  && CATEGORYP (XCONS (elt)->car)
+	  && CATEGORYP (XCONS (elt)->cdr)
+	  && CATEGORY_MEMBER (XCHAR (XCONS (elt)->car), category_set1)
+	  && CATEGORY_MEMBER (XCHAR (XCONS (elt)->cdr), category_set2))
+	return !default_result;
+    }
+  return default_result;
+}
 #endif /* MULE */
 
 
@@ -1780,5 +1847,50 @@
   Vstandard_category_table = Qnil;
   Vstandard_category_table = Fcopy_category_table (Qnil);
   staticpro (&Vstandard_category_table);
+
+  DEFVAR_LISP ("word-combining-categories", &Vword_combining_categories /*
+List of pair (cons) of categories to determine word boundary.
+
+Emacs treats a sequence of word constituent characters as a single
+word (i.e. finds no word boundary between them) iff they belongs to
+the same charset.  But, exceptions are allowed in the following cases.
+
+(1) The case that characters are in different charsets is controlled
+by the variable `word-combining-categories'.
+
+Emacs finds no word boundary between characters of different charsets
+if they have categories matching some element of this list.
+
+More precisely, if an element of this list is a cons of category CAT1
+and CAT2, and a multibyte character C1 which has CAT1 is followed by
+C2 which has CAT2, there's no word boundary between C1 and C2.
+
+For instance, to tell that ASCII characters and Latin-1 characters can
+form a single word, the element `(?l . ?l)' should be in this list
+because both characters have the category `l' (Latin characters).
+
+(2) The case that character are in the same charset is controlled by
+the variable `word-separating-categories'.
+
+Emacs find a word boundary between characters of the same charset
+if they have categories matching some element of this list.
+
+More precisely, if an element of this list is a cons of category CAT1
+and CAT2, and a multibyte character C1 which has CAT1 is followed by
+C2 which has CAT2, there's a word boundary between C1 and C2.
+
+For instance, to tell that there's a word boundary between Japanese
+Hiragana and Japanese Kanji (both are in the same charset), the
+element `(?H . ?C) should be in this list.
+*/ );
+
+  Vword_combining_categories = Qnil;
+
+  DEFVAR_LISP ("word-separating-categories", &Vword_separating_categories /*
+List of pair (cons) of categories to determine word boundary.
+See the documentation of the variable `word-combining-categories'.
+*/ );
+
+  Vword_separating_categories = Qnil;
 #endif /* MULE */
 }
Index: XEmacs/src/syntax.c
diff -u XEmacs/src/syntax.c:1.1.3.2.2.1 XEmacs/src/syntax.c:1.1.3.2.2.2
--- XEmacs/src/syntax.c:1.1.3.2.2.1	Wed May 19 17:46:08 1999
+++ XEmacs/src/syntax.c	Sun Jun 20 23:26:16 1999
@@ -53,6 +53,7 @@
 two such characters.  */
 
 /* Mule 2.4 doesn't seem to have Sextword - I'm removing it -- mrb */
+/* Recovered by tomo */
 
 Lisp_Object Qsyntax_table_p;
 
@@ -327,15 +328,15 @@
 
 
 
-static int
-word_constituent_p (struct buffer *buf, Bufpos pos,
-		    struct Lisp_Char_Table *tab)
-{
-  enum syntaxcode code = SYNTAX_UNSAFE (tab, BUF_FETCH_CHAR (buf, pos));
-  return ((words_include_escapes &&
-	   (code == Sescape || code == Scharquote))
-	  || (code == Sword));
-}
+/* Return 1 if there is a word boundary between two word-constituent
+   characters C1 and C2 if they appear in this order, else return 0.
+   There is no word boundary between two word-constituent ASCII
+   characters.  */
+#define WORD_BOUNDARY_P(c1, c2)			\
+  (!(CHAR_ASCII_P (c1) && CHAR_ASCII_P (c2))	\
+   && word_boundary_p (c1, c2))
+
+extern int word_boundary_p (Emchar c1, Emchar c2);
 
 /* Return the position across COUNT words from FROM.
    If that many words cannot be found before the end of the buffer, return 0.
@@ -346,6 +347,9 @@
 {
   Bufpos limit = count > 0 ? BUF_ZV (buf) : BUF_BEGV (buf);
   struct Lisp_Char_Table *mirrortab = XCHAR_TABLE (buf->mirror_syntax_table);
+  Emchar ch0, ch1;
+  enum syntaxcode code;
+
   while (count > 0)
     {
       QUIT;
@@ -354,16 +358,28 @@
 	{
 	  if (from == limit)
 	    return 0;
-	  if (word_constituent_p (buf, from, mirrortab))
-	    break;
+	  ch0 = BUF_FETCH_CHAR (buf, from);
+	  code = SYNTAX_UNSAFE (mirrortab, ch0);
 	  from++;
+	  if (words_include_escapes
+	      && (code == Sescape || code == Scharquote))
+	    break;
+	  if (code == Sword)
+	    break;
 	}
 
       QUIT;
 
-      while ((from != limit) && word_constituent_p (buf, from, mirrortab))
+      while ( from != limit )
 	{
+	  ch1 = BUF_FETCH_CHAR (buf, from);
+	  code = SYNTAX_UNSAFE (mirrortab, ch1);
+	  if (!(words_include_escapes
+		&& (code == Sescape || code == Scharquote)))
+	    if (code != Sword || WORD_BOUNDARY_P (ch0, ch1))
+	      break;
 	  from++;
+	  ch0 = ch1;
 	}
       count--;
     }
@@ -376,16 +392,28 @@
 	{
 	  if (from == limit)
 	    return 0;
-	  if (word_constituent_p (buf, from - 1, mirrortab))
-	    break;
 	  from--;
+	  ch1 = BUF_FETCH_CHAR (buf, from - 1);
+	  code = SYNTAX_UNSAFE (mirrortab, ch1);
+	  if (words_include_escapes
+	      && (code == Sescape || code == Scharquote))
+	    break;
+	  if (code == Sword)
+	    break;
 	}
 
       QUIT;
 
-      while ((from != limit) && word_constituent_p (buf, from - 1, mirrortab))
+      while ( from != limit )
 	{
+	  ch0 = BUF_FETCH_CHAR (buf, from - 1);
+	  code = SYNTAX_UNSAFE (mirrortab, ch0);
+	  if (!(words_include_escapes
+		&& (code == Sescape || code == Scharquote)))
+	    if (code != Sword || WORD_BOUNDARY_P (ch0, ch1))
+	      break;
 	  from--;
+	  ch1 = ch0;
 	}
       count++;
     }
