2 Copyright (C) 1993 Free Software Foundation.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
20 /* This is derived from work by Lucid (some parts very loosely so). */
22 #include <sys/types.h>
32 #include "dispextern.h"
34 #include "blockinput.h"
37 /* Compensate for bug in Xos.h on some systems. */
38 #ifdef XOS_NEEDS_TIME_H
43 /* These don't seem to be used. */
45 /* Display Context for the icons */
46 #include <X11/Intrinsic.h>
47 #include <X11/StringDefs.h>
48 #include <X11/Xmu/Drawing.h>
54 /* An explanation of the face data structures. */
56 /* ========================= Face Data Structures =========================
58 All lisp code uses symbols as face names.
60 Each frame has a face_alist member (with the frame-face-alist and
61 set-frame-face-alist accessors), associating the face names with
63 [face NAME ID FONT FOREGROUND BACKGROUND BACKGROUND-PIXMAP UNDERLINE-P]
65 face is the symbol `face',
66 NAME is the symbol with which this vector is associated (a backpointer),
67 ID is the face ID, an integer used internally by the C code to identify
69 FONT, FOREGROUND, and BACKGROUND are strings naming the fonts and colors
71 BACKGROUND-PIXMAP is the name of an x bitmap filename, which we don't
73 UNDERLINE-P is non-nil if the face should be underlined.
74 If any of these elements are nil, that allows the frame's parameters to
76 (lisp/faces.el maintains these association lists.)
78 The frames' private alists hold the frame-local definitions for the
79 faces. The lisp variable global-face-data contains the global
80 defaults for faces. (See lisp/faces.el for this too.)
82 In the C code, we also have a `struct face' with the elements
83 `foreground', `background', `font', and `underline',
84 which specify its visual appearance, and elements
85 `gc' and `cached_index';
86 `gc' may be an X GC which has been built for the given display
87 parameters. Faces with GC's are called `display faces'. Whether
88 or not a face has a GC depends on what data structure the face is
89 in; we explain these more below. (See src/dispextern.h.)
91 Each frame also has members called `faces' and `n_faces' (with the
92 accessors FRAME_FACES and FRAME_N_FACES), which define an array of
93 struct face pointers, indexed by face ID (element 2 of the
94 vector). These are called "frame faces".
95 Element 0 is the default face --- the one used for normal text.
96 Element 1 is the modeline face.
97 These faces have their GC's set; the rest do not.
98 If faces[i] is filled in (i.e. non-zero) on one frame, then it must
99 be filled in on all frames. Code assumes that face ID's can be
100 used on any frame. (See src/xterm.h.)
102 The global variables `face_vector' and `nfaces' define another
103 array of struct face pointers, with their GC's set. This array
104 acts as a cache of GC's to be used by all frames. The function
105 `intern_face', passed a struct face *, searches face_vector for a
106 struct face with the same parameters, adds a new one with a GC if
107 it doesn't find one, and returns it. If you have a `struct face',
108 and you want a GC for it, call intern_face on that struct, and it
109 will return a `struct face *' with its GC set. The faces in
110 face_vector are called `cached faces.' (See src/xfaces.c.)
112 The `GLYPH' data type is an unsigned integer type; the bottom byte
113 is a character code, and the byte above that is a face id. The
114 `struct frame_glyphs' structure, used to describe frames' current
115 or desired contents, is essentially a matrix of GLYPHs; the face
116 ID's in a struct frame_glyphs are indices into FRAME_FACES. (See
121 Since face_vector is just a cache --- there are no pointers into it
122 from the rest of the code, and everyone accesses it through
123 intern_face --- we could just free its GC's and throw the whole
124 thing away without breaking anything. This gives us a simple way
125 to garbage-collect old GC's nobody's using any more - we can just
126 purge face_vector, and then let subsequent calls to intern_face
127 refill it as needed. The function clear_face_vector performs this
130 We're often applying intern_face to faces in frames' local arrays -
131 for example, we do this while sending GLYPHs from a struct
132 frame_glyphs to X during redisplay. It would be nice to avoid
133 searching all of face_vector every time we intern a frame's face.
134 So, when intern_face finds a match for FACE in face_vector, it
135 stores the index of the match in FACE's cached_index member, and
136 checks there first next time. */
139 /* Definitions and declarations. */
141 /* A table of display faces. */
142 struct face
**face_vector
;
143 /* The length in use of the table. */
145 /* The allocated length of the table. */
146 int nfaces_allocated
;
148 /* The number of face-id's in use (same for all frames). */
151 /* The number of the face to use to indicate the region. */
154 /* This is what appears in a slot in a face to signify that the face
155 does not specify that display aspect. */
156 #define FACE_DEFAULT (~0)
158 Lisp_Object Qface
, Qwindow
, Qpriority
;
160 static void build_face ( /* FRAME_PTR, struct face * */ );
161 int face_name_id_number ( /* FRAME_PTR, Lisp_Object name */ );
163 struct face
*intern_face ( /* FRAME_PTR, struct face * */ );
164 static void ensure_face_ready ( /* FRAME_PTR, int id */ );
165 static void recompute_basic_faces ( /* FRAME_PTR f */ );
167 /* Allocating, copying, and comparing struct faces. */
169 /* Allocate a new face */
173 struct face
*result
= (struct face
*) xmalloc (sizeof (struct face
));
174 bzero (result
, sizeof (struct face
));
175 result
->font
= (XFontStruct
*) FACE_DEFAULT
;
176 result
->foreground
= FACE_DEFAULT
;
177 result
->background
= FACE_DEFAULT
;
178 result
->stipple
= FACE_DEFAULT
;
182 /* Make a new face that's a copy of an existing one. */
187 struct face
*result
= allocate_face ();
189 result
->font
= face
->font
;
190 result
->foreground
= face
->foreground
;
191 result
->background
= face
->background
;
192 result
->stipple
= face
->stipple
;
193 result
->underline
= face
->underline
;
199 face_eql (face1
, face2
)
200 struct face
*face1
, *face2
;
202 return ( face1
->font
== face2
->font
203 && face1
->foreground
== face2
->foreground
204 && face1
->background
== face2
->background
205 && face1
->stipple
== face2
->stipple
206 && face1
->underline
== face2
->underline
);
209 /* Interning faces in the `face_vector' cache, and clearing that cache. */
211 /* Return the unique display face corresponding to the user-level face FACE.
212 If there isn't one, make one, and find a slot in the face_vector to
215 get_cached_face (f
, face
)
222 /* Perhaps FACE->cached_index is valid; this could happen if FACE is
223 in a frame's face list. */
224 if (face
->cached_index
>= 0
225 && face
->cached_index
< nfaces
226 && face_eql (face_vector
[face
->cached_index
], face
))
227 return face_vector
[face
->cached_index
];
229 /* Look for an existing display face that does the job.
230 Also find an empty slot if any. */
231 for (i
= 0; i
< nfaces
; i
++)
233 if (face_eql (face_vector
[i
], face
))
234 return face_vector
[i
];
235 if (face_vector
[i
] == 0)
239 /* If no empty slots, make one. */
240 if (empty
< 0 && nfaces
== nfaces_allocated
)
242 int newsize
= nfaces
+ 20;
244 = (struct face
**) xrealloc (face_vector
,
245 newsize
* sizeof (struct face
*));
246 nfaces_allocated
= newsize
;
252 /* Put a new display face in the empty slot. */
253 result
= copy_face (face
);
254 face_vector
[empty
] = result
;
256 /* Make a graphics context for it. */
257 build_face (f
, result
);
262 /* Given a frame face, return an equivalent display face
263 (one which has a graphics context). */
266 intern_face (f
, face
)
270 /* If it's equivalent to the default face, use that. */
271 if (face_eql (face
, FRAME_DEFAULT_FACE (f
)))
273 if (!FRAME_DEFAULT_FACE (f
)->gc
)
274 build_face (f
, FRAME_DEFAULT_FACE (f
));
275 return FRAME_DEFAULT_FACE (f
);
278 /* If it's equivalent to the mode line face, use that. */
279 if (face_eql (face
, FRAME_MODE_LINE_FACE (f
)))
281 if (!FRAME_MODE_LINE_FACE (f
)->gc
)
282 build_face (f
, FRAME_MODE_LINE_FACE (f
));
283 return FRAME_MODE_LINE_FACE (f
);
286 /* If it's not one of the frame's default faces, it shouldn't have a GC. */
290 /* Get a specialized display face. */
291 return get_cached_face (f
, face
);
294 /* Clear out face_vector and start anew.
295 This should be done from time to time just to avoid
296 keeping too many graphics contexts in face_vector
297 that are no longer needed. */
303 Display
*dpy
= x_current_display
;
307 /* Free the display faces in the face_vector. */
308 for (i
= 0; i
< nfaces
; i
++)
310 struct face
*face
= face_vector
[i
];
312 XFreeGC (dpy
, face
->gc
);
320 /* Allocating and freeing X resources for display faces. */
322 /* Make a graphics context for face FACE, which is on frame F,
323 if that can be done. */
335 if (face
->foreground
!= FACE_DEFAULT
)
336 xgcv
.foreground
= face
->foreground
;
338 xgcv
.foreground
= f
->display
.x
->foreground_pixel
;
340 if (face
->background
!= FACE_DEFAULT
)
341 xgcv
.background
= face
->background
;
343 xgcv
.background
= f
->display
.x
->background_pixel
;
345 if (face
->font
&& (int) face
->font
!= FACE_DEFAULT
)
346 xgcv
.font
= face
->font
->fid
;
348 xgcv
.font
= f
->display
.x
->font
->fid
;
350 xgcv
.graphics_exposures
= 0;
352 mask
= GCForeground
| GCBackground
| GCFont
| GCGraphicsExposures
;
353 gc
= XCreateGC (x_current_display
, FRAME_X_WINDOW (f
),
357 if (face
->stipple
&& face
->stipple
!= FACE_DEFAULT
)
358 XSetStipple (x_current_display
, gc
, face
->stipple
);
366 /* Allocating, freeing, and duplicating fonts, colors, and pixmaps. */
376 return (XFontStruct
*) FACE_DEFAULT
;
378 CHECK_STRING (name
, 0);
380 font
= XLoadQueryFont (x_current_display
, (char *) XSTRING (name
)->data
);
384 Fsignal (Qerror
, Fcons (build_string ("undefined font"),
385 Fcons (name
, Qnil
)));
390 unload_font (f
, font
)
394 if (!font
|| font
== ((XFontStruct
*) FACE_DEFAULT
))
398 XFreeFont (x_current_display
, font
);
407 Display
*dpy
= x_current_display
;
415 cmap
= DefaultColormapOfScreen (DefaultScreenOfDisplay (x_current_display
));
417 CHECK_STRING (name
, 0);
419 result
= XParseColor (dpy
, cmap
, (char *) XSTRING (name
)->data
, &color
);
422 Fsignal (Qerror
, Fcons (build_string ("undefined color"),
423 Fcons (name
, Qnil
)));
425 result
= XAllocColor (dpy
, cmap
, &color
);
428 Fsignal (Qerror
, Fcons (build_string ("X server cannot allocate color"),
429 Fcons (name
, Qnil
)));
430 return (unsigned long) color
.pixel
;
434 unload_color (f
, pixel
)
438 /* Since faces get built by copying parameters from other faces, the
439 allocation counts for the colors get all screwed up. I don't see
440 any solution that will take less than 10 minutes, and it's better
441 to have a color leak than a crash, so I'm just dyking this out.
442 This isn't really a color leak, anyway - if we ask for it again,
443 we'll get the same pixel. */
446 Display
*dpy
= x_current_display
;
447 if (pixel
== FACE_DEFAULT
448 || pixel
== BLACK_PIX_DEFAULT
449 || pixel
== WHITE_PIX_DEFAULT
)
451 cmap
= DefaultColormapOfScreen (DefaultScreenOfDisplay (x_current_display
));
453 XFreeColors (dpy
, cmap
, &pixel
, 1, 0);
458 /* Initializing face arrays for frames. */
464 ensure_face_ready (f
, 0);
465 ensure_face_ready (f
, 1);
467 recompute_basic_faces (f
);
469 /* Find another X frame. */
471 Lisp_Object tail
, frame
, result
;
474 FOR_EACH_FRAME (tail
, frame
)
475 if (FRAME_X_P (XFRAME (frame
))
476 && XFRAME (frame
) != f
)
482 /* If we didn't find any X frames other than f, then we don't need
483 any faces other than 0 and 1, so we're okay. Otherwise, make
484 sure that all faces valid on the selected frame are also valid
485 on this new frame. */
489 int n_faces
= XFRAME (result
)->display
.x
->n_faces
;
490 struct face
**faces
= XFRAME (result
)->display
.x
->faces
;
492 for (i
= 2; i
< n_faces
; i
++)
494 ensure_face_ready (f
, i
);
500 /* Called from Fdelete_frame. */
505 Display
*dpy
= x_current_display
;
510 for (i
= 0; i
< FRAME_N_FACES (f
); i
++)
512 struct face
*face
= FRAME_FACES (f
) [i
];
516 XFreeGC (dpy
, face
->gc
);
519 unload_font (f
, face
->font
);
520 unload_color (f
, face
->foreground
);
521 unload_color (f
, face
->background
);
523 unload_pixmap (f
, face
->stipple
);
529 xfree (FRAME_FACES (f
));
531 FRAME_N_FACES (f
) = 0;
536 /* Interning faces in a frame's face array. */
538 /* Find a match for NEW_FACE in a FRAME's face array, and add it if we don't
541 intern_frame_face (frame
, new_face
)
543 struct face
*new_face
;
545 int len
= FRAME_N_FACES (frame
);
548 /* Search for a face already on FRAME equivalent to FACE. */
549 for (i
= 0; i
< len
; i
++)
551 struct face
*frame_face
= FRAME_FACES (frame
)[i
];
553 if (frame_face
&& face_eql (new_face
, frame_face
))
557 /* We didn't find one; add a new one. */
560 ensure_face_ready (frame
, i
);
561 bcopy (new_face
, FRAME_FACES (frame
)[i
], sizeof (*new_face
));
562 FRAME_FACES (frame
)[i
]->copy
= 1;
567 /* Make face id ID valid on frame F. */
570 ensure_face_ready (f
, id
)
574 if (FRAME_N_FACES (f
) <= id
)
578 if (!FRAME_N_FACES (f
))
580 = (struct face
**) xmalloc (sizeof (struct face
*) * n
);
583 = (struct face
**) xrealloc (FRAME_FACES (f
),
584 sizeof (struct face
*) * n
);
586 bzero (FRAME_FACES (f
) + FRAME_N_FACES (f
),
587 (n
- FRAME_N_FACES (f
)) * sizeof (struct face
*));
588 FRAME_N_FACES (f
) = n
;
591 if (FRAME_FACES (f
) [id
] == 0)
592 FRAME_FACES (f
) [id
] = allocate_face ();
595 /* Computing faces appropriate for a given piece of text in a buffer. */
597 /* Return non-zero if FONT1 and FONT2 have the same size bounding box.
598 We assume that they're both character-cell fonts. */
600 same_size_fonts (font1
, font2
)
601 XFontStruct
*font1
, *font2
;
603 XCharStruct
*bounds1
= &font1
->min_bounds
;
604 XCharStruct
*bounds2
= &font2
->min_bounds
;
606 return (bounds1
->width
== bounds2
->width
);
607 /* Checking the following caused bad results in some cases
608 when fonts that should be the same size
609 actually have very slightly different size.
610 It is possible that this reintroduces the bug whereby line positions
611 were not right. However, the right way to fix that is to change xterm.c
612 so that the vertical positions of lines
613 depend only on the height of the frame's font.
614 && bounds1->ascent == bounds2->ascent
615 && bounds1->descent == bounds2->descent); */
618 /* Modify face TO by copying from FROM all properties which have
619 nondefault settings. */
621 merge_faces (from
, to
)
622 struct face
*from
, *to
;
624 /* Only merge the font if it's the same size as the base font. */
625 if (from
->font
!= (XFontStruct
*) FACE_DEFAULT
626 && same_size_fonts (from
->font
, to
->font
))
627 to
->font
= from
->font
;
628 if (from
->foreground
!= FACE_DEFAULT
)
629 to
->foreground
= from
->foreground
;
630 if (from
->background
!= FACE_DEFAULT
)
631 to
->background
= from
->background
;
632 if (from
->stipple
!= FACE_DEFAULT
)
633 to
->stipple
= from
->stipple
;
635 to
->underline
= from
->underline
;
638 /* Set up the basic set of facial parameters, based on the frame's
639 data; all faces are deltas applied to this. */
641 compute_base_face (f
, face
)
645 struct x_display
*d
= f
->display
.x
;
648 face
->foreground
= d
->foreground_pixel
;
649 face
->background
= d
->background_pixel
;
650 face
->font
= d
->font
;
654 /* Avoid a face comparison by making this invalid. */
655 face
->cached_index
= -1;
667 sort_overlays (s1
, s2
)
668 struct sortvec
*s1
, *s2
;
670 if (s1
->priority
!= s2
->priority
)
671 return s1
->priority
- s2
->priority
;
672 if (s1
->beg
!= s2
->beg
)
673 return s1
->beg
- s2
->beg
;
674 if (s1
->end
!= s2
->end
)
675 return s2
->end
- s1
->end
;
679 /* Return the face ID associated with a buffer position POS.
680 Store into *ENDPTR the position at which a different face is needed.
681 This does not take account of glyphs that specify their own face codes.
682 F is the frame in use for display, and W is a window displaying
685 REGION_BEG, REGION_END delimit the region, so it can be highlighted. */
688 compute_char_face (f
, w
, pos
, region_beg
, region_end
, endptr
)
692 int region_beg
, region_end
;
696 Lisp_Object prop
, position
;
699 Lisp_Object
*overlay_vec
;
700 struct sortvec
*sortvec
;
704 /* W must display the current buffer. We could write this function
705 to use the frame and buffer of W, but right now it doesn't. */
706 if (XBUFFER (w
->buffer
) != current_buffer
)
709 XSET (frame
, Lisp_Frame
, f
);
712 if (pos
< region_beg
&& region_beg
< endpos
)
715 XFASTINT (position
) = pos
;
716 prop
= Fget_text_property (position
, Qface
, w
->buffer
);
720 end
= Fnext_single_property_change (position
, Qface
, w
->buffer
);
729 /* First try with room for 40 overlays. */
731 overlay_vec
= (Lisp_Object
*) alloca (len
* sizeof (Lisp_Object
));
733 noverlays
= overlays_at (pos
, 0, &overlay_vec
, &len
, &next_overlay
);
735 /* If there are more than 40,
736 make enough space for all, and try again. */
740 overlay_vec
= (Lisp_Object
*) alloca (len
* sizeof (Lisp_Object
));
741 noverlays
= overlays_at (pos
, 0, &overlay_vec
, &len
, &next_overlay
);
744 if (next_overlay
< endpos
)
745 endpos
= next_overlay
;
750 /* Optimize the default case. */
751 if (noverlays
== 0 && NILP (prop
)
752 && !(pos
>= region_beg
&& pos
< region_end
))
755 compute_base_face (f
, &face
);
759 facecode
= face_name_id_number (f
, prop
);
760 if (facecode
>= 0 && facecode
< FRAME_N_FACES (f
)
761 && FRAME_FACES (f
) [facecode
] != 0)
762 merge_faces (FRAME_FACES (f
) [facecode
], &face
);
765 /* Put the valid and relevant overlays into sortvec. */
766 sortvec
= (struct sortvec
*) alloca (noverlays
* sizeof (struct sortvec
));
768 for (i
= 0, j
= 0; i
< noverlays
; i
++)
770 Lisp_Object overlay
= overlay_vec
[i
];
772 if (OVERLAY_VALID (overlay
)
773 && OVERLAY_POSITION (OVERLAY_START (overlay
)) > 0
774 && OVERLAY_POSITION (OVERLAY_END (overlay
)) > 0)
777 window
= Foverlay_get (overlay
, Qwindow
);
779 /* Also ignore overlays limited to one window
780 if it's not the window we are using. */
781 if (XTYPE (window
) != Lisp_Window
782 || XWINDOW (window
) == w
)
786 /* This overlay is good and counts:
787 put it in sortvec. */
788 sortvec
[j
].overlay
= overlay
;
789 sortvec
[j
].beg
= OVERLAY_POSITION (OVERLAY_START (overlay
));
790 sortvec
[j
].end
= OVERLAY_POSITION (OVERLAY_END (overlay
));
791 tem
= Foverlay_get (overlay
, Qpriority
);
793 sortvec
[j
].priority
= XINT (tem
);
795 sortvec
[j
].priority
= 0;
802 /* Sort the overlays into the proper order: increasing priority. */
805 qsort (sortvec
, noverlays
, sizeof (struct sortvec
), sort_overlays
);
807 /* Now merge the overlay data in that order. */
808 for (i
= 0; i
< noverlays
; i
++)
810 prop
= Foverlay_get (sortvec
[i
].overlay
, Qface
);
816 facecode
= face_name_id_number (f
, prop
);
817 if (facecode
>= 0 && facecode
< FRAME_N_FACES (f
)
818 && FRAME_FACES (f
) [facecode
] != 0)
819 merge_faces (FRAME_FACES (f
) [facecode
], &face
);
821 oend
= OVERLAY_END (sortvec
[i
].overlay
);
822 oendpos
= OVERLAY_POSITION (oend
);
823 if (oendpos
< endpos
)
828 if (pos
>= region_beg
&& pos
< region_end
)
830 if (region_end
< endpos
)
832 if (region_face
>= 0 && region_face
< next_face_id
)
833 merge_faces (FRAME_FACES (f
) [region_face
], &face
);
838 return intern_frame_face (f
, &face
);
841 /* Return the face ID to use to display a special glyph which selects
842 FACE_CODE as the face ID, assuming that ordinarily the face would
843 be BASIC_FACE. F is the frame. */
845 compute_glyph_face (f
, face_code
)
851 compute_base_face (f
, &face
);
853 if (face_code
>= 0 && face_code
< FRAME_N_FACES (f
)
854 && FRAME_FACES (f
) [face_code
] != 0)
855 merge_faces (FRAME_FACES (f
) [face_code
], &face
);
857 return intern_frame_face (f
, &face
);
861 /* Recompute the GC's for the default and modeline faces.
862 We call this after changing frame parameters on which those GC's
865 recompute_basic_faces (f
)
868 /* If the frame's faces haven't been initialized yet, don't worry about
870 if (FRAME_N_FACES (f
) < 2)
875 if (FRAME_DEFAULT_FACE (f
)->gc
)
876 XFreeGC (x_current_display
, FRAME_DEFAULT_FACE (f
)->gc
);
877 build_face (f
, FRAME_DEFAULT_FACE (f
));
879 if (FRAME_MODE_LINE_FACE (f
)->gc
)
880 XFreeGC (x_current_display
, FRAME_MODE_LINE_FACE (f
)->gc
);
881 build_face (f
, FRAME_MODE_LINE_FACE (f
));
888 /* Lisp interface. */
890 DEFUN ("frame-face-alist", Fframe_face_alist
, Sframe_face_alist
, 1, 1, 0,
895 CHECK_FRAME (frame
, 0);
896 return XFRAME (frame
)->face_alist
;
899 DEFUN ("set-frame-face-alist", Fset_frame_face_alist
, Sset_frame_face_alist
,
902 Lisp_Object frame
, value
;
904 CHECK_FRAME (frame
, 0);
905 XFRAME (frame
)->face_alist
= value
;
910 DEFUN ("make-face-internal", Fmake_face_internal
, Smake_face_internal
, 1, 1, 0,
911 "Create face number FACE-ID on all frames.")
916 int id
= XINT (face_id
);
918 CHECK_NUMBER (face_id
, 0);
919 if (id
< 0 || id
>= next_face_id
)
920 error ("Face id out of range");
922 for (rest
= Vframe_list
; !NILP (rest
); rest
= XCONS (rest
)->cdr
)
924 struct frame
*f
= XFRAME (XCONS (rest
)->car
);
926 ensure_face_ready (f
, id
);
932 DEFUN ("set-face-attribute-internal", Fset_face_attribute_internal
,
933 Sset_face_attribute_internal
, 4, 4, 0, "")
934 (face_id
, attr_name
, attr_value
, frame
)
935 Lisp_Object face_id
, attr_name
, attr_value
, frame
;
942 CHECK_FRAME (frame
, 0);
943 CHECK_NUMBER (face_id
, 0);
944 CHECK_SYMBOL (attr_name
, 0);
948 if (id
< 0 || id
>= next_face_id
)
949 error ("Face id out of range");
954 ensure_face_ready (f
, id
);
955 face
= FRAME_FACES (f
) [XFASTINT (face_id
)];
957 if (EQ (attr_name
, intern ("font")))
959 XFontStruct
*font
= load_font (f
, attr_value
);
960 if (face
->font
!= f
->display
.x
->font
)
961 unload_font (f
, face
->font
);
964 else if (EQ (attr_name
, intern ("foreground")))
966 unsigned long new_color
= load_color (f
, attr_value
);
967 unload_color (f
, face
->foreground
);
968 face
->foreground
= new_color
;
970 else if (EQ (attr_name
, intern ("background")))
972 unsigned long new_color
= load_color (f
, attr_value
);
973 unload_color (f
, face
->background
);
974 face
->background
= new_color
;
977 else if (EQ (attr_name
, intern ("background-pixmap")))
979 unsigned int w
, h
, d
;
980 unsigned long new_pixmap
= load_pixmap (f
, attr_value
, &w
, &h
, &d
, 0);
981 unload_pixmap (f
, face
->stipple
);
982 if (NILP (attr_value
))
984 face
->stipple
= new_pixmap
;
987 /* face->pixmap_depth = d; */
990 else if (EQ (attr_name
, intern ("underline")))
992 int new = !NILP (attr_value
);
993 face
->underline
= new;
996 error ("unknown face attribute");
1001 if (FRAME_DEFAULT_FACE (f
)->gc
!= 0)
1002 XFreeGC (x_current_display
, FRAME_DEFAULT_FACE (f
)->gc
);
1003 build_face (f
, FRAME_DEFAULT_FACE (f
));
1010 if (FRAME_MODE_LINE_FACE (f
)->gc
!= 0)
1011 XFreeGC (x_current_display
, FRAME_MODE_LINE_FACE (f
)->gc
);
1012 build_face (f
, FRAME_MODE_LINE_FACE (f
));
1016 /* If we're modifying either of the frame's display faces, that
1017 means that we're changing the parameters of a fixed face code;
1018 since the color/font/whatever is changed but the face ID hasn't,
1019 redisplay won't know to redraw the affected sections. Give it a
1021 if (id
== 0 || id
== 1)
1022 SET_FRAME_GARBAGED (f
);
1024 /* Otherwise, it's enough to tell it to redisplay the text. */
1025 windows_or_buffers_changed
= 1;
1030 DEFUN ("internal-next-face-id", Finternal_next_face_id
, Sinternal_next_face_id
,
1034 return make_number (next_face_id
++);
1037 /* Return the face id for name NAME on frame FRAME.
1038 (It should be the same for all frames,
1039 but it's as easy to use the "right" frame to look it up
1040 as to use any other one.) */
1043 face_name_id_number (f
, name
)
1049 tem
= Fcdr (Fassq (name
, f
->face_alist
));
1052 CHECK_VECTOR (tem
, 0);
1053 tem
= XVECTOR (tem
)->contents
[2];
1054 CHECK_NUMBER (tem
, 0);
1058 /* Emacs initialization. */
1063 Qwindow
= intern ("window");
1064 staticpro (&Qwindow
);
1065 Qface
= intern ("face");
1067 Qpriority
= intern ("priority");
1068 staticpro (&Qpriority
);
1070 DEFVAR_INT ("region-face", ®ion_face
,
1071 "Face number to use to highlight the region\n\
1072 The region is highlighted with this face\n\
1073 when Transient Mark mode is enabled and the mark is active.");
1075 defsubr (&Sframe_face_alist
);
1076 defsubr (&Sset_frame_face_alist
);
1077 defsubr (&Smake_face_internal
);
1078 defsubr (&Sset_face_attribute_internal
);
1079 defsubr (&Sinternal_next_face_id
);
1082 #endif /* HAVE_X_WINDOWS */