Include frame.h unconditionally.
[bpt/emacs.git] / src / xfaces.c
index 1c0ed8e..bb746bb 100644 (file)
@@ -15,7 +15,8 @@ GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with GNU Emacs; see the file COPYING.  If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
 
 /* This is derived from work by Lucid (some parts very loosely so).  */
 
@@ -25,17 +26,24 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include <config.h>
 #include "lisp.h"
 
+#include "charset.h"
+
+#include "frame.h"
+
+/* The number of face-id's in use (same for all frames).  */
+static int next_face_id;
+
 #ifdef HAVE_FACES
 
 #ifdef HAVE_X_WINDOWS
 #include "xterm.h"
+#include "fontset.h"
 #endif
 #ifdef MSDOS
 #include "dosfns.h"
 #endif
 #include "buffer.h"
 #include "dispextern.h"
-#include "frame.h"
 #include "blockinput.h"
 #include "window.h"
 #include "intervals.h"
@@ -75,7 +83,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, 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
-           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.
@@ -147,9 +155,6 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 \f
 /* Definitions and declarations.  */
 
-/* The number of face-id's in use (same for all frames).  */
-static int next_face_id;
-
 /* The number of the face to use to indicate the region.  */
 static int region_face;
 
@@ -177,6 +182,7 @@ allocate_face ()
   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;
@@ -191,6 +197,7 @@ copy_face (face)
   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;
@@ -206,6 +213,7 @@ face_eql (face1, face2)
      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
@@ -260,6 +268,10 @@ intern_face (f, face)
                  mask, &xgcv);
 
   face->gc = gc;
+  /* We used the following GC for all non-ASCII characters by changing
+     only GCfont each time.  */
+  face->non_ascii_gc = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+                                 mask, &xgcv);
 
   UNBLOCK_INPUT;
 
@@ -289,7 +301,10 @@ clear_face_cache ()
            {
              struct face *face = FRAME_COMPUTED_FACES (f) [i];
              if (face->gc)
-               XFreeGC (dpy, face->gc);
+               {
+                 XFreeGC (dpy, face->gc);
+                 XFreeGC (dpy, face->non_ascii_gc);
+               }
              face->gc = 0;
            }
        }
@@ -559,14 +574,13 @@ init_frame_faces (f)
   new_computed_face (f, FRAME_PARAM_FACES (f)[1]);
   recompute_basic_faces (f);
 
-#ifdef MULTI_FRAME
   /* Find another X frame.  */
   {
     Lisp_Object tail, frame, result;
     
     result = Qnil;
     FOR_EACH_FRAME (tail, frame)
-      if (FRAME_X_P (XFRAME (frame))
+      if ((FRAME_MSDOS_P (XFRAME (frame)) || FRAME_X_P (XFRAME (frame)))
          && XFRAME (frame) != f)
        {
          result = frame;
@@ -588,7 +602,6 @@ init_frame_faces (f)
            ensure_face_ready (f, i);
       }
   }
-#endif /* MULTI_FRAME */
 }
 
 
@@ -608,7 +621,8 @@ free_frame_faces (f)
       struct face *face = FRAME_PARAM_FACES (f) [i];
       if (face)
        {
-         unload_font (f, face->font);
+         if (face->fontset < 0)
+           unload_font (f, face->font);
          unload_color (f, face->foreground);
          unload_color (f, face->background);
          x_destroy_bitmap (f, face->stipple);
@@ -628,7 +642,10 @@ free_frame_faces (f)
       if (face)
        {
          if (face->gc)
-           XFreeGC (dpy, face->gc);
+           {
+             XFreeGC (dpy, face->gc);
+             XFreeGC (dpy, face->non_ascii_gc);
+           }
          xfree (face);
        }
     }
