Mercurial > emacs
annotate src/xfaces.c @ 2728:93c9529b2b69
* config.h.in: Remove mention of GLYPH datatype; that shouldn't be
a user option.
* lisp.h (GLYPH, MAKE_GLYPH, GLYPH_CHAR, GLYPH_FACE): New macros.
author | Jim Blandy <jimb@redhat.com> |
---|---|
date | Mon, 10 May 1993 00:17:55 +0000 |
parents | 78420d74d47f |
children | 139740855fa6 |
rev | line source |
---|---|
2336 | 1 /* "Face" primitives |
2342 | 2 Copyright (C) 1992, 1993 Free Software Foundation. |
3 | |
2336 | 4 This file is part of GNU Emacs. |
5 | |
6 GNU Emacs is free software; you can redistribute it and/or modify | |
7 it under the terms of the GNU General Public License as published by | |
2342 | 8 the Free Software Foundation; either version 2, or (at your option) |
2336 | 9 any later version. |
10 | |
11 GNU Emacs is distributed in the hope that it will be useful, | |
12 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 GNU General Public License for more details. | |
15 | |
16 You should have received a copy of the GNU General Public License | |
17 along with GNU Emacs; see the file COPYING. If not, write to | |
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ | |
19 | |
2438 | 20 /* This is derived from work by Lucid (some parts very loosely so). */ |
2342 | 21 |
2336 | 22 #include <sys/types.h> |
23 #include <sys/stat.h> | |
24 | |
25 #include "config.h" | |
26 #include "lisp.h" | |
27 | |
28 #include "xterm.h" | |
29 #include "buffer.h" | |
2391 | 30 #include "dispextern.h" |
2342 | 31 #include "frame.h" |
2438 | 32 #include "blockinput.h" |
2391 | 33 /* #include "window.h" */ |
2336 | 34 |
35 /* Display Context for the icons */ | |
36 #include <X11/Intrinsic.h> | |
37 #include <X11/StringDefs.h> | |
2538
78420d74d47f
Don't include Xmu/Drawing.h.
Richard M. Stallman <rms@gnu.org>
parents:
2513
diff
changeset
|
38 /* #include <X11/Xmu/Drawing.h> */ /* Appears not to be used */ |
2336 | 39 #include <X11/Xos.h> |
40 | |
2342 | 41 /* We use face structures in two ways: |
2391 | 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). | |
2342 | 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". | |
47 | |
48 Faces number 0 and 1 have graphics contexts. | |
2438 | 49 They can be used in the redisplay code directly. |
2342 | 50 Higher numbered frame faces do not have graphics contexts. |
51 | |
52 There are also "cached faces". They have graphics contexts. | |
53 They are kept in a C vector called face_vector. | |
54 | |
55 A "display face" is a face with a graphics context. | |
56 It is either a frame face number 0 or 1, | |
57 or a cached face. */ | |
58 | |
2336 | 59 /* A table of display faces. */ |
60 struct face **face_vector; | |
61 /* The length in use of the table. */ | |
62 int nfaces; | |
63 /* The allocated length of the table. */ | |
64 int nfaces_allocated; | |
65 | |
66 /* The number of face-id's in use (same for all frames). */ | |
67 int next_face_id; | |
68 | |
2342 | 69 #define FACE_DEFAULT (~0) |
70 | |
2391 | 71 Lisp_Object Qface, Qwindow, Qpriority; |
72 | |
2336 | 73 static struct face *allocate_face (); |
74 static void build_face (); | |
2391 | 75 static int sort_overlays (); |
76 static struct face *get_display_face (); | |
77 static Lisp_Object face_name_id_number (); | |
2336 | 78 |
79 /* Make a new face that's a copy of an existing one. */ | |
80 | |
81 static struct face * | |
82 copy_face (face) | |
83 struct face *face; | |
84 { | |
85 struct face *result = allocate_face (); | |
86 | |
87 result->font = face->font; | |
88 result->foreground = face->foreground; | |
89 result->background = face->background; | |
2391 | 90 result->stipple = face->stipple; |
2336 | 91 result->underline = face->underline; |
92 | |
93 return result; | |
94 } | |
95 | |
96 static int | |
97 face_eql (face1, face2) | |
98 struct face *face1, *face2; | |
99 { | |
100 return (face1->font == face2->font | |
101 && face1->foreground == face2->foreground | |
102 && face1->background == face2->background | |
2391 | 103 && face1->stipple == face2->stipple |
2336 | 104 && face1->underline == face2->underline); |
105 } | |
106 | |
107 /* Return the unique display face corresponding to the user-level face FACE. | |
108 | |
109 If there isn't one, make one, and find a slot in the face_vector to | |
110 put it in. */ | |
111 | |
112 static struct face * | |
2342 | 113 get_cached_face (f, face) |
2336 | 114 struct frame *f; |
115 struct face *face; | |
116 { | |
117 int i, empty = -1; | |
2391 | 118 struct face *result; |
2336 | 119 |
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++) | |
123 { | |
124 if (face_eql (face_vector[i], face)) | |
125 return face_vector[i]; | |
126 if (face_vector[i] == 0) | |
127 empty = i; | |
128 } | |
129 | |
130 /* If no empty slots, make one. */ | |
131 if (empty < 0 && nfaces == nfaces_allocated) | |
132 { | |
133 int newsize = nfaces + 20; | |
134 face_vector | |
135 = (struct face **) xrealloc (face_vector, | |
136 newsize * sizeof (struct face *)); | |
137 nfaces_allocated = newsize; | |
138 } | |
139 | |
140 if (empty < 0) | |
141 empty = nfaces++; | |
142 | |
143 /* Put a new display face in the empty slot. */ | |
144 result = copy_face (face); | |
145 face_vector[empty] = result; | |
146 | |
147 /* Make a graphics context for it. */ | |
148 build_face (f, result); | |
149 | |
150 return result; | |
151 } | |
152 | |
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. */ | |
157 | |
158 void | |
159 clear_face_vector () | |
160 { | |
161 Lisp_Object rest; | |
162 Display *dpy = x_current_display; | |
2391 | 163 int i; |
2336 | 164 |
165 BLOCK_INPUT; | |
166 /* Free the display faces in the face_vector. */ | |
167 for (i = 0; i < nfaces; i++) | |
168 { | |
169 struct face *face = face_vector[i]; | |
2391 | 170 if (face->gc) |
171 XFreeGC (dpy, face->gc); | |
2336 | 172 xfree (face); |
173 } | |
174 nfaces = 0; | |
175 | |
176 UNBLOCK_INPUT; | |
177 } | |
178 | |
2391 | 179 /* Make a graphics context for face FACE, which is on frame F, |
180 if that can be done. */ | |
2336 | 181 |
182 static void | |
183 build_face (f, face) | |
184 struct frame* f; | |
185 struct face* face; | |
186 { | |
187 GC gc; | |
188 XGCValues xgcv; | |
189 unsigned long mask; | |
190 | |
2391 | 191 if (face->foreground != FACE_DEFAULT) |
192 xgcv.foreground = face->foreground; | |
193 else | |
194 xgcv. foreground = f->display.x->foreground_pixel; | |
195 if (face->background != FACE_DEFAULT) | |
196 xgcv.background = face->background; | |
197 else | |
198 xgcv. background = f->display.x->background_pixel; | |
199 if (face->font && (int) face->font != FACE_DEFAULT) | |
200 xgcv.font = face->font->fid; | |
201 else | |
202 xgcv.font = f->display.x->font->fid; | |
2336 | 203 xgcv.graphics_exposures = 0; |
204 mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures; | |
205 gc = XCreateGC (x_current_display, FRAME_X_WINDOW (f), | |
206 mask, &xgcv); | |
207 #if 0 | |
2391 | 208 if (face->stipple && face->stipple != FACE_DEFAULT) |
209 XSetStipple (x_current_display, gc, face->stipple); | |
2336 | 210 #endif |
2391 | 211 face->gc = gc; |
2336 | 212 } |
213 | |
2342 | 214 /* Modify face TO by copying from FROM all properties which have |
215 nondefault settings. */ | |
216 | |
217 static void | |
218 merge_faces (from, to) | |
219 struct face *from, *to; | |
220 { | |
221 if (from->font != (XFontStruct *)FACE_DEFAULT) | |
222 { | |
223 to->font = from->font; | |
224 } | |
225 if (from->foreground != FACE_DEFAULT) | |
226 to->foreground = from->foreground; | |
227 if (from->background != FACE_DEFAULT) | |
228 to->background = from->background; | |
2391 | 229 if (from->stipple != FACE_DEFAULT) |
230 to->stipple = from->stipple; | |
2342 | 231 if (from->underline) |
232 to->underline = from->underline; | |
233 } | |
234 | |
2391 | 235 struct sortvec |
236 { | |
237 Lisp_Object overlay; | |
238 int beg, end; | |
239 int priority; | |
240 }; | |
241 | |
2342 | 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. | |
2391 | 245 F is the frame in use for display, and W is the window. */ |
2342 | 246 |
247 struct face * | |
2391 | 248 compute_char_face (f, w, pos, endptr) |
2342 | 249 struct frame *f; |
2391 | 250 struct window *w; |
2342 | 251 int pos; |
252 int *endptr; | |
253 { | |
254 struct face face; | |
255 Lisp_Object prop, position, length; | |
256 Lisp_Object overlay, start, end; | |
257 int i, j, noverlays; | |
258 int facecode; | |
259 int endpos; | |
260 Lisp_Object *overlay_vec; | |
261 int len; | |
2391 | 262 struct sortvec *sortvec; |
263 Lisp_Object frame; | |
264 | |
265 XSET (frame, Lisp_Frame, f); | |
2342 | 266 |
267 XFASTINT (position) = pos; | |
268 prop = Fget_text_property (position, Qface); | |
269 | |
270 len = 10; | |
271 overlay_vec = (Lisp_Object *) xmalloc (len * sizeof (Lisp_Object)); | |
272 noverlays = overlays_at (pos, &overlay_vec, &len, &endpos); | |
273 | |
274 /* Optimize the default case. */ | |
275 if (noverlays == 0 && NILP (prop)) | |
2391 | 276 return FRAME_DEFAULT_FACE (f); |
2342 | 277 |
2391 | 278 bcopy (FRAME_DEFAULT_FACE (f), &face, sizeof (struct face)); |
2342 | 279 |
280 if (!NILP (prop)) | |
281 { | |
2391 | 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); | |
2342 | 286 } |
287 | |
2391 | 288 /* Put the valid and relevant overlays into sortvec. */ |
289 sortvec = (struct sortvec *) alloca (noverlays * sizeof (struct sortvec)); | |
290 | |
2342 | 291 for (i = 0, j = 0; i < noverlays; i++) |
292 { | |
293 overlay = overlay_vec[i]; | |
294 | |
295 if (OVERLAY_VALID (overlay) | |
296 && OVERLAY_POSITION (OVERLAY_START (overlay)) > 0 | |
297 && OVERLAY_POSITION (OVERLAY_END (overlay)) > 0) | |
2391 | 298 { |
299 Lisp_Object window; | |
300 window = Foverlay_get (overlay, Qwindow); | |
301 | |
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) | |
305 { | |
306 Lisp_Object tem; | |
307 | |
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); | |
314 if (INTEGERP (tem)) | |
315 sortvec[j].priority = XINT (tem); | |
316 else | |
317 sortvec[j].priority = 0; | |
318 j++; | |
319 } | |
320 } | |
2342 | 321 } |
322 noverlays = j; | |
323 | |
2391 | 324 /* Sort the overlays into the proper order: increasing priority. */ |
325 | |
326 qsort (sortvec, noverlays, sizeof (struct sortvec), sort_overlays); | |
2342 | 327 |
328 /* Now merge the overlay data in that order. */ | |
329 | |
330 for (i = 0; i < noverlays; i++) | |
331 { | |
332 prop = Foverlay_get (overlay_vec[i], Qface); | |
333 if (!NILP (prop)) | |
334 { | |
335 Lisp_Object oend; | |
336 int oendpos; | |
337 | |
2391 | 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); | |
2342 | 342 |
343 oend = OVERLAY_END (overlay_vec[i]); | |
344 oendpos = OVERLAY_POSITION (oend); | |
345 if (oendpos > endpos) | |
346 endpos = oendpos; | |
347 } | |
348 } | |
349 | |
350 xfree (overlay_vec); | |
351 | |
352 *endptr = endpos; | |
353 | |
354 return get_display_face (f, &face); | |
355 } | |
356 | |
2513
d93605655958
* xfaces.c (sort_overlays): Define this to be static, as declared.
Jim Blandy <jimb@redhat.com>
parents:
2438
diff
changeset
|
357 static int |
2391 | 358 sort_overlays (s1, s2) |
359 struct sortvec *s1, *s2; | |
360 { | |
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; | |
367 return 0; | |
368 } | |
369 | |
2342 | 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. | |
373 F is the frame. */ | |
374 | |
375 struct face * | |
376 compute_glyph_face (f, basic_face, face_code) | |
377 struct frame *f; | |
378 struct face *basic_face; | |
379 int face_code; | |
380 { | |
381 struct face face; | |
382 | |
383 bcopy (basic_face, &face, sizeof (struct face)); | |
384 | |
2391 | 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); | |
2342 | 388 |
389 return get_display_face (f, &face); | |
390 } | |
391 | |
2336 | 392 /* Given a frame face, return an equivalent display face |
393 (one which has a graphics context). */ | |
394 | |
395 static struct face * | |
396 get_display_face (f, face) | |
397 struct frame *f; | |
398 struct face *face; | |
399 { | |
400 struct face *result; | |
401 | |
402 /* Does the face have a GC already? */ | |
2391 | 403 if (face->gc) |
2336 | 404 return face; |
405 | |
2391 | 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) | |
2336 | 412 { |
2391 | 413 if (!FRAME_DEFAULT_FACE (f)->gc) |
414 build_face (f, FRAME_DEFAULT_FACE (f)); | |
415 return FRAME_DEFAULT_FACE (f); | |
2336 | 416 } |
417 | |
418 /* If it's equivalent to the mode line face, use that. */ | |
2391 | 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) | |
2336 | 424 { |
2391 | 425 if (!FRAME_MODE_LINE_FACE (f)->gc) |
426 build_face (f, FRAME_MODE_LINE_FACE (f)); | |
427 return FRAME_MODE_LINE_FACE (f); | |
2336 | 428 } |
429 | |
430 /* Get a specialized display face. */ | |
431 return get_cached_face (f, face); | |
432 } | |
433 | |
434 | |
435 /* Allocate a new face */ | |
436 static struct face * | |
437 allocate_face () | |
438 { | |
439 struct face *result = (struct face *) xmalloc (sizeof (struct face)); | |
440 bzero (result, sizeof (struct face)); | |
2342 | 441 result->font = (XFontStruct *) FACE_DEFAULT; |
442 result->foreground = FACE_DEFAULT; | |
443 result->background = FACE_DEFAULT; | |
2391 | 444 result->stipple = FACE_DEFAULT; |
2336 | 445 return result; |
446 } | |
447 | |
448 /* Make face id ID valid on frame F. */ | |
449 | |
450 void | |
451 ensure_face_ready (f, id) | |
452 struct frame *f; | |
453 int id; | |
454 { | |
2391 | 455 if (FRAME_N_FACES (f) <= id) |
2336 | 456 { |
457 int n = id + 10; | |
458 int i; | |
2391 | 459 if (!FRAME_N_FACES (f)) |
460 FRAME_FACES (f) | |
461 = (struct face **) xmalloc (sizeof (struct face *) * n); | |
2336 | 462 else |
2391 | 463 FRAME_FACES (f) |
464 = (struct face **) xrealloc (FRAME_FACES (f), | |
465 sizeof (struct face *) * n); | |
2336 | 466 |
2391 | 467 bzero (FRAME_FACES (f) + FRAME_N_FACES (f), |
468 (n - FRAME_N_FACES (f)) * sizeof (struct face *)); | |
469 FRAME_N_FACES (f) = n; | |
2336 | 470 } |
471 | |
2391 | 472 if (FRAME_FACES (f) [id] == 0) |
473 FRAME_FACES (f) [id] = allocate_face (); | |
2336 | 474 } |
475 | |
476 /* Allocating, freeing, and duplicating fonts, colors, and pixmaps. */ | |
477 | |
478 #ifdef HAVE_X_WINDOWS | |
479 | |
480 static XFontStruct * | |
481 load_font (f, name) | |
482 struct frame *f; | |
483 Lisp_Object name; | |
484 { | |
485 XFontStruct *font; | |
486 | |
2342 | 487 if (NILP (name)) |
488 return (XFontStruct *) FACE_DEFAULT; | |
489 | |
2336 | 490 CHECK_STRING (name, 0); |
491 BLOCK_INPUT; | |
492 font = XLoadQueryFont (x_current_display, (char *) XSTRING (name)->data); | |
493 UNBLOCK_INPUT; | |
494 | |
495 if (! font) | |
496 Fsignal (Qerror, Fcons (build_string ("undefined font"), | |
497 Fcons (name, Qnil))); | |
498 return font; | |
499 } | |
500 | |
501 static void | |
502 unload_font (f, font) | |
503 struct frame *f; | |
504 XFontStruct *font; | |
505 { | |
506 if (!font || font == ((XFontStruct *) FACE_DEFAULT)) | |
507 return; | |
508 XFreeFont (x_current_display, font); | |
509 } | |
510 | |
511 static unsigned long | |
512 load_color (f, name) | |
513 struct frame *f; | |
514 Lisp_Object name; | |
515 { | |
516 Display *dpy = x_current_display; | |
517 Colormap cmap; | |
518 XColor color; | |
519 int result; | |
520 | |
2342 | 521 if (NILP (name)) |
522 return FACE_DEFAULT; | |
523 | |
2391 | 524 cmap = DefaultColormapOfScreen (DefaultScreenOfDisplay (x_current_display)); |
2336 | 525 |
526 CHECK_STRING (name, 0); | |
527 BLOCK_INPUT; | |
528 result = XParseColor (dpy, cmap, (char *) XSTRING (name)->data, &color); | |
529 UNBLOCK_INPUT; | |
530 if (! result) | |
531 Fsignal (Qerror, Fcons (build_string ("undefined color"), | |
532 Fcons (name, Qnil))); | |
533 BLOCK_INPUT; | |
534 result = XAllocColor (dpy, cmap, &color); | |
535 UNBLOCK_INPUT; | |
536 if (! result) | |
537 Fsignal (Qerror, Fcons (build_string ("X server cannot allocate color"), | |
538 Fcons (name, Qnil))); | |
539 return (unsigned long) color.pixel; | |
540 } | |
541 | |
542 static void | |
543 unload_color (f, pixel) | |
544 struct frame *f; | |
545 Pixel pixel; | |
546 { | |
547 Colormap cmap; | |
548 Display *dpy = x_current_display; | |
549 if (pixel == FACE_DEFAULT) | |
550 return; | |
2391 | 551 cmap = DefaultColormapOfScreen (DefaultScreenOfDisplay (x_current_display)); |
2336 | 552 BLOCK_INPUT; |
553 XFreeColors (dpy, cmap, &pixel, 1, 0); | |
554 UNBLOCK_INPUT; | |
555 } | |
556 | |
557 #endif /* HAVE_X_WINDOWS */ | |
558 | |
559 | |
560 /* frames */ | |
561 | |
562 void | |
563 init_frame_faces (f) | |
2391 | 564 struct frame *f; |
2336 | 565 { |
566 struct frame *other_frame = 0; | |
567 Lisp_Object rest; | |
568 | |
569 for (rest = Vframe_list; !NILP (rest); rest = Fcdr (rest)) | |
570 { | |
571 struct frame *f2 = XFRAME (Fcar (rest)); | |
2391 | 572 if (f2 != f && FRAME_X_P (f2)) |
2336 | 573 { |
574 other_frame = f2; | |
575 break; | |
576 } | |
577 } | |
578 | |
579 if (other_frame) | |
580 { | |
581 /* Make sure this frame's face vector is as big as the others. */ | |
2391 | 582 FRAME_N_FACES (f) = FRAME_N_FACES (other_frame); |
583 FRAME_FACES (f) | |
584 = (struct face **) xmalloc (FRAME_N_FACES (f) * sizeof (struct face *)); | |
2336 | 585 |
586 /* Make sure the frame has the two basic faces. */ | |
2391 | 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)); | |
2336 | 591 } |
592 } | |
593 | |
594 | |
595 /* Called from Fdelete_frame? */ | |
596 | |
597 void | |
598 free_screen_faces (f) | |
599 struct frame *f; | |
600 { | |
601 Display *dpy = x_current_display; | |
602 int i; | |
603 | |
2391 | 604 for (i = 0; i < FRAME_N_FACES (f); i++) |
2336 | 605 { |
2391 | 606 struct face *face = FRAME_FACES (f) [i]; |
2336 | 607 if (! face) |
608 continue; | |
2391 | 609 if (face->gc) |
610 XFreeGC (dpy, face->gc); | |
2336 | 611 unload_font (f, face->font); |
612 unload_color (f, face->foreground); | |
613 unload_color (f, face->background); | |
2391 | 614 #if 0 |
615 unload_pixmap (f, face->stipple); | |
616 #endif | |
2336 | 617 xfree (face); |
618 } | |
2391 | 619 xfree (FRAME_FACES (f)); |
620 FRAME_FACES (f) = 0; | |
621 FRAME_N_FACES (f) = 0; | |
2336 | 622 } |
623 | |
624 | |
625 /* Lisp interface */ | |
626 | |
627 DEFUN ("frame-face-alist", Fframe_face_alist, Sframe_face_alist, 1, 1, 0, | |
628 "") | |
629 (frame) | |
630 Lisp_Object frame; | |
631 { | |
632 CHECK_FRAME (frame, 0); | |
633 return XFRAME (frame)->face_alist; | |
634 } | |
635 | |
636 DEFUN ("set-frame-face-alist", Fset_frame_face_alist, Sset_frame_face_alist, | |
637 2, 2, 0, "") | |
638 (frame, value) | |
639 Lisp_Object frame, value; | |
640 { | |
641 CHECK_FRAME (frame, 0); | |
642 XFRAME (frame)->face_alist = value; | |
643 return value; | |
644 } | |
645 | |
646 | |
647 DEFUN ("make-face-internal", Fmake_face_internal, Smake_face_internal, 1, 1, 0, | |
648 "Create face number FACE-ID on all frames.") | |
649 (face_id) | |
650 Lisp_Object face_id; | |
651 { | |
652 Lisp_Object rest; | |
653 int id = XINT (face_id); | |
654 | |
2391 | 655 CHECK_NUMBER (face_id, 0); |
656 if (id < 0 || id >= next_face_id) | |
657 error ("Face id out of range"); | |
2336 | 658 |
659 for (rest = Vframe_list; !NILP (rest); rest = XCONS (rest)->cdr) | |
660 { | |
661 struct frame *f = XFRAME (XCONS (rest)->car); | |
662 ensure_face_ready (f, id); | |
663 } | |
664 return Qnil; | |
665 } | |
666 | |
667 | |
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; | |
672 { | |
673 struct face *face; | |
674 struct frame *f; | |
675 int magic_p; | |
676 int id; | |
677 | |
678 CHECK_FRAME (frame, 0); | |
2391 | 679 CHECK_NUMBER (face_id, 0); |
2336 | 680 CHECK_SYMBOL (attr_name, 0); |
681 | |
682 f = XFRAME (frame); | |
683 id = XINT (face_id); | |
2391 | 684 if (id < 0 || id >= next_face_id) |
685 error ("Face id out of range"); | |
2336 | 686 |
687 ensure_face_ready (f, id); | |
2391 | 688 face = FRAME_FACES (f) [XFASTINT (face_id)]; |
2336 | 689 |
690 if (EQ (attr_name, intern ("font"))) | |
691 { | |
2391 | 692 XFontStruct *font = load_font (f, attr_value); |
2336 | 693 unload_font (f, face->font); |
694 face->font = font; | |
695 } | |
696 else if (EQ (attr_name, intern ("foreground"))) | |
697 { | |
2391 | 698 unsigned long new_color = load_color (f, attr_value); |
2336 | 699 unload_color (f, face->foreground); |
700 face->foreground = new_color; | |
701 } | |
702 else if (EQ (attr_name, intern ("background"))) | |
703 { | |
2391 | 704 unsigned long new_color = load_color (f, attr_value); |
2336 | 705 unload_color (f, face->background); |
706 face->background = new_color; | |
707 } | |
708 #if 0 | |
709 else if (EQ (attr_name, intern ("background-pixmap"))) | |
710 { | |
711 unsigned int w, h, d; | |
712 unsigned long new_pixmap = load_pixmap (f, attr_value, &w, &h, &d, 0); | |
2391 | 713 unload_pixmap (f, face->stipple); |
714 if (NILP (attr_value)) | |
715 new_pixmap = 0; | |
716 face->stipple = new_pixmap; | |
2336 | 717 face->pixmap_w = w; |
718 face->pixmap_h = h; | |
719 /* face->pixmap_depth = d; */ | |
720 } | |
721 #endif /* 0 */ | |
722 else if (EQ (attr_name, intern ("underline"))) | |
723 { | |
724 int new = !NILP (attr_value); | |
725 face->underline = new; | |
726 } | |
727 else | |
728 error ("unknown face attribute"); | |
729 | |
730 if (id == 0) | |
731 { | |
732 BLOCK_INPUT; | |
2391 | 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)); | |
2336 | 736 UNBLOCK_INPUT; |
737 } | |
738 | |
739 if (id == 1) | |
740 { | |
741 BLOCK_INPUT; | |
2391 | 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)); | |
2336 | 745 UNBLOCK_INPUT; |
746 } | |
747 | |
748 return Qnil; | |
749 } | |
750 | |
751 DEFUN ("internal-next-face-id", Finternal_next_face_id, Sinternal_next_face_id, | |
752 0, 0, 0, "") | |
753 () | |
754 { | |
755 return make_number (next_face_id++); | |
756 } | |
2391 | 757 |
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.) */ | |
762 | |
763 static Lisp_Object | |
764 face_name_id_number (frame, name) | |
765 Lisp_Object frame, name; | |
766 { | |
767 Lisp_Object tem; | |
768 | |
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); | |
774 return XINT (tem); | |
775 } | |
2336 | 776 |
777 void | |
2391 | 778 syms_of_xfaces () |
2336 | 779 { |
2391 | 780 Qwindow = intern ("window"); |
781 staticpro (&Qwindow); | |
782 Qface = intern ("face"); | |
783 staticpro (&Qface); | |
784 Qpriority = intern ("priority"); | |
785 staticpro (&Qpriority); | |
786 | |
2336 | 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); | |
792 } |