2 Copyright (C) 1992, 1993 Free Software Foundation.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
20 /* This is derived from work by Lucid (some parts very loosely so). */
22 #include <sys/types.h>
30 #include "dispextern.h"
32 #include "blockinput.h"
33 /* #include "window.h" */
35 /* Display Context for the icons */
36 #include <X11/Intrinsic.h>
37 #include <X11/StringDefs.h>
38 /* #include <X11/Xmu/Drawing.h> */ /* Appears not to be used */
41 /* We use face structures in two ways:
42 At the frame level, each frame has a vector of faces (FRAME_FACES).
43 Face number 0 is the default face (for normal text).
44 Face number 1 is the mode line face.
45 Higher face numbers have no built-in meaning.
46 The faces in these vectors are called "frame faces".
48 Faces number 0 and 1 have graphics contexts.
49 They can be used in the redisplay code directly.
50 Higher numbered frame faces do not have graphics contexts.
52 There are also "cached faces". They have graphics contexts.
53 They are kept in a C vector called face_vector.
55 A "display face" is a face with a graphics context.
56 It is either a frame face number 0 or 1,
59 /* A table of display faces. */
60 struct face
**face_vector
;
61 /* The length in use of the table. */
63 /* The allocated length of the table. */
66 /* The number of face-id's in use (same for all frames). */
69 #define FACE_DEFAULT (~0)
71 Lisp_Object Qface
, Qwindow
, Qpriority
;
73 static struct face
*allocate_face ();
74 static void build_face ();
75 static int sort_overlays ();
76 static struct face
*get_display_face ();
77 static Lisp_Object
face_name_id_number ();
79 /* Make a new face that's a copy of an existing one. */
85 struct face
*result
= allocate_face ();
87 result
->font
= face
->font
;
88 result
->foreground
= face
->foreground
;
89 result
->background
= face
->background
;
90 result
->stipple
= face
->stipple
;
91 result
->underline
= face
->underline
;
97 face_eql (face1
, face2
)
98 struct face
*face1
, *face2
;
100 return (face1
->font
== face2
->font
101 && face1
->foreground
== face2
->foreground
102 && face1
->background
== face2
->background
103 && face1
->stipple
== face2
->stipple
104 && face1
->underline
== face2
->underline
);
107 /* Return the unique display face corresponding to the user-level face FACE.
109 If there isn't one, make one, and find a slot in the face_vector to
113 get_cached_face (f
, face
)
120 /* Look for an existing display face that does the job.
121 Also find an empty slot if any. */
122 for (i
= 0; i
< nfaces
; i
++)
124 if (face_eql (face_vector
[i
], face
))
125 return face_vector
[i
];
126 if (face_vector
[i
] == 0)
130 /* If no empty slots, make one. */
131 if (empty
< 0 && nfaces
== nfaces_allocated
)
133 int newsize
= nfaces
+ 20;
135 = (struct face
**) xrealloc (face_vector
,
136 newsize
* sizeof (struct face
*));
137 nfaces_allocated
= newsize
;
143 /* Put a new display face in the empty slot. */
144 result
= copy_face (face
);
145 face_vector
[empty
] = result
;
147 /* Make a graphics context for it. */
148 build_face (f
, result
);
153 /* Clear out face_vector and start anew.
154 This should be done from time to time just to avoid
155 keeping too many graphics contexts in face_vector
156 that are no longer needed. */
162 Display
*dpy
= x_current_display
;
166 /* Free the display faces in the face_vector. */
167 for (i
= 0; i
< nfaces
; i
++)
169 struct face
*face
= face_vector
[i
];
171 XFreeGC (dpy
, face
->gc
);
179 /* Make a graphics context for face FACE, which is on frame F,
180 if that can be done. */
191 if (face
->foreground
!= FACE_DEFAULT
)
192 xgcv
.foreground
= face
->foreground
;
194 xgcv
. foreground
= f
->display
.x
->foreground_pixel
;
195 if (face
->background
!= FACE_DEFAULT
)
196 xgcv
.background
= face
->background
;
198 xgcv
. background
= f
->display
.x
->background_pixel
;
199 if (face
->font
&& (int) face
->font
!= FACE_DEFAULT
)
200 xgcv
.font
= face
->font
->fid
;
202 xgcv
.font
= f
->display
.x
->font
->fid
;
203 xgcv
.graphics_exposures
= 0;
204 mask
= GCForeground
| GCBackground
| GCFont
| GCGraphicsExposures
;
205 gc
= XCreateGC (x_current_display
, FRAME_X_WINDOW (f
),
208 if (face
->stipple
&& face
->stipple
!= FACE_DEFAULT
)
209 XSetStipple (x_current_display
, gc
, face
->stipple
);
214 /* Modify face TO by copying from FROM all properties which have
215 nondefault settings. */
218 merge_faces (from
, to
)
219 struct face
*from
, *to
;
221 if (from
->font
!= (XFontStruct
*)FACE_DEFAULT
)
223 to
->font
= from
->font
;
225 if (from
->foreground
!= FACE_DEFAULT
)
226 to
->foreground
= from
->foreground
;
227 if (from
->background
!= FACE_DEFAULT
)
228 to
->background
= from
->background
;
229 if (from
->stipple
!= FACE_DEFAULT
)
230 to
->stipple
= from
->stipple
;
232 to
->underline
= from
->underline
;
242 /* Return the display face associated with a buffer position POS.
243 Store into *ENDPTR the position at which a different face is needed.
244 This does not take account of glyphs that specify their own face codes.
245 F is the frame in use for display, and W is the window. */
248 compute_char_face (f
, w
, pos
, endptr
)
255 Lisp_Object prop
, position
, length
;
256 Lisp_Object overlay
, start
, end
;
260 Lisp_Object
*overlay_vec
;
262 struct sortvec
*sortvec
;
265 XSET (frame
, Lisp_Frame
, f
);
267 XFASTINT (position
) = pos
;
268 prop
= Fget_text_property (position
, Qface
);
271 overlay_vec
= (Lisp_Object
*) xmalloc (len
* sizeof (Lisp_Object
));
272 noverlays
= overlays_at (pos
, &overlay_vec
, &len
, &endpos
);
274 /* Optimize the default case. */
275 if (noverlays
== 0 && NILP (prop
))
276 return FRAME_DEFAULT_FACE (f
);
278 bcopy (FRAME_DEFAULT_FACE (f
), &face
, sizeof (struct face
));
282 facecode
= face_name_id_number (frame
, prop
);
283 if (facecode
>= 0 && facecode
< FRAME_N_FACES (f
)
284 && FRAME_FACES (f
) [facecode
] != 0)
285 merge_faces (FRAME_FACES (f
) [facecode
], &face
);
288 /* Put the valid and relevant overlays into sortvec. */
289 sortvec
= (struct sortvec
*) alloca (noverlays
* sizeof (struct sortvec
));
291 for (i
= 0, j
= 0; i
< noverlays
; i
++)
293 overlay
= overlay_vec
[i
];
295 if (OVERLAY_VALID (overlay
)
296 && OVERLAY_POSITION (OVERLAY_START (overlay
)) > 0
297 && OVERLAY_POSITION (OVERLAY_END (overlay
)) > 0)
300 window
= Foverlay_get (overlay
, Qwindow
);
302 /* Also ignore overlays limited to one window
303 if it's not the window we are using. */
304 if (NILP (window
) || XWINDOW (window
) == w
)
308 /* This overlay is good and counts:
309 put it in sortvec. */
310 sortvec
[j
].overlay
= overlay
;
311 sortvec
[j
].beg
= OVERLAY_POSITION (OVERLAY_START (overlay
));
312 sortvec
[j
].end
= OVERLAY_POSITION (OVERLAY_END (overlay
));
313 tem
= Foverlay_get (overlay
, Qpriority
);
315 sortvec
[j
].priority
= XINT (tem
);
317 sortvec
[j
].priority
= 0;
324 /* Sort the overlays into the proper order: increasing priority. */
326 qsort (sortvec
, noverlays
, sizeof (struct sortvec
), sort_overlays
);
328 /* Now merge the overlay data in that order. */
330 for (i
= 0; i
< noverlays
; i
++)
332 prop
= Foverlay_get (overlay_vec
[i
], Qface
);
338 facecode
= face_name_id_number (frame
, prop
);
339 if (facecode
>= 0 && facecode
< FRAME_N_FACES (f
)
340 && FRAME_FACES (f
) [facecode
] != 0)
341 merge_faces (FRAME_FACES (f
) [facecode
], &face
);
343 oend
= OVERLAY_END (overlay_vec
[i
]);
344 oendpos
= OVERLAY_POSITION (oend
);
345 if (oendpos
> endpos
)
354 return get_display_face (f
, &face
);
358 sort_overlays (s1
, s2
)
359 struct sortvec
*s1
, *s2
;
361 if (s1
->priority
!= s2
->priority
)
362 return s1
->priority
- s2
->priority
;
363 if (s1
->beg
!= s2
->beg
)
364 return s1
->beg
- s2
->beg
;
365 if (s1
->end
!= s2
->end
)
366 return s2
->end
- s1
->end
;
370 /* Return the display face to use to display a special glyph
371 which selects FACE_CODE as the face ID,
372 assuming that ordinarily the face would be BASIC_FACE.
376 compute_glyph_face (f
, basic_face
, face_code
)
378 struct face
*basic_face
;
383 bcopy (basic_face
, &face
, sizeof (struct face
));
385 if (face_code
>= 0 && face_code
< FRAME_N_FACES (f
)
386 && FRAME_FACES (f
) [face_code
] != 0)
387 merge_faces (FRAME_FACES (f
) [face_code
], &face
);
389 return get_display_face (f
, &face
);
392 /* Given a frame face, return an equivalent display face
393 (one which has a graphics context). */
396 get_display_face (f
, face
)
402 /* Does the face have a GC already? */
406 /* If it's equivalent to the default face, use that. */
407 if (face
->font
== FRAME_DEFAULT_FACE (f
)->font
408 && face
->foreground
== FRAME_DEFAULT_FACE (f
)->foreground
409 && face
->background
== FRAME_DEFAULT_FACE (f
)->background
410 && face
->stipple
== FRAME_DEFAULT_FACE (f
)->stipple
411 && face
->underline
== FRAME_DEFAULT_FACE (f
)->underline
)
413 if (!FRAME_DEFAULT_FACE (f
)->gc
)
414 build_face (f
, FRAME_DEFAULT_FACE (f
));
415 return FRAME_DEFAULT_FACE (f
);
418 /* If it's equivalent to the mode line face, use that. */
419 if (face
->font
== FRAME_MODE_LINE_FACE (f
)->font
420 && face
->foreground
== FRAME_MODE_LINE_FACE (f
)->foreground
421 && face
->background
== FRAME_MODE_LINE_FACE (f
)->background
422 && face
->stipple
== FRAME_MODE_LINE_FACE (f
)->stipple
423 && face
->underline
== FRAME_MODE_LINE_FACE (f
)->underline
)
425 if (!FRAME_MODE_LINE_FACE (f
)->gc
)
426 build_face (f
, FRAME_MODE_LINE_FACE (f
));
427 return FRAME_MODE_LINE_FACE (f
);
430 /* Get a specialized display face. */
431 return get_cached_face (f
, face
);
435 /* Allocate a new face */
439 struct face
*result
= (struct face
*) xmalloc (sizeof (struct face
));
440 bzero (result
, sizeof (struct face
));
441 result
->font
= (XFontStruct
*) FACE_DEFAULT
;
442 result
->foreground
= FACE_DEFAULT
;
443 result
->background
= FACE_DEFAULT
;
444 result
->stipple
= FACE_DEFAULT
;
448 /* Make face id ID valid on frame F. */
451 ensure_face_ready (f
, id
)
455 if (FRAME_N_FACES (f
) <= id
)
459 if (!FRAME_N_FACES (f
))
461 = (struct face
**) xmalloc (sizeof (struct face
*) * n
);
464 = (struct face
**) xrealloc (FRAME_FACES (f
),
465 sizeof (struct face
*) * n
);
467 bzero (FRAME_FACES (f
) + FRAME_N_FACES (f
),
468 (n
- FRAME_N_FACES (f
)) * sizeof (struct face
*));
469 FRAME_N_FACES (f
) = n
;
472 if (FRAME_FACES (f
) [id
] == 0)
473 FRAME_FACES (f
) [id
] = allocate_face ();
476 /* Allocating, freeing, and duplicating fonts, colors, and pixmaps. */
478 #ifdef HAVE_X_WINDOWS
488 return (XFontStruct
*) FACE_DEFAULT
;
490 CHECK_STRING (name
, 0);
492 font
= XLoadQueryFont (x_current_display
, (char *) XSTRING (name
)->data
);
496 Fsignal (Qerror
, Fcons (build_string ("undefined font"),
497 Fcons (name
, Qnil
)));
502 unload_font (f
, font
)
506 if (!font
|| font
== ((XFontStruct
*) FACE_DEFAULT
))
508 XFreeFont (x_current_display
, font
);
516 Display
*dpy
= x_current_display
;
524 cmap
= DefaultColormapOfScreen (DefaultScreenOfDisplay (x_current_display
));
526 CHECK_STRING (name
, 0);
528 result
= XParseColor (dpy
, cmap
, (char *) XSTRING (name
)->data
, &color
);
531 Fsignal (Qerror
, Fcons (build_string ("undefined color"),
532 Fcons (name
, Qnil
)));
534 result
= XAllocColor (dpy
, cmap
, &color
);
537 Fsignal (Qerror
, Fcons (build_string ("X server cannot allocate color"),
538 Fcons (name
, Qnil
)));
539 return (unsigned long) color
.pixel
;
543 unload_color (f
, pixel
)
548 Display
*dpy
= x_current_display
;
549 if (pixel
== FACE_DEFAULT
)
551 cmap
= DefaultColormapOfScreen (DefaultScreenOfDisplay (x_current_display
));
553 XFreeColors (dpy
, cmap
, &pixel
, 1, 0);
557 #endif /* HAVE_X_WINDOWS */
566 struct frame
*other_frame
= 0;
569 for (rest
= Vframe_list
; !NILP (rest
); rest
= Fcdr (rest
))
571 struct frame
*f2
= XFRAME (Fcar (rest
));
572 if (f2
!= f
&& FRAME_X_P (f2
))
581 /* Make sure this frame's face vector is as big as the others. */
582 FRAME_N_FACES (f
) = FRAME_N_FACES (other_frame
);
584 = (struct face
**) xmalloc (FRAME_N_FACES (f
) * sizeof (struct face
*));
586 /* Make sure the frame has the two basic faces. */
587 FRAME_DEFAULT_FACE (f
)
588 = copy_face (FRAME_DEFAULT_FACE (other_frame
));
589 FRAME_MODE_LINE_FACE (f
)
590 = copy_face (FRAME_MODE_LINE_FACE (other_frame
));
595 /* Called from Fdelete_frame? */
598 free_screen_faces (f
)
601 Display
*dpy
= x_current_display
;
604 for (i
= 0; i
< FRAME_N_FACES (f
); i
++)
606 struct face
*face
= FRAME_FACES (f
) [i
];
610 XFreeGC (dpy
, face
->gc
);
611 unload_font (f
, face
->font
);
612 unload_color (f
, face
->foreground
);
613 unload_color (f
, face
->background
);
615 unload_pixmap (f
, face
->stipple
);
619 xfree (FRAME_FACES (f
));
621 FRAME_N_FACES (f
) = 0;
627 DEFUN ("frame-face-alist", Fframe_face_alist
, Sframe_face_alist
, 1, 1, 0,
632 CHECK_FRAME (frame
, 0);
633 return XFRAME (frame
)->face_alist
;
636 DEFUN ("set-frame-face-alist", Fset_frame_face_alist
, Sset_frame_face_alist
,
639 Lisp_Object frame
, value
;
641 CHECK_FRAME (frame
, 0);
642 XFRAME (frame
)->face_alist
= value
;
647 DEFUN ("make-face-internal", Fmake_face_internal
, Smake_face_internal
, 1, 1, 0,
648 "Create face number FACE-ID on all frames.")
653 int id
= XINT (face_id
);
655 CHECK_NUMBER (face_id
, 0);
656 if (id
< 0 || id
>= next_face_id
)
657 error ("Face id out of range");
659 for (rest
= Vframe_list
; !NILP (rest
); rest
= XCONS (rest
)->cdr
)
661 struct frame
*f
= XFRAME (XCONS (rest
)->car
);
662 ensure_face_ready (f
, id
);
668 DEFUN ("set-face-attribute-internal", Fset_face_attribute_internal
,
669 Sset_face_attribute_internal
, 4, 4, 0, "")
670 (face_id
, attr_name
, attr_value
, frame
)
671 Lisp_Object face_id
, attr_name
, attr_value
, frame
;
678 CHECK_FRAME (frame
, 0);
679 CHECK_NUMBER (face_id
, 0);
680 CHECK_SYMBOL (attr_name
, 0);
684 if (id
< 0 || id
>= next_face_id
)
685 error ("Face id out of range");
687 ensure_face_ready (f
, id
);
688 face
= FRAME_FACES (f
) [XFASTINT (face_id
)];
690 if (EQ (attr_name
, intern ("font")))
692 XFontStruct
*font
= load_font (f
, attr_value
);
693 unload_font (f
, face
->font
);
696 else if (EQ (attr_name
, intern ("foreground")))
698 unsigned long new_color
= load_color (f
, attr_value
);
699 unload_color (f
, face
->foreground
);
700 face
->foreground
= new_color
;
702 else if (EQ (attr_name
, intern ("background")))
704 unsigned long new_color
= load_color (f
, attr_value
);
705 unload_color (f
, face
->background
);
706 face
->background
= new_color
;
709 else if (EQ (attr_name
, intern ("background-pixmap")))
711 unsigned int w
, h
, d
;
712 unsigned long new_pixmap
= load_pixmap (f
, attr_value
, &w
, &h
, &d
, 0);
713 unload_pixmap (f
, face
->stipple
);
714 if (NILP (attr_value
))
716 face
->stipple
= new_pixmap
;
719 /* face->pixmap_depth = d; */
722 else if (EQ (attr_name
, intern ("underline")))
724 int new = !NILP (attr_value
);
725 face
->underline
= new;
728 error ("unknown face attribute");
733 if (FRAME_DEFAULT_FACE (f
)->gc
!= 0)
734 XFreeGC (x_current_display
, FRAME_DEFAULT_FACE (f
)->gc
);
735 build_face (f
, FRAME_DEFAULT_FACE (f
));
742 if (FRAME_MODE_LINE_FACE (f
)->gc
!= 0)
743 XFreeGC (x_current_display
, FRAME_MODE_LINE_FACE (f
)->gc
);
744 build_face (f
, FRAME_MODE_LINE_FACE (f
));
751 DEFUN ("internal-next-face-id", Finternal_next_face_id
, Sinternal_next_face_id
,
755 return make_number (next_face_id
++);
758 /* Return the face id for name NAME on frame FRAME.
759 (It should be the same for all frames,
760 but it's as easy to use the "right" frame to look it up
761 as to use any other one.) */
764 face_name_id_number (frame
, name
)
765 Lisp_Object frame
, name
;
769 CHECK_FRAME (frame
, 0);
770 tem
= Fcdr (Fassq (name
, XFRAME (frame
)->face_alist
));
771 CHECK_VECTOR (tem
, 0);
772 tem
= XVECTOR (tem
)->contents
[2];
773 CHECK_NUMBER (tem
, 0);
780 Qwindow
= intern ("window");
781 staticpro (&Qwindow
);
782 Qface
= intern ("face");
784 Qpriority
= intern ("priority");
785 staticpro (&Qpriority
);
787 defsubr (&Sframe_face_alist
);
788 defsubr (&Sset_frame_face_alist
);
789 defsubr (&Smake_face_internal
);
790 defsubr (&Sset_face_attribute_internal
);
791 defsubr (&Sinternal_next_face_id
);