@@ -753,13 +770,19 @@ frame_update_line_height (f)
      FRAME_PTR f;
 {
   int i;
-  int biggest = FONT_HEIGHT (f->output_data.x->font);
+  int fontset = f->output_data.x->fontset;
+  int biggest = (fontset > 0
+                ? FRAME_FONTSET_DATA (f)->fontset_table[fontset]->height
+                : FONT_HEIGHT (f->output_data.x->font));
 
   for (i = 0; i < f->output_data.x->n_param_faces; i++)
     if (f->output_data.x->param_faces[i] != 0
        && f->output_data.x->param_faces[i]->font != (XFontStruct *) FACE_DEFAULT)
       {
-       int height = FONT_HEIGHT (f->output_data.x->param_faces[i]->font);
+       int height = ((fontset = f->output_data.x->param_faces[i]->fontset) > 0
+                     ? FRAME_FONTSET_DATA (f)->fontset_table[fontset]->height
+                     : FONT_HEIGHT (f->output_data.x->param_faces[i]->font));
+
        if (height > biggest)
          biggest = height;
       }
@@ -784,6 +807,8 @@ merge_faces (from, to)
   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)
@@ -810,6 +835,7 @@ compute_base_face (f, face)
   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;
 }
@@ -1066,10 +1092,15 @@ recompute_basic_faces (f)
   BLOCK_INPUT;
 
   if (FRAME_DEFAULT_FACE (f)->gc)
-    XFreeGC (FRAME_X_DISPLAY (f), FRAME_DEFAULT_FACE (f)->gc);
+    {
+      XFreeGC (FRAME_X_DISPLAY (f), FRAME_DEFAULT_FACE (f)->gc);
+      XFreeGC (FRAME_X_DISPLAY (f), FRAME_DEFAULT_FACE (f)->non_ascii_gc);
+    }
   if (FRAME_MODE_LINE_FACE (f)->gc)
-    XFreeGC (FRAME_X_DISPLAY (f), FRAME_MODE_LINE_FACE (f)->gc);
-
+    {
+      XFreeGC (FRAME_X_DISPLAY (f), FRAME_MODE_LINE_FACE (f)->gc);
+      XFreeGC (FRAME_X_DISPLAY (f), FRAME_MODE_LINE_FACE (f)->non_ascii_gc);
+    }
   compute_base_face (f, FRAME_DEFAULT_FACE (f));
   compute_base_face (f, FRAME_MODE_LINE_FACE (f));
 
@@ -1086,26 +1117,6 @@ recompute_basic_faces (f)
 \f
 /* Lisp interface. */
 
-DEFUN ("frame-face-alist", Fframe_face_alist, Sframe_face_alist, 1, 1, 0,
-       "")
-     (frame)
-     Lisp_Object frame;
-{
-  CHECK_FRAME (frame, 0);
-  return XFRAME (frame)->face_alist;
-}
-
-DEFUN ("set-frame-face-alist", Fset_frame_face_alist, Sset_frame_face_alist,
-       2, 2, 0, "")
-     (frame, value)
-     Lisp_Object frame, value;
-{
-  CHECK_FRAME (frame, 0);
-  XFRAME (frame)->face_alist = value;
-  return value;
-}
-
-
 DEFUN ("make-face-internal", Fmake_face_internal, Smake_face_internal, 1, 1, 0,
   "Create face number FACE-ID on all frames.")
   (face_id)
