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 Let FACE-NAME be a symbol naming a face.
60 Let FACE-VECTOR be (assq FACE-NAME (frame-face-alist FRAME))
61 FACE-VECTOR is either nil, or a vector of the form
62 [face NAME ID FONT FOREGROUND BACKGROUND BACKGROUND-PIXMAP UNDERLINE-P]
64 face is the symbol `face',
65 NAME is the symbol with which this vector is associated (a backpointer),
66 ID is the face ID, an integer used internally by the C code to identify
68 FONT, FOREGROUND, and BACKGROUND are strings naming the fonts and colors
70 BACKGROUND-PIXMAP is the name of an x bitmap filename, which we don't
72 UNDERLINE-P is non-nil if the face should be underlined.
73 If any of these elements are nil, that parameter is considered
74 unspecified; parameters from faces specified by lower-priority
75 overlays or text properties, or the parameters of the frame itself,
76 can show through. (lisp/faces.el maintains these lists.)
78 (assq FACE-NAME global-face-data) returns a vector describing the
79 global parameters for that face.
81 Let PARAM-FACE be FRAME->display.x->param_faces[Faref (FACE-VECTOR, 2)].
82 PARAM_FACE is a struct face whose members are the Xlib analogues of
83 the parameters in FACE-VECTOR. If an element of FACE-VECTOR is
84 nil, then the corresponding member of PARAM_FACE is FACE_DEFAULT.
85 These faces are called "parameter faces", because they're the ones
86 lisp manipulates to control what gets displayed. Elements 0 and 1
87 of FRAME->display.x->param_faces are special - they describe the
88 default and mode line faces. None of the faces in param_faces have
89 GC's. (See src/dispextern.h for the definiton of struct face.
90 lisp/faces.el maintains the isomorphism between face_alist and
93 The functions compute_char_face and compute_glyph_face find and
94 combine the parameter faces associated with overlays and text
95 properties. The resulting faces are called "computed faces"; none
96 of their members are FACE_DEFAULT; they are completely specified.
97 They then call intern_compute_face to search
98 FRAME->display.x->computed_faces for a matching face, add one if
99 none is found, and return the index into
100 FRAME->display.x->computed_faces. FRAME's glyph matrices use these
101 indices to record the faces of the matrix characters, and the X
102 display hooks consult compute_faces to decide how to display these
103 characters. Elements 0 and 1 of computed_faces always describe the
104 default and mode-line faces.
106 Elements 0 and 1 of computed_faces have GC's; all the other faces
107 in computed_faces do not. The global array face_vector contains
108 faces with their GC's set. Given a computed_face, the function
109 intern_face finds (or adds) an element of face_vector with
110 equivalent parameters, and returns a pointer to that face, whose GC
111 can then be used for display.
115 Symbols naming faces must have associations on all frames; for any
116 FRAME, for all FACE-NAME, if (assq FACE-NAME (frame-face-alist
117 FRAME)) is non-nil, it must be non-nil for all frames.
119 Analogously, indices into param_faces must be valid on all frames;
120 if param_faces[i] is a non-zero face pointer on one frame, then it
121 must be filled in on all frames. Code assumes that face ID's can
122 be used on any frame.
126 Why do we keep param_faces and computed_faces separate?
127 computed_faces contains an element for every combination of facial
128 parameters we have ever displayed. indices into param_faces have
129 to be valid on all frames. If they were the same array, then that
130 array would grow very large on all frames, because any facial
131 combination displayed on any frame would need to be a valid entry
134 Since face_vector is just a cache --- there are no pointers into it
135 from the rest of the code, and everyone accesses it through
136 intern_face --- we could just free its GC's and throw the whole
137 thing away without breaking anything. This gives us a simple way
138 to garbage-collect old GC's nobody's using any more - we can just
139 purge face_vector, and then let subsequent calls to intern_face
140 refill it as needed. The function clear_face_vector performs this
143 We're often applying intern_face to faces in computed_faces -
144 for example, we do this while sending GLYPHs from a struct
145 frame_glyphs to X during redisplay. It would be nice to avoid
146 searching all of face_vector every time we intern a frame's face.
147 So, when intern_face finds a match for FACE in face_vector, it
148 stores the index of the match in FACE's cached_index member, and
149 checks there first next time. */
152 /* Definitions and declarations. */
154 /* A table of display faces. */
155 static struct face
**face_vector
;
156 /* The length in use of the table. */
158 /* The allocated length of the table. */
159 static int nfaces_allocated
;
161 /* The number of face-id's in use (same for all frames). */
164 /* The number of the face to use to indicate the region. */
167 /* This is what appears in a slot in a face to signify that the face
168 does not specify that display aspect. */
169 #define FACE_DEFAULT (~0)
171 Lisp_Object Qface
, Qwindow
, Qpriority
;
173 static void build_face ( /* FRAME_PTR, struct face * */ );
174 int face_name_id_number ( /* FRAME_PTR, Lisp_Object name */ );
176 struct face
*intern_face ( /* FRAME_PTR, struct face * */ );
177 static int new_computed_face ( /* FRAME_PTR, struct face * */ );
178 static int intern_computed_face ( /* FRAME_PTR, struct face * */ );
179 static void ensure_face_ready ( /* FRAME_PTR, int id */ );
180 void recompute_basic_faces ( /* FRAME_PTR f */ );
182 /* Allocating, copying, and comparing struct faces. */
184 /* Allocate a new face */
188 struct face
*result
= (struct face
*) xmalloc (sizeof (struct face
));
189 bzero (result
, sizeof (struct face
));
190 result
->font
= (XFontStruct
*) FACE_DEFAULT
;
191 result
->foreground
= FACE_DEFAULT
;
192 result
->background
= FACE_DEFAULT
;
193 result
->stipple
= FACE_DEFAULT
;
197 /* Make a new face that's a copy of an existing one. */
202 struct face
*result
= allocate_face ();
204 result
->font
= face
->font
;
205 result
->foreground
= face
->foreground
;
206 result
->background
= face
->background
;
207 result
->stipple
= face
->stipple
;
208 result
->underline
= face
->underline
;
214 face_eql (face1
, face2
)
215 struct face
*face1
, *face2
;
217 return ( face1
->font
== face2
->font
218 && face1
->foreground
== face2
->foreground
219 && face1
->background
== face2
->background
220 && face1
->stipple
== face2
->stipple
221 && face1
->underline
== face2
->underline
);
224 /* Interning faces in the `face_vector' cache, and clearing that cache. */
226 /* Return the unique display face corresponding to the user-level face FACE.
227 If there isn't one, make one, and find a slot in the face_vector to
230 get_cached_face (f
, face
)
237 /* Perhaps FACE->cached_index is valid; this could happen if FACE is
238 in a frame's face list. */
239 if (face
->cached_index
>= 0
240 && face
->cached_index
< nfaces
241 && face_eql (face_vector
[face
->cached_index
], face
))
242 return face_vector
[face
->cached_index
];
244 /* Look for an existing display face that does the job.
245 Also find an empty slot if any. */
246 for (i
= 0; i
< nfaces
; i
++)
248 if (face_eql (face_vector
[i
], face
))
249 return face_vector
[i
];
250 if (face_vector
[i
] == 0)
254 /* If no empty slots, make one. */
255 if (empty
< 0 && nfaces
== nfaces_allocated
)
257 int newsize
= nfaces
+ 20;
259 = (struct face
**) xrealloc (face_vector
,
260 newsize
* sizeof (struct face
*));
261 nfaces_allocated
= newsize
;
267 /* Put a new display face in the empty slot. */
268 result
= copy_face (face
);
269 face_vector
[empty
] = result
;
271 /* Make a graphics context for it. */
272 build_face (f
, result
);
277 /* Given a computed face, return an equivalent display face
278 (one which has a graphics context). */
281 intern_face (f
, face
)
285 /* If it's equivalent to the default face, use that. */
286 if (face_eql (face
, FRAME_DEFAULT_FACE (f
)))
288 if (!FRAME_DEFAULT_FACE (f
)->gc
)
289 build_face (f
, FRAME_DEFAULT_FACE (f
));
290 return FRAME_DEFAULT_FACE (f
);
293 /* If it's equivalent to the mode line face, use that. */
294 if (face_eql (face
, FRAME_MODE_LINE_FACE (f
)))
296 if (!FRAME_MODE_LINE_FACE (f
)->gc
)
297 build_face (f
, FRAME_MODE_LINE_FACE (f
));
298 return FRAME_MODE_LINE_FACE (f
);
301 /* If it's not one of the frame's default faces, it shouldn't have a GC. */
305 /* Get a specialized display face. */
306 return get_cached_face (f
, face
);
309 /* Clear out face_vector and start anew.
310 This should be done from time to time just to avoid
311 keeping too many graphics contexts in face_vector
312 that are no longer needed. */
318 Display
*dpy
= x_current_display
;
322 /* Free the display faces in the face_vector. */
323 for (i
= 0; i
< nfaces
; i
++)
325 struct face
*face
= face_vector
[i
];
327 XFreeGC (dpy
, face
->gc
);
335 /* Allocating and freeing X resources for display faces. */
337 /* Make a graphics context for face FACE, which is on frame F,
338 if that can be done. */
350 if (face
->foreground
!= FACE_DEFAULT
)
351 xgcv
.foreground
= face
->foreground
;
353 xgcv
.foreground
= f
->display
.x
->foreground_pixel
;
355 if (face
->background
!= FACE_DEFAULT
)
356 xgcv
.background
= face
->background
;
358 xgcv
.background
= f
->display
.x
->background_pixel
;
360 if (face
->font
&& (int) face
->font
!= FACE_DEFAULT
)
361 xgcv
.font
= face
->font
->fid
;
363 xgcv
.font
= f
->display
.x
->font
->fid
;
365 xgcv
.graphics_exposures
= 0;
367 mask
= GCForeground
| GCBackground
| GCFont
| GCGraphicsExposures
;
368 gc
= XCreateGC (x_current_display
, FRAME_X_WINDOW (f
),
372 if (face
->stipple
&& face
->stipple
!= FACE_DEFAULT
)
373 XSetStipple (x_current_display
, gc
, face
->stipple
);
381 /* Allocating, freeing, and duplicating fonts, colors, and pixmaps. */
391 return (XFontStruct
*) FACE_DEFAULT
;
393 CHECK_STRING (name
, 0);
395 font
= XLoadQueryFont (x_current_display
, (char *) XSTRING (name
)->data
);
399 Fsignal (Qerror
, Fcons (build_string ("undefined font"),
400 Fcons (name
, Qnil
)));
405 unload_font (f
, font
)
409 if (!font
|| font
== ((XFontStruct
*) FACE_DEFAULT
))
413 XFreeFont (x_current_display
, font
);
422 Display
*dpy
= x_current_display
;
430 cmap
= DefaultColormapOfScreen (DefaultScreenOfDisplay (x_current_display
));
432 CHECK_STRING (name
, 0);
434 result
= XParseColor (dpy
, cmap
, (char *) XSTRING (name
)->data
, &color
);
437 Fsignal (Qerror
, Fcons (build_string ("undefined color"),
438 Fcons (name
, Qnil
)));
440 result
= XAllocColor (dpy
, cmap
, &color
);
443 Fsignal (Qerror
, Fcons (build_string ("X server cannot allocate color"),
444 Fcons (name
, Qnil
)));
445 return (unsigned long) color
.pixel
;
449 unload_color (f
, pixel
)
453 /* Since faces get built by copying parameters from other faces, the
454 allocation counts for the colors get all screwed up. I don't see
455 any solution that will take less than 10 minutes, and it's better
456 to have a color leak than a crash, so I'm just dyking this out.
457 This isn't really a color leak, anyway - if we ask for it again,
458 we'll get the same pixel. */
461 Display
*dpy
= x_current_display
;
462 if (pixel
== FACE_DEFAULT
463 || pixel
== BLACK_PIX_DEFAULT
464 || pixel
== WHITE_PIX_DEFAULT
)
466 cmap
= DefaultColormapOfScreen (DefaultScreenOfDisplay (x_current_display
));
468 XFreeColors (dpy
, cmap
, &pixel
, 1, 0);
473 /* Managing parameter face arrays for frames. */
479 ensure_face_ready (f
, 0);
480 ensure_face_ready (f
, 1);
482 new_computed_face (f
, FRAME_PARAM_FACES (f
)[0]);
483 new_computed_face (f
, FRAME_PARAM_FACES (f
)[1]);
484 recompute_basic_faces (f
);
486 /* Find another X frame. */
488 Lisp_Object tail
, frame
, result
;
491 FOR_EACH_FRAME (tail
, frame
)
492 if (FRAME_X_P (XFRAME (frame
))
493 && XFRAME (frame
) != f
)
499 /* If we didn't find any X frames other than f, then we don't need
500 any faces other than 0 and 1, so we're okay. Otherwise, make
501 sure that all faces valid on the selected frame are also valid
502 on this new frame. */
506 int n_faces
= FRAME_N_PARAM_FACES (XFRAME (result
));
507 struct face
**faces
= FRAME_PARAM_FACES (XFRAME (result
));
509 for (i
= 2; i
< n_faces
; i
++)
511 ensure_face_ready (f
, i
);
517 /* Called from Fdelete_frame. */
522 Display
*dpy
= x_current_display
;
527 for (i
= 0; i
< FRAME_N_PARAM_FACES (f
); i
++)
529 struct face
*face
= FRAME_PARAM_FACES (f
) [i
];
533 XFreeGC (dpy
, face
->gc
);
534 unload_font (f
, face
->font
);
535 unload_color (f
, face
->foreground
);
536 unload_color (f
, face
->background
);
538 unload_pixmap (f
, face
->stipple
);
543 xfree (FRAME_PARAM_FACES (f
));
544 FRAME_PARAM_FACES (f
) = 0;
545 FRAME_N_PARAM_FACES (f
) = 0;
547 /* All faces in FRAME_COMPUTED_FACES use resources copied from
548 FRAME_PARAM_FACES; we can free them without fuss. */
549 xfree (FRAME_COMPUTED_FACES (f
));
550 FRAME_COMPUTED_FACES (f
) = 0;
551 FRAME_N_COMPUTED_FACES (f
) = 0;
556 /* Interning faces in a frame's face array. */
559 new_computed_face (f
, new_face
)
561 struct face
*new_face
;
563 int i
= FRAME_N_COMPUTED_FACES (f
);
565 if (i
>= FRAME_SIZE_COMPUTED_FACES (f
))
567 int new_size
= i
+ 32;
569 FRAME_COMPUTED_FACES (f
)
571 (FRAME_SIZE_COMPUTED_FACES (f
) == 0
572 ? xmalloc (new_size
* sizeof (struct face
*))
573 : xrealloc (FRAME_COMPUTED_FACES (f
),
574 new_size
* sizeof (struct face
*)));
575 FRAME_SIZE_COMPUTED_FACES (f
) = new_size
;
578 i
= FRAME_N_COMPUTED_FACES (f
)++;
579 FRAME_COMPUTED_FACES (f
)[i
] = copy_face (new_face
);
584 /* Find a match for NEW_FACE in a FRAME's computed face array, and add
585 it if we don't find one. */
587 intern_computed_face (f
, new_face
)
589 struct face
*new_face
;
591 int len
= FRAME_N_COMPUTED_FACES (f
);
594 /* Search for a computed face already on F equivalent to FACE. */
595 for (i
= 0; i
< len
; i
++)
597 if (! FRAME_COMPUTED_FACES (f
)[i
])
599 if (face_eql (new_face
, FRAME_COMPUTED_FACES (f
)[i
]))
603 /* We didn't find one; add a new one. */
604 return new_computed_face (f
, new_face
);
607 /* Make parameter face id ID valid on frame F. */
610 ensure_face_ready (f
, id
)
614 if (FRAME_N_PARAM_FACES (f
) <= id
)
618 if (!FRAME_N_PARAM_FACES (f
))
619 FRAME_PARAM_FACES (f
)
620 = (struct face
**) xmalloc (sizeof (struct face
*) * n
);
622 FRAME_PARAM_FACES (f
)
623 = (struct face
**) xrealloc (FRAME_PARAM_FACES (f
),
624 sizeof (struct face
*) * n
);
626 bzero (FRAME_PARAM_FACES (f
) + FRAME_N_PARAM_FACES (f
),
627 (n
- FRAME_N_PARAM_FACES (f
)) * sizeof (struct face
*));
628 FRAME_N_PARAM_FACES (f
) = n
;
631 if (FRAME_PARAM_FACES (f
) [id
] == 0)
632 FRAME_PARAM_FACES (f
) [id
] = allocate_face ();
635 /* Computing faces appropriate for a given piece of text in a buffer. */
637 /* Return non-zero if FONT1 and FONT2 have the same size bounding box.
638 We assume that they're both character-cell fonts. */
640 same_size_fonts (font1
, font2
)
641 XFontStruct
*font1
, *font2
;
643 XCharStruct
*bounds1
= &font1
->min_bounds
;
644 XCharStruct
*bounds2
= &font2
->min_bounds
;
646 return (bounds1
->width
== bounds2
->width
);
647 /* Checking the following caused bad results in some cases
648 when fonts that should be the same size
649 actually have very slightly different size.
650 It is possible that this reintroduces the bug whereby line positions
651 were not right. However, the right way to fix that is to change xterm.c
652 so that the vertical positions of lines
653 depend only on the height of the frame's font.
654 && bounds1->ascent == bounds2->ascent
655 && bounds1->descent == bounds2->descent); */
658 /* Modify face TO by copying from FROM all properties which have
659 nondefault settings. */
661 merge_faces (from
, to
)
662 struct face
*from
, *to
;
664 /* Only merge the font if it's the same size as the base font. */
665 if (from
->font
!= (XFontStruct
*) FACE_DEFAULT
666 && same_size_fonts (from
->font
, to
->font
))
667 to
->font
= from
->font
;
668 if (from
->foreground
!= FACE_DEFAULT
)
669 to
->foreground
= from
->foreground
;
670 if (from
->background
!= FACE_DEFAULT
)
671 to
->background
= from
->background
;
672 if (from
->stipple
!= FACE_DEFAULT
)
673 to
->stipple
= from
->stipple
;
675 to
->underline
= from
->underline
;
678 /* Set up the basic set of facial parameters, based on the frame's
679 data; all faces are deltas applied to this. */
681 compute_base_face (f
, face
)
685 struct x_display
*d
= f
->display
.x
;
688 face
->foreground
= d
->foreground_pixel
;
689 face
->background
= d
->background_pixel
;
690 face
->font
= d
->font
;
694 /* Avoid a face comparison by making this invalid. */
695 face
->cached_index
= -1;
707 sort_overlays (s1
, s2
)
708 struct sortvec
*s1
, *s2
;
710 if (s1
->priority
!= s2
->priority
)
711 return s1
->priority
- s2
->priority
;
712 if (s1
->beg
!= s2
->beg
)
713 return s1
->beg
- s2
->beg
;
714 if (s1
->end
!= s2
->end
)
715 return s2
->end
- s1
->end
;
719 /* Return the face ID associated with a buffer position POS.
720 Store into *ENDPTR the position at which a different face is needed.
721 This does not take account of glyphs that specify their own face codes.
722 F is the frame in use for display, and W is a window displaying
725 REGION_BEG, REGION_END delimit the region, so it can be highlighted. */
728 compute_char_face (f
, w
, pos
, region_beg
, region_end
, endptr
)
732 int region_beg
, region_end
;
736 Lisp_Object prop
, position
;
739 Lisp_Object
*overlay_vec
;
740 struct sortvec
*sortvec
;
744 /* W must display the current buffer. We could write this function
745 to use the frame and buffer of W, but right now it doesn't. */
746 if (XBUFFER (w
->buffer
) != current_buffer
)
749 XSET (frame
, Lisp_Frame
, f
);
752 if (pos
< region_beg
&& region_beg
< endpos
)
755 XFASTINT (position
) = pos
;
756 prop
= Fget_text_property (position
, Qface
, w
->buffer
);
760 end
= Fnext_single_property_change (position
, Qface
, w
->buffer
);
769 /* First try with room for 40 overlays. */
771 overlay_vec
= (Lisp_Object
*) alloca (len
* sizeof (Lisp_Object
));
773 noverlays
= overlays_at (pos
, 0, &overlay_vec
, &len
, &next_overlay
);
775 /* If there are more than 40,
776 make enough space for all, and try again. */
780 overlay_vec
= (Lisp_Object
*) alloca (len
* sizeof (Lisp_Object
));
781 noverlays
= overlays_at (pos
, 0, &overlay_vec
, &len
, &next_overlay
);
784 if (next_overlay
< endpos
)
785 endpos
= next_overlay
;
790 /* Optimize the default case. */
791 if (noverlays
== 0 && NILP (prop
)
792 && !(pos
>= region_beg
&& pos
< region_end
))
795 compute_base_face (f
, &face
);
799 facecode
= face_name_id_number (f
, prop
);
800 if (facecode
>= 0 && facecode
< FRAME_N_PARAM_FACES (f
)
801 && FRAME_PARAM_FACES (f
) [facecode
] != 0)
802 merge_faces (FRAME_PARAM_FACES (f
) [facecode
], &face
);
805 /* Put the valid and relevant overlays into sortvec. */
806 sortvec
= (struct sortvec
*) alloca (noverlays
* sizeof (struct sortvec
));
808 for (i
= 0, j
= 0; i
< noverlays
; i
++)
810 Lisp_Object overlay
= overlay_vec
[i
];
812 if (OVERLAY_VALID (overlay
)
813 && OVERLAY_POSITION (OVERLAY_START (overlay
)) > 0
814 && OVERLAY_POSITION (OVERLAY_END (overlay
)) > 0)
817 window
= Foverlay_get (overlay
, Qwindow
);
819 /* Also ignore overlays limited to one window
820 if it's not the window we are using. */
821 if (XTYPE (window
) != Lisp_Window
822 || XWINDOW (window
) == w
)
826 /* This overlay is good and counts:
827 put it in sortvec. */
828 sortvec
[j
].overlay
= overlay
;
829 sortvec
[j
].beg
= OVERLAY_POSITION (OVERLAY_START (overlay
));
830 sortvec
[j
].end
= OVERLAY_POSITION (OVERLAY_END (overlay
));
831 tem
= Foverlay_get (overlay
, Qpriority
);
833 sortvec
[j
].priority
= XINT (tem
);
835 sortvec
[j
].priority
= 0;
842 /* Sort the overlays into the proper order: increasing priority. */
845 qsort (sortvec
, noverlays
, sizeof (struct sortvec
), sort_overlays
);
847 /* Now merge the overlay data in that order. */
848 for (i
= 0; i
< noverlays
; i
++)
850 prop
= Foverlay_get (sortvec
[i
].overlay
, Qface
);
856 facecode
= face_name_id_number (f
, prop
);
857 if (facecode
>= 0 && facecode
< FRAME_N_PARAM_FACES (f
)
858 && FRAME_PARAM_FACES (f
) [facecode
] != 0)
859 merge_faces (FRAME_PARAM_FACES (f
) [facecode
], &face
);
861 oend
= OVERLAY_END (sortvec
[i
].overlay
);
862 oendpos
= OVERLAY_POSITION (oend
);
863 if (oendpos
< endpos
)
868 if (pos
>= region_beg
&& pos
< region_end
)
870 if (region_end
< endpos
)
872 if (region_face
>= 0 && region_face
< next_face_id
)
873 merge_faces (FRAME_PARAM_FACES (f
) [region_face
], &face
);
878 return intern_computed_face (f
, &face
);
881 /* Return the face ID to use to display a special glyph which selects
882 FACE_CODE as the face ID, assuming that ordinarily the face would
883 be BASIC_FACE. F is the frame. */
885 compute_glyph_face (f
, face_code
)
891 compute_base_face (f
, &face
);
893 if (face_code
>= 0 && face_code
< FRAME_N_PARAM_FACES (f
)
894 && FRAME_PARAM_FACES (f
) [face_code
] != 0)
895 merge_faces (FRAME_PARAM_FACES (f
) [face_code
], &face
);
897 return intern_computed_face (f
, &face
);
901 /* Recompute the GC's for the default and modeline faces.
902 We call this after changing frame parameters on which those GC's
905 recompute_basic_faces (f
)
908 /* If the frame's faces haven't been initialized yet, don't worry about
910 if (FRAME_N_PARAM_FACES (f
) < 2)
915 if (FRAME_DEFAULT_FACE (f
)->gc
)
916 XFreeGC (x_current_display
, FRAME_DEFAULT_FACE (f
)->gc
);
917 if (FRAME_MODE_LINE_FACE (f
)->gc
)
918 XFreeGC (x_current_display
, FRAME_MODE_LINE_FACE (f
)->gc
);
920 compute_base_face (f
, FRAME_DEFAULT_FACE (f
));
921 compute_base_face (f
, FRAME_MODE_LINE_FACE (f
));
923 merge_faces (FRAME_DEFAULT_PARAM_FACE (f
), FRAME_DEFAULT_FACE (f
));
924 merge_faces (FRAME_MODE_LINE_PARAM_FACE (f
), FRAME_MODE_LINE_FACE (f
));
926 build_face (f
, FRAME_DEFAULT_FACE (f
));
927 build_face (f
, FRAME_MODE_LINE_FACE (f
));
934 /* Lisp interface. */
936 DEFUN ("frame-face-alist", Fframe_face_alist
, Sframe_face_alist
, 1, 1, 0,
941 CHECK_FRAME (frame
, 0);
942 return XFRAME (frame
)->face_alist
;
945 DEFUN ("set-frame-face-alist", Fset_frame_face_alist
, Sset_frame_face_alist
,
948 Lisp_Object frame
, value
;
950 CHECK_FRAME (frame
, 0);
951 XFRAME (frame
)->face_alist
= value
;
956 DEFUN ("make-face-internal", Fmake_face_internal
, Smake_face_internal
, 1, 1, 0,
957 "Create face number FACE-ID on all frames.")
962 int id
= XINT (face_id
);
964 CHECK_NUMBER (face_id
, 0);
965 if (id
< 0 || id
>= next_face_id
)
966 error ("Face id out of range");
968 for (rest
= Vframe_list
; !NILP (rest
); rest
= XCONS (rest
)->cdr
)
970 struct frame
*f
= XFRAME (XCONS (rest
)->car
);
972 ensure_face_ready (f
, id
);
978 DEFUN ("set-face-attribute-internal", Fset_face_attribute_internal
,
979 Sset_face_attribute_internal
, 4, 4, 0, "")
980 (face_id
, attr_name
, attr_value
, frame
)
981 Lisp_Object face_id
, attr_name
, attr_value
, frame
;
988 CHECK_FRAME (frame
, 0);
989 CHECK_NUMBER (face_id
, 0);
990 CHECK_SYMBOL (attr_name
, 0);
994 if (id
< 0 || id
>= next_face_id
)
995 error ("Face id out of range");
1000 ensure_face_ready (f
, id
);
1001 face
= FRAME_PARAM_FACES (f
) [XFASTINT (face_id
)];
1003 if (EQ (attr_name
, intern ("font")))
1005 XFontStruct
*font
= load_font (f
, attr_value
);
1006 if (face
->font
!= f
->display
.x
->font
)
1007 unload_font (f
, face
->font
);
1010 else if (EQ (attr_name
, intern ("foreground")))
1012 unsigned long new_color
= load_color (f
, attr_value
);
1013 unload_color (f
, face
->foreground
);
1014 face
->foreground
= new_color
;
1016 else if (EQ (attr_name
, intern ("background")))
1018 unsigned long new_color
= load_color (f
, attr_value
);
1019 unload_color (f
, face
->background
);
1020 face
->background
= new_color
;
1023 else if (EQ (attr_name
, intern ("background-pixmap")))
1025 unsigned int w
, h
, d
;
1026 unsigned long new_pixmap
= load_pixmap (f
, attr_value
, &w
, &h
, &d
, 0);
1027 unload_pixmap (f
, face
->stipple
);
1028 if (NILP (attr_value
))
1030 face
->stipple
= new_pixmap
;
1033 /* face->pixmap_depth = d; */
1036 else if (EQ (attr_name
, intern ("underline")))
1038 int new = !NILP (attr_value
);
1039 face
->underline
= new;
1042 error ("unknown face attribute");
1044 if (id
== 0 || id
== 1)
1045 recompute_basic_faces (f
);
1047 /* If we're modifying either of the frame's display faces, that
1048 means that we're changing the parameters of a fixed face code;
1049 since the color/font/whatever is changed but the face ID hasn't,
1050 redisplay won't know to redraw the affected sections. Give it a
1052 if (id
== 0 || id
== 1)
1053 SET_FRAME_GARBAGED (f
);
1055 /* Otherwise, it's enough to tell it to redisplay the text. */
1056 windows_or_buffers_changed
= 1;
1061 DEFUN ("internal-next-face-id", Finternal_next_face_id
, Sinternal_next_face_id
,
1065 return make_number (next_face_id
++);
1068 /* Return the face id for name NAME on frame FRAME.
1069 (It should be the same for all frames,
1070 but it's as easy to use the "right" frame to look it up
1071 as to use any other one.) */
1074 face_name_id_number (f
, name
)
1080 tem
= Fcdr (Fassq (name
, f
->face_alist
));
1083 CHECK_VECTOR (tem
, 0);
1084 tem
= XVECTOR (tem
)->contents
[2];
1085 CHECK_NUMBER (tem
, 0);
1089 /* Emacs initialization. */
1094 Qwindow
= intern ("window");
1095 staticpro (&Qwindow
);
1096 Qface
= intern ("face");
1098 Qpriority
= intern ("priority");
1099 staticpro (&Qpriority
);
1101 DEFVAR_INT ("region-face", ®ion_face
,
1102 "Face number to use to highlight the region\n\
1103 The region is highlighted with this face\n\
1104 when Transient Mark mode is enabled and the mark is active.");
1106 defsubr (&Sframe_face_alist
);
1107 defsubr (&Sset_frame_face_alist
);
1108 defsubr (&Smake_face_internal
);
1109 defsubr (&Sset_face_attribute_internal
);
1110 defsubr (&Sinternal_next_face_id
);
1113 #endif /* HAVE_X_WINDOWS */