+
+#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);
+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 (EQ (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;
+}