]> code.delx.au - gnu-emacs/blob - src/xfaces.c
5638ed65d5f587d0bbda16f0af54c1854cd55cc5
[gnu-emacs] / src / xfaces.c
1 /* "Face" primitives.
2 Copyright (C) 1993 Free Software Foundation.
3
4 This file is part of GNU Emacs.
5
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)
9 any later version.
10
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.
15
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. */
19
20 /* This is derived from work by Lucid (some parts very loosely so). */
21
22 #include <sys/types.h>
23 #include <sys/stat.h>
24
25 #include "config.h"
26 #include "lisp.h"
27
28 #ifdef HAVE_X_WINDOWS
29
30 #include "xterm.h"
31 #include "buffer.h"
32 #include "dispextern.h"
33 #include "frame.h"
34 #include "blockinput.h"
35 #include "window.h"
36
37 /* Display Context for the icons */
38 #include <X11/Intrinsic.h>
39 #include <X11/StringDefs.h>
40 /* #include <X11/Xmu/Drawing.h> */ /* Appears not to be used */
41 #include <X11/Xos.h>
42
43 \f
44 /* An explanation of the face data structures. */
45
46 /* ========================= Face Data Structures =========================
47
48 All lisp code uses symbols as face names.
49
50 Each frame has a face_alist member (with the frame-face-alist and
51 set-frame-face-alist accessors), associating the face names with
52 vectors of the form
53 [face NAME ID FONT FOREGROUND BACKGROUND BACKGROUND-PIXMAP UNDERLINE-P]
54 where
55 face is the symbol `face',
56 NAME is the symbol with which this vector is associated (a backpointer),
57 ID is the face ID, an integer used internally by the C code to identify
58 the face,
59 FONT, FOREGROUND, and BACKGROUND are strings naming the fonts and colors
60 to use with the face,
61 BACKGROUND-PIXMAP is the name of an x bitmap filename, which we don't
62 use right now, and
63 UNDERLINE-P is non-nil if the face should be underlined.
64 (lisp/faces.el maintains these association lists.)
65
66 The frames' private alists hold the frame-local definitions for the
67 faces. The lisp variable global-face-data contains the global
68 defaults for faces. (See lisp/faces.el for this too.)
69
70 In the C code, we also have a `struct face' with the elements
71 `foreground', `background', `font', and `underline',
72 which specify its visual appearance, and elements
73 `gc' and `cached_index';
74 `gc' may be an X GC which has been built for the given display
75 parameters. Faces with GC's are called `display faces'. Whether
76 or not a face has a GC depends on what data structure the face is
77 in; we explain these more below. (See src/dispextern.h.)
78
79 Each frame also has members called `faces' and `n_faces' (with the
80 accessors FRAME_FACES and FRAME_N_FACES), which define an array of
81 struct face pointers, indexed by face ID (element 2 of the
82 vector). These are called "frame faces".
83 Element 0 is the default face --- the one used for normal text.
84 Element 1 is the modeline face.
85 These faces have their GC's set; the rest do not. (See src/xterm.h.)
86
87 The global variables `face_vector' and `nfaces' define another
88 array of struct face pointers, with their GC's set. This array
89 acts as a cache of GC's to be used by all frames. The function
90 `intern_face', passed a struct face *, searches face_vector for a
91 struct face with the same parameters, adds a new one with a GC if
92 it doesn't find one, and returns it. If you have a `struct face',
93 and you want a GC for it, call intern_face on that struct, and it
94 will return a `struct face *' with its GC set. The faces in
95 face_vector are called `cached faces.' (See src/xfaces.c.)
96
97 The `GLYPH' data type is an unsigned integer type; the bottom byte
98 is a character code, and the byte above that is a face id. The
99 `struct frame_glyphs' structure, used to describe frames' current
100 or desired contents, is essentially a matrix of GLYPHs; the face
101 ID's in a struct frame_glyphs are indices into FRAME_FACES. (See
102 src/dispextern.h.)
103
104 Some subtleties:
105
106 Since face_vector is just a cache --- there are no pointers into it
107 from the rest of the code, and everyone accesses it through
108 intern_face --- we could just free its GC's and throw the whole
109 thing away without breaking anything. This gives us a simple way
110 to garbage-collect old GC's nobody's using any more - we can just
111 purge face_vector, and then let subsequent calls to intern_face
112 refill it as needed. The function clear_face_vector performs this
113 purge.
114
115 We're often applying intern_face to faces in frames' local arrays -
116 for example, we do this while sending GLYPHs from a struct
117 frame_glyphs to X during redisplay. It would be nice to avoid
118 searching all of face_vector every time we intern a frame's face.
119 So, when intern_face finds a match for FACE in face_vector, it
120 stores the index of the match in FACE's cached_index member, and
121 checks there first next time. */
122
123 \f
124 /* Definitions and declarations. */
125
126 /* A table of display faces. */
127 struct face **face_vector;
128 /* The length in use of the table. */
129 int nfaces;
130 /* The allocated length of the table. */
131 int nfaces_allocated;
132
133 /* The number of face-id's in use (same for all frames). */
134 int next_face_id;
135
136 /* The number of the face to use to indicate the region. */
137 int region_face;
138
139 /* This is what appears in a slot in a face to signify that the face
140 does not specify that display aspect. */
141 #define FACE_DEFAULT (~0)
142
143 Lisp_Object Qface, Qwindow, Qpriority;
144
145 static void build_face ();
146 static Lisp_Object face_name_id_number ();
147
148 struct face *intern_face ();
149 static void ensure_face_ready ();
150 \f
151 /* Allocating, copying, and comparing struct faces. */
152
153 /* Allocate a new face */
154 static struct face *
155 allocate_face ()
156 {
157 struct face *result = (struct face *) xmalloc (sizeof (struct face));
158 bzero (result, sizeof (struct face));
159 result->font = (XFontStruct *) FACE_DEFAULT;
160 result->foreground = FACE_DEFAULT;
161 result->background = FACE_DEFAULT;
162 result->stipple = FACE_DEFAULT;
163 return result;
164 }
165
166 /* Make a new face that's a copy of an existing one. */
167 static struct face *
168 copy_face (face)
169 struct face *face;
170 {
171 struct face *result = allocate_face ();
172
173 result->font = face->font;
174 result->foreground = face->foreground;
175 result->background = face->background;
176 result->stipple = face->stipple;
177 result->underline = face->underline;
178
179 return result;
180 }
181
182 static int
183 face_eql (face1, face2)
184 struct face *face1, *face2;
185 {
186 return ( face1->font == face2->font
187 && face1->foreground == face2->foreground
188 && face1->background == face2->background
189 && face1->stipple == face2->stipple
190 && face1->underline == face2->underline);
191 }
192 \f
193 /* Interning faces in the `face_vector' cache, and clearing that cache. */
194
195 /* Return the unique display face corresponding to the user-level face FACE.
196 If there isn't one, make one, and find a slot in the face_vector to
197 put it in. */
198 static struct face *
199 get_cached_face (f, face)
200 struct frame *f;
201 struct face *face;
202 {
203 int i, empty = -1;
204 struct face *result;
205
206 /* Perhaps FACE->cached_index is valid; this could happen if FACE is
207 in a frame's face list. */
208 if (face->cached_index >= 0
209 && face->cached_index < nfaces
210 && face_eql (face_vector[face->cached_index], face))
211 return face_vector[face->cached_index];
212
213 /* Look for an existing display face that does the job.
214 Also find an empty slot if any. */
215 for (i = 0; i < nfaces; i++)
216 {
217 if (face_eql (face_vector[i], face))
218 return face_vector[i];
219 if (face_vector[i] == 0)
220 empty = i;
221 }
222
223 /* If no empty slots, make one. */
224 if (empty < 0 && nfaces == nfaces_allocated)
225 {
226 int newsize = nfaces + 20;
227 face_vector
228 = (struct face **) xrealloc (face_vector,
229 newsize * sizeof (struct face *));
230 nfaces_allocated = newsize;
231 }
232
233 if (empty < 0)
234 empty = nfaces++;
235
236 /* Put a new display face in the empty slot. */
237 result = copy_face (face);
238 face_vector[empty] = result;
239
240 /* Make a graphics context for it. */
241 build_face (f, result);
242
243 return result;
244 }
245
246 /* Given a frame face, return an equivalent display face
247 (one which has a graphics context). */
248
249 struct face *
250 intern_face (f, face)
251 struct frame *f;
252 struct face *face;
253 {
254 /* If it's equivalent to the default face, use that. */
255 if (face_eql (face, FRAME_DEFAULT_FACE (f)))
256 {
257 if (!FRAME_DEFAULT_FACE (f)->gc)
258 build_face (f, FRAME_DEFAULT_FACE (f));
259 return FRAME_DEFAULT_FACE (f);
260 }
261
262 /* If it's equivalent to the mode line face, use that. */
263 if (face_eql (face, FRAME_MODE_LINE_FACE (f)))
264 {
265 if (!FRAME_MODE_LINE_FACE (f)->gc)
266 build_face (f, FRAME_MODE_LINE_FACE (f));
267 return FRAME_MODE_LINE_FACE (f);
268 }
269
270 /* If it's not one of the frame's default faces, it shouldn't have a GC. */
271 if (face->gc)
272 abort ();
273
274 /* Get a specialized display face. */
275 return get_cached_face (f, face);
276 }
277
278 /* Clear out face_vector and start anew.
279 This should be done from time to time just to avoid
280 keeping too many graphics contexts in face_vector
281 that are no longer needed. */
282
283 void
284 clear_face_vector ()
285 {
286 Lisp_Object rest;
287 Display *dpy = x_current_display;
288 int i;
289
290 BLOCK_INPUT;
291 /* Free the display faces in the face_vector. */
292 for (i = 0; i < nfaces; i++)
293 {
294 struct face *face = face_vector[i];
295 if (face->gc)
296 XFreeGC (dpy, face->gc);
297 xfree (face);
298 }
299 nfaces = 0;
300
301 UNBLOCK_INPUT;
302 }
303 \f
304 /* Allocating and freeing X resources for display faces. */
305
306 /* Make a graphics context for face FACE, which is on frame F,
307 if that can be done. */
308 static void
309 build_face (f, face)
310 struct frame *f;
311 struct face *face;
312 {
313 GC gc;
314 XGCValues xgcv;
315 unsigned long mask;
316
317 if (face->foreground != FACE_DEFAULT)
318 xgcv.foreground = face->foreground;
319 else
320 xgcv. foreground = f->display.x->foreground_pixel;
321 if (face->background != FACE_DEFAULT)
322 xgcv.background = face->background;
323 else
324 xgcv. background = f->display.x->background_pixel;
325 if (face->font && (int) face->font != FACE_DEFAULT)
326 xgcv.font = face->font->fid;
327 else
328 xgcv.font = f->display.x->font->fid;
329 xgcv.graphics_exposures = 0;
330 mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;
331 gc = XCreateGC (x_current_display, FRAME_X_WINDOW (f),
332 mask, &xgcv);
333 #if 0
334 if (face->stipple && face->stipple != FACE_DEFAULT)
335 XSetStipple (x_current_display, gc, face->stipple);
336 #endif
337 face->gc = gc;
338 }
339
340 /* Allocating, freeing, and duplicating fonts, colors, and pixmaps. */
341
342 static XFontStruct *
343 load_font (f, name)
344 struct frame *f;
345 Lisp_Object name;
346 {
347 XFontStruct *font;
348
349 if (NILP (name))
350 return (XFontStruct *) FACE_DEFAULT;
351
352 CHECK_STRING (name, 0);
353 BLOCK_INPUT;
354 font = XLoadQueryFont (x_current_display, (char *) XSTRING (name)->data);
355 UNBLOCK_INPUT;
356
357 if (! font)
358 Fsignal (Qerror, Fcons (build_string ("undefined font"),
359 Fcons (name, Qnil)));
360 return font;
361 }
362
363 static void
364 unload_font (f, font)
365 struct frame *f;
366 XFontStruct *font;
367 {
368 if (!font || font == ((XFontStruct *) FACE_DEFAULT))
369 return;
370 XFreeFont (x_current_display, font);
371 }
372
373 static unsigned long
374 load_color (f, name)
375 struct frame *f;
376 Lisp_Object name;
377 {
378 Display *dpy = x_current_display;
379 Colormap cmap;
380 XColor color;
381 int result;
382
383 if (NILP (name))
384 return FACE_DEFAULT;
385
386 cmap = DefaultColormapOfScreen (DefaultScreenOfDisplay (x_current_display));
387
388 CHECK_STRING (name, 0);
389 BLOCK_INPUT;
390 result = XParseColor (dpy, cmap, (char *) XSTRING (name)->data, &color);
391 UNBLOCK_INPUT;
392 if (! result)
393 Fsignal (Qerror, Fcons (build_string ("undefined color"),
394 Fcons (name, Qnil)));
395 BLOCK_INPUT;
396 result = XAllocColor (dpy, cmap, &color);
397 UNBLOCK_INPUT;
398 if (! result)
399 Fsignal (Qerror, Fcons (build_string ("X server cannot allocate color"),
400 Fcons (name, Qnil)));
401 return (unsigned long) color.pixel;
402 }
403
404 static void
405 unload_color (f, pixel)
406 struct frame *f;
407 Pixel pixel;
408 {
409 Colormap cmap;
410 Display *dpy = x_current_display;
411 if (pixel == FACE_DEFAULT
412 || pixel == BLACK_PIX_DEFAULT
413 || pixel == WHITE_PIX_DEFAULT)
414 return;
415 cmap = DefaultColormapOfScreen (DefaultScreenOfDisplay (x_current_display));
416 BLOCK_INPUT;
417 XFreeColors (dpy, cmap, &pixel, 1, 0);
418 UNBLOCK_INPUT;
419 }
420 \f
421 /* Initializing face arrays for frames. */
422
423 /* Set up faces 0 and 1 based on the normal text and modeline GC's.
424 This gets called whenever the parameters stored in the frame itself
425 (i.e. font, background color, etcetera) change.
426
427 Note that the first two faces just contain references to the
428 frame's own resources. We shouldn't free them. */
429 void
430 init_frame_faces (f)
431 struct frame *f;
432 {
433 ensure_face_ready (f, 0);
434 {
435 XGCValues gcv;
436 struct face *face = FRAME_FACES (f) [0];
437
438 XGetGCValues (x_current_display, f->display.x->normal_gc,
439 GCForeground | GCBackground | GCFont, &gcv);
440 face->gc = f->display.x->normal_gc;
441 face->foreground = gcv.foreground;
442 face->background = gcv.background;
443 face->font = f->display.x->font;
444 face->stipple = 0;
445 face->underline = 0;
446 }
447
448 ensure_face_ready (f, 1);
449 {
450 XGCValues gcv;
451 struct face *face = FRAME_FACES (f) [1];
452
453 XGetGCValues (x_current_display, f->display.x->reverse_gc,
454 GCForeground | GCBackground | GCFont, &gcv);
455 face->gc = f->display.x->reverse_gc;
456 face->foreground = gcv.foreground;
457 face->background = gcv.background;
458 face->font = f->display.x->font;
459 face->stipple = 0;
460 face->underline = 0;
461 }
462 }
463
464 /* Called from Fdelete_frame. */
465 void
466 free_frame_faces (f)
467 struct frame *f;
468 {
469 Display *dpy = x_current_display;
470 int i;
471
472 /* The first two faces on the frame are just made of resources which
473 we borrowed from the frame's GC's, so don't free them. Let
474 them get freed by the x_destroy_window code. */
475 for (i = 2; i < FRAME_N_FACES (f); i++)
476 {
477 struct face *face = FRAME_FACES (f) [i];
478 if (! face)
479 continue;
480 if (face->gc)
481 XFreeGC (dpy, face->gc);
482 unload_font (f, face->font);
483 unload_color (f, face->foreground);
484 unload_color (f, face->background);
485 #if 0
486 unload_pixmap (f, face->stipple);
487 #endif
488 xfree (face);
489 }
490 xfree (FRAME_FACES (f));
491 FRAME_FACES (f) = 0;
492 FRAME_N_FACES (f) = 0;
493 }
494 \f
495 /* Interning faces in a frame's face array. */
496
497 /* Find a match for NEW_FACE in a FRAME's face array, and add it if we don't
498 find one. */
499 int
500 intern_frame_face (frame, new_face)
501 struct frame *frame;
502 struct face *new_face;
503 {
504 int len = FRAME_N_FACES (frame);
505 int i;
506
507 /* Search for a face already on FRAME equivalent to FACE. */
508 for (i = 0; i < len; i++)
509 {
510 struct face *frame_face = FRAME_FACES (frame)[i];
511
512 if (frame_face && face_eql (new_face, frame_face))
513 return i;
514 }
515
516 /* We didn't find one; add a new one. */
517 i = next_face_id++;
518
519 ensure_face_ready (frame, i);
520 bcopy (new_face, FRAME_FACES (frame)[i], sizeof (*new_face));
521
522 return i;
523 }
524
525 /* Make face id ID valid on frame F. */
526
527 static void
528 ensure_face_ready (f, id)
529 struct frame *f;
530 int id;
531 {
532 if (FRAME_N_FACES (f) <= id)
533 {
534 int n = id + 10;
535 int i;
536 if (!FRAME_N_FACES (f))
537 FRAME_FACES (f)
538 = (struct face **) xmalloc (sizeof (struct face *) * n);
539 else
540 FRAME_FACES (f)
541 = (struct face **) xrealloc (FRAME_FACES (f),
542 sizeof (struct face *) * n);
543
544 bzero (FRAME_FACES (f) + FRAME_N_FACES (f),
545 (n - FRAME_N_FACES (f)) * sizeof (struct face *));
546 FRAME_N_FACES (f) = n;
547 }
548
549 if (FRAME_FACES (f) [id] == 0)
550 FRAME_FACES (f) [id] = allocate_face ();
551 }
552 \f
553 /* Computing faces appropriate for a given piece of text in a buffer. */
554
555 /* Return non-zero if FONT1 and FONT2 have the same size bounding box.
556 We assume that they're both character-cell fonts. */
557 static int
558 same_size_fonts (font1, font2)
559 XFontStruct *font1, *font2;
560 {
561 XCharStruct *bounds1 = &font1->min_bounds;
562 XCharStruct *bounds2 = &font2->min_bounds;
563
564 return (bounds1->width == bounds2->width
565 && bounds1->ascent == bounds2->ascent
566 && bounds1->descent == bounds2->descent);
567 }
568
569
570 /* Modify face TO by copying from FROM all properties which have
571 nondefault settings. */
572 static void
573 merge_faces (from, to)
574 struct face *from, *to;
575 {
576 /* Only merge the font if it's the same size as the base font. */
577 if (from->font != (XFontStruct *) FACE_DEFAULT
578 && ! from->font->per_char
579 && same_size_fonts (from->font, to->font))
580 to->font = from->font;
581 if (from->foreground != FACE_DEFAULT)
582 to->foreground = from->foreground;
583 if (from->background != FACE_DEFAULT)
584 to->background = from->background;
585 if (from->stipple != FACE_DEFAULT)
586 to->stipple = from->stipple;
587 if (from->underline)
588 to->underline = from->underline;
589 }
590
591 struct sortvec
592 {
593 Lisp_Object overlay;
594 int beg, end;
595 int priority;
596 };
597
598 static int
599 sort_overlays (s1, s2)
600 struct sortvec *s1, *s2;
601 {
602 if (s1->priority != s2->priority)
603 return s1->priority - s2->priority;
604 if (s1->beg != s2->beg)
605 return s1->beg - s2->beg;
606 if (s1->end != s2->end)
607 return s2->end - s1->end;
608 return 0;
609 }
610
611 /* Return the face ID associated with a buffer position POS.
612 Store into *ENDPTR the position at which a different face is needed.
613 This does not take account of glyphs that specify their own face codes.
614 F is the frame in use for display, and W is a window displaying
615 the current buffer.
616
617 REGION_BEG, REGION_END delimit the region, so it can be highlighted. */
618
619 int
620 compute_char_face (f, w, pos, region_beg, region_end, endptr)
621 struct frame *f;
622 struct window *w;
623 int pos;
624 int region_beg, region_end;
625 int *endptr;
626 {
627 struct face face;
628 Lisp_Object prop, position;
629 int i, j, noverlays;
630 int facecode;
631 Lisp_Object *overlay_vec;
632 struct sortvec *sortvec;
633 Lisp_Object frame;
634 int endpos;
635
636 /* W must display the current buffer. We could write this function
637 to use the frame and buffer of W, but right now it doesn't. */
638 if (XBUFFER (w->buffer) != current_buffer)
639 abort ();
640
641 XSET (frame, Lisp_Frame, f);
642
643 endpos = ZV;
644 if (pos < region_beg && region_beg < endpos)
645 endpos = region_beg;
646
647 XFASTINT (position) = pos;
648 prop = Fget_text_property (position, Qface, w->buffer);
649 {
650 Lisp_Object end;
651
652 end = Fnext_single_property_change (position, Qface, w->buffer);
653 if (INTEGERP (end))
654 endpos = XINT (end);
655 }
656
657 {
658 int next_overlay;
659 int len;
660
661 /* First try with room for 40 overlays. */
662 len = 40;
663 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
664
665 noverlays = overlays_at (pos, 0, &overlay_vec, &len, &next_overlay);
666
667 /* If there are more than 40,
668 make enough space for all, and try again. */
669 if (noverlays > len)
670 {
671 len = noverlays;
672 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
673 noverlays = overlays_at (pos, 0, &overlay_vec, &len, &next_overlay);
674 }
675
676 if (next_overlay < endpos)
677 endpos = next_overlay;
678 }
679
680 *endptr = endpos;
681
682 /* Optimize the default case. */
683 if (noverlays == 0 && NILP (prop)
684 && !(pos >= region_beg && pos < region_end))
685 return 0;
686
687 bcopy (FRAME_DEFAULT_FACE (f), &face, sizeof (struct face));
688 face.gc = 0;
689
690 if (!NILP (prop))
691 {
692 facecode = face_name_id_number (frame, prop);
693 if (facecode >= 0 && facecode < FRAME_N_FACES (f)
694 && FRAME_FACES (f) [facecode] != 0)
695 merge_faces (FRAME_FACES (f) [facecode], &face);
696 }
697
698 /* Put the valid and relevant overlays into sortvec. */
699 sortvec = (struct sortvec *) alloca (noverlays * sizeof (struct sortvec));
700
701 for (i = 0, j = 0; i < noverlays; i++)
702 {
703 Lisp_Object overlay = overlay_vec[i];
704
705 if (OVERLAY_VALID (overlay)
706 && OVERLAY_POSITION (OVERLAY_START (overlay)) > 0
707 && OVERLAY_POSITION (OVERLAY_END (overlay)) > 0)
708 {
709 Lisp_Object window;
710 window = Foverlay_get (overlay, Qwindow);
711
712 /* Also ignore overlays limited to one window
713 if it's not the window we are using. */
714 if (XTYPE (window) != Lisp_Window
715 || XWINDOW (window) == w)
716 {
717 Lisp_Object tem;
718
719 /* This overlay is good and counts:
720 put it in sortvec. */
721 sortvec[j].overlay = overlay;
722 sortvec[j].beg = OVERLAY_POSITION (OVERLAY_START (overlay));
723 sortvec[j].end = OVERLAY_POSITION (OVERLAY_END (overlay));
724 tem = Foverlay_get (overlay, Qpriority);
725 if (INTEGERP (tem))
726 sortvec[j].priority = XINT (tem);
727 else
728 sortvec[j].priority = 0;
729 j++;
730 }
731 }
732 }
733 noverlays = j;
734
735 /* Sort the overlays into the proper order: increasing priority. */
736
737 if (noverlays > 1)
738 qsort (sortvec, noverlays, sizeof (struct sortvec), sort_overlays);
739
740 /* Now merge the overlay data in that order. */
741 for (i = 0; i < noverlays; i++)
742 {
743 prop = Foverlay_get (sortvec[i].overlay, Qface);
744 if (!NILP (prop))
745 {
746 Lisp_Object oend;
747 int oendpos;
748
749 facecode = face_name_id_number (frame, prop);
750 if (facecode >= 0 && facecode < FRAME_N_FACES (f)
751 && FRAME_FACES (f) [facecode] != 0)
752 merge_faces (FRAME_FACES (f) [facecode], &face);
753
754 oend = OVERLAY_END (sortvec[i].overlay);
755 oendpos = OVERLAY_POSITION (oend);
756 if (oendpos < endpos)
757 endpos = oendpos;
758 }
759 }
760
761 if (pos >= region_beg && pos < region_end)
762 {
763 if (region_end < endpos)
764 endpos = region_end;
765 if (region_face >= 0 && region_face < next_face_id)
766 merge_faces (FRAME_FACES (f) [region_face], &face);
767 }
768
769 *endptr = endpos;
770
771 return intern_frame_face (f, &face);
772 }
773
774 /* Return the face ID to use to display a special glyph which selects
775 FACE_CODE as the face ID, assuming that ordinarily the face would
776 be BASIC_FACE. F is the frame. */
777 int
778 compute_glyph_face (f, face_code)
779 struct frame *f;
780 int face_code;
781 {
782 struct face face;
783
784 bcopy (FRAME_DEFAULT_FACE (f), &face, sizeof (face));
785 face.gc = 0;
786
787 if (face_code >= 0 && face_code < FRAME_N_FACES (f)
788 && FRAME_FACES (f) [face_code] != 0)
789 merge_faces (FRAME_FACES (f) [face_code], &face);
790
791 return intern_frame_face (f, &face);
792 }
793 \f
794 /* Lisp interface. */
795
796 DEFUN ("frame-face-alist", Fframe_face_alist, Sframe_face_alist, 1, 1, 0,
797 "")
798 (frame)
799 Lisp_Object frame;
800 {
801 CHECK_FRAME (frame, 0);
802 return XFRAME (frame)->face_alist;
803 }
804
805 DEFUN ("set-frame-face-alist", Fset_frame_face_alist, Sset_frame_face_alist,
806 2, 2, 0, "")
807 (frame, value)
808 Lisp_Object frame, value;
809 {
810 CHECK_FRAME (frame, 0);
811 XFRAME (frame)->face_alist = value;
812 return value;
813 }
814
815
816 DEFUN ("make-face-internal", Fmake_face_internal, Smake_face_internal, 1, 1, 0,
817 "Create face number FACE-ID on all frames.")
818 (face_id)
819 Lisp_Object face_id;
820 {
821 Lisp_Object rest;
822 int id = XINT (face_id);
823
824 CHECK_NUMBER (face_id, 0);
825 if (id < 0 || id >= next_face_id)
826 error ("Face id out of range");
827
828 for (rest = Vframe_list; !NILP (rest); rest = XCONS (rest)->cdr)
829 {
830 struct frame *f = XFRAME (XCONS (rest)->car);
831 if (FRAME_X_P (f))
832 ensure_face_ready (f, id);
833 }
834 return Qnil;
835 }
836
837
838 DEFUN ("set-face-attribute-internal", Fset_face_attribute_internal,
839 Sset_face_attribute_internal, 4, 4, 0, "")
840 (face_id, attr_name, attr_value, frame)
841 Lisp_Object face_id, attr_name, attr_value, frame;
842 {
843 struct face *face;
844 struct frame *f;
845 int magic_p;
846 int id;
847
848 CHECK_FRAME (frame, 0);
849 CHECK_NUMBER (face_id, 0);
850 CHECK_SYMBOL (attr_name, 0);
851
852 f = XFRAME (frame);
853 id = XINT (face_id);
854 if (id < 0 || id >= next_face_id)
855 error ("Face id out of range");
856
857 if (! FRAME_X_P (f))
858 return;
859
860 ensure_face_ready (f, id);
861 face = FRAME_FACES (f) [XFASTINT (face_id)];
862
863 if (EQ (attr_name, intern ("font")))
864 {
865 XFontStruct *font = load_font (f, attr_value);
866 unload_font (f, face->font);
867 face->font = font;
868 }
869 else if (EQ (attr_name, intern ("foreground")))
870 {
871 unsigned long new_color = load_color (f, attr_value);
872 unload_color (f, face->foreground);
873 face->foreground = new_color;
874 }
875 else if (EQ (attr_name, intern ("background")))
876 {
877 unsigned long new_color = load_color (f, attr_value);
878 unload_color (f, face->background);
879 face->background = new_color;
880 }
881 #if 0
882 else if (EQ (attr_name, intern ("background-pixmap")))
883 {
884 unsigned int w, h, d;
885 unsigned long new_pixmap = load_pixmap (f, attr_value, &w, &h, &d, 0);
886 unload_pixmap (f, face->stipple);
887 if (NILP (attr_value))
888 new_pixmap = 0;
889 face->stipple = new_pixmap;
890 face->pixmap_w = w;
891 face->pixmap_h = h;
892 /* face->pixmap_depth = d; */
893 }
894 #endif /* 0 */
895 else if (EQ (attr_name, intern ("underline")))
896 {
897 int new = !NILP (attr_value);
898 face->underline = new;
899 }
900 else
901 error ("unknown face attribute");
902
903 if (id == 0)
904 {
905 BLOCK_INPUT;
906 if (FRAME_DEFAULT_FACE (f)->gc != 0)
907 XFreeGC (x_current_display, FRAME_DEFAULT_FACE (f)->gc);
908 build_face (f, FRAME_DEFAULT_FACE (f));
909 UNBLOCK_INPUT;
910 }
911
912 if (id == 1)
913 {
914 BLOCK_INPUT;
915 if (FRAME_MODE_LINE_FACE (f)->gc != 0)
916 XFreeGC (x_current_display, FRAME_MODE_LINE_FACE (f)->gc);
917 build_face (f, FRAME_MODE_LINE_FACE (f));
918 UNBLOCK_INPUT;
919 }
920
921 /* If we're modifying either of the frame's display faces, that
922 means that we're changing the parameters of a fixed face code;
923 since the color/font/whatever is changed but the face ID hasn't,
924 redisplay won't know to redraw the affected sections. Give it a
925 kick. */
926 if (id == 0 || id == 1)
927 SET_FRAME_GARBAGED (f);
928 else
929 /* Otherwise, it's enough to tell it to redisplay the text. */
930 windows_or_buffers_changed = 1;
931
932 return Qnil;
933 }
934
935 DEFUN ("internal-next-face-id", Finternal_next_face_id, Sinternal_next_face_id,
936 0, 0, 0, "")
937 ()
938 {
939 return make_number (next_face_id++);
940 }
941
942 /* Return the face id for name NAME on frame FRAME.
943 (It should be the same for all frames,
944 but it's as easy to use the "right" frame to look it up
945 as to use any other one.) */
946
947 static Lisp_Object
948 face_name_id_number (frame, name)
949 Lisp_Object frame, name;
950 {
951 Lisp_Object tem;
952
953 CHECK_FRAME (frame, 0);
954 tem = Fcdr (Fassq (name, XFRAME (frame)->face_alist));
955 if (NILP (tem))
956 return 0;
957 CHECK_VECTOR (tem, 0);
958 tem = XVECTOR (tem)->contents[2];
959 CHECK_NUMBER (tem, 0);
960 return XINT (tem);
961 }
962 \f
963 /* Emacs initialization. */
964
965 void
966 syms_of_xfaces ()
967 {
968 Qwindow = intern ("window");
969 staticpro (&Qwindow);
970 Qface = intern ("face");
971 staticpro (&Qface);
972 Qpriority = intern ("priority");
973 staticpro (&Qpriority);
974
975 DEFVAR_INT ("region-face", &region_face,
976 "Face number to use to highlight the region\n\
977 The region is highlighted with this face\n\
978 when Transient Mark mode is enabled and the mark is active.");
979
980 defsubr (&Sframe_face_alist);
981 defsubr (&Sset_frame_face_alist);
982 defsubr (&Smake_face_internal);
983 defsubr (&Sset_face_attribute_internal);
984 defsubr (&Sinternal_next_face_id);
985 }
986
987 #endif /* HAVE_X_WINDOWS */
988