(adjust_frame_glyphs): Remove reference to
[bpt/emacs.git] / src / w32faces.c
index 1a229f4..6b9356a 100644 (file)
@@ -33,6 +33,8 @@ Boston, MA 02111-1307, USA.  */
 #include "blockinput.h"
 #include "window.h"
 #include "intervals.h"
 #include "blockinput.h"
 #include "window.h"
 #include "intervals.h"
+#include "charset.h"
+#include "fontset.h"
 
 \f
 /* An explanation of the face data structures.  */
 
 \f
 /* An explanation of the face data structures.  */
@@ -50,7 +52,7 @@ Boston, MA 02111-1307, USA.  */
        ID is the face ID, an integer used internally by the C code to identify
            the face,
        FONT, FOREGROUND, and BACKGROUND are strings naming the fonts and colors
        ID is the face ID, an integer used internally by the C code to identify
            the face,
        FONT, FOREGROUND, and BACKGROUND are strings naming the fonts and colors
-           to use with the face,
+           to use with the face, FONT may name fontsets,
        BACKGROUND-PIXMAP is the name of an x bitmap filename, which we don't
            use right now, and
        UNDERLINE-P is non-nil if the face should be underlined.
        BACKGROUND-PIXMAP is the name of an x bitmap filename, which we don't
            use right now, and
        UNDERLINE-P is non-nil if the face should be underlined.
@@ -62,13 +64,13 @@ Boston, MA 02111-1307, USA.  */
    (assq FACE-NAME global-face-data) returns a vector describing the
    global parameters for that face.
 
    (assq FACE-NAME global-face-data) returns a vector describing the
    global parameters for that face.
 
-   Let PARAM-FACE be FRAME->display.x->param_faces[Faref (FACE-VECTOR, 2)].
+   Let PARAM-FACE be FRAME->output_data.w32->param_faces[Faref(FACE-VECTOR,2)].
    PARAM_FACE is a struct face whose members are the Xlib analogues of
    the parameters in FACE-VECTOR.  If an element of FACE-VECTOR is
    nil, then the corresponding member of PARAM_FACE is FACE_DEFAULT.
    These faces are called "parameter faces", because they're the ones
    lisp manipulates to control what gets displayed.  Elements 0 and 1
    PARAM_FACE is a struct face whose members are the Xlib analogues of
    the parameters in FACE-VECTOR.  If an element of FACE-VECTOR is
    nil, then the corresponding member of PARAM_FACE is FACE_DEFAULT.
    These faces are called "parameter faces", because they're the ones
    lisp manipulates to control what gets displayed.  Elements 0 and 1
-   of FRAME->display.x->param_faces are special - they describe the
+   of FRAME->output_data.w32->param_faces are special - they describe the
    default and mode line faces.  None of the faces in param_faces have
    GC's.  (See src/dispextern.h for the definition of struct face.
    lisp/faces.el maintains the isomorphism between face_alist and
    default and mode line faces.  None of the faces in param_faces have
    GC's.  (See src/dispextern.h for the definition of struct face.
    lisp/faces.el maintains the isomorphism between face_alist and
@@ -79,9 +81,9 @@ Boston, MA 02111-1307, USA.  */
    properties.  The resulting faces are called "computed faces"; none
    of their members are FACE_DEFAULT; they are completely specified.
    They then call intern_compute_face to search
    properties.  The resulting faces are called "computed faces"; none
    of their members are FACE_DEFAULT; they are completely specified.
    They then call intern_compute_face to search
-   FRAME->display.x->computed_faces for a matching face, add one if
+   FRAME->output_data.x->computed_faces for a matching face, add one if
    none is found, and return the index into
    none is found, and return the index into
-   FRAME->display.x->computed_faces.  FRAME's glyph matrices use these
+   FRAME->output_data.x->computed_faces.  FRAME's glyph matrices use these
    indices to record the faces of the matrix characters, and the X
    display hooks consult compute_faces to decide how to display these
    characters.  Elements 0 and 1 of computed_faces always describe the
    indices to record the faces of the matrix characters, and the X
    display hooks consult compute_faces to decide how to display these
    characters.  Elements 0 and 1 of computed_faces always describe the
