+ if (SINGLE_BYTE_CHAR_P (c))
+ {
+ FONTSET_ASCII (fontset) = newelt;
+ return;
+ }
+
+ SPLIT_CHAR (c, charset, code[0], code[1]);
+ code[2] = 0; /* anchor */
+ elt = &XCHAR_TABLE (fontset)->contents[charset + 128];
+ for (i = 0; code[i] > 0; i++)
+ {
+ if (!SUB_CHAR_TABLE_P (*elt))
+ *elt = make_sub_char_table (*elt);
+ elt = &XCHAR_TABLE (*elt)->contents[code[i]];
+ }
+ if (SUB_CHAR_TABLE_P (*elt))
+ XCHAR_TABLE (*elt)->defalt = newelt;
+ else
+ *elt = newelt;
+}
+
+
+/* Return a newly created fontset with NAME. If BASE is nil, make a
+ base fontset. Otherwise make a realized fontset whose parent is
+ BASE. */
+
+static Lisp_Object
+make_fontset (frame, name, base)
+ Lisp_Object frame, name, base;
+{
+ Lisp_Object fontset;
+ int size = ASIZE (Vfontset_table);
+ int id = next_fontset_id;
+
+ /* Find a free slot in Vfontset_table. Usually, next_fontset_id is
+ the next available fontset ID. So it is expected that this loop
+ terminates quickly. In addition, as the last element of
+ Vfontset_table is always nil, we don't have to check the range of
+ id. */
+ while (!NILP (AREF (Vfontset_table, id))) id++;
+
+ if (id + 1 == size)
+ {
+ Lisp_Object tem;
+ int i;
+
+ tem = Fmake_vector (make_number (size + 8), Qnil);
+ for (i = 0; i < size; i++)
+ AREF (tem, i) = AREF (Vfontset_table, i);
+ Vfontset_table = tem;
+ }
+
+ fontset = Fmake_char_table (Qfontset, Qnil);
+
+ FONTSET_ID (fontset) = make_number (id);
+ FONTSET_NAME (fontset) = name;
+ FONTSET_FRAME (fontset) = frame;
+ FONTSET_BASE (fontset) = base;
+
+ AREF (Vfontset_table, id) = fontset;
+ next_fontset_id = id + 1;
+ return fontset;
+}
+
+
+/* Return 1 if ID is a valid fontset id, else return 0. */
+
+static INLINE int
+fontset_id_valid_p (id)
+ int id;
+{
+ return (id >= 0 && id < ASIZE (Vfontset_table) - 1);
+}
+
+
+/* Extract `family' and `registry' string from FONTNAME and a cons of
+ them. Actually, `family' may also contain `foundry', `registry'
+ may also contain `encoding' of FONTNAME. But, if FONTNAME doesn't
+ conform to XLFD nor explicitely specifies the other fields
+ (i.e. not using wildcard `*'), return FONTNAME. If FORCE is
+ nonzero, specifications of the other fields are ignored, and return
+ a cons as far as FONTNAME conform to XLFD. */
+
+static Lisp_Object
+font_family_registry (fontname, force)
+ Lisp_Object fontname;
+ int force;
+{
+ Lisp_Object family, registry;
+ const char *p = SDATA (fontname);
+ const char *sep[15];
+ int i = 0;
+
+ while (*p && i < 15)
+ if (*p++ == '-')
+ {
+ if (!force && i >= 2 && i <= 11 && *p != '*' && p[1] != '-')
+ return fontname;
+ sep[i++] = p;
+ }
+ if (i != 14)
+ return fontname;
+
+ family = make_unibyte_string (sep[0], sep[2] - 1 - sep[0]);
+ registry = make_unibyte_string (sep[12], p - sep[12]);
+ return Fcons (family, registry);
+}
+
+\f
+/********** INTERFACES TO xfaces.c and dispextern.h **********/
+
+/* Return name of the fontset with ID. */
+
+Lisp_Object
+fontset_name (id)
+ int id;
+{
+ Lisp_Object fontset;
+ fontset = FONTSET_FROM_ID (id);
+ return FONTSET_NAME (fontset);
+}
+
+
+/* Return ASCII font name of the fontset with ID. */
+
+Lisp_Object
+fontset_ascii (id)
+ int id;
+{
+ Lisp_Object fontset, elt;
+ fontset= FONTSET_FROM_ID (id);
+ elt = FONTSET_ASCII (fontset);
+ return XCDR (elt);
+}
+
+
+/* Free fontset of FACE. Called from free_realized_face. */
+
+void
+free_face_fontset (f, face)
+ FRAME_PTR f;
+ struct face *face;
+{
+ if (fontset_id_valid_p (face->fontset))
+ {
+ AREF (Vfontset_table, face->fontset) = Qnil;
+ if (face->fontset < next_fontset_id)
+ next_fontset_id = face->fontset;
+ }
+}
+
+
+/* Return 1 iff FACE is suitable for displaying character C.
+ Otherwise return 0. Called from the macro FACE_SUITABLE_FOR_CHAR_P
+ when C is not a single byte character.. */
+
+int
+face_suitable_for_char_p (face, c)
+ struct face *face;
+ int c;
+{
+ Lisp_Object fontset, elt;
+
+ if (SINGLE_BYTE_CHAR_P (c))
+ return (face == face->ascii_face);
+
+ xassert (fontset_id_valid_p (face->fontset));
+ fontset = FONTSET_FROM_ID (face->fontset);
+ xassert (!BASE_FONTSET_P (fontset));
+
+ elt = FONTSET_REF_VIA_BASE (fontset, c);
+ return (!NILP (elt) && face->id == XFASTINT (elt));
+}
+
+
+/* Return ID of face suitable for displaying character C on frame F.
+ The selection of face is done based on the fontset of FACE. FACE
+ should already have been realized for ASCII characters. Called
+ from the macro FACE_FOR_CHAR when C is not a single byte character. */
+
+int
+face_for_char (f, face, c)
+ FRAME_PTR f;
+ struct face *face;
+ int c;
+{
+ Lisp_Object fontset, elt;
+ int face_id;
+
+ xassert (fontset_id_valid_p (face->fontset));
+ fontset = FONTSET_FROM_ID (face->fontset);
+ xassert (!BASE_FONTSET_P (fontset));
+
+ elt = FONTSET_REF_VIA_BASE (fontset, c);
+ if (!NILP (elt))
+ return XINT (elt);
+
+ /* No face is recorded for C in the fontset of FACE. Make a new
+ realized face for C that has the same fontset. */
+ face_id = lookup_face (f, face->lface, c, face);
+
+ /* Record the face ID in FONTSET at the same index as the
+ information in the base fontset. */
+ FONTSET_SET (fontset, c, make_number (face_id));
+ return face_id;
+}
+
+
+/* Make a realized fontset for ASCII face FACE on frame F from the
+ base fontset BASE_FONTSET_ID. If BASE_FONTSET_ID is -1, use the
+ default fontset as the base. Value is the id of the new fontset.
+ Called from realize_x_face. */
+
+int
+make_fontset_for_ascii_face (f, base_fontset_id)
+ FRAME_PTR f;
+ int base_fontset_id;
+{
+ Lisp_Object base_fontset, fontset, frame;
+
+ XSETFRAME (frame, f);
+ if (base_fontset_id >= 0)