Separate parameter faces (those created and modified by the user)
[bpt/emacs.git] / src / xfaces.c
CommitLineData
cb637678 1/* "Face" primitives.
c6c5df7f 2 Copyright (C) 1993 Free Software Foundation.
7b7739b1 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 36
6233db35
RS
37/* Compensate for bug in Xos.h on some systems. */
38#ifdef XOS_NEEDS_TIME_H
e11d186d
RS
39#include <time.h>
40#define __TIMEVAL__
41#endif
42
7a4d2269
JB
43/* These don't seem to be used. */
44#if 0
c115973b
JB
45/* Display Context for the icons */
46#include <X11/Intrinsic.h>
47#include <X11/StringDefs.h>
7a4d2269
JB
48#include <X11/Xmu/Drawing.h>
49#endif
50
c115973b
JB
51#include <X11/Xos.h>
52
cb637678
JB
53\f
54/* An explanation of the face data structures. */
55
56/* ========================= Face Data Structures =========================
57
58 All lisp code uses symbols as face names.
59
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
62 vectors of the form
63 [face NAME ID FONT FOREGROUND BACKGROUND BACKGROUND-PIXMAP UNDERLINE-P]
64 where
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
68 the face,
69 FONT, FOREGROUND, and BACKGROUND are strings naming the fonts and colors
70 to use with the face,
71 BACKGROUND-PIXMAP is the name of an x bitmap filename, which we don't
72 use right now, and
73 UNDERLINE-P is non-nil if the face should be underlined.
660ed669
JB
74 If any of these elements are nil, that allows the frame's parameters to
75 show through.
cb637678
JB
76 (lisp/faces.el maintains these association lists.)
77
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.)
81
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.)
90
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.
7b37f67b
JB
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.)
cb637678
JB
101
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.)
111
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
117 src/dispextern.h.)
118
119 Some subtleties:
7b7739b1 120
cb637678
JB
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
128 purge.
129
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. */
137
138\f
139/* Definitions and declarations. */
140
c115973b
JB
141/* A table of display faces. */
142struct face **face_vector;
143/* The length in use of the table. */
144int nfaces;
145/* The allocated length of the table. */
146int nfaces_allocated;
147
148/* The number of face-id's in use (same for all frames). */
149int next_face_id;
150
bc0db68d
RS
151/* The number of the face to use to indicate the region. */
152int region_face;
153
9516fe94
RS
154/* This is what appears in a slot in a face to signify that the face
155 does not specify that display aspect. */
7b7739b1
JB
156#define FACE_DEFAULT (~0)
157
f211082d
JB
158Lisp_Object Qface, Qwindow, Qpriority;
159
415445e2
JB
160static void build_face ( /* FRAME_PTR, struct face * */ );
161int face_name_id_number ( /* FRAME_PTR, Lisp_Object name */ );
cb637678 162
415445e2
JB
163struct face *intern_face ( /* FRAME_PTR, struct face * */ );
164static void ensure_face_ready ( /* FRAME_PTR, int id */ );
254a1b66 165void recompute_basic_faces ( /* FRAME_PTR f */ );
c115973b 166\f
cb637678
JB
167/* Allocating, copying, and comparing struct faces. */
168
169/* Allocate a new face */
170static struct face *
171allocate_face ()
172{
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;
179 return result;
180}
c115973b 181
cb637678 182/* Make a new face that's a copy of an existing one. */
c115973b
JB
183static struct face *
184copy_face (face)
185 struct face *face;
186{
187 struct face *result = allocate_face ();
188
189 result->font = face->font;
190 result->foreground = face->foreground;
191 result->background = face->background;
f211082d 192 result->stipple = face->stipple;
c115973b
JB
193 result->underline = face->underline;
194
195 return result;
196}
197
198static int
199face_eql (face1, face2)
200 struct face *face1, *face2;
201{
cb637678 202 return ( face1->font == face2->font
c115973b
JB
203 && face1->foreground == face2->foreground
204 && face1->background == face2->background
cb637678
JB
205 && face1->stipple == face2->stipple
206 && face1->underline == face2->underline);
c115973b 207}
cb637678
JB
208\f
209/* Interning faces in the `face_vector' cache, and clearing that cache. */
c115973b
JB
210
211/* Return the unique display face corresponding to the user-level face FACE.
c115973b
JB
212 If there isn't one, make one, and find a slot in the face_vector to
213 put it in. */
c115973b 214static struct face *
7b7739b1 215get_cached_face (f, face)
c115973b
JB
216 struct frame *f;
217 struct face *face;
218{
219 int i, empty = -1;
f211082d 220 struct face *result;
c115973b 221
cb637678
JB
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];
228
c115973b
JB
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++)
232 {
233 if (face_eql (face_vector[i], face))
234 return face_vector[i];
235 if (face_vector[i] == 0)
236 empty = i;
237 }
238
239 /* If no empty slots, make one. */
240 if (empty < 0 && nfaces == nfaces_allocated)
241 {
242 int newsize = nfaces + 20;
243 face_vector
244 = (struct face **) xrealloc (face_vector,
245 newsize * sizeof (struct face *));
246 nfaces_allocated = newsize;
247 }
248
249 if (empty < 0)
250 empty = nfaces++;
251
252 /* Put a new display face in the empty slot. */
253 result = copy_face (face);
254 face_vector[empty] = result;
255
256 /* Make a graphics context for it. */
257 build_face (f, result);
258
259 return result;
260}
261
cb637678
JB
262/* Given a frame face, return an equivalent display face
263 (one which has a graphics context). */
264
265struct face *
266intern_face (f, face)
267 struct frame *f;
268 struct face *face;
269{
cb637678
JB
270 /* If it's equivalent to the default face, use that. */
271 if (face_eql (face, FRAME_DEFAULT_FACE (f)))
272 {
273 if (!FRAME_DEFAULT_FACE (f)->gc)
274 build_face (f, FRAME_DEFAULT_FACE (f));
275 return FRAME_DEFAULT_FACE (f);
276 }
277
278 /* If it's equivalent to the mode line face, use that. */
279 if (face_eql (face, FRAME_MODE_LINE_FACE (f)))
280 {
281 if (!FRAME_MODE_LINE_FACE (f)->gc)
282 build_face (f, FRAME_MODE_LINE_FACE (f));
283 return FRAME_MODE_LINE_FACE (f);
284 }
285
f6b98e0b
JB
286 /* If it's not one of the frame's default faces, it shouldn't have a GC. */
287 if (face->gc)
288 abort ();
289
cb637678
JB
290 /* Get a specialized display face. */
291 return get_cached_face (f, face);
292}
293
c115973b
JB
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. */
298
299void
300clear_face_vector ()
301{
302 Lisp_Object rest;
303 Display *dpy = x_current_display;
f211082d 304 int i;
c115973b
JB
305
306 BLOCK_INPUT;
307 /* Free the display faces in the face_vector. */
308 for (i = 0; i < nfaces; i++)
309 {
310 struct face *face = face_vector[i];
f211082d
JB
311 if (face->gc)
312 XFreeGC (dpy, face->gc);
c115973b
JB
313 xfree (face);
314 }
315 nfaces = 0;
316
317 UNBLOCK_INPUT;
318}
319\f
cb637678
JB
320/* Allocating and freeing X resources for display faces. */
321
f211082d
JB
322/* Make a graphics context for face FACE, which is on frame F,
323 if that can be done. */
c115973b
JB
324static void
325build_face (f, face)
cb637678
JB
326 struct frame *f;
327 struct face *face;
c115973b
JB
328{
329 GC gc;
330 XGCValues xgcv;
331 unsigned long mask;
332
660ed669
JB
333 BLOCK_INPUT;
334
f211082d
JB
335 if (face->foreground != FACE_DEFAULT)
336 xgcv.foreground = face->foreground;
337 else
660ed669
JB
338 xgcv.foreground = f->display.x->foreground_pixel;
339
f211082d
JB
340 if (face->background != FACE_DEFAULT)
341 xgcv.background = face->background;
342 else
660ed669
JB
343 xgcv.background = f->display.x->background_pixel;
344
f211082d
JB
345 if (face->font && (int) face->font != FACE_DEFAULT)
346 xgcv.font = face->font->fid;
347 else
348 xgcv.font = f->display.x->font->fid;
660ed669 349
c115973b 350 xgcv.graphics_exposures = 0;
660ed669 351
c115973b
JB
352 mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;
353 gc = XCreateGC (x_current_display, FRAME_X_WINDOW (f),
354 mask, &xgcv);
660ed669 355
c115973b 356#if 0
f211082d
JB
357 if (face->stipple && face->stipple != FACE_DEFAULT)
358 XSetStipple (x_current_display, gc, face->stipple);
c115973b 359#endif
660ed669 360
f211082d 361 face->gc = gc;
660ed669
JB
362
363 UNBLOCK_INPUT;
c115973b 364}
cb637678
JB
365
366/* Allocating, freeing, and duplicating fonts, colors, and pixmaps. */
367
368static XFontStruct *
369load_font (f, name)
370 struct frame *f;
371 Lisp_Object name;
372{
373 XFontStruct *font;
374
375 if (NILP (name))
376 return (XFontStruct *) FACE_DEFAULT;
377
378 CHECK_STRING (name, 0);
379 BLOCK_INPUT;
380 font = XLoadQueryFont (x_current_display, (char *) XSTRING (name)->data);
381 UNBLOCK_INPUT;
382
383 if (! font)
384 Fsignal (Qerror, Fcons (build_string ("undefined font"),
385 Fcons (name, Qnil)));
386 return font;
387}
388
389static void
390unload_font (f, font)
391 struct frame *f;
392 XFontStruct *font;
393{
394 if (!font || font == ((XFontStruct *) FACE_DEFAULT))
395 return;
660ed669
JB
396
397 BLOCK_INPUT;
cb637678 398 XFreeFont (x_current_display, font);
660ed669 399 UNBLOCK_INPUT;
cb637678
JB
400}
401
402static unsigned long
403load_color (f, name)
404 struct frame *f;
405 Lisp_Object name;
406{
407 Display *dpy = x_current_display;
408 Colormap cmap;
409 XColor color;
410 int result;
411
412 if (NILP (name))
413 return FACE_DEFAULT;
414
415 cmap = DefaultColormapOfScreen (DefaultScreenOfDisplay (x_current_display));
416
417 CHECK_STRING (name, 0);
418 BLOCK_INPUT;
419 result = XParseColor (dpy, cmap, (char *) XSTRING (name)->data, &color);
420 UNBLOCK_INPUT;
421 if (! result)
422 Fsignal (Qerror, Fcons (build_string ("undefined color"),
423 Fcons (name, Qnil)));
424 BLOCK_INPUT;
425 result = XAllocColor (dpy, cmap, &color);
426 UNBLOCK_INPUT;
427 if (! result)
428 Fsignal (Qerror, Fcons (build_string ("X server cannot allocate color"),
429 Fcons (name, Qnil)));
430 return (unsigned long) color.pixel;
431}
432
433static void
434unload_color (f, pixel)
435 struct frame *f;
7a4d2269 436 unsigned long pixel;
cb637678 437{
1d9fd7fe
JB
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. */
444#if 0
cb637678
JB
445 Colormap cmap;
446 Display *dpy = x_current_display;
32dc0866
JB
447 if (pixel == FACE_DEFAULT
448 || pixel == BLACK_PIX_DEFAULT
449 || pixel == WHITE_PIX_DEFAULT)
cb637678
JB
450 return;
451 cmap = DefaultColormapOfScreen (DefaultScreenOfDisplay (x_current_display));
452 BLOCK_INPUT;
453 XFreeColors (dpy, cmap, &pixel, 1, 0);
454 UNBLOCK_INPUT;
1d9fd7fe 455#endif
cb637678
JB
456}
457\f
458/* Initializing face arrays for frames. */
459
cb637678
JB
460void
461init_frame_faces (f)
660ed669 462 FRAME_PTR f;
cb637678
JB
463{
464 ensure_face_ready (f, 0);
cb637678 465 ensure_face_ready (f, 1);
660ed669
JB
466
467 recompute_basic_faces (f);
7b37f67b 468
1120eb5e
JB
469 /* Find another X frame. */
470 {
471 Lisp_Object tail, frame, result;
472
473 result = Qnil;
474 FOR_EACH_FRAME (tail, frame)
475 if (FRAME_X_P (XFRAME (frame))
476 && XFRAME (frame) != f)
477 {
478 result = frame;
479 break;
480 }
481
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. */
486 if (FRAMEP (result))
487 {
488 int i;
489 int n_faces = XFRAME (result)->display.x->n_faces;
490 struct face **faces = XFRAME (result)->display.x->faces;
491
492 for (i = 2; i < n_faces; i++)
493 if (faces[i])
494 ensure_face_ready (f, i);
495 }
496 }
cb637678
JB
497}
498
660ed669 499
cb637678
JB
500/* Called from Fdelete_frame. */
501void
502free_frame_faces (f)
503 struct frame *f;
504{
505 Display *dpy = x_current_display;
506 int i;
507
660ed669
JB
508 BLOCK_INPUT;
509
510 for (i = 0; i < FRAME_N_FACES (f); i++)
cb637678
JB
511 {
512 struct face *face = FRAME_FACES (f) [i];
660ed669
JB
513 if (face)
514 {
515 if (face->gc)
516 XFreeGC (dpy, face->gc);
517 if (! face->copy)
518 {
519 unload_font (f, face->font);
520 unload_color (f, face->foreground);
521 unload_color (f, face->background);
cb637678 522#if 0
660ed669 523 unload_pixmap (f, face->stipple);
cb637678 524#endif
660ed669
JB
525 }
526 xfree (face);
527 }
cb637678
JB
528 }
529 xfree (FRAME_FACES (f));
530 FRAME_FACES (f) = 0;
531 FRAME_N_FACES (f) = 0;
660ed669
JB
532
533 UNBLOCK_INPUT;
cb637678 534}
c115973b 535\f
cb637678
JB
536/* Interning faces in a frame's face array. */
537
538/* Find a match for NEW_FACE in a FRAME's face array, and add it if we don't
539 find one. */
660ed669 540static int
b6d40e46 541intern_frame_face (frame, new_face)
cb637678 542 struct frame *frame;
b6d40e46 543 struct face *new_face;
cb637678
JB
544{
545 int len = FRAME_N_FACES (frame);
546 int i;
547
548 /* Search for a face already on FRAME equivalent to FACE. */
549 for (i = 0; i < len; i++)
550 {
551 struct face *frame_face = FRAME_FACES (frame)[i];
552
553 if (frame_face && face_eql (new_face, frame_face))
554 return i;
555 }
556
557 /* We didn't find one; add a new one. */
558 i = next_face_id++;
559
560 ensure_face_ready (frame, i);
f6b98e0b 561 bcopy (new_face, FRAME_FACES (frame)[i], sizeof (*new_face));
660ed669 562 FRAME_FACES (frame)[i]->copy = 1;
cb637678
JB
563
564 return i;
565}
566
567/* Make face id ID valid on frame F. */
568
569static void
570ensure_face_ready (f, id)
571 struct frame *f;
572 int id;
573{
574 if (FRAME_N_FACES (f) <= id)
575 {
576 int n = id + 10;
577 int i;
578 if (!FRAME_N_FACES (f))
579 FRAME_FACES (f)
580 = (struct face **) xmalloc (sizeof (struct face *) * n);
581 else
582 FRAME_FACES (f)
583 = (struct face **) xrealloc (FRAME_FACES (f),
584 sizeof (struct face *) * n);
585
586 bzero (FRAME_FACES (f) + FRAME_N_FACES (f),
587 (n - FRAME_N_FACES (f)) * sizeof (struct face *));
588 FRAME_N_FACES (f) = n;
589 }
590
591 if (FRAME_FACES (f) [id] == 0)
592 FRAME_FACES (f) [id] = allocate_face ();
593}
594\f
595/* Computing faces appropriate for a given piece of text in a buffer. */
596
660ed669
JB
597/* Return non-zero if FONT1 and FONT2 have the same size bounding box.
598 We assume that they're both character-cell fonts. */
599int
600same_size_fonts (font1, font2)
601 XFontStruct *font1, *font2;
602{
603 XCharStruct *bounds1 = &font1->min_bounds;
604 XCharStruct *bounds2 = &font2->min_bounds;
605
46407861
RS
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.
660ed669 614 && bounds1->ascent == bounds2->ascent
46407861 615 && bounds1->descent == bounds2->descent); */
660ed669
JB
616}
617
7b7739b1
JB
618/* Modify face TO by copying from FROM all properties which have
619 nondefault settings. */
7b7739b1
JB
620static void
621merge_faces (from, to)
622 struct face *from, *to;
623{
68a97335
JB
624 /* Only merge the font if it's the same size as the base font. */
625 if (from->font != (XFontStruct *) FACE_DEFAULT
68a97335
JB
626 && same_size_fonts (from->font, to->font))
627 to->font = from->font;
7b7739b1
JB
628 if (from->foreground != FACE_DEFAULT)
629 to->foreground = from->foreground;
630 if (from->background != FACE_DEFAULT)
631 to->background = from->background;
f211082d
JB
632 if (from->stipple != FACE_DEFAULT)
633 to->stipple = from->stipple;
7b7739b1
JB
634 if (from->underline)
635 to->underline = from->underline;
636}
637
660ed669
JB
638/* Set up the basic set of facial parameters, based on the frame's
639 data; all faces are deltas applied to this. */
640static void
641compute_base_face (f, face)
642 FRAME_PTR f;
643 struct face *face;
644{
645 struct x_display *d = f->display.x;
646
647 face->gc = 0;
648 face->foreground = d->foreground_pixel;
649 face->background = d->background_pixel;
650 face->font = d->font;
582080c1 651 face->stipple = 0;
660ed669 652 face->underline = 0;
582080c1
JB
653
654 /* Avoid a face comparison by making this invalid. */
655 face->cached_index = -1;
660ed669
JB
656}
657
658
f211082d
JB
659struct sortvec
660{
661 Lisp_Object overlay;
662 int beg, end;
663 int priority;
664};
665
cb637678
JB
666static int
667sort_overlays (s1, s2)
668 struct sortvec *s1, *s2;
669{
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;
676 return 0;
677}
678
679/* Return the face ID associated with a buffer position POS.
7b7739b1
JB
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.
f6b98e0b 682 F is the frame in use for display, and W is a window displaying
bc0db68d
RS
683 the current buffer.
684
685 REGION_BEG, REGION_END delimit the region, so it can be highlighted. */
686
cb637678 687int
bc0db68d 688compute_char_face (f, w, pos, region_beg, region_end, endptr)
7b7739b1 689 struct frame *f;
f211082d 690 struct window *w;
7b7739b1 691 int pos;
bc0db68d 692 int region_beg, region_end;
7b7739b1
JB
693 int *endptr;
694{
695 struct face face;
b6d40e46 696 Lisp_Object prop, position;
7b7739b1
JB
697 int i, j, noverlays;
698 int facecode;
7b7739b1 699 Lisp_Object *overlay_vec;
f211082d
JB
700 struct sortvec *sortvec;
701 Lisp_Object frame;
f6b98e0b
JB
702 int endpos;
703
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)
707 abort ();
f211082d
JB
708
709 XSET (frame, Lisp_Frame, f);
7b7739b1 710
f6b98e0b 711 endpos = ZV;
bc0db68d
RS
712 if (pos < region_beg && region_beg < endpos)
713 endpos = region_beg;
f6b98e0b 714
7b7739b1 715 XFASTINT (position) = pos;
b6d40e46
JB
716 prop = Fget_text_property (position, Qface, w->buffer);
717 {
718 Lisp_Object end;
7b7739b1 719
b6d40e46
JB
720 end = Fnext_single_property_change (position, Qface, w->buffer);
721 if (INTEGERP (end))
722 endpos = XINT (end);
723 }
724
725 {
f6b98e0b 726 int next_overlay;
9516fe94
RS
727 int len;
728
729 /* First try with room for 40 overlays. */
730 len = 40;
731 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
732
733 noverlays = overlays_at (pos, 0, &overlay_vec, &len, &next_overlay);
734
735 /* If there are more than 40,
736 make enough space for all, and try again. */
737 if (noverlays > len)
738 {
739 len = noverlays;
740 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
741 noverlays = overlays_at (pos, 0, &overlay_vec, &len, &next_overlay);
742 }
b6d40e46 743
f6b98e0b
JB
744 if (next_overlay < endpos)
745 endpos = next_overlay;
b6d40e46
JB
746 }
747
748 *endptr = endpos;
7b7739b1
JB
749
750 /* Optimize the default case. */
bc0db68d
RS
751 if (noverlays == 0 && NILP (prop)
752 && !(pos >= region_beg && pos < region_end))
cb637678 753 return 0;
7b7739b1 754
660ed669 755 compute_base_face (f, &face);
7b7739b1
JB
756
757 if (!NILP (prop))
758 {
1d9fd7fe 759 facecode = face_name_id_number (f, prop);
f211082d
JB
760 if (facecode >= 0 && facecode < FRAME_N_FACES (f)
761 && FRAME_FACES (f) [facecode] != 0)
762 merge_faces (FRAME_FACES (f) [facecode], &face);
7b7739b1
JB
763 }
764
f211082d
JB
765 /* Put the valid and relevant overlays into sortvec. */
766 sortvec = (struct sortvec *) alloca (noverlays * sizeof (struct sortvec));
767
7b7739b1
JB
768 for (i = 0, j = 0; i < noverlays; i++)
769 {
b6d40e46 770 Lisp_Object overlay = overlay_vec[i];
7b7739b1
JB
771
772 if (OVERLAY_VALID (overlay)
773 && OVERLAY_POSITION (OVERLAY_START (overlay)) > 0
774 && OVERLAY_POSITION (OVERLAY_END (overlay)) > 0)
f211082d
JB
775 {
776 Lisp_Object window;
777 window = Foverlay_get (overlay, Qwindow);
778
779 /* Also ignore overlays limited to one window
780 if it's not the window we are using. */
f6b98e0b
JB
781 if (XTYPE (window) != Lisp_Window
782 || XWINDOW (window) == w)
f211082d
JB
783 {
784 Lisp_Object tem;
785
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);
792 if (INTEGERP (tem))
793 sortvec[j].priority = XINT (tem);
794 else
795 sortvec[j].priority = 0;
796 j++;
797 }
798 }
7b7739b1
JB
799 }
800 noverlays = j;
801
f211082d
JB
802 /* Sort the overlays into the proper order: increasing priority. */
803
bc0db68d
RS
804 if (noverlays > 1)
805 qsort (sortvec, noverlays, sizeof (struct sortvec), sort_overlays);
7b7739b1
JB
806
807 /* Now merge the overlay data in that order. */
7b7739b1
JB
808 for (i = 0; i < noverlays; i++)
809 {
f6b98e0b 810 prop = Foverlay_get (sortvec[i].overlay, Qface);
7b7739b1
JB
811 if (!NILP (prop))
812 {
813 Lisp_Object oend;
814 int oendpos;
815
1d9fd7fe 816 facecode = face_name_id_number (f, prop);
f211082d
JB
817 if (facecode >= 0 && facecode < FRAME_N_FACES (f)
818 && FRAME_FACES (f) [facecode] != 0)
819 merge_faces (FRAME_FACES (f) [facecode], &face);
7b7739b1 820
f6b98e0b 821 oend = OVERLAY_END (sortvec[i].overlay);
7b7739b1 822 oendpos = OVERLAY_POSITION (oend);
f6b98e0b 823 if (oendpos < endpos)
7b7739b1
JB
824 endpos = oendpos;
825 }
826 }
827
bc0db68d
RS
828 if (pos >= region_beg && pos < region_end)
829 {
830 if (region_end < endpos)
831 endpos = region_end;
832 if (region_face >= 0 && region_face < next_face_id)
833 merge_faces (FRAME_FACES (f) [region_face], &face);
834 }
835
7b7739b1
JB
836 *endptr = endpos;
837
cb637678 838 return intern_frame_face (f, &face);
f211082d
JB
839}
840
cb637678
JB
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. */
844int
18004d2b 845compute_glyph_face (f, face_code)
7b7739b1 846 struct frame *f;
7b7739b1
JB
847 int face_code;
848{
849 struct face face;
850
660ed669 851 compute_base_face (f, &face);
7b7739b1 852
f211082d
JB
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);
7b7739b1 856
cb637678 857 return intern_frame_face (f, &face);
c115973b 858}
660ed669
JB
859
860
861/* Recompute the GC's for the default and modeline faces.
862 We call this after changing frame parameters on which those GC's
863 depend. */
864void
865recompute_basic_faces (f)
866 FRAME_PTR f;
867{
868 /* If the frame's faces haven't been initialized yet, don't worry about
869 this stuff. */
870 if (FRAME_N_FACES (f) < 2)
871 return;
872
873 BLOCK_INPUT;
874
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));
878
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));
882
883 UNBLOCK_INPUT;
884}
885
886
c115973b 887\f
cb637678 888/* Lisp interface. */
c115973b
JB
889
890DEFUN ("frame-face-alist", Fframe_face_alist, Sframe_face_alist, 1, 1, 0,
891 "")
892 (frame)
893 Lisp_Object frame;
894{
895 CHECK_FRAME (frame, 0);
896 return XFRAME (frame)->face_alist;
897}
898
899DEFUN ("set-frame-face-alist", Fset_frame_face_alist, Sset_frame_face_alist,
900 2, 2, 0, "")
901 (frame, value)
902 Lisp_Object frame, value;
903{
904 CHECK_FRAME (frame, 0);
905 XFRAME (frame)->face_alist = value;
906 return value;
907}
908
909
910DEFUN ("make-face-internal", Fmake_face_internal, Smake_face_internal, 1, 1, 0,
911 "Create face number FACE-ID on all frames.")
912 (face_id)
913 Lisp_Object face_id;
914{
915 Lisp_Object rest;
916 int id = XINT (face_id);
917
f211082d
JB
918 CHECK_NUMBER (face_id, 0);
919 if (id < 0 || id >= next_face_id)
920 error ("Face id out of range");
c115973b
JB
921
922 for (rest = Vframe_list; !NILP (rest); rest = XCONS (rest)->cdr)
923 {
924 struct frame *f = XFRAME (XCONS (rest)->car);
cb637678
JB
925 if (FRAME_X_P (f))
926 ensure_face_ready (f, id);
c115973b
JB
927 }
928 return Qnil;
929}
930
931
932DEFUN ("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;
936{
937 struct face *face;
938 struct frame *f;
939 int magic_p;
940 int id;
941
942 CHECK_FRAME (frame, 0);
f211082d 943 CHECK_NUMBER (face_id, 0);
c115973b
JB
944 CHECK_SYMBOL (attr_name, 0);
945
946 f = XFRAME (frame);
947 id = XINT (face_id);
f211082d
JB
948 if (id < 0 || id >= next_face_id)
949 error ("Face id out of range");
c115973b 950
b6d40e46
JB
951 if (! FRAME_X_P (f))
952 return;
953
c115973b 954 ensure_face_ready (f, id);
f211082d 955 face = FRAME_FACES (f) [XFASTINT (face_id)];
c115973b
JB
956
957 if (EQ (attr_name, intern ("font")))
958 {
f211082d 959 XFontStruct *font = load_font (f, attr_value);
ebc64af3
RS
960 if (face->font != f->display.x->font)
961 unload_font (f, face->font);
c115973b 962 face->font = font;
c115973b
JB
963 }
964 else if (EQ (attr_name, intern ("foreground")))
965 {
f211082d 966 unsigned long new_color = load_color (f, attr_value);
c115973b
JB
967 unload_color (f, face->foreground);
968 face->foreground = new_color;
c115973b
JB
969 }
970 else if (EQ (attr_name, intern ("background")))
971 {
f211082d 972 unsigned long new_color = load_color (f, attr_value);
c115973b
JB
973 unload_color (f, face->background);
974 face->background = new_color;
c115973b
JB
975 }
976#if 0
977 else if (EQ (attr_name, intern ("background-pixmap")))
978 {
c115973b
JB
979 unsigned int w, h, d;
980 unsigned long new_pixmap = load_pixmap (f, attr_value, &w, &h, &d, 0);
f211082d
JB
981 unload_pixmap (f, face->stipple);
982 if (NILP (attr_value))
983 new_pixmap = 0;
984 face->stipple = new_pixmap;
c115973b
JB
985 face->pixmap_w = w;
986 face->pixmap_h = h;
987/* face->pixmap_depth = d; */
c115973b
JB
988 }
989#endif /* 0 */
990 else if (EQ (attr_name, intern ("underline")))
991 {
992 int new = !NILP (attr_value);
993 face->underline = new;
994 }
995 else
996 error ("unknown face attribute");
997
998 if (id == 0)
999 {
1000 BLOCK_INPUT;
660ed669 1001 if (FRAME_DEFAULT_FACE (f)->gc != 0)
f211082d
JB
1002 XFreeGC (x_current_display, FRAME_DEFAULT_FACE (f)->gc);
1003 build_face (f, FRAME_DEFAULT_FACE (f));
c115973b
JB
1004 UNBLOCK_INPUT;
1005 }
1006
1007 if (id == 1)
1008 {
1009 BLOCK_INPUT;
660ed669 1010 if (FRAME_MODE_LINE_FACE (f)->gc != 0)
f211082d
JB
1011 XFreeGC (x_current_display, FRAME_MODE_LINE_FACE (f)->gc);
1012 build_face (f, FRAME_MODE_LINE_FACE (f));
c115973b
JB
1013 UNBLOCK_INPUT;
1014 }
1015
584d0634
JB
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
1020 kick. */
1021 if (id == 0 || id == 1)
1022 SET_FRAME_GARBAGED (f);
1023 else
1024 /* Otherwise, it's enough to tell it to redisplay the text. */
1025 windows_or_buffers_changed = 1;
1026
c115973b
JB
1027 return Qnil;
1028}
1029
1030DEFUN ("internal-next-face-id", Finternal_next_face_id, Sinternal_next_face_id,
1031 0, 0, 0, "")
1032 ()
1033{
1034 return make_number (next_face_id++);
1035}
f211082d
JB
1036
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.) */
1041
1d9fd7fe
JB
1042int
1043face_name_id_number (f, name)
1044 FRAME_PTR f;
1045 Lisp_Object name;
f211082d
JB
1046{
1047 Lisp_Object tem;
1048
1d9fd7fe 1049 tem = Fcdr (Fassq (name, f->face_alist));
b6d40e46
JB
1050 if (NILP (tem))
1051 return 0;
f211082d
JB
1052 CHECK_VECTOR (tem, 0);
1053 tem = XVECTOR (tem)->contents[2];
1054 CHECK_NUMBER (tem, 0);
1055 return XINT (tem);
1056}
c115973b 1057\f
cb637678
JB
1058/* Emacs initialization. */
1059
c115973b 1060void
f211082d 1061syms_of_xfaces ()
c115973b 1062{
f211082d
JB
1063 Qwindow = intern ("window");
1064 staticpro (&Qwindow);
1065 Qface = intern ("face");
1066 staticpro (&Qface);
1067 Qpriority = intern ("priority");
1068 staticpro (&Qpriority);
1069
bc0db68d
RS
1070 DEFVAR_INT ("region-face", &region_face,
1071 "Face number to use to highlight the region\n\
1072The region is highlighted with this face\n\
1073when Transient Mark mode is enabled and the mark is active.");
1074
c115973b
JB
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);
1080}
cb637678
JB
1081
1082#endif /* HAVE_X_WINDOWS */
1083