More changes from David J. Mackenzie.
[bpt/emacs.git] / src / xfaces.c
CommitLineData
cb637678 1/* "Face" primitives.
7b7739b1
JB
2 Copyright (C) 1992, 1993 Free Software Foundation.
3
c115973b
JB
4This file is part of GNU Emacs.
5
6GNU Emacs is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
7b7739b1 8the Free Software Foundation; either version 2, or (at your option)
c115973b
JB
9any later version.
10
11GNU Emacs is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Emacs; see the file COPYING. If not, write to
18the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
19
357f32fc 20/* This is derived from work by Lucid (some parts very loosely so). */
7b7739b1 21
c115973b
JB
22#include <sys/types.h>
23#include <sys/stat.h>
24
25#include "config.h"
26#include "lisp.h"
27
cb637678
JB
28#ifdef HAVE_X_WINDOWS
29
c115973b
JB
30#include "xterm.h"
31#include "buffer.h"
f211082d 32#include "dispextern.h"
7b7739b1 33#include "frame.h"
357f32fc 34#include "blockinput.h"
b6d40e46 35#include "window.h"
c115973b
JB
36
37/* Display Context for the icons */
38#include <X11/Intrinsic.h>
39#include <X11/StringDefs.h>
3dbae1e4 40/* #include <X11/Xmu/Drawing.h> */ /* Appears not to be used */
c115973b
JB
41#include <X11/Xos.h>
42
cb637678
JB
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:
7b7739b1 105
cb637678
JB
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
c115973b
JB
126/* A table of display faces. */
127struct face **face_vector;
128/* The length in use of the table. */
129int nfaces;
130/* The allocated length of the table. */
131int nfaces_allocated;
132
133/* The number of face-id's in use (same for all frames). */
134int next_face_id;
135
bc0db68d
RS
136/* The number of the face to use to indicate the region. */
137int region_face;
138
7b7739b1
JB
139#define FACE_DEFAULT (~0)
140
f211082d
JB
141Lisp_Object Qface, Qwindow, Qpriority;
142
c115973b 143static void build_face ();
f211082d 144static Lisp_Object face_name_id_number ();
cb637678
JB
145
146struct face *intern_face ();
147static void ensure_face_ready ();
c115973b 148\f
cb637678
JB
149/* Allocating, copying, and comparing struct faces. */
150
151/* Allocate a new face */
152static struct face *
153allocate_face ()
154{
155 struct face *result = (struct face *) xmalloc (sizeof (struct face));
156 bzero (result, sizeof (struct face));
157 result->font = (XFontStruct *) FACE_DEFAULT;
158 result->foreground = FACE_DEFAULT;
159 result->background = FACE_DEFAULT;
160 result->stipple = FACE_DEFAULT;
161 return result;
162}
c115973b 163
cb637678 164/* Make a new face that's a copy of an existing one. */
c115973b
JB
165static struct face *
166copy_face (face)
167 struct face *face;
168{
169 struct face *result = allocate_face ();
170
171 result->font = face->font;
172 result->foreground = face->foreground;
173 result->background = face->background;
f211082d 174 result->stipple = face->stipple;
c115973b
JB
175 result->underline = face->underline;
176
177 return result;
178}
179
180static int
181face_eql (face1, face2)
182 struct face *face1, *face2;
183{
cb637678 184 return ( face1->font == face2->font
c115973b
JB
185 && face1->foreground == face2->foreground
186 && face1->background == face2->background
cb637678
JB
187 && face1->stipple == face2->stipple
188 && face1->underline == face2->underline);
c115973b 189}
cb637678
JB
190\f
191/* Interning faces in the `face_vector' cache, and clearing that cache. */
c115973b
JB
192
193/* Return the unique display face corresponding to the user-level face FACE.
c115973b
JB
194 If there isn't one, make one, and find a slot in the face_vector to
195 put it in. */
c115973b 196static struct face *
7b7739b1 197get_cached_face (f, face)
c115973b
JB
198 struct frame *f;
199 struct face *face;
200{
201 int i, empty = -1;
f211082d 202 struct face *result;
c115973b 203
cb637678
JB
204 /* Perhaps FACE->cached_index is valid; this could happen if FACE is
205 in a frame's face list. */
206 if (face->cached_index >= 0
207 && face->cached_index < nfaces
208 && face_eql (face_vector[face->cached_index], face))
209 return face_vector[face->cached_index];
210
c115973b
JB
211 /* Look for an existing display face that does the job.
212 Also find an empty slot if any. */
213 for (i = 0; i < nfaces; i++)
214 {
215 if (face_eql (face_vector[i], face))
216 return face_vector[i];
217 if (face_vector[i] == 0)
218 empty = i;
219 }
220
221 /* If no empty slots, make one. */
222 if (empty < 0 && nfaces == nfaces_allocated)
223 {
224 int newsize = nfaces + 20;
225 face_vector
226 = (struct face **) xrealloc (face_vector,
227 newsize * sizeof (struct face *));
228 nfaces_allocated = newsize;
229 }
230
231 if (empty < 0)
232 empty = nfaces++;
233
234 /* Put a new display face in the empty slot. */
235 result = copy_face (face);
236 face_vector[empty] = result;
237
238 /* Make a graphics context for it. */
239 build_face (f, result);
240
241 return result;
242}
243
cb637678
JB
244/* Given a frame face, return an equivalent display face
245 (one which has a graphics context). */
246
247struct face *
248intern_face (f, face)
249 struct frame *f;
250 struct face *face;
251{
cb637678
JB
252 /* If it's equivalent to the default face, use that. */
253 if (face_eql (face, FRAME_DEFAULT_FACE (f)))
254 {
255 if (!FRAME_DEFAULT_FACE (f)->gc)
256 build_face (f, FRAME_DEFAULT_FACE (f));
257 return FRAME_DEFAULT_FACE (f);
258 }
259
260 /* If it's equivalent to the mode line face, use that. */
261 if (face_eql (face, FRAME_MODE_LINE_FACE (f)))
262 {
263 if (!FRAME_MODE_LINE_FACE (f)->gc)
264 build_face (f, FRAME_MODE_LINE_FACE (f));
265 return FRAME_MODE_LINE_FACE (f);
266 }
267
f6b98e0b
JB
268 /* If it's not one of the frame's default faces, it shouldn't have a GC. */
269 if (face->gc)
270 abort ();
271
cb637678
JB
272 /* Get a specialized display face. */
273 return get_cached_face (f, face);
274}
275
c115973b
JB
276/* Clear out face_vector and start anew.
277 This should be done from time to time just to avoid
278 keeping too many graphics contexts in face_vector
279 that are no longer needed. */
280
281void
282clear_face_vector ()
283{
284 Lisp_Object rest;
285 Display *dpy = x_current_display;
f211082d 286 int i;
c115973b
JB
287
288 BLOCK_INPUT;
289 /* Free the display faces in the face_vector. */
290 for (i = 0; i < nfaces; i++)
291 {
292 struct face *face = face_vector[i];
f211082d
JB
293 if (face->gc)
294 XFreeGC (dpy, face->gc);
c115973b
JB
295 xfree (face);
296 }
297 nfaces = 0;
298
299 UNBLOCK_INPUT;
300}
301\f
cb637678
JB
302/* Allocating and freeing X resources for display faces. */
303
f211082d
JB
304/* Make a graphics context for face FACE, which is on frame F,
305 if that can be done. */
c115973b
JB
306static void
307build_face (f, face)
cb637678
JB
308 struct frame *f;
309 struct face *face;
c115973b
JB
310{
311 GC gc;
312 XGCValues xgcv;
313 unsigned long mask;
314
f211082d
JB
315 if (face->foreground != FACE_DEFAULT)
316 xgcv.foreground = face->foreground;
317 else
318 xgcv. foreground = f->display.x->foreground_pixel;
319 if (face->background != FACE_DEFAULT)
320 xgcv.background = face->background;
321 else
322 xgcv. background = f->display.x->background_pixel;
323 if (face->font && (int) face->font != FACE_DEFAULT)
324 xgcv.font = face->font->fid;
325 else
326 xgcv.font = f->display.x->font->fid;
c115973b
JB
327 xgcv.graphics_exposures = 0;
328 mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;
329 gc = XCreateGC (x_current_display, FRAME_X_WINDOW (f),
330 mask, &xgcv);
331#if 0
f211082d
JB
332 if (face->stipple && face->stipple != FACE_DEFAULT)
333 XSetStipple (x_current_display, gc, face->stipple);
c115973b 334#endif
f211082d 335 face->gc = gc;
c115973b 336}
cb637678
JB
337
338/* Allocating, freeing, and duplicating fonts, colors, and pixmaps. */
339
340static XFontStruct *
341load_font (f, name)
342 struct frame *f;
343 Lisp_Object name;
344{
345 XFontStruct *font;
346
347 if (NILP (name))
348 return (XFontStruct *) FACE_DEFAULT;
349
350 CHECK_STRING (name, 0);
351 BLOCK_INPUT;
352 font = XLoadQueryFont (x_current_display, (char *) XSTRING (name)->data);
353 UNBLOCK_INPUT;
354
355 if (! font)
356 Fsignal (Qerror, Fcons (build_string ("undefined font"),
357 Fcons (name, Qnil)));
358 return font;
359}
360
361static void
362unload_font (f, font)
363 struct frame *f;
364 XFontStruct *font;
365{
366 if (!font || font == ((XFontStruct *) FACE_DEFAULT))
367 return;
368 XFreeFont (x_current_display, font);
369}
370
371static unsigned long
372load_color (f, name)
373 struct frame *f;
374 Lisp_Object name;
375{
376 Display *dpy = x_current_display;
377 Colormap cmap;
378 XColor color;
379 int result;
380
381 if (NILP (name))
382 return FACE_DEFAULT;
383
384 cmap = DefaultColormapOfScreen (DefaultScreenOfDisplay (x_current_display));
385
386 CHECK_STRING (name, 0);
387 BLOCK_INPUT;
388 result = XParseColor (dpy, cmap, (char *) XSTRING (name)->data, &color);
389 UNBLOCK_INPUT;
390 if (! result)
391 Fsignal (Qerror, Fcons (build_string ("undefined color"),
392 Fcons (name, Qnil)));
393 BLOCK_INPUT;
394 result = XAllocColor (dpy, cmap, &color);
395 UNBLOCK_INPUT;
396 if (! result)
397 Fsignal (Qerror, Fcons (build_string ("X server cannot allocate color"),
398 Fcons (name, Qnil)));
399 return (unsigned long) color.pixel;
400}
401
402static void
403unload_color (f, pixel)
404 struct frame *f;
405 Pixel pixel;
406{
407 Colormap cmap;
408 Display *dpy = x_current_display;
409 if (pixel == FACE_DEFAULT)
410 return;
411 cmap = DefaultColormapOfScreen (DefaultScreenOfDisplay (x_current_display));
412 BLOCK_INPUT;
413 XFreeColors (dpy, cmap, &pixel, 1, 0);
414 UNBLOCK_INPUT;
415}
416\f
417/* Initializing face arrays for frames. */
418
419/* Set up faces 0 and 1 based on the normal text and modeline GC's. */
420void
421init_frame_faces (f)
422 struct frame *f;
423{
424 ensure_face_ready (f, 0);
425 {
426 XGCValues gcv;
427 struct face *face = FRAME_FACES (f) [0];
428
429 XGetGCValues (x_current_display, f->display.x->normal_gc,
430 GCForeground | GCBackground | GCFont, &gcv);
431 face->gc = f->display.x->normal_gc;
432 face->foreground = gcv.foreground;
433 face->background = gcv.background;
434 face->font = XQueryFont (x_current_display, gcv.font);
435 face->stipple = 0;
436 face->underline = 0;
437 }
438
439 ensure_face_ready (f, 1);
440 {
441 XGCValues gcv;
442 struct face *face = FRAME_FACES (f) [1];
443
444 XGetGCValues (x_current_display, f->display.x->reverse_gc,
445 GCForeground | GCBackground | GCFont, &gcv);
446 face->gc = f->display.x->reverse_gc;
447 face->foreground = gcv.foreground;
448 face->background = gcv.background;
449 face->font = XQueryFont (x_current_display, gcv.font);
450 face->stipple = 0;
451 face->underline = 0;
452 }
453}
454
455#if 0
456void
457init_frame_faces (f)
458 struct frame *f;
459{
460 struct frame *other_frame = 0;
461 Lisp_Object rest;
462
463 for (rest = Vframe_list; !NILP (rest); rest = Fcdr (rest))
464 {
465 struct frame *f2 = XFRAME (Fcar (rest));
466 if (f2 != f && FRAME_X_P (f2))
467 {
468 other_frame = f2;
469 break;
470 }
471 }
472
473 if (other_frame)
474 {
475 /* Make sure this frame's face vector is as big as the others. */
476 FRAME_N_FACES (f) = FRAME_N_FACES (other_frame);
477 FRAME_FACES (f)
478 = (struct face **) xmalloc (FRAME_N_FACES (f) * sizeof (struct face *));
479
480 /* Make sure the frame has the two basic faces. */
481 FRAME_DEFAULT_FACE (f)
482 = copy_face (FRAME_DEFAULT_FACE (other_frame));
483 FRAME_MODE_LINE_FACE (f)
484 = copy_face (FRAME_MODE_LINE_FACE (other_frame));
485 }
486}
487#endif
488
489
490/* Called from Fdelete_frame. */
491void
492free_frame_faces (f)
493 struct frame *f;
494{
495 Display *dpy = x_current_display;
496 int i;
497
498 for (i = 0; i < FRAME_N_FACES (f); i++)
499 {
500 struct face *face = FRAME_FACES (f) [i];
501 if (! face)
502 continue;
503 if (face->gc)
504 XFreeGC (dpy, face->gc);
505 unload_font (f, face->font);
506 unload_color (f, face->foreground);
507 unload_color (f, face->background);
508#if 0
509 unload_pixmap (f, face->stipple);
510#endif
511 xfree (face);
512 }
513 xfree (FRAME_FACES (f));
514 FRAME_FACES (f) = 0;
515 FRAME_N_FACES (f) = 0;
516}
c115973b 517\f
cb637678
JB
518/* Interning faces in a frame's face array. */
519
520/* Find a match for NEW_FACE in a FRAME's face array, and add it if we don't
521 find one. */
522int
b6d40e46 523intern_frame_face (frame, new_face)
cb637678 524 struct frame *frame;
b6d40e46 525 struct face *new_face;
cb637678
JB
526{
527 int len = FRAME_N_FACES (frame);
528 int i;
529
530 /* Search for a face already on FRAME equivalent to FACE. */
531 for (i = 0; i < len; i++)
532 {
533 struct face *frame_face = FRAME_FACES (frame)[i];
534
535 if (frame_face && face_eql (new_face, frame_face))
536 return i;
537 }
538
539 /* We didn't find one; add a new one. */
540 i = next_face_id++;
541
542 ensure_face_ready (frame, i);
f6b98e0b 543 bcopy (new_face, FRAME_FACES (frame)[i], sizeof (*new_face));
cb637678
JB
544
545 return i;
546}
547
548/* Make face id ID valid on frame F. */
549
550static void
551ensure_face_ready (f, id)
552 struct frame *f;
553 int id;
554{
555 if (FRAME_N_FACES (f) <= id)
556 {
557 int n = id + 10;
558 int i;
559 if (!FRAME_N_FACES (f))
560 FRAME_FACES (f)
561 = (struct face **) xmalloc (sizeof (struct face *) * n);
562 else
563 FRAME_FACES (f)
564 = (struct face **) xrealloc (FRAME_FACES (f),
565 sizeof (struct face *) * n);
566
567 bzero (FRAME_FACES (f) + FRAME_N_FACES (f),
568 (n - FRAME_N_FACES (f)) * sizeof (struct face *));
569 FRAME_N_FACES (f) = n;
570 }
571
572 if (FRAME_FACES (f) [id] == 0)
573 FRAME_FACES (f) [id] = allocate_face ();
574}
575\f
576/* Computing faces appropriate for a given piece of text in a buffer. */
577
7b7739b1
JB
578/* Modify face TO by copying from FROM all properties which have
579 nondefault settings. */
7b7739b1
JB
580static void
581merge_faces (from, to)
582 struct face *from, *to;
583{
584 if (from->font != (XFontStruct *)FACE_DEFAULT)
585 {
586 to->font = from->font;
587 }
588 if (from->foreground != FACE_DEFAULT)
589 to->foreground = from->foreground;
590 if (from->background != FACE_DEFAULT)
591 to->background = from->background;
f211082d
JB
592 if (from->stipple != FACE_DEFAULT)
593 to->stipple = from->stipple;
7b7739b1
JB
594 if (from->underline)
595 to->underline = from->underline;
596}
597
f211082d
JB
598struct sortvec
599{
600 Lisp_Object overlay;
601 int beg, end;
602 int priority;
603};
604
cb637678
JB
605static int
606sort_overlays (s1, s2)
607 struct sortvec *s1, *s2;
608{
609 if (s1->priority != s2->priority)
610 return s1->priority - s2->priority;
611 if (s1->beg != s2->beg)
612 return s1->beg - s2->beg;
613 if (s1->end != s2->end)
614 return s2->end - s1->end;
615 return 0;
616}
617
618/* Return the face ID associated with a buffer position POS.
7b7739b1
JB
619 Store into *ENDPTR the position at which a different face is needed.
620 This does not take account of glyphs that specify their own face codes.
f6b98e0b 621 F is the frame in use for display, and W is a window displaying
bc0db68d
RS
622 the current buffer.
623
624 REGION_BEG, REGION_END delimit the region, so it can be highlighted. */
625
cb637678 626int
bc0db68d 627compute_char_face (f, w, pos, region_beg, region_end, endptr)
7b7739b1 628 struct frame *f;
f211082d 629 struct window *w;
7b7739b1 630 int pos;
bc0db68d 631 int region_beg, region_end;
7b7739b1
JB
632 int *endptr;
633{
634 struct face face;
b6d40e46 635 Lisp_Object prop, position;
7b7739b1
JB
636 int i, j, noverlays;
637 int facecode;
7b7739b1
JB
638 Lisp_Object *overlay_vec;
639 int len;
f211082d
JB
640 struct sortvec *sortvec;
641 Lisp_Object frame;
f6b98e0b
JB
642 int endpos;
643
644 /* W must display the current buffer. We could write this function
645 to use the frame and buffer of W, but right now it doesn't. */
646 if (XBUFFER (w->buffer) != current_buffer)
647 abort ();
f211082d
JB
648
649 XSET (frame, Lisp_Frame, f);
7b7739b1 650
f6b98e0b 651 endpos = ZV;
bc0db68d
RS
652 if (pos < region_beg && region_beg < endpos)
653 endpos = region_beg;
f6b98e0b 654
7b7739b1 655 XFASTINT (position) = pos;
b6d40e46
JB
656 prop = Fget_text_property (position, Qface, w->buffer);
657 {
658 Lisp_Object end;
7b7739b1 659
b6d40e46
JB
660 end = Fnext_single_property_change (position, Qface, w->buffer);
661 if (INTEGERP (end))
662 endpos = XINT (end);
663 }
664
665 {
f6b98e0b 666 int next_overlay;
b6d40e46
JB
667
668 len = 10;
669 overlay_vec = (Lisp_Object *) xmalloc (len * sizeof (Lisp_Object));
f6b98e0b
JB
670 noverlays = overlays_at (pos, &overlay_vec, &len, &next_overlay);
671 if (next_overlay < endpos)
672 endpos = next_overlay;
b6d40e46
JB
673 }
674
675 *endptr = endpos;
7b7739b1
JB
676
677 /* Optimize the default case. */
bc0db68d
RS
678 if (noverlays == 0 && NILP (prop)
679 && !(pos >= region_beg && pos < region_end))
cb637678 680 return 0;
7b7739b1 681
f211082d 682 bcopy (FRAME_DEFAULT_FACE (f), &face, sizeof (struct face));
f6b98e0b 683 face.gc = 0;
7b7739b1
JB
684
685 if (!NILP (prop))
686 {
f211082d
JB
687 facecode = face_name_id_number (frame, prop);
688 if (facecode >= 0 && facecode < FRAME_N_FACES (f)
689 && FRAME_FACES (f) [facecode] != 0)
690 merge_faces (FRAME_FACES (f) [facecode], &face);
7b7739b1
JB
691 }
692
f211082d
JB
693 /* Put the valid and relevant overlays into sortvec. */
694 sortvec = (struct sortvec *) alloca (noverlays * sizeof (struct sortvec));
695
7b7739b1
JB
696 for (i = 0, j = 0; i < noverlays; i++)
697 {
b6d40e46 698 Lisp_Object overlay = overlay_vec[i];
7b7739b1
JB
699
700 if (OVERLAY_VALID (overlay)
701 && OVERLAY_POSITION (OVERLAY_START (overlay)) > 0
702 && OVERLAY_POSITION (OVERLAY_END (overlay)) > 0)
f211082d
JB
703 {
704 Lisp_Object window;
705 window = Foverlay_get (overlay, Qwindow);
706
707 /* Also ignore overlays limited to one window
708 if it's not the window we are using. */
f6b98e0b
JB
709 if (XTYPE (window) != Lisp_Window
710 || XWINDOW (window) == w)
f211082d
JB
711 {
712 Lisp_Object tem;
713
714 /* This overlay is good and counts:
715 put it in sortvec. */
716 sortvec[j].overlay = overlay;
717 sortvec[j].beg = OVERLAY_POSITION (OVERLAY_START (overlay));
718 sortvec[j].end = OVERLAY_POSITION (OVERLAY_END (overlay));
719 tem = Foverlay_get (overlay, Qpriority);
720 if (INTEGERP (tem))
721 sortvec[j].priority = XINT (tem);
722 else
723 sortvec[j].priority = 0;
724 j++;
725 }
726 }
7b7739b1
JB
727 }
728 noverlays = j;
729
f211082d
JB
730 /* Sort the overlays into the proper order: increasing priority. */
731
bc0db68d
RS
732 if (noverlays > 1)
733 qsort (sortvec, noverlays, sizeof (struct sortvec), sort_overlays);
7b7739b1
JB
734
735 /* Now merge the overlay data in that order. */
7b7739b1
JB
736 for (i = 0; i < noverlays; i++)
737 {
f6b98e0b 738 prop = Foverlay_get (sortvec[i].overlay, Qface);
7b7739b1
JB
739 if (!NILP (prop))
740 {
741 Lisp_Object oend;
742 int oendpos;
743
f211082d
JB
744 facecode = face_name_id_number (frame, prop);
745 if (facecode >= 0 && facecode < FRAME_N_FACES (f)
746 && FRAME_FACES (f) [facecode] != 0)
747 merge_faces (FRAME_FACES (f) [facecode], &face);
7b7739b1 748
f6b98e0b 749 oend = OVERLAY_END (sortvec[i].overlay);
7b7739b1 750 oendpos = OVERLAY_POSITION (oend);
f6b98e0b 751 if (oendpos < endpos)
7b7739b1
JB
752 endpos = oendpos;
753 }
754 }
755
bc0db68d
RS
756 if (pos >= region_beg && pos < region_end)
757 {
758 if (region_end < endpos)
759 endpos = region_end;
760 if (region_face >= 0 && region_face < next_face_id)
761 merge_faces (FRAME_FACES (f) [region_face], &face);
762 }
763
7b7739b1
JB
764 xfree (overlay_vec);
765
766 *endptr = endpos;
767
cb637678 768 return intern_frame_face (f, &face);
f211082d
JB
769}
770
cb637678
JB
771/* Return the face ID to use to display a special glyph which selects
772 FACE_CODE as the face ID, assuming that ordinarily the face would
773 be BASIC_FACE. F is the frame. */
774int
18004d2b 775compute_glyph_face (f, face_code)
7b7739b1 776 struct frame *f;
7b7739b1
JB
777 int face_code;
778{
779 struct face face;
780
18004d2b 781 bcopy (FRAME_DEFAULT_FACE (f), &face, sizeof (face));
f6b98e0b 782 face.gc = 0;
7b7739b1 783
f211082d
JB
784 if (face_code >= 0 && face_code < FRAME_N_FACES (f)
785 && FRAME_FACES (f) [face_code] != 0)
786 merge_faces (FRAME_FACES (f) [face_code], &face);
7b7739b1 787
cb637678 788 return intern_frame_face (f, &face);
c115973b 789}
c115973b 790\f
cb637678 791/* Lisp interface. */
c115973b
JB
792
793DEFUN ("frame-face-alist", Fframe_face_alist, Sframe_face_alist, 1, 1, 0,
794 "")
795 (frame)
796 Lisp_Object frame;
797{
798 CHECK_FRAME (frame, 0);
799 return XFRAME (frame)->face_alist;
800}
801
802DEFUN ("set-frame-face-alist", Fset_frame_face_alist, Sset_frame_face_alist,
803 2, 2, 0, "")
804 (frame, value)
805 Lisp_Object frame, value;
806{
807 CHECK_FRAME (frame, 0);
808 XFRAME (frame)->face_alist = value;
809 return value;
810}
811
812
813DEFUN ("make-face-internal", Fmake_face_internal, Smake_face_internal, 1, 1, 0,
814 "Create face number FACE-ID on all frames.")
815 (face_id)
816 Lisp_Object face_id;
817{
818 Lisp_Object rest;
819 int id = XINT (face_id);
820
f211082d
JB
821 CHECK_NUMBER (face_id, 0);
822 if (id < 0 || id >= next_face_id)
823 error ("Face id out of range");
c115973b
JB
824
825 for (rest = Vframe_list; !NILP (rest); rest = XCONS (rest)->cdr)
826 {
827 struct frame *f = XFRAME (XCONS (rest)->car);
cb637678
JB
828 if (FRAME_X_P (f))
829 ensure_face_ready (f, id);
c115973b
JB
830 }
831 return Qnil;
832}
833
834
835DEFUN ("set-face-attribute-internal", Fset_face_attribute_internal,
836 Sset_face_attribute_internal, 4, 4, 0, "")
837 (face_id, attr_name, attr_value, frame)
838 Lisp_Object face_id, attr_name, attr_value, frame;
839{
840 struct face *face;
841 struct frame *f;
842 int magic_p;
843 int id;
844
845 CHECK_FRAME (frame, 0);
f211082d 846 CHECK_NUMBER (face_id, 0);
c115973b
JB
847 CHECK_SYMBOL (attr_name, 0);
848
849 f = XFRAME (frame);
850 id = XINT (face_id);
f211082d
JB
851 if (id < 0 || id >= next_face_id)
852 error ("Face id out of range");
c115973b 853
b6d40e46
JB
854 if (! FRAME_X_P (f))
855 return;
856
c115973b 857 ensure_face_ready (f, id);
f211082d 858 face = FRAME_FACES (f) [XFASTINT (face_id)];
c115973b
JB
859
860 if (EQ (attr_name, intern ("font")))
861 {
f211082d 862 XFontStruct *font = load_font (f, attr_value);
c115973b
JB
863 unload_font (f, face->font);
864 face->font = font;
c115973b
JB
865 }
866 else if (EQ (attr_name, intern ("foreground")))
867 {
f211082d 868 unsigned long new_color = load_color (f, attr_value);
c115973b
JB
869 unload_color (f, face->foreground);
870 face->foreground = new_color;
c115973b
JB
871 }
872 else if (EQ (attr_name, intern ("background")))
873 {
f211082d 874 unsigned long new_color = load_color (f, attr_value);
c115973b
JB
875 unload_color (f, face->background);
876 face->background = new_color;
c115973b
JB
877 }
878#if 0
879 else if (EQ (attr_name, intern ("background-pixmap")))
880 {
c115973b
JB
881 unsigned int w, h, d;
882 unsigned long new_pixmap = load_pixmap (f, attr_value, &w, &h, &d, 0);
f211082d
JB
883 unload_pixmap (f, face->stipple);
884 if (NILP (attr_value))
885 new_pixmap = 0;
886 face->stipple = new_pixmap;
c115973b
JB
887 face->pixmap_w = w;
888 face->pixmap_h = h;
889/* face->pixmap_depth = d; */
c115973b
JB
890 }
891#endif /* 0 */
892 else if (EQ (attr_name, intern ("underline")))
893 {
894 int new = !NILP (attr_value);
895 face->underline = new;
896 }
897 else
898 error ("unknown face attribute");
899
900 if (id == 0)
901 {
902 BLOCK_INPUT;
f211082d
JB
903 if (FRAME_DEFAULT_FACE (f)->gc != 0)
904 XFreeGC (x_current_display, FRAME_DEFAULT_FACE (f)->gc);
905 build_face (f, FRAME_DEFAULT_FACE (f));
c115973b
JB
906 UNBLOCK_INPUT;
907 }
908
909 if (id == 1)
910 {
911 BLOCK_INPUT;
f211082d
JB
912 if (FRAME_MODE_LINE_FACE (f)->gc != 0)
913 XFreeGC (x_current_display, FRAME_MODE_LINE_FACE (f)->gc);
914 build_face (f, FRAME_MODE_LINE_FACE (f));
c115973b
JB
915 UNBLOCK_INPUT;
916 }
917
918 return Qnil;
919}
920
921DEFUN ("internal-next-face-id", Finternal_next_face_id, Sinternal_next_face_id,
922 0, 0, 0, "")
923 ()
924{
925 return make_number (next_face_id++);
926}
f211082d
JB
927
928/* Return the face id for name NAME on frame FRAME.
929 (It should be the same for all frames,
930 but it's as easy to use the "right" frame to look it up
931 as to use any other one.) */
932
933static Lisp_Object
934face_name_id_number (frame, name)
935 Lisp_Object frame, name;
936{
937 Lisp_Object tem;
938
939 CHECK_FRAME (frame, 0);
940 tem = Fcdr (Fassq (name, XFRAME (frame)->face_alist));
b6d40e46
JB
941 if (NILP (tem))
942 return 0;
f211082d
JB
943 CHECK_VECTOR (tem, 0);
944 tem = XVECTOR (tem)->contents[2];
945 CHECK_NUMBER (tem, 0);
946 return XINT (tem);
947}
c115973b 948\f
cb637678
JB
949/* Emacs initialization. */
950
c115973b 951void
f211082d 952syms_of_xfaces ()
c115973b 953{
f211082d
JB
954 Qwindow = intern ("window");
955 staticpro (&Qwindow);
956 Qface = intern ("face");
957 staticpro (&Qface);
958 Qpriority = intern ("priority");
959 staticpro (&Qpriority);
960
bc0db68d
RS
961 DEFVAR_INT ("region-face", &region_face,
962 "Face number to use to highlight the region\n\
963The region is highlighted with this face\n\
964when Transient Mark mode is enabled and the mark is active.");
965
c115973b
JB
966 defsubr (&Sframe_face_alist);
967 defsubr (&Sset_frame_face_alist);
968 defsubr (&Smake_face_internal);
969 defsubr (&Sset_face_attribute_internal);
970 defsubr (&Sinternal_next_face_id);
971}
cb637678
JB
972
973#endif /* HAVE_X_WINDOWS */
974