@@ -96,6 +98,9 @@ Boston, MA 02111-1307, USA.  */
    This is done from time to time so that we don't hold on to
    lots of GCs that are no longer needed.
 
    This is done from time to time so that we don't hold on to
    lots of GCs that are no longer needed.
 
+   If a computed face has 0 as its font,
+   it is unused, and can be reused by new_computed_face.
+
    Constraints:
 
    Symbols naming faces must have associations on all frames; for any
    Constraints:
 
    Symbols naming faces must have associations on all frames; for any
@@ -129,9 +134,11 @@ static int region_face;
    does not specify that display aspect.  */
 #define FACE_DEFAULT (~0)
 
    does not specify that display aspect.  */
 #define FACE_DEFAULT (~0)
 
-Lisp_Object Qface, Qmouse_face;
+Lisp_Object Qface;
 Lisp_Object Qpixmap_spec_p;
 
 Lisp_Object Qpixmap_spec_p;
 
+extern Lisp_Object Qmouse_face;  /* In textprop.c.  */
+
 int face_name_id_number ( /* FRAME_PTR, Lisp_Object name */ );
 
 struct face *intern_face ( /* FRAME_PTR, struct face * */ );
 int face_name_id_number ( /* FRAME_PTR, Lisp_Object name */ );
 
 struct face *intern_face ( /* FRAME_PTR, struct face * */ );
@@ -139,6 +146,9 @@ static int new_computed_face ( /* FRAME_PTR, struct face * */ );
 static int intern_computed_face ( /* FRAME_PTR, struct face * */ );
 static void ensure_face_ready ( /* FRAME_PTR, int id */ );
 void recompute_basic_faces ( /* FRAME_PTR f */ );
 static int intern_computed_face ( /* FRAME_PTR, struct face * */ );
 static void ensure_face_ready ( /* FRAME_PTR, int id */ );
 void recompute_basic_faces ( /* FRAME_PTR f */ );
+static void merge_face_list ( /* FRAME_PTR, struct face *, Lisp_Object */ );
+
+extern Lisp_Object Qforeground_color, Qbackground_color;
 \f
 /* Allocating, copying, and comparing struct faces.  */
 
 \f
 /* Allocating, copying, and comparing struct faces.  */
 
@@ -149,6 +159,7 @@ allocate_face ()
   struct face *result = (struct face *) xmalloc (sizeof (struct face));
   bzero (result, sizeof (struct face));
   result->font = (XFontStruct *) FACE_DEFAULT;
   struct face *result = (struct face *) xmalloc (sizeof (struct face));
   bzero (result, sizeof (struct face));
   result->font = (XFontStruct *) FACE_DEFAULT;
+  result->fontset = -1;
   result->foreground = FACE_DEFAULT;
   result->background = FACE_DEFAULT;
   result->stipple = FACE_DEFAULT;
   result->foreground = FACE_DEFAULT;
   result->background = FACE_DEFAULT;
   result->stipple = FACE_DEFAULT;
@@ -163,6 +174,7 @@ copy_face (face)
   struct face *result = allocate_face ();
 
   result->font = face->font;
   struct face *result = allocate_face ();
 
   result->font = face->font;
+  result->fontset = face->fontset;
   result->foreground = face->foreground;
   result->background = face->background;
   result->stipple = face->stipple;
   result->foreground = face->foreground;
   result->background = face->background;
   result->stipple = face->stipple;
@@ -178,6 +190,7 @@ face_eql (face1, face2)
      struct face *face1, *face2;
 {
   return (   face1->font       == face2->font
      struct face *face1, *face2;
 {
   return (   face1->font       == face2->font
+          && face1->fontset    == face2->fontset
          && face1->foreground == face2->foreground
          && face1->background == face2->background
          && face1->stipple    == face2->stipple
          && face1->foreground == face2->foreground
          && face1->background == face2->background
          && face1->stipple    == face2->stipple
@@ -220,15 +233,18 @@ load_font (f, name)
      struct frame *f;
      Lisp_Object name;
 {
      struct frame *f;
      Lisp_Object name;
 {
-  XFontStruct *font;
+  struct font_info *fontinf;
+  XFontStruct *font = NULL;
 
   if (NILP (name))
     return (XFontStruct *) FACE_DEFAULT;
 
   CHECK_STRING (name, 0);
   BLOCK_INPUT;
 
   if (NILP (name))
     return (XFontStruct *) FACE_DEFAULT;
 
   CHECK_STRING (name, 0);
   BLOCK_INPUT;
-  font = w32_load_font (FRAME_W32_DISPLAY_INFO (f), (char *) XSTRING (name)->data);
+  fontinf = w32_load_font (f, (char *) XSTRING (name)->data, 0);
   UNBLOCK_INPUT;
   UNBLOCK_INPUT;
+  if (fontinf)
+    font = (XFontStruct *)fontinf->font;
 
   if (! font)
     Fsignal (Qerror, Fcons (build_string ("undefined font"),
 
   if (! font)
     Fsignal (Qerror, Fcons (build_string ("undefined font"),
@@ -278,24 +294,24 @@ unload_color (f, pixel)
 }
 
 DEFUN ("pixmap-spec-p", Fpixmap_spec_p, Spixmap_spec_p, 1, 1, 0,
 }
 
 DEFUN ("pixmap-spec-p", Fpixmap_spec_p, Spixmap_spec_p, 1, 1, 0,
-  "Return t if ARG is a valid pixmap specification.")
-  (arg)
-     Lisp_Object arg;
+  "Return t if OBJECT is a valid pixmap specification.")
+  (object)
+     Lisp_Object object;
 {
   Lisp_Object height, width;
 
 {
   Lisp_Object height, width;
 
-  return ((STRINGP (arg)
-          || (CONSP (arg)
-              && CONSP (XCONS (arg)->cdr)
-              && CONSP (XCONS (XCONS (arg)->cdr)->cdr)
-              && NILP (XCONS (XCONS (XCONS (arg)->cdr)->cdr)->cdr)
-              && (width = XCONS (arg)->car, INTEGERP (width))
-              && (height = XCONS (XCONS (arg)->cdr)->car, INTEGERP (height))
-              && STRINGP (XCONS (XCONS (XCONS (arg)->cdr)->cdr)->car)
+  return ((STRINGP (object)
+          || (CONSP (object)
+              && CONSP (XCONS (object)->cdr)
+              && CONSP (XCONS (XCONS (object)->cdr)->cdr)
+              && NILP (XCONS (XCONS (XCONS (object)->cdr)->cdr)->cdr)
+              && (width = XCONS (object)->car, INTEGERP (width))
+              && (height = XCONS (XCONS (object)->cdr)->car, INTEGERP (height))
+              && STRINGP (XCONS (XCONS (XCONS (object)->cdr)->cdr)->car)
               && XINT (width) > 0
               && XINT (height) > 0
               /* The string must have enough bits for width * height.  */
               && XINT (width) > 0
               && XINT (height) > 0
               /* The string must have enough bits for width * height.  */
-              && ((XSTRING (XCONS (XCONS (XCONS (arg)->cdr)->cdr)->car)->size
+              && ((XSTRING (XCONS (XCONS (XCONS (object)->cdr)->cdr)->car)->size
                    * (BITS_PER_INT / sizeof (int)))
                   >= XFASTINT (width) * XFASTINT (height))))
          ? Qt : Qnil);
                    * (BITS_PER_INT / sizeof (int)))
                   >= XFASTINT (width) * XFASTINT (height))))
          ? Qt : Qnil);
@@ -419,6 +435,7 @@ free_frame_faces (f)
       struct face *face = FRAME_PARAM_FACES (f) [i];
       if (face)
        {
       struct face *face = FRAME_PARAM_FACES (f) [i];
       if (face)
        {
+          if (face->fontset < 0)
          unload_font (f, face->font);
          unload_color (f, face->foreground);
          unload_color (f, face->background);
          unload_font (f, face->font);
          unload_color (f, face->foreground);
          unload_color (f, face->background);
@@ -455,7 +472,19 @@ new_computed_face (f, new_face)
      struct frame *f;
      struct face *new_face;
 {
      struct frame *f;
      struct face *new_face;
 {
-  int i = FRAME_N_COMPUTED_FACES (f);
+  int len = FRAME_N_COMPUTED_FACES (f);
+  int i;
+
+  /* Search for an unused computed face in the middle of the table.  */
+  for (i = 0; i < len; i++)
+    {
+      struct face *face = FRAME_COMPUTED_FACES (f)[i];
+      if (face->font == 0)
+       {
+         FRAME_COMPUTED_FACES (f)[i] = copy_face (new_face);
+         return i;
+       }
+    }
 
   if (i >= FRAME_SIZE_COMPUTED_FACES (f))
     {
 
   if (i >= FRAME_SIZE_COMPUTED_FACES (f))
     {
@@ -546,21 +575,28 @@ frame_update_line_height (f)
      FRAME_PTR f;
 {
   int i;
      FRAME_PTR f;
 {
   int i;
-  int biggest = FONT_HEIGHT (f->output_data.w32->font);
+  int fontset = FRAME_FONTSET (f);
+  int biggest = (fontset > 0
+                 ? FRAME_FONTSET_DATA (f)->fontset_table[fontset]->height
+                 : FONT_HEIGHT (FRAME_FONT (f)));
 
 
-  for (i = 0; i < f->output_data.w32->n_param_faces; i++)
-    if (f->output_data.w32->param_faces[i] != 0
-       && f->output_data.w32->param_faces[i]->font != (XFontStruct *) FACE_DEFAULT)
+  for (i = 0; i < FRAME_N_PARAM_FACES (f); i++)
+    if (FRAME_PARAM_FACES (f)[i] != 0
+       && FRAME_PARAM_FACES (f)[i]->font != (XFontStruct *) FACE_DEFAULT)
       {
       {
-       int height = FONT_HEIGHT (f->output_data.w32->param_faces[i]->font);
+       int height = ((fontset =
+                       FRAME_PARAM_FACES (f)[i]->fontset) > 0
+                      ? FRAME_FONTSET_DATA (f)->fontset_table[fontset]->height
+                      : FONT_HEIGHT
+                          (FRAME_PARAM_FACES (f)[i]->font));
        if (height > biggest)
          biggest = height;
       }
 
        if (height > biggest)
          biggest = height;
       }
 
-  if (biggest == f->output_data.w32->line_height)
+  if (biggest == FRAME_LINE_HEIGHT (f))
     return 0;
 
     return 0;
 
-  f->output_data.w32->line_height = biggest;
+  FRAME_LINE_HEIGHT (f) = biggest;
   return 1;
 }
 \f
   return 1;
 }
 \f
@@ -576,6 +612,8 @@ merge_faces (from, to)
   if (from->font != (XFontStruct *) FACE_DEFAULT
       && same_size_fonts (from->font, to->font))
     to->font = from->font;
   if (from->font != (XFontStruct *) FACE_DEFAULT
       && same_size_fonts (from->font, to->font))
     to->font = from->font;
+  if (from->fontset != -1)
+    to->fontset = from->fontset;
   if (from->foreground != FACE_DEFAULT)
     to->foreground = from->foreground;
   if (from->background != FACE_DEFAULT)
   if (from->foreground != FACE_DEFAULT)
     to->foreground = from->foreground;
   if (from->background != FACE_DEFAULT)
@@ -602,6 +640,7 @@ compute_base_face (f, face)
   face->foreground = FRAME_FOREGROUND_PIXEL (f);
   face->background = FRAME_BACKGROUND_PIXEL (f);
   face->font = FRAME_FONT (f);
   face->foreground = FRAME_FOREGROUND_PIXEL (f);
   face->background = FRAME_BACKGROUND_PIXEL (f);
   face->font = FRAME_FONT (f);
+  face->fontset = -1;
   face->stipple = 0;
   face->underline = 0;
 }
   face->stipple = 0;
   face->underline = 0;
 }
@@ -663,7 +702,6 @@ compute_glyph_face_1 (f, face_name, current_face)
    the time this function can take.
 
    If MOUSE is nonzero, use the character's mouse-face, not its face.  */
    the time this function can take.
 
    If MOUSE is nonzero, use the character's mouse-face, not its face.  */
-
 int
 compute_char_face (f, w, pos, region_beg, region_end, endptr, limit, mouse)
      struct frame *f;
 int
 compute_char_face (f, w, pos, region_beg, region_end, endptr, limit, mouse)
      struct frame *f;
@@ -746,82 +784,23 @@ compute_char_face (f, w, pos, region_beg, region_end, endptr, limit, mouse)
 
   compute_base_face (f, &face);
 
 
   compute_base_face (f, &face);
 
-  if (CONSP (prop))
-    {
-      /* We have a list of faces, merge them in reverse order */
-      Lisp_Object length = Flength (prop);
-      int len = XINT (length);
-      Lisp_Object *faces;
-
-      /* Put them into an array */
-      faces = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
-      for (j = 0; j < len; j++)
-       {
-         faces[j] = Fcar (prop);
-         prop = Fcdr (prop);
-       }
-      /* So that we can merge them in the reverse order */
-      for (j = len - 1; j >= 0; j--)
-       {
-         facecode = face_name_id_number (f, faces[j]);
-         if (facecode >= 0 && facecode < FRAME_N_PARAM_FACES (f)
-             && FRAME_PARAM_FACES (f) [facecode] != 0)
-           merge_faces (FRAME_PARAM_FACES (f) [facecode], &face);
-       }
-    }
-  else if (!NILP (prop))
-    {
-      facecode = face_name_id_number (f, prop);
-      if (facecode >= 0 && facecode < FRAME_N_PARAM_FACES (f)
-         && FRAME_PARAM_FACES (f) [facecode] != 0)
-       merge_faces (FRAME_PARAM_FACES (f) [facecode], &face);
-    }
+  merge_face_list (f, &face, prop);
 
   noverlays = sort_overlays (overlay_vec, noverlays, w);
 
   /* Now merge the overlay data in that order.  */
   for (i = 0; i < noverlays; i++)
     {
 
   noverlays = sort_overlays (overlay_vec, noverlays, w);
 
   /* Now merge the overlay data in that order.  */
   for (i = 0; i < noverlays; i++)
     {
-      prop = Foverlay_get (overlay_vec[i], propname);
-      if (CONSP (prop))
-       {
-         /* We have a list of faces, merge them in reverse order */
-         Lisp_Object length = Flength (prop);
-         int len = XINT (length);
-         Lisp_Object *faces;
-         int i;
-
-         /* Put them into an array */
-         faces = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
-         for (j = 0; j < len; j++)
-           {
-             faces[j] = Fcar (prop);
-             prop = Fcdr (prop);
-           }
-         /* So that we can merge them in the reverse order */
-         for (j = len - 1; j >= 0; j--)
-           {
-             facecode = face_name_id_number (f, faces[j]);
-             if (facecode >= 0 && facecode < FRAME_N_PARAM_FACES (f)
-                 && FRAME_PARAM_FACES (f) [facecode] != 0)
-               merge_faces (FRAME_PARAM_FACES (f) [facecode], &face);
-           }
-       }
-      else if (!NILP (prop))
-       {
-         Lisp_Object oend;
-         int oendpos;
+      Lisp_Object oend;
+      int oendpos;
 
 
-         facecode = face_name_id_number (f, prop);
-         if (facecode >= 0 && facecode < FRAME_N_PARAM_FACES (f)
-             && FRAME_PARAM_FACES (f) [facecode] != 0)
-           merge_faces (FRAME_PARAM_FACES (f)[facecode], &face);
+      prop = Foverlay_get (overlay_vec[i], propname);
+      merge_face_list (f, &face, prop);
 
 
-         oend = OVERLAY_END (overlay_vec[i]);
-         oendpos = OVERLAY_POSITION (oend);
-         if (oendpos < endpos)
-           endpos = oendpos;
-       }
+      oend = OVERLAY_END (overlay_vec[i]);
+      oendpos = OVERLAY_POSITION (oend);
+      if (oendpos < endpos)
+       endpos = oendpos;
     }
 
   if (pos >= region_beg && pos < region_end)
     }
 
   if (pos >= region_beg && pos < region_end)
@@ -836,6 +815,61 @@ compute_char_face (f, w, pos, region_beg, region_end, endptr, limit, mouse)
 
   return intern_computed_face (f, &face);
 }
 
   return intern_computed_face (f, &face);
 }
+
+static void
+merge_face_list (f, face, prop)
+     FRAME_PTR f;
+     struct face *face;
+     Lisp_Object prop;
+{
+  Lisp_Object length;
+  int len;
+  Lisp_Object *faces;
+  int j;
+
+  if (CONSP (prop)
+      && ! STRINGP (XCONS (prop)->cdr))
+    {
+      /* We have a list of faces, merge them in reverse order.  */
+
+      length = Fsafe_length (prop);
+      len = XFASTINT (length);
+
+      /* Put them into an array.  */
+      faces = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
+      for (j = 0; j < len; j++)
+       {
+         faces[j] = Fcar (prop);
+         prop = Fcdr (prop);
+       }
+      /* So that we can merge them in the reverse order.  */
+    }
+  else
+    {
+      faces = (Lisp_Object *) alloca (sizeof (Lisp_Object));
+      faces[0] = prop;
+      len = 1;
+    }
+
+  for (j = len - 1; j >= 0; j--)
+    {
+      if (CONSP (faces[j]))
+       {
+         if (EQ (XCONS (faces[j])->car, Qbackground_color))
+           face->background = load_color (f, XCONS (faces[j])->cdr);
+         if (EQ (XCONS (faces[j])->car, Qforeground_color))
+           face->foreground = load_color (f, XCONS (faces[j])->cdr);
+       }
+      else
+       {
+         int facecode = face_name_id_number (f, faces[j]);
+         if (facecode >= 0 && facecode < FRAME_N_PARAM_FACES (f)
+             && FRAME_PARAM_FACES (f) [facecode] != 0)
+           merge_faces (FRAME_PARAM_FACES (f) [facecode], face);
+       }
+    }
+}
+
 \f
 /* Recompute the GC's for the default and modeline faces.
    We call this after changing frame parameters on which those GC's
 \f
 /* Recompute the GC's for the default and modeline faces.
    We call this after changing frame parameters on which those GC's
@@ -929,7 +963,7 @@ DEFUN ("set-face-attribute-internal", Fset_face_attribute_internal,
   if (id < 0 || id >= next_face_id)
     error ("Face id out of range");
 
   if (id < 0 || id >= next_face_id)
     error ("Face id out of range");
 
-  if (! FRAME_W32_P (f))
+  if (! FRAME_WINDOW_P (f))
     return Qnil;
 
   ensure_face_ready (f, id);
     return Qnil;
 
   ensure_face_ready (f, id);
@@ -937,10 +971,36 @@ DEFUN ("set-face-attribute-internal", Fset_face_attribute_internal,
 
   if (EQ (attr_name, intern ("font")))
     {
 
   if (EQ (attr_name, intern ("font")))
     {
-      XFontStruct *font = load_font (f, attr_value);
-      if (face->font != f->output_data.w32->font)
+      XFontStruct *font = NULL;
+      int fontset;
+
+      if (NILP (attr_value))
+        {
+          font = (XFontStruct *) FACE_DEFAULT;
+          fontset = -1;
+        }
+      else
+        {
+          CHECK_STRING (attr_value, 0);
+          fontset = fs_query_fontset (f, XSTRING (attr_value)->data);
+          if (fontset >= 0)
+            {
+              struct font_info *fontp;
+
+              if (!(fontp = FS_LOAD_FONT (f, FRAME_W32_FONT_TABLE (f),
+                                          CHARSET_ASCII, NULL, fontset)))
+                Fsignal (Qerror,
+                         Fcons (build_string ("ASCII font can't be loaded"),
+                                Fcons (attr_value, Qnil)));
+              font = (XFontStruct *) (fontp->font);
+            }
+          else
+            font = load_font (f, attr_value);
+        }
+      if (face->fontset == -1 && face->font != f->output_data.w32->font)
        unload_font (f, face->font);
       face->font = font;
        unload_font (f, face->font);
       face->font = font;
+      face->fontset = fontset;
       if (frame_update_line_height (f))
        x_set_window_size (f, 0, f->width, f->height);
       /* Must clear cache, since it might contain the font
       if (frame_update_line_height (f))
        x_set_window_size (f, 0, f->width, f->height);
       /* Must clear cache, since it might contain the font