(XOS_NEEDS_TIME_H): Defined.
[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
e11d186d 37/* Compensate for bug in Xos.h on hpux. */
28d72e6d 38#ifdef HPUX
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
c115973b 160static void build_face ();
1d9fd7fe 161int face_name_id_number ();
cb637678
JB
162
163struct face *intern_face ();
164static void ensure_face_ready ();
c115973b 165\f
cb637678
JB
166/* Allocating, copying, and comparing struct faces. */
167
168/* Allocate a new face */
169static struct face *
170allocate_face ()
171{
172 struct face *result = (struct face *) xmalloc (sizeof (struct face));
173 bzero (result, sizeof (struct face));
174 result->font = (XFontStruct *) FACE_DEFAULT;
175 result->foreground = FACE_DEFAULT;
176 result->background = FACE_DEFAULT;
177 result->stipple = FACE_DEFAULT;
178 return result;
179}
c115973b 180
cb637678 181/* Make a new face that's a copy of an existing one. */
c115973b
JB
182static struct face *
183copy_face (face)
184 struct face *face;
185{
186 struct face *result = allocate_face ();
187
188 result->font = face->font;
189 result->foreground = face->foreground;
190 result->background = face->background;
f211082d 191 result->stipple = face->stipple;
c115973b
JB
192 result->underline = face->underline;
193
194 return result;
195}
196
197static int
198face_eql (face1, face2)
199 struct face *face1, *face2;
200{
cb637678 201 return ( face1->font == face2->font
c115973b
JB
202 && face1->foreground == face2->foreground
203 && face1->background == face2->background
cb637678
JB
204 && face1->stipple == face2->stipple
205 && face1->underline == face2->underline);
c115973b 206}
cb637678
JB
207\f
208/* Interning faces in the `face_vector' cache, and clearing that cache. */
c115973b
JB
209
210/* Return the unique display face corresponding to the user-level face FACE.
c115973b
JB
211 If there isn't one, make one, and find a slot in the face_vector to
212 put it in. */
c115973b 213static struct face *
7b7739b1 214get_cached_face (f, face)
c115973b
JB
215 struct frame *f;
216 struct face *face;
217{
218 int i, empty = -1;
f211082d 219 struct face *result;
c115973b 220
cb637678
JB
221 /* Perhaps FACE->cached_index is valid; this could happen if FACE is
222 in a frame's face list. */
223 if (face->cached_index >= 0
224 && face->cached_index < nfaces
225 && face_eql (face_vector[face->cached_index], face))
226 return face_vector[face->cached_index];
227
c115973b
JB
228 /* Look for an existing display face that does the job.
229 Also find an empty slot if any. */
230 for (i = 0; i < nfaces; i++)
231 {
232 if (face_eql (face_vector[i], face))
233 return face_vector[i];
234 if (face_vector[i] == 0)
235 empty = i;
236 }
237
238 /* If no empty slots, make one. */
239 if (empty < 0 && nfaces == nfaces_allocated)
240 {
241 int newsize = nfaces + 20;
242 face_vector
243 = (struct face **) xrealloc (face_vector,
244 newsize * sizeof (struct face *));
245 nfaces_allocated = newsize;
246 }
247
248 if (empty < 0)
249 empty = nfaces++;
250
251 /* Put a new display face in the empty slot. */
252 result = copy_face (face);
253 face_vector[empty] = result;
254
255 /* Make a graphics context for it. */
256 build_face (f, result);
257
258 return result;
259}
260
cb637678
JB
261/* Given a frame face, return an equivalent display face
262 (one which has a graphics context). */
263
264struct face *
265intern_face (f, face)
266 struct frame *f;
267 struct face *face;
268{
cb637678
JB
269 /* If it's equivalent to the default face, use that. */
270 if (face_eql (face, FRAME_DEFAULT_FACE (f)))
271 {
272 if (!FRAME_DEFAULT_FACE (f)->gc)
273 build_face (f, FRAME_DEFAULT_FACE (f));
274 return FRAME_DEFAULT_FACE (f);
275 }
276
277 /* If it's equivalent to the mode line face, use that. */
278 if (face_eql (face, FRAME_MODE_LINE_FACE (f)))
279 {
280 if (!FRAME_MODE_LINE_FACE (f)->gc)
281 build_face (f, FRAME_MODE_LINE_FACE (f));
282 return FRAME_MODE_LINE_FACE (f);
283 }
284
f6b98e0b
JB
285 /* If it's not one of the frame's default faces, it shouldn't have a GC. */
286 if (face->gc)
287 abort ();
288
cb637678
JB
289 /* Get a specialized display face. */
290 return get_cached_face (f, face);
291}
292
c115973b
JB
293/* Clear out face_vector and start anew.
294 This should be done from time to time just to avoid
295 keeping too many graphics contexts in face_vector
296 that are no longer needed. */
297
298void
299clear_face_vector ()
300{
301 Lisp_Object rest;
302 Display *dpy = x_current_display;
f211082d 303 int i;
c115973b
JB
304
305 BLOCK_INPUT;
306 /* Free the display faces in the face_vector. */
307 for (i = 0; i < nfaces; i++)
308 {
309 struct face *face = face_vector[i];
f211082d
JB
310 if (face->gc)
311 XFreeGC (dpy, face->gc);
c115973b
JB
312 xfree (face);
313 }
314 nfaces = 0;
315
316 UNBLOCK_INPUT;
317}
318\f
cb637678
JB
319/* Allocating and freeing X resources for display faces. */
320
f211082d
JB
321/* Make a graphics context for face FACE, which is on frame F,
322 if that can be done. */
c115973b
JB
323static void
324build_face (f, face)
cb637678
JB
325 struct frame *f;
326 struct face *face;
c115973b
JB
327{
328 GC gc;
329 XGCValues xgcv;
330 unsigned long mask;
331
660ed669
JB
332 BLOCK_INPUT;
333
f211082d
JB
334 if (face->foreground != FACE_DEFAULT)
335 xgcv.foreground = face->foreground;
336 else
660ed669
JB
337 xgcv.foreground = f->display.x->foreground_pixel;
338
f211082d
JB
339 if (face->background != FACE_DEFAULT)
340 xgcv.background = face->background;
341 else
660ed669
JB
342 xgcv.background = f->display.x->background_pixel;
343
f211082d
JB
344 if (face->font && (int) face->font != FACE_DEFAULT)
345 xgcv.font = face->font->fid;
346 else
347 xgcv.font = f->display.x->font->fid;
660ed669 348
c115973b 349 xgcv.graphics_exposures = 0;
660ed669 350
c115973b
JB
351 mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;
352 gc = XCreateGC (x_current_display, FRAME_X_WINDOW (f),
353 mask, &xgcv);
660ed669 354
c115973b 355#if 0
f211082d
JB
356 if (face->stipple && face->stipple != FACE_DEFAULT)
357 XSetStipple (x_current_display, gc, face->stipple);
c115973b 358#endif
660ed669 359
f211082d 360 face->gc = gc;
660ed669
JB
361
362 UNBLOCK_INPUT;
c115973b 363}
cb637678
JB
364
365/* Allocating, freeing, and duplicating fonts, colors, and pixmaps. */
366
367static XFontStruct *
368load_font (f, name)
369 struct frame *f;
370 Lisp_Object name;
371{
372 XFontStruct *font;
373
374 if (NILP (name))
375 return (XFontStruct *) FACE_DEFAULT;
376
377 CHECK_STRING (name, 0);
378 BLOCK_INPUT;
379 font = XLoadQueryFont (x_current_display, (char *) XSTRING (name)->data);
380 UNBLOCK_INPUT;
381
382 if (! font)
383 Fsignal (Qerror, Fcons (build_string ("undefined font"),
384 Fcons (name, Qnil)));
385 return font;
386}
387
388static void
389unload_font (f, font)
390 struct frame *f;
391 XFontStruct *font;
392{
393 if (!font || font == ((XFontStruct *) FACE_DEFAULT))
394 return;
660ed669
JB
395
396 BLOCK_INPUT;
cb637678 397 XFreeFont (x_current_display, font);
660ed669 398 UNBLOCK_INPUT;
cb637678
JB
399}
400
401static unsigned long
402load_color (f, name)
403 struct frame *f;
404 Lisp_Object name;
405{
406 Display *dpy = x_current_display;
407 Colormap cmap;
408 XColor color;
409 int result;
410
411 if (NILP (name))
412 return FACE_DEFAULT;
413
414 cmap = DefaultColormapOfScreen (DefaultScreenOfDisplay (x_current_display));
415
416 CHECK_STRING (name, 0);
417 BLOCK_INPUT;
418 result = XParseColor (dpy, cmap, (char *) XSTRING (name)->data, &color);
419 UNBLOCK_INPUT;
420 if (! result)
421 Fsignal (Qerror, Fcons (build_string ("undefined color"),
422 Fcons (name, Qnil)));
423 BLOCK_INPUT;
424 result = XAllocColor (dpy, cmap, &color);
425 UNBLOCK_INPUT;
426 if (! result)
427 Fsignal (Qerror, Fcons (build_string ("X server cannot allocate color"),
428 Fcons (name, Qnil)));
429 return (unsigned long) color.pixel;
430}
431
432static void
433unload_color (f, pixel)
434 struct frame *f;
7a4d2269 435 unsigned long pixel;
cb637678 436{
1d9fd7fe
JB
437 /* Since faces get built by copying parameters from other faces, the
438 allocation counts for the colors get all screwed up. I don't see
439 any solution that will take less than 10 minutes, and it's better
440 to have a color leak than a crash, so I'm just dyking this out.
441 This isn't really a color leak, anyway - if we ask for it again,
442 we'll get the same pixel. */
443#if 0
cb637678
JB
444 Colormap cmap;
445 Display *dpy = x_current_display;
32dc0866
JB
446 if (pixel == FACE_DEFAULT
447 || pixel == BLACK_PIX_DEFAULT
448 || pixel == WHITE_PIX_DEFAULT)
cb637678
JB
449 return;
450 cmap = DefaultColormapOfScreen (DefaultScreenOfDisplay (x_current_display));
451 BLOCK_INPUT;
452 XFreeColors (dpy, cmap, &pixel, 1, 0);
453 UNBLOCK_INPUT;
1d9fd7fe 454#endif
cb637678
JB
455}
456\f
457/* Initializing face arrays for frames. */
458
cb637678
JB
459void
460init_frame_faces (f)
660ed669 461 FRAME_PTR f;
cb637678
JB
462{
463 ensure_face_ready (f, 0);
cb637678 464 ensure_face_ready (f, 1);
660ed669
JB
465
466 recompute_basic_faces (f);
7b37f67b
JB
467
468 /* Supposedly, we only apply this function to newly-created frames. */
469 if (selected_frame == f)
470 abort ();
471
472 /* Make sure that all faces valid on the selected frame are also valid
473 on this new frame. */
b3d7fa6a
RS
474 if (FRAME_X_P (selected_frame))
475 {
476 int i;
477 int n_faces = selected_frame->display.x->n_faces;
478 struct face **faces = selected_frame->display.x->faces;
479
480 for (i = 2; i < n_faces; i++)
481 if (faces[i])
482 ensure_face_ready (f, i);
483 }
cb637678
JB
484}
485
660ed669 486
cb637678
JB
487/* Called from Fdelete_frame. */
488void
489free_frame_faces (f)
490 struct frame *f;
491{
492 Display *dpy = x_current_display;
493 int i;
494
660ed669
JB
495 BLOCK_INPUT;
496
497 for (i = 0; i < FRAME_N_FACES (f); i++)
cb637678
JB
498 {
499 struct face *face = FRAME_FACES (f) [i];
660ed669
JB
500 if (face)
501 {
502 if (face->gc)
503 XFreeGC (dpy, face->gc);
504 if (! face->copy)
505 {
506 unload_font (f, face->font);
507 unload_color (f, face->foreground);
508 unload_color (f, face->background);
cb637678 509#if 0
660ed669 510 unload_pixmap (f, face->stipple);
cb637678 511#endif
660ed669
JB
512 }
513 xfree (face);
514 }
cb637678
JB
515 }
516 xfree (FRAME_FACES (f));
517 FRAME_FACES (f) = 0;
518 FRAME_N_FACES (f) = 0;
660ed669
JB
519
520 UNBLOCK_INPUT;
cb637678 521}
c115973b 522\f
cb637678
JB
523/* Interning faces in a frame's face array. */
524
525/* Find a match for NEW_FACE in a FRAME's face array, and add it if we don't
526 find one. */
660ed669 527static int
b6d40e46 528intern_frame_face (frame, new_face)
cb637678 529 struct frame *frame;
b6d40e46 530 struct face *new_face;
cb637678
JB
531{
532 int len = FRAME_N_FACES (frame);
533 int i;
534
535 /* Search for a face already on FRAME equivalent to FACE. */
536 for (i = 0; i < len; i++)
537 {
538 struct face *frame_face = FRAME_FACES (frame)[i];
539
540 if (frame_face && face_eql (new_face, frame_face))
541 return i;
542 }
543
544 /* We didn't find one; add a new one. */
545 i = next_face_id++;
546
547 ensure_face_ready (frame, i);
f6b98e0b 548 bcopy (new_face, FRAME_FACES (frame)[i], sizeof (*new_face));
660ed669 549 FRAME_FACES (frame)[i]->copy = 1;
cb637678
JB
550
551 return i;
552}
553
554/* Make face id ID valid on frame F. */
555
556static void
557ensure_face_ready (f, id)
558 struct frame *f;
559 int id;
560{
561 if (FRAME_N_FACES (f) <= id)
562 {
563 int n = id + 10;
564 int i;
565 if (!FRAME_N_FACES (f))
566 FRAME_FACES (f)
567 = (struct face **) xmalloc (sizeof (struct face *) * n);
568 else
569 FRAME_FACES (f)
570 = (struct face **) xrealloc (FRAME_FACES (f),
571 sizeof (struct face *) * n);
572
573 bzero (FRAME_FACES (f) + FRAME_N_FACES (f),
574 (n - FRAME_N_FACES (f)) * sizeof (struct face *));
575 FRAME_N_FACES (f) = n;
576 }
577
578 if (FRAME_FACES (f) [id] == 0)
579 FRAME_FACES (f) [id] = allocate_face ();
580}
581\f
582/* Computing faces appropriate for a given piece of text in a buffer. */
583
660ed669
JB
584/* Return non-zero if FONT1 and FONT2 have the same size bounding box.
585 We assume that they're both character-cell fonts. */
586int
587same_size_fonts (font1, font2)
588 XFontStruct *font1, *font2;
589{
590 XCharStruct *bounds1 = &font1->min_bounds;
591 XCharStruct *bounds2 = &font2->min_bounds;
592
593 return (bounds1->width == bounds2->width
594 && bounds1->ascent == bounds2->ascent
595 && bounds1->descent == bounds2->descent);
596}
597
7b7739b1
JB
598/* Modify face TO by copying from FROM all properties which have
599 nondefault settings. */
7b7739b1
JB
600static void
601merge_faces (from, to)
602 struct face *from, *to;
603{
68a97335
JB
604 /* Only merge the font if it's the same size as the base font. */
605 if (from->font != (XFontStruct *) FACE_DEFAULT
68a97335
JB
606 && same_size_fonts (from->font, to->font))
607 to->font = from->font;
7b7739b1
JB
608 if (from->foreground != FACE_DEFAULT)
609 to->foreground = from->foreground;
610 if (from->background != FACE_DEFAULT)
611 to->background = from->background;
f211082d
JB
612 if (from->stipple != FACE_DEFAULT)
613 to->stipple = from->stipple;
7b7739b1
JB
614 if (from->underline)
615 to->underline = from->underline;
616}
617
660ed669
JB
618/* Set up the basic set of facial parameters, based on the frame's
619 data; all faces are deltas applied to this. */
620static void
621compute_base_face (f, face)
622 FRAME_PTR f;
623 struct face *face;
624{
625 struct x_display *d = f->display.x;
626
627 face->gc = 0;
628 face->foreground = d->foreground_pixel;
629 face->background = d->background_pixel;
630 face->font = d->font;
631 face->underline = 0;
632}
633
634
f211082d
JB
635struct sortvec
636{
637 Lisp_Object overlay;
638 int beg, end;
639 int priority;
640};
641
cb637678
JB
642static int
643sort_overlays (s1, s2)
644 struct sortvec *s1, *s2;
645{
646 if (s1->priority != s2->priority)
647 return s1->priority - s2->priority;
648 if (s1->beg != s2->beg)
649 return s1->beg - s2->beg;
650 if (s1->end != s2->end)
651 return s2->end - s1->end;
652 return 0;
653}
654
655/* Return the face ID associated with a buffer position POS.
7b7739b1
JB
656 Store into *ENDPTR the position at which a different face is needed.
657 This does not take account of glyphs that specify their own face codes.
f6b98e0b 658 F is the frame in use for display, and W is a window displaying
bc0db68d
RS
659 the current buffer.
660
661 REGION_BEG, REGION_END delimit the region, so it can be highlighted. */
662
cb637678 663int
bc0db68d 664compute_char_face (f, w, pos, region_beg, region_end, endptr)
7b7739b1 665 struct frame *f;
f211082d 666 struct window *w;
7b7739b1 667 int pos;
bc0db68d 668 int region_beg, region_end;
7b7739b1
JB
669 int *endptr;
670{
671 struct face face;
b6d40e46 672 Lisp_Object prop, position;
7b7739b1
JB
673 int i, j, noverlays;
674 int facecode;
7b7739b1 675 Lisp_Object *overlay_vec;
f211082d
JB
676 struct sortvec *sortvec;
677 Lisp_Object frame;
f6b98e0b
JB
678 int endpos;
679
680 /* W must display the current buffer. We could write this function
681 to use the frame and buffer of W, but right now it doesn't. */
682 if (XBUFFER (w->buffer) != current_buffer)
683 abort ();
f211082d
JB
684
685 XSET (frame, Lisp_Frame, f);
7b7739b1 686
f6b98e0b 687 endpos = ZV;
bc0db68d
RS
688 if (pos < region_beg && region_beg < endpos)
689 endpos = region_beg;
f6b98e0b 690
7b7739b1 691 XFASTINT (position) = pos;
b6d40e46
JB
692 prop = Fget_text_property (position, Qface, w->buffer);
693 {
694 Lisp_Object end;
7b7739b1 695
b6d40e46
JB
696 end = Fnext_single_property_change (position, Qface, w->buffer);
697 if (INTEGERP (end))
698 endpos = XINT (end);
699 }
700
701 {
f6b98e0b 702 int next_overlay;
9516fe94
RS
703 int len;
704
705 /* First try with room for 40 overlays. */
706 len = 40;
707 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
708
709 noverlays = overlays_at (pos, 0, &overlay_vec, &len, &next_overlay);
710
711 /* If there are more than 40,
712 make enough space for all, and try again. */
713 if (noverlays > len)
714 {
715 len = noverlays;
716 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
717 noverlays = overlays_at (pos, 0, &overlay_vec, &len, &next_overlay);
718 }
b6d40e46 719
f6b98e0b
JB
720 if (next_overlay < endpos)
721 endpos = next_overlay;
b6d40e46
JB
722 }
723
724 *endptr = endpos;
7b7739b1
JB
725
726 /* Optimize the default case. */
bc0db68d
RS
727 if (noverlays == 0 && NILP (prop)
728 && !(pos >= region_beg && pos < region_end))
cb637678 729 return 0;
7b7739b1 730
660ed669 731 compute_base_face (f, &face);
7b7739b1
JB
732
733 if (!NILP (prop))
734 {
1d9fd7fe 735 facecode = face_name_id_number (f, prop);
f211082d
JB
736 if (facecode >= 0 && facecode < FRAME_N_FACES (f)
737 && FRAME_FACES (f) [facecode] != 0)
738 merge_faces (FRAME_FACES (f) [facecode], &face);
7b7739b1
JB
739 }
740
f211082d
JB
741 /* Put the valid and relevant overlays into sortvec. */
742 sortvec = (struct sortvec *) alloca (noverlays * sizeof (struct sortvec));
743
7b7739b1
JB
744 for (i = 0, j = 0; i < noverlays; i++)
745 {
b6d40e46 746 Lisp_Object overlay = overlay_vec[i];
7b7739b1
JB
747
748 if (OVERLAY_VALID (overlay)
749 && OVERLAY_POSITION (OVERLAY_START (overlay)) > 0
750 && OVERLAY_POSITION (OVERLAY_END (overlay)) > 0)
f211082d
JB
751 {
752 Lisp_Object window;
753 window = Foverlay_get (overlay, Qwindow);
754
755 /* Also ignore overlays limited to one window
756 if it's not the window we are using. */
f6b98e0b
JB
757 if (XTYPE (window) != Lisp_Window
758 || XWINDOW (window) == w)
f211082d
JB
759 {
760 Lisp_Object tem;
761
762 /* This overlay is good and counts:
763 put it in sortvec. */
764 sortvec[j].overlay = overlay;
765 sortvec[j].beg = OVERLAY_POSITION (OVERLAY_START (overlay));
766 sortvec[j].end = OVERLAY_POSITION (OVERLAY_END (overlay));
767 tem = Foverlay_get (overlay, Qpriority);
768 if (INTEGERP (tem))
769 sortvec[j].priority = XINT (tem);
770 else
771 sortvec[j].priority = 0;
772 j++;
773 }
774 }
7b7739b1
JB
775 }
776 noverlays = j;
777
f211082d
JB
778 /* Sort the overlays into the proper order: increasing priority. */
779
bc0db68d
RS
780 if (noverlays > 1)
781 qsort (sortvec, noverlays, sizeof (struct sortvec), sort_overlays);
7b7739b1
JB
782
783 /* Now merge the overlay data in that order. */
7b7739b1
JB
784 for (i = 0; i < noverlays; i++)
785 {
f6b98e0b 786 prop = Foverlay_get (sortvec[i].overlay, Qface);
7b7739b1
JB
787 if (!NILP (prop))
788 {
789 Lisp_Object oend;
790 int oendpos;
791
1d9fd7fe 792 facecode = face_name_id_number (f, prop);
f211082d
JB
793 if (facecode >= 0 && facecode < FRAME_N_FACES (f)
794 && FRAME_FACES (f) [facecode] != 0)
795 merge_faces (FRAME_FACES (f) [facecode], &face);
7b7739b1 796
f6b98e0b 797 oend = OVERLAY_END (sortvec[i].overlay);
7b7739b1 798 oendpos = OVERLAY_POSITION (oend);
f6b98e0b 799 if (oendpos < endpos)
7b7739b1
JB
800 endpos = oendpos;
801 }
802 }
803
bc0db68d
RS
804 if (pos >= region_beg && pos < region_end)
805 {
806 if (region_end < endpos)
807 endpos = region_end;
808 if (region_face >= 0 && region_face < next_face_id)
809 merge_faces (FRAME_FACES (f) [region_face], &face);
810 }
811
7b7739b1
JB
812 *endptr = endpos;
813
cb637678 814 return intern_frame_face (f, &face);
f211082d
JB
815}
816
cb637678
JB
817/* Return the face ID to use to display a special glyph which selects
818 FACE_CODE as the face ID, assuming that ordinarily the face would
819 be BASIC_FACE. F is the frame. */
820int
18004d2b 821compute_glyph_face (f, face_code)
7b7739b1 822 struct frame *f;
7b7739b1
JB
823 int face_code;
824{
825 struct face face;
826
660ed669 827 compute_base_face (f, &face);
7b7739b1 828
f211082d
JB
829 if (face_code >= 0 && face_code < FRAME_N_FACES (f)
830 && FRAME_FACES (f) [face_code] != 0)
831 merge_faces (FRAME_FACES (f) [face_code], &face);
7b7739b1 832
cb637678 833 return intern_frame_face (f, &face);
c115973b 834}
660ed669
JB
835
836
837/* Recompute the GC's for the default and modeline faces.
838 We call this after changing frame parameters on which those GC's
839 depend. */
840void
841recompute_basic_faces (f)
842 FRAME_PTR f;
843{
844 /* If the frame's faces haven't been initialized yet, don't worry about
845 this stuff. */
846 if (FRAME_N_FACES (f) < 2)
847 return;
848
849 BLOCK_INPUT;
850
851 if (FRAME_DEFAULT_FACE (f)->gc)
852 XFreeGC (x_current_display, FRAME_DEFAULT_FACE (f)->gc);
853 build_face (f, FRAME_DEFAULT_FACE (f));
854
855 if (FRAME_MODE_LINE_FACE (f)->gc)
856 XFreeGC (x_current_display, FRAME_MODE_LINE_FACE (f)->gc);
857 build_face (f, FRAME_MODE_LINE_FACE (f));
858
859 UNBLOCK_INPUT;
860}
861
862
c115973b 863\f
cb637678 864/* Lisp interface. */
c115973b
JB
865
866DEFUN ("frame-face-alist", Fframe_face_alist, Sframe_face_alist, 1, 1, 0,
867 "")
868 (frame)
869 Lisp_Object frame;
870{
871 CHECK_FRAME (frame, 0);
872 return XFRAME (frame)->face_alist;
873}
874
875DEFUN ("set-frame-face-alist", Fset_frame_face_alist, Sset_frame_face_alist,
876 2, 2, 0, "")
877 (frame, value)
878 Lisp_Object frame, value;
879{
880 CHECK_FRAME (frame, 0);
881 XFRAME (frame)->face_alist = value;
882 return value;
883}
884
885
886DEFUN ("make-face-internal", Fmake_face_internal, Smake_face_internal, 1, 1, 0,
887 "Create face number FACE-ID on all frames.")
888 (face_id)
889 Lisp_Object face_id;
890{
891 Lisp_Object rest;
892 int id = XINT (face_id);
893
f211082d
JB
894 CHECK_NUMBER (face_id, 0);
895 if (id < 0 || id >= next_face_id)
896 error ("Face id out of range");
c115973b
JB
897
898 for (rest = Vframe_list; !NILP (rest); rest = XCONS (rest)->cdr)
899 {
900 struct frame *f = XFRAME (XCONS (rest)->car);
cb637678
JB
901 if (FRAME_X_P (f))
902 ensure_face_ready (f, id);
c115973b
JB
903 }
904 return Qnil;
905}
906
907
908DEFUN ("set-face-attribute-internal", Fset_face_attribute_internal,
909 Sset_face_attribute_internal, 4, 4, 0, "")
910 (face_id, attr_name, attr_value, frame)
911 Lisp_Object face_id, attr_name, attr_value, frame;
912{
913 struct face *face;
914 struct frame *f;
915 int magic_p;
916 int id;
917
918 CHECK_FRAME (frame, 0);
f211082d 919 CHECK_NUMBER (face_id, 0);
c115973b
JB
920 CHECK_SYMBOL (attr_name, 0);
921
922 f = XFRAME (frame);
923 id = XINT (face_id);
f211082d
JB
924 if (id < 0 || id >= next_face_id)
925 error ("Face id out of range");
c115973b 926
b6d40e46
JB
927 if (! FRAME_X_P (f))
928 return;
929
c115973b 930 ensure_face_ready (f, id);
f211082d 931 face = FRAME_FACES (f) [XFASTINT (face_id)];
c115973b
JB
932
933 if (EQ (attr_name, intern ("font")))
934 {
f211082d 935 XFontStruct *font = load_font (f, attr_value);
ebc64af3
RS
936 if (face->font != f->display.x->font)
937 unload_font (f, face->font);
c115973b 938 face->font = font;
c115973b
JB
939 }
940 else if (EQ (attr_name, intern ("foreground")))
941 {
f211082d 942 unsigned long new_color = load_color (f, attr_value);
c115973b
JB
943 unload_color (f, face->foreground);
944 face->foreground = new_color;
c115973b
JB
945 }
946 else if (EQ (attr_name, intern ("background")))
947 {
f211082d 948 unsigned long new_color = load_color (f, attr_value);
c115973b
JB
949 unload_color (f, face->background);
950 face->background = new_color;
c115973b
JB
951 }
952#if 0
953 else if (EQ (attr_name, intern ("background-pixmap")))
954 {
c115973b
JB
955 unsigned int w, h, d;
956 unsigned long new_pixmap = load_pixmap (f, attr_value, &w, &h, &d, 0);
f211082d
JB
957 unload_pixmap (f, face->stipple);
958 if (NILP (attr_value))
959 new_pixmap = 0;
960 face->stipple = new_pixmap;
c115973b
JB
961 face->pixmap_w = w;
962 face->pixmap_h = h;
963/* face->pixmap_depth = d; */
c115973b
JB
964 }
965#endif /* 0 */
966 else if (EQ (attr_name, intern ("underline")))
967 {
968 int new = !NILP (attr_value);
969 face->underline = new;
970 }
971 else
972 error ("unknown face attribute");
973
974 if (id == 0)
975 {
976 BLOCK_INPUT;
660ed669 977 if (FRAME_DEFAULT_FACE (f)->gc != 0)
f211082d
JB
978 XFreeGC (x_current_display, FRAME_DEFAULT_FACE (f)->gc);
979 build_face (f, FRAME_DEFAULT_FACE (f));
c115973b
JB
980 UNBLOCK_INPUT;
981 }
982
983 if (id == 1)
984 {
985 BLOCK_INPUT;
660ed669 986 if (FRAME_MODE_LINE_FACE (f)->gc != 0)
f211082d
JB
987 XFreeGC (x_current_display, FRAME_MODE_LINE_FACE (f)->gc);
988 build_face (f, FRAME_MODE_LINE_FACE (f));
c115973b
JB
989 UNBLOCK_INPUT;
990 }
991
584d0634
JB
992 /* If we're modifying either of the frame's display faces, that
993 means that we're changing the parameters of a fixed face code;
994 since the color/font/whatever is changed but the face ID hasn't,
995 redisplay won't know to redraw the affected sections. Give it a
996 kick. */
997 if (id == 0 || id == 1)
998 SET_FRAME_GARBAGED (f);
999 else
1000 /* Otherwise, it's enough to tell it to redisplay the text. */
1001 windows_or_buffers_changed = 1;
1002
c115973b
JB
1003 return Qnil;
1004}
1005
1006DEFUN ("internal-next-face-id", Finternal_next_face_id, Sinternal_next_face_id,
1007 0, 0, 0, "")
1008 ()
1009{
1010 return make_number (next_face_id++);
1011}
f211082d
JB
1012
1013/* Return the face id for name NAME on frame FRAME.
1014 (It should be the same for all frames,
1015 but it's as easy to use the "right" frame to look it up
1016 as to use any other one.) */
1017
1d9fd7fe
JB
1018int
1019face_name_id_number (f, name)
1020 FRAME_PTR f;
1021 Lisp_Object name;
f211082d
JB
1022{
1023 Lisp_Object tem;
1024
1d9fd7fe 1025 tem = Fcdr (Fassq (name, f->face_alist));
b6d40e46
JB
1026 if (NILP (tem))
1027 return 0;
f211082d
JB
1028 CHECK_VECTOR (tem, 0);
1029 tem = XVECTOR (tem)->contents[2];
1030 CHECK_NUMBER (tem, 0);
1031 return XINT (tem);
1032}
c115973b 1033\f
cb637678
JB
1034/* Emacs initialization. */
1035
c115973b 1036void
f211082d 1037syms_of_xfaces ()
c115973b 1038{
f211082d
JB
1039 Qwindow = intern ("window");
1040 staticpro (&Qwindow);
1041 Qface = intern ("face");
1042 staticpro (&Qface);
1043 Qpriority = intern ("priority");
1044 staticpro (&Qpriority);
1045
bc0db68d
RS
1046 DEFVAR_INT ("region-face", &region_face,
1047 "Face number to use to highlight the region\n\
1048The region is highlighted with this face\n\
1049when Transient Mark mode is enabled and the mark is active.");
1050
c115973b
JB
1051 defsubr (&Sframe_face_alist);
1052 defsubr (&Sset_frame_face_alist);
1053 defsubr (&Smake_face_internal);
1054 defsubr (&Sset_face_attribute_internal);
1055 defsubr (&Sinternal_next_face_id);
1056}
cb637678
JB
1057
1058#endif /* HAVE_X_WINDOWS */
1059