@@ -1120,7 +1131,7 @@ DEFUN ("make-face-internal", Fmake_face_internal, Smake_face_internal, 1, 1, 0,
 
   FOR_EACH_FRAME (rest, frame)
     {
-      if (FRAME_X_P (XFRAME (frame)))
+      if (FRAME_MSDOS_P (XFRAME (frame)) || FRAME_X_P (XFRAME (frame)))
        ensure_face_ready (XFRAME (frame), id);
     }
   return Qnil;
@@ -1147,7 +1158,7 @@ DEFUN ("set-face-attribute-internal", Fset_face_attribute_internal,
   if (id < 0 || id >= next_face_id)
     error ("Face id out of range");
 
-  if (! FRAME_X_P (f))
+  if (! FRAME_X_P (f) && ! FRAME_MSDOS_P (f))
     return Qnil;
 
   ensure_face_ready (f, id);
@@ -1160,10 +1171,38 @@ DEFUN ("set-face-attribute-internal", Fset_face_attribute_internal,
         is taken to mean an unused face nowadays).  */
       face->font = (XFontStruct *)1 ;
 #else
-      XFontStruct *font = load_font (f, attr_value);
-      if (face->font != f->output_data.x->font)
+      XFontStruct *font;
+      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_X_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.x->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
@@ -1182,9 +1221,6 @@ DEFUN ("set-face-attribute-internal", Fset_face_attribute_internal,
     {
       unsigned long new_color = load_color (f, attr_value);
       unload_color (f, face->background);
-#if defined (MSDOS) && !defined (HAVE_X_WINDOWS)
-      new_color &= ~8;  /* Bright would give blinking characters.  */
-#endif
       face->background = new_color;
       garbaged = 1;
     }
@@ -1215,18 +1251,13 @@ DEFUN ("set-face-attribute-internal", Fset_face_attribute_internal,
      And we must inhibit any Expose events until the redraw is done,
      since they would try to use the invalid display faces.  */
   if (garbaged)
-    SET_FRAME_GARBAGED (f);
+    {
+      SET_FRAME_GARBAGED (f);
+      FRAME_X_DISPLAY_INFO (f)->mouse_face_defer = 1;
+    }
 
   return Qnil;
 }
-
-DEFUN ("internal-next-face-id", Finternal_next_face_id, Sinternal_next_face_id,
-  0, 0, 0, "")
-  ()
-{
-  return make_number (next_face_id++);
-}
-
 /* Return the face id for name NAME on frame FRAME.
    (It should be the same for all frames,
    but it's as easy to use the "right" frame to look it up
@@ -1247,12 +1278,42 @@ face_name_id_number (f, name)
   CHECK_NUMBER (tem, 0);
   return XINT (tem);
 }
+
+#endif /* HAVE_FACES */
+
+\f
+DEFUN ("frame-face-alist", Fframe_face_alist, Sframe_face_alist, 1, 1, 0,
+       "")
+     (frame)
+     Lisp_Object frame;
+{
+  CHECK_FRAME (frame, 0);
+  return XFRAME (frame)->face_alist;
+}
+
+DEFUN ("set-frame-face-alist", Fset_frame_face_alist, Sset_frame_face_alist,
+       2, 2, 0, "")
+     (frame, value)
+     Lisp_Object frame, value;
+{
+  CHECK_FRAME (frame, 0);
+  XFRAME (frame)->face_alist = value;
+  return value;
+}
+
+DEFUN ("internal-next-face-id", Finternal_next_face_id, Sinternal_next_face_id,
+  0, 0, 0, "")
+  ()
+{
+  return make_number (next_face_id++);
+}
 \f
 /* Emacs initialization.  */
 
 void
 syms_of_xfaces ()
 {
+#ifdef HAVE_FACES
   Qface = intern ("face");
   staticpro (&Qface);
   Qmouse_face = intern ("mouse-face");
@@ -1265,14 +1326,15 @@ syms_of_xfaces ()
 The region is highlighted with this face\n\
 when Transient Mark mode is enabled and the mark is active.");
 
+  defsubr (&Smake_face_internal);
+  defsubr (&Sset_face_attribute_internal);
+#endif /* HAVE_FACES */
+
 #ifdef HAVE_X_WINDOWS
   defsubr (&Spixmap_spec_p);
 #endif
+
   defsubr (&Sframe_face_alist);
   defsubr (&Sset_frame_face_alist);
-  defsubr (&Smake_face_internal);
-  defsubr (&Sset_face_attribute_internal);
   defsubr (&Sinternal_next_face_id);
 }
-
-#endif /* HAVE_FACES */