-/* "Face" primitives.
- Copyright (C) 1993, 1994, 1995 Free Software Foundation.
+/* "Face" primitives on the Microsoft W32 API.
+ Copyright (C) 1993, 1994, 1995, 1999 Free Software Foundation.
This file is part of GNU Emacs.
the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-/* Ported xfaces.c for win32 - Kevin Gallo */
+/* Ported xfaces.c for w32 - Kevin Gallo */
+#include <config.h>
#include <sys/types.h>
#include <sys/stat.h>
-#include <config.h>
#include "lisp.h"
#include "w32term.h"
#include "blockinput.h"
#include "window.h"
#include "intervals.h"
+#include "charset.h"
+#include "fontset.h"
\f
/* An explanation of the face data structures. */
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.
(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
- 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
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
- 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
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
does not specify that display aspect. */
#define FACE_DEFAULT (~0)
-Lisp_Object Qface, Qmouse_face;
+Lisp_Object Qface;
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 * */ );
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. */
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;
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;
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
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;
- font = win32_load_font (FRAME_WIN32_DISPLAY_INFO (f), (char *) XSTRING (name)->data);
+ fontinf = w32_load_font (f, (char *) XSTRING (name)->data, 0);
UNBLOCK_INPUT;
+ if (fontinf)
+ font = (XFontStruct *)fontinf->font;
if (! font)
Fsignal (Qerror, Fcons (build_string ("undefined font"),
return;
BLOCK_INPUT;
- win32_unload_font (FRAME_WIN32_DISPLAY_INFO (f), font);
+ w32_unload_font (FRAME_W32_DISPLAY_INFO (f), font);
UNBLOCK_INPUT;
}
}
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;
- 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 (XCDR (object))
+ && CONSP (XCDR (XCDR (object)))
+ && NILP (XCDR (XCDR (XCDR (object))))
+ && (width = XCAR (object), INTEGERP (width))
+ && (height = XCAR (XCDR (object)), INTEGERP (height))
+ && STRINGP (XCAR (XCDR (XCDR (object))))
&& 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 (XCAR (XCDR (XCDR (object))))->size
* (BITS_PER_INT / sizeof (int)))
>= XFASTINT (width) * XFASTINT (height))))
? Qt : Qnil);
new_computed_face (f, FRAME_PARAM_FACES (f)[1]);
recompute_basic_faces (f);
-#ifdef MULTI_FRAME
/* Find another frame. */
{
Lisp_Object tail, frame, result;
result = Qnil;
FOR_EACH_FRAME (tail, frame)
- if (FRAME_WIN32_P (XFRAME (frame))
+ if (FRAME_W32_P (XFRAME (frame))
&& XFRAME (frame) != f)
{
result = frame;
ensure_face_ready (f, i);
}
}
-#endif /* MULTI_FRAME */
}
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);
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))
{
FRAME_PTR f;
{
int i;
- int biggest = FONT_HEIGHT (f->output_data.win32->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.win32->n_param_faces; i++)
- if (f->output_data.win32->param_faces[i] != 0
- && f->output_data.win32->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.win32->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 (biggest == f->output_data.win32->line_height)
+ if (biggest == FRAME_LINE_HEIGHT (f))
return 0;
- f->output_data.win32->line_height = biggest;
+ FRAME_LINE_HEIGHT (f) = biggest;
return 1;
}
\f
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)
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;
}
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;
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++)
{
- 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)
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 (XCDR (prop)))
+ {
+ /* 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 (XCAR (faces[j]), Qbackground_color))
+ face->background = load_color (f, XCDR (faces[j]));
+ if (EQ (XCAR (faces[j]), Qforeground_color))
+ face->foreground = load_color (f, XCDR (faces[j]));
+ }
+ 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
FOR_EACH_FRAME (rest, frame)
{
- if (FRAME_WIN32_P (XFRAME (frame)))
+ if (FRAME_W32_P (XFRAME (frame)))
ensure_face_ready (XFRAME (frame), id);
}
return Qnil;
if (id < 0 || id >= next_face_id)
error ("Face id out of range");
- if (! FRAME_WIN32_P (f))
+ if (! FRAME_WINDOW_P (f))
return Qnil;
ensure_face_ready (f, id);
if (EQ (attr_name, intern ("font")))
{
- XFontStruct *font = load_font (f, attr_value);
- if (face->font != f->output_data.win32->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;
+ 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
/* Emacs initialization. */
void
-syms_of_win32faces ()
+syms_of_w32faces ()
{
Qface = intern ("face");
staticpro (&Qface);