Use XCAR and XCDR instead of explicit member references.
[bpt/emacs.git] / src / w32faces.c
1 /* "Face" primitives on the Microsoft W32 API.
2 Copyright (C) 1993, 1994, 1995 Free Software Foundation.
3
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
8 the Free Software Foundation; either version 2, or (at your option)
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, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
20
21 /* Ported xfaces.c for w32 - Kevin Gallo */
22
23 #include <sys/types.h>
24 #include <sys/stat.h>
25
26 #include <config.h>
27 #include "lisp.h"
28
29 #include "w32term.h"
30 #include "buffer.h"
31 #include "dispextern.h"
32 #include "frame.h"
33 #include "blockinput.h"
34 #include "window.h"
35 #include "intervals.h"
36 #include "charset.h"
37 #include "fontset.h"
38
39 \f
40 /* An explanation of the face data structures. */
41
42 /* ========================= Face Data Structures =========================
43
44 Let FACE-NAME be a symbol naming a face.
45
46 Let FACE-VECTOR be (assq FACE-NAME (frame-face-alist FRAME))
47 FACE-VECTOR is either nil, or a vector of the form
48 [face NAME ID FONT FOREGROUND BACKGROUND BACKGROUND-PIXMAP UNDERLINE-P]
49 where
50 face is the symbol `face',
51 NAME is the symbol with which this vector is associated (a backpointer),
52 ID is the face ID, an integer used internally by the C code to identify
53 the face,
54 FONT, FOREGROUND, and BACKGROUND are strings naming the fonts and colors
55 to use with the face, FONT may name fontsets,
56 BACKGROUND-PIXMAP is the name of an x bitmap filename, which we don't
57 use right now, and
58 UNDERLINE-P is non-nil if the face should be underlined.
59 If any of these elements are nil, that parameter is considered
60 unspecified; parameters from faces specified by lower-priority
61 overlays or text properties, or the parameters of the frame itself,
62 can show through. (lisp/faces.el maintains these lists.)
63
64 (assq FACE-NAME global-face-data) returns a vector describing the
65 global parameters for that face.
66
67 Let PARAM-FACE be FRAME->output_data.w32->param_faces[Faref(FACE-VECTOR,2)].
68 PARAM_FACE is a struct face whose members are the Xlib analogues of
69 the parameters in FACE-VECTOR. If an element of FACE-VECTOR is
70 nil, then the corresponding member of PARAM_FACE is FACE_DEFAULT.
71 These faces are called "parameter faces", because they're the ones
72 lisp manipulates to control what gets displayed. Elements 0 and 1
73 of FRAME->output_data.w32->param_faces are special - they describe the
74 default and mode line faces. None of the faces in param_faces have
75 GC's. (See src/dispextern.h for the definition of struct face.
76 lisp/faces.el maintains the isomorphism between face_alist and
77 param_faces.)
78
79 The functions compute_char_face and compute_glyph_face find and
80 combine the parameter faces associated with overlays and text
81 properties. The resulting faces are called "computed faces"; none
82 of their members are FACE_DEFAULT; they are completely specified.
83 They then call intern_compute_face to search
84 FRAME->output_data.x->computed_faces for a matching face, add one if
85 none is found, and return the index into
86 FRAME->output_data.x->computed_faces. FRAME's glyph matrices use these
87 indices to record the faces of the matrix characters, and the X
88 display hooks consult compute_faces to decide how to display these
89 characters. Elements 0 and 1 of computed_faces always describe the
90 default and mode-line faces.
91
92 Each computed face belongs to a particular frame.
93
94 Computed faces have graphics contexts some of the time.
95 intern_face builds a GC for a specified computed face
96 if it doesn't have one already.
97 clear_face_cache clears out the GCs of all computed faces.
98 This is done from time to time so that we don't hold on to
99 lots of GCs that are no longer needed.
100
101 If a computed face has 0 as its font,
102 it is unused, and can be reused by new_computed_face.
103
104 Constraints:
105
106 Symbols naming faces must have associations on all frames; for any
107 FRAME, for all FACE-NAME, if (assq FACE-NAME (frame-face-alist
108 FRAME)) is non-nil, it must be non-nil for all frames.
109
110 Analogously, indices into param_faces must be valid on all frames;
111 if param_faces[i] is a non-zero face pointer on one frame, then it
112 must be filled in on all frames. Code assumes that face ID's can
113 be used on any frame.
114
115 Some subtleties:
116
117 Why do we keep param_faces and computed_faces separate?
118 computed_faces contains an element for every combination of facial
119 parameters we have ever displayed. indices into param_faces have
120 to be valid on all frames. If they were the same array, then that
121 array would grow very large on all frames, because any facial
122 combination displayed on any frame would need to be a valid entry
123 on all frames. */
124 \f
125 /* Definitions and declarations. */
126
127 /* The number of face-id's in use (same for all frames). */
128 static int next_face_id;
129
130 /* The number of the face to use to indicate the region. */
131 static int region_face;
132
133 /* This is what appears in a slot in a face to signify that the face
134 does not specify that display aspect. */
135 #define FACE_DEFAULT (~0)
136
137 Lisp_Object Qface;
138 Lisp_Object Qpixmap_spec_p;
139
140 extern Lisp_Object Qmouse_face; /* In textprop.c. */
141
142 int face_name_id_number ( /* FRAME_PTR, Lisp_Object name */ );
143
144 struct face *intern_face ( /* FRAME_PTR, struct face * */ );
145 static int new_computed_face ( /* FRAME_PTR, struct face * */ );
146 static int intern_computed_face ( /* FRAME_PTR, struct face * */ );
147 static void ensure_face_ready ( /* FRAME_PTR, int id */ );
148 void recompute_basic_faces ( /* FRAME_PTR f */ );
149 static void merge_face_list ( /* FRAME_PTR, struct face *, Lisp_Object */ );
150
151 extern Lisp_Object Qforeground_color, Qbackground_color;
152 \f
153 /* Allocating, copying, and comparing struct faces. */
154
155 /* Allocate a new face */
156 static struct face *
157 allocate_face ()
158 {
159 struct face *result = (struct face *) xmalloc (sizeof (struct face));
160 bzero (result, sizeof (struct face));
161 result->font = (XFontStruct *) FACE_DEFAULT;
162 result->fontset = -1;
163 result->foreground = FACE_DEFAULT;
164 result->background = FACE_DEFAULT;
165 result->stipple = FACE_DEFAULT;
166 return result;
167 }
168
169 /* Make a new face that's a copy of an existing one. */
170 static struct face *
171 copy_face (face)
172 struct face *face;
173 {
174 struct face *result = allocate_face ();
175
176 result->font = face->font;
177 result->fontset = face->fontset;
178 result->foreground = face->foreground;
179 result->background = face->background;
180 result->stipple = face->stipple;
181 result->underline = face->underline;
182 result->pixmap_h = face->pixmap_h;
183 result->pixmap_w = face->pixmap_w;
184
185 return result;
186 }
187
188 static int
189 face_eql (face1, face2)
190 struct face *face1, *face2;
191 {
192 return ( face1->font == face2->font
193 && face1->fontset == face2->fontset
194 && face1->foreground == face2->foreground
195 && face1->background == face2->background
196 && face1->stipple == face2->stipple
197 && face1->underline == face2->underline);
198 }
199 \f
200 /* Managing graphics contexts of faces. */
201
202 /* Given a computed face, construct its graphics context if necessary. */
203
204 struct face *
205 intern_face (f, face)
206 struct frame *f;
207 struct face *face;
208 {
209 face->gc = NULL;
210
211 return face;
212 }
213
214 /* Clear out all graphics contexts for all computed faces
215 except for the default and mode line faces.
216 This should be done from time to time just to avoid
217 keeping too many graphics contexts that are no longer needed. */
218
219 void
220 clear_face_cache ()
221 {
222 /* Nothing extra */
223 }
224 \f
225 /* Allocating, freeing, and duplicating fonts, colors, and pixmaps.
226
227 These functions operate on param faces only.
228 Computed faces get their fonts, colors and pixmaps
229 by merging param faces. */
230
231 static XFontStruct *
232 load_font (f, name)
233 struct frame *f;
234 Lisp_Object name;
235 {
236 struct font_info *fontinf;
237 XFontStruct *font = NULL;
238
239 if (NILP (name))
240 return (XFontStruct *) FACE_DEFAULT;
241
242 CHECK_STRING (name, 0);
243 BLOCK_INPUT;
244 fontinf = w32_load_font (f, (char *) XSTRING (name)->data, 0);
245 UNBLOCK_INPUT;
246 if (fontinf)
247 font = (XFontStruct *)fontinf->font;
248
249 if (! font)
250 Fsignal (Qerror, Fcons (build_string ("undefined font"),
251 Fcons (name, Qnil)));
252 return font;
253 }
254
255 static void
256 unload_font (f, font)
257 struct frame *f;
258 XFontStruct *font;
259 {
260 if (!font || font == ((XFontStruct *) FACE_DEFAULT))
261 return;
262
263 BLOCK_INPUT;
264 w32_unload_font (FRAME_W32_DISPLAY_INFO (f), font);
265 UNBLOCK_INPUT;
266 }
267
268 static unsigned long
269 load_color (f, name)
270 struct frame *f;
271 Lisp_Object name;
272 {
273 COLORREF color;
274 int result;
275
276 if (NILP (name))
277 return FACE_DEFAULT;
278
279 CHECK_STRING (name, 0);
280 /* if the colormap is full, defined_color will return a best match
281 to the values in an an existing cell. */
282 result = defined_color(f, (char *) XSTRING (name)->data, &color, 1);
283 if (! result)
284 Fsignal (Qerror, Fcons (build_string ("undefined color"),
285 Fcons (name, Qnil)));
286 return (unsigned long) color;
287 }
288
289 static void
290 unload_color (f, pixel)
291 struct frame *f;
292 unsigned long pixel;
293 {
294 }
295
296 DEFUN ("pixmap-spec-p", Fpixmap_spec_p, Spixmap_spec_p, 1, 1, 0,
297 "Return t if OBJECT is a valid pixmap specification.")
298 (object)
299 Lisp_Object object;
300 {
301 Lisp_Object height, width;
302
303 return ((STRINGP (object)
304 || (CONSP (object)
305 && CONSP (XCDR (object))
306 && CONSP (XCDR (XCDR (object)))
307 && NILP (XCDR (XCDR (XCDR (object))))
308 && (width = XCAR (object), INTEGERP (width))
309 && (height = XCAR (XCDR (object)), INTEGERP (height))
310 && STRINGP (XCAR (XCDR (XCDR (object))))
311 && XINT (width) > 0
312 && XINT (height) > 0
313 /* The string must have enough bits for width * height. */
314 && ((XSTRING (XCAR (XCDR (XCDR (object))))->size
315 * (BITS_PER_INT / sizeof (int)))
316 >= XFASTINT (width) * XFASTINT (height))))
317 ? Qt : Qnil);
318 }
319
320 /* Load a bitmap according to NAME (which is either a file name
321 or a pixmap spec). Return the bitmap_id (see xfns.c)
322 or get an error if NAME is invalid.
323
324 Store the bitmap width in *W_PTR and height in *H_PTR. */
325
326 static long
327 load_pixmap (f, name, w_ptr, h_ptr)
328 FRAME_PTR f;
329 Lisp_Object name;
330 unsigned int *w_ptr, *h_ptr;
331 {
332 int bitmap_id;
333 Lisp_Object tem;
334
335 if (NILP (name))
336 return FACE_DEFAULT;
337
338 tem = Fpixmap_spec_p (name);
339 if (NILP (tem))
340 wrong_type_argument (Qpixmap_spec_p, name);
341
342 BLOCK_INPUT;
343
344 if (CONSP (name))
345 {
346 /* Decode a bitmap spec into a bitmap. */
347
348 int h, w;
349 Lisp_Object bits;
350
351 w = XINT (Fcar (name));
352 h = XINT (Fcar (Fcdr (name)));
353 bits = Fcar (Fcdr (Fcdr (name)));
354
355 bitmap_id = x_create_bitmap_from_data (f, XSTRING (bits)->data,
356 w, h);
357 }
358 else
359 {
360 /* It must be a string -- a file name. */
361 bitmap_id = x_create_bitmap_from_file (f, name);
362 }
363 UNBLOCK_INPUT;
364
365 if (bitmap_id < 0)
366 Fsignal (Qerror, Fcons (build_string ("invalid or undefined bitmap"),
367 Fcons (name, Qnil)));
368
369 *w_ptr = x_bitmap_width (f, bitmap_id);
370 *h_ptr = x_bitmap_height (f, bitmap_id);
371
372 return bitmap_id;
373 }
374
375 \f
376 /* Managing parameter face arrays for frames. */
377
378 void
379 init_frame_faces (f)
380 FRAME_PTR f;
381 {
382 ensure_face_ready (f, 0);
383 ensure_face_ready (f, 1);
384
385 FRAME_N_COMPUTED_FACES (f) = 0;
386 FRAME_SIZE_COMPUTED_FACES (f) = 0;
387
388 new_computed_face (f, FRAME_PARAM_FACES (f)[0]);
389 new_computed_face (f, FRAME_PARAM_FACES (f)[1]);
390 recompute_basic_faces (f);
391
392 /* Find another frame. */
393 {
394 Lisp_Object tail, frame, result;
395
396 result = Qnil;
397 FOR_EACH_FRAME (tail, frame)
398 if (FRAME_W32_P (XFRAME (frame))
399 && XFRAME (frame) != f)
400 {
401 result = frame;
402 break;
403 }
404
405 /* If we didn't find any X frames other than f, then we don't need
406 any faces other than 0 and 1, so we're okay. Otherwise, make
407 sure that all faces valid on the selected frame are also valid
408 on this new frame. */
409 if (FRAMEP (result))
410 {
411 int i;
412 int n_faces = FRAME_N_PARAM_FACES (XFRAME (result));
413 struct face **faces = FRAME_PARAM_FACES (XFRAME (result));
414
415 for (i = 2; i < n_faces; i++)
416 if (faces[i])
417 ensure_face_ready (f, i);
418 }
419 }
420 }
421
422
423 /* Called from Fdelete_frame. */
424
425 void
426 free_frame_faces (f)
427 struct frame *f;
428 {
429 int i;
430
431 BLOCK_INPUT;
432
433 for (i = 0; i < FRAME_N_PARAM_FACES (f); i++)
434 {
435 struct face *face = FRAME_PARAM_FACES (f) [i];
436 if (face)
437 {
438 if (face->fontset < 0)
439 unload_font (f, face->font);
440 unload_color (f, face->foreground);
441 unload_color (f, face->background);
442 x_destroy_bitmap (f, face->stipple);
443 xfree (face);
444 }
445 }
446 xfree (FRAME_PARAM_FACES (f));
447 FRAME_PARAM_FACES (f) = 0;
448 FRAME_N_PARAM_FACES (f) = 0;
449
450 /* All faces in FRAME_COMPUTED_FACES use resources copied from
451 FRAME_PARAM_FACES; we can free them without fuss.
452 But we do free the GCs and the face objects themselves. */
453 for (i = 0; i < FRAME_N_COMPUTED_FACES (f); i++)
454 {
455 struct face *face = FRAME_COMPUTED_FACES (f) [i];
456 if (face)
457 {
458 xfree (face);
459 }
460 }
461 xfree (FRAME_COMPUTED_FACES (f));
462 FRAME_COMPUTED_FACES (f) = 0;
463 FRAME_N_COMPUTED_FACES (f) = 0;
464
465 UNBLOCK_INPUT;
466 }
467 \f
468 /* Interning faces in a frame's face array. */
469
470 static int
471 new_computed_face (f, new_face)
472 struct frame *f;
473 struct face *new_face;
474 {
475 int len = FRAME_N_COMPUTED_FACES (f);
476 int i;
477
478 /* Search for an unused computed face in the middle of the table. */
479 for (i = 0; i < len; i++)
480 {
481 struct face *face = FRAME_COMPUTED_FACES (f)[i];
482 if (face->font == 0)
483 {
484 FRAME_COMPUTED_FACES (f)[i] = copy_face (new_face);
485 return i;
486 }
487 }
488
489 if (i >= FRAME_SIZE_COMPUTED_FACES (f))
490 {
491 int new_size = i + 32;
492
493 FRAME_COMPUTED_FACES (f)
494 = (struct face **) (FRAME_SIZE_COMPUTED_FACES (f) == 0
495 ? xmalloc (new_size * sizeof (struct face *))
496 : xrealloc (FRAME_COMPUTED_FACES (f),
497 new_size * sizeof (struct face *)));
498 FRAME_SIZE_COMPUTED_FACES (f) = new_size;
499 }
500
501 i = FRAME_N_COMPUTED_FACES (f)++;
502 FRAME_COMPUTED_FACES (f)[i] = copy_face (new_face);
503 return i;
504 }
505
506
507 /* Find a match for NEW_FACE in a FRAME's computed face array, and add
508 it if we don't find one. */
509 static int
510 intern_computed_face (f, new_face)
511 struct frame *f;
512 struct face *new_face;
513 {
514 int len = FRAME_N_COMPUTED_FACES (f);
515 int i;
516
517 /* Search for a computed face already on F equivalent to FACE. */
518 for (i = 0; i < len; i++)
519 {
520 if (! FRAME_COMPUTED_FACES (f)[i])
521 abort ();
522 if (face_eql (new_face, FRAME_COMPUTED_FACES (f)[i]))
523 return i;
524 }
525
526 /* We didn't find one; add a new one. */
527 return new_computed_face (f, new_face);
528 }
529
530 /* Make parameter face id ID valid on frame F. */
531
532 static void
533 ensure_face_ready (f, id)
534 struct frame *f;
535 int id;
536 {
537 if (FRAME_N_PARAM_FACES (f) <= id)
538 {
539 int n = id + 10;
540 int i;
541 if (!FRAME_N_PARAM_FACES (f))
542 FRAME_PARAM_FACES (f)
543 = (struct face **) xmalloc (sizeof (struct face *) * n);
544 else
545 FRAME_PARAM_FACES (f)
546 = (struct face **) xrealloc (FRAME_PARAM_FACES (f),
547 sizeof (struct face *) * n);
548
549 bzero (FRAME_PARAM_FACES (f) + FRAME_N_PARAM_FACES (f),
550 (n - FRAME_N_PARAM_FACES (f)) * sizeof (struct face *));
551 FRAME_N_PARAM_FACES (f) = n;
552 }
553
554 if (FRAME_PARAM_FACES (f) [id] == 0)
555 FRAME_PARAM_FACES (f) [id] = allocate_face ();
556 }
557 \f
558 /* Return non-zero if FONT1 and FONT2 have the same width.
559 We do not check the height, because we can now deal with
560 different heights.
561 We assume that they're both character-cell fonts. */
562
563 int
564 same_size_fonts (font1, font2)
565 XFontStruct *font1, *font2;
566 {
567 return (FONT_WIDTH(font1) == FONT_WIDTH(font2));
568 }
569
570 /* Update the line_height of frame F according to the biggest font in
571 any face. Return nonzero if if line_height changes. */
572
573 int
574 frame_update_line_height (f)
575 FRAME_PTR f;
576 {
577 int i;
578 int fontset = FRAME_FONTSET (f);
579 int biggest = (fontset > 0
580 ? FRAME_FONTSET_DATA (f)->fontset_table[fontset]->height
581 : FONT_HEIGHT (FRAME_FONT (f)));
582
583 for (i = 0; i < FRAME_N_PARAM_FACES (f); i++)
584 if (FRAME_PARAM_FACES (f)[i] != 0
585 && FRAME_PARAM_FACES (f)[i]->font != (XFontStruct *) FACE_DEFAULT)
586 {
587 int height = ((fontset =
588 FRAME_PARAM_FACES (f)[i]->fontset) > 0
589 ? FRAME_FONTSET_DATA (f)->fontset_table[fontset]->height
590 : FONT_HEIGHT
591 (FRAME_PARAM_FACES (f)[i]->font));
592 if (height > biggest)
593 biggest = height;
594 }
595
596 if (biggest == FRAME_LINE_HEIGHT (f))
597 return 0;
598
599 FRAME_LINE_HEIGHT (f) = biggest;
600 return 1;
601 }
602 \f
603 /* Modify face TO by copying from FROM all properties which have
604 nondefault settings. */
605
606 static void
607 merge_faces (from, to)
608 struct face *from, *to;
609 {
610 /* Only merge the font if it's the same width as the base font.
611 Otherwise ignore it, since we can't handle it properly. */
612 if (from->font != (XFontStruct *) FACE_DEFAULT
613 && same_size_fonts (from->font, to->font))
614 to->font = from->font;
615 if (from->fontset != -1)
616 to->fontset = from->fontset;
617 if (from->foreground != FACE_DEFAULT)
618 to->foreground = from->foreground;
619 if (from->background != FACE_DEFAULT)
620 to->background = from->background;
621 if (from->stipple != FACE_DEFAULT)
622 {
623 to->stipple = from->stipple;
624 to->pixmap_h = from->pixmap_h;
625 to->pixmap_w = from->pixmap_w;
626 }
627 if (from->underline)
628 to->underline = from->underline;
629 }
630
631 /* Set up the basic set of facial parameters, based on the frame's
632 data; all faces are deltas applied to this. */
633
634 static void
635 compute_base_face (f, face)
636 FRAME_PTR f;
637 struct face *face;
638 {
639 face->gc = 0;
640 face->foreground = FRAME_FOREGROUND_PIXEL (f);
641 face->background = FRAME_BACKGROUND_PIXEL (f);
642 face->font = FRAME_FONT (f);
643 face->fontset = -1;
644 face->stipple = 0;
645 face->underline = 0;
646 }
647
648 /* Return the face ID to use to display a special glyph which selects
649 FACE_CODE as the face ID, assuming that ordinarily the face would
650 be CURRENT_FACE. F is the frame. */
651
652 int
653 compute_glyph_face (f, face_code, current_face)
654 struct frame *f;
655 int face_code, current_face;
656 {
657 struct face face;
658
659 face = *FRAME_COMPUTED_FACES (f)[current_face];
660
661 if (face_code >= 0 && face_code < FRAME_N_PARAM_FACES (f)
662 && FRAME_PARAM_FACES (f) [face_code] != 0)
663 merge_faces (FRAME_PARAM_FACES (f) [face_code], &face);
664
665 return intern_computed_face (f, &face);
666 }
667
668 /* Return the face ID to use to display a special glyph which selects
669 FACE_CODE as the face ID, assuming that ordinarily the face would
670 be CURRENT_FACE. F is the frame. */
671
672 int
673 compute_glyph_face_1 (f, face_name, current_face)
674 struct frame *f;
675 Lisp_Object face_name;
676 int current_face;
677 {
678 struct face face;
679
680 face = *FRAME_COMPUTED_FACES (f)[current_face];
681
682 if (!NILP (face_name))
683 {
684 int facecode = face_name_id_number (f, face_name);
685 if (facecode >= 0 && facecode < FRAME_N_PARAM_FACES (f)
686 && FRAME_PARAM_FACES (f) [facecode] != 0)
687 merge_faces (FRAME_PARAM_FACES (f) [facecode], &face);
688 }
689
690 return intern_computed_face (f, &face);
691 }
692 \f
693 /* Return the face ID associated with a buffer position POS.
694 Store into *ENDPTR the position at which a different face is needed.
695 This does not take account of glyphs that specify their own face codes.
696 F is the frame in use for display, and W is a window displaying
697 the current buffer.
698
699 REGION_BEG, REGION_END delimit the region, so it can be highlighted.
700
701 LIMIT is a position not to scan beyond. That is to limit
702 the time this function can take.
703
704 If MOUSE is nonzero, use the character's mouse-face, not its face. */
705 int
706 compute_char_face (f, w, pos, region_beg, region_end, endptr, limit, mouse)
707 struct frame *f;
708 struct window *w;
709 int pos;
710 int region_beg, region_end;
711 int *endptr;
712 int limit;
713 int mouse;
714 {
715 struct face face;
716 Lisp_Object prop, position;
717 int i, j, noverlays;
718 int facecode;
719 Lisp_Object *overlay_vec;
720 Lisp_Object frame;
721 int endpos;
722 Lisp_Object propname;
723
724 /* W must display the current buffer. We could write this function
725 to use the frame and buffer of W, but right now it doesn't. */
726 if (XBUFFER (w->buffer) != current_buffer)
727 abort ();
728
729 XSETFRAME (frame, f);
730
731 endpos = ZV;
732 if (pos < region_beg && region_beg < endpos)
733 endpos = region_beg;
734
735 XSETFASTINT (position, pos);
736
737 if (mouse)
738 propname = Qmouse_face;
739 else
740 propname = Qface;
741
742 prop = Fget_text_property (position, propname, w->buffer);
743
744 {
745 Lisp_Object limit1, end;
746
747 XSETFASTINT (limit1, (limit < endpos ? limit : endpos));
748 end = Fnext_single_property_change (position, propname, w->buffer, limit1);
749 if (INTEGERP (end))
750 endpos = XINT (end);
751 }
752
753 {
754 int next_overlay;
755 int len;
756
757 /* First try with room for 40 overlays. */
758 len = 40;
759 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
760
761 noverlays = overlays_at (pos, 0, &overlay_vec, &len,
762 &next_overlay, (int *) 0);
763
764 /* If there are more than 40,
765 make enough space for all, and try again. */
766 if (noverlays > len)
767 {
768 len = noverlays;
769 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
770 noverlays = overlays_at (pos, 0, &overlay_vec, &len,
771 &next_overlay, (int *) 0);
772 }
773
774 if (next_overlay < endpos)
775 endpos = next_overlay;
776 }
777
778 *endptr = endpos;
779
780 /* Optimize the default case. */
781 if (noverlays == 0 && NILP (prop)
782 && !(pos >= region_beg && pos < region_end))
783 return 0;
784
785 compute_base_face (f, &face);
786
787 merge_face_list (f, &face, prop);
788
789 noverlays = sort_overlays (overlay_vec, noverlays, w);
790
791 /* Now merge the overlay data in that order. */
792 for (i = 0; i < noverlays; i++)
793 {
794 Lisp_Object oend;
795 int oendpos;
796
797 prop = Foverlay_get (overlay_vec[i], propname);
798 merge_face_list (f, &face, prop);
799
800 oend = OVERLAY_END (overlay_vec[i]);
801 oendpos = OVERLAY_POSITION (oend);
802 if (oendpos < endpos)
803 endpos = oendpos;
804 }
805
806 if (pos >= region_beg && pos < region_end)
807 {
808 if (region_end < endpos)
809 endpos = region_end;
810 if (region_face >= 0 && region_face < next_face_id)
811 merge_faces (FRAME_PARAM_FACES (f)[region_face], &face);
812 }
813
814 *endptr = endpos;
815
816 return intern_computed_face (f, &face);
817 }
818
819 static void
820 merge_face_list (f, face, prop)
821 FRAME_PTR f;
822 struct face *face;
823 Lisp_Object prop;
824 {
825 Lisp_Object length;
826 int len;
827 Lisp_Object *faces;
828 int j;
829
830 if (CONSP (prop)
831 && ! STRINGP (XCDR (prop)))
832 {
833 /* We have a list of faces, merge them in reverse order. */
834
835 length = Fsafe_length (prop);
836 len = XFASTINT (length);
837
838 /* Put them into an array. */
839 faces = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
840 for (j = 0; j < len; j++)
841 {
842 faces[j] = Fcar (prop);
843 prop = Fcdr (prop);
844 }
845 /* So that we can merge them in the reverse order. */
846 }
847 else
848 {
849 faces = (Lisp_Object *) alloca (sizeof (Lisp_Object));
850 faces[0] = prop;
851 len = 1;
852 }
853
854 for (j = len - 1; j >= 0; j--)
855 {
856 if (CONSP (faces[j]))
857 {
858 if (EQ (XCAR (faces[j]), Qbackground_color))
859 face->background = load_color (f, XCDR (faces[j]));
860 if (EQ (XCAR (faces[j]), Qforeground_color))
861 face->foreground = load_color (f, XCDR (faces[j]));
862 }
863 else
864 {
865 int facecode = face_name_id_number (f, faces[j]);
866 if (facecode >= 0 && facecode < FRAME_N_PARAM_FACES (f)
867 && FRAME_PARAM_FACES (f) [facecode] != 0)
868 merge_faces (FRAME_PARAM_FACES (f) [facecode], face);
869 }
870 }
871 }
872
873 \f
874 /* Recompute the GC's for the default and modeline faces.
875 We call this after changing frame parameters on which those GC's
876 depend. */
877
878 void
879 recompute_basic_faces (f)
880 FRAME_PTR f;
881 {
882 /* If the frame's faces haven't been initialized yet, don't worry about
883 this stuff. */
884 if (FRAME_N_PARAM_FACES (f) < 2)
885 return;
886
887 BLOCK_INPUT;
888
889 compute_base_face (f, FRAME_DEFAULT_FACE (f));
890 compute_base_face (f, FRAME_MODE_LINE_FACE (f));
891
892 merge_faces (FRAME_DEFAULT_PARAM_FACE (f), FRAME_DEFAULT_FACE (f));
893 merge_faces (FRAME_MODE_LINE_PARAM_FACE (f), FRAME_MODE_LINE_FACE (f));
894
895 intern_face (f, FRAME_DEFAULT_FACE (f));
896 intern_face (f, FRAME_MODE_LINE_FACE (f));
897
898 UNBLOCK_INPUT;
899 }
900
901
902 \f
903 /* Lisp interface. */
904
905 DEFUN ("frame-face-alist", Fframe_face_alist, Sframe_face_alist, 1, 1, 0,
906 "")
907 (frame)
908 Lisp_Object frame;
909 {
910 CHECK_FRAME (frame, 0);
911 return XFRAME (frame)->face_alist;
912 }
913
914 DEFUN ("set-frame-face-alist", Fset_frame_face_alist, Sset_frame_face_alist,
915 2, 2, 0, "")
916 (frame, value)
917 Lisp_Object frame, value;
918 {
919 CHECK_FRAME (frame, 0);
920 XFRAME (frame)->face_alist = value;
921 return value;
922 }
923
924
925 DEFUN ("make-face-internal", Fmake_face_internal, Smake_face_internal, 1, 1, 0,
926 "Create face number FACE-ID on all frames.")
927 (face_id)
928 Lisp_Object face_id;
929 {
930 Lisp_Object rest, frame;
931 int id = XINT (face_id);
932
933 CHECK_NUMBER (face_id, 0);
934 if (id < 0 || id >= next_face_id)
935 error ("Face id out of range");
936
937 FOR_EACH_FRAME (rest, frame)
938 {
939 if (FRAME_W32_P (XFRAME (frame)))
940 ensure_face_ready (XFRAME (frame), id);
941 }
942 return Qnil;
943 }
944
945
946 DEFUN ("set-face-attribute-internal", Fset_face_attribute_internal,
947 Sset_face_attribute_internal, 4, 4, 0, "")
948 (face_id, attr_name, attr_value, frame)
949 Lisp_Object face_id, attr_name, attr_value, frame;
950 {
951 struct face *face;
952 struct frame *f;
953 int magic_p;
954 int id;
955 int garbaged = 0;
956
957 CHECK_FRAME (frame, 0);
958 CHECK_NUMBER (face_id, 0);
959 CHECK_SYMBOL (attr_name, 0);
960
961 f = XFRAME (frame);
962 id = XINT (face_id);
963 if (id < 0 || id >= next_face_id)
964 error ("Face id out of range");
965
966 if (! FRAME_WINDOW_P (f))
967 return Qnil;
968
969 ensure_face_ready (f, id);
970 face = FRAME_PARAM_FACES (f) [XFASTINT (face_id)];
971
972 if (EQ (attr_name, intern ("font")))
973 {
974 XFontStruct *font = NULL;
975 int fontset;
976
977 if (NILP (attr_value))
978 {
979 font = (XFontStruct *) FACE_DEFAULT;
980 fontset = -1;
981 }
982 else
983 {
984 CHECK_STRING (attr_value, 0);
985 fontset = fs_query_fontset (f, XSTRING (attr_value)->data);
986 if (fontset >= 0)
987 {
988 struct font_info *fontp;
989
990 if (!(fontp = FS_LOAD_FONT (f, FRAME_W32_FONT_TABLE (f),
991 CHARSET_ASCII, NULL, fontset)))
992 Fsignal (Qerror,
993 Fcons (build_string ("ASCII font can't be loaded"),
994 Fcons (attr_value, Qnil)));
995 font = (XFontStruct *) (fontp->font);
996 }
997 else
998 font = load_font (f, attr_value);
999 }
1000 if (face->fontset == -1 && face->font != f->output_data.w32->font)
1001 unload_font (f, face->font);
1002 face->font = font;
1003 face->fontset = fontset;
1004 if (frame_update_line_height (f))
1005 x_set_window_size (f, 0, f->width, f->height);
1006 /* Must clear cache, since it might contain the font
1007 we just got rid of. */
1008 garbaged = 1;
1009 }
1010 else if (EQ (attr_name, intern ("foreground")))
1011 {
1012 unsigned long new_color = load_color (f, attr_value);
1013 unload_color (f, face->foreground);
1014 face->foreground = new_color;
1015 garbaged = 1;
1016 }
1017 else if (EQ (attr_name, intern ("background")))
1018 {
1019 unsigned long new_color = load_color (f, attr_value);
1020 unload_color (f, face->background);
1021 face->background = new_color;
1022 garbaged = 1;
1023 }
1024 else if (EQ (attr_name, intern ("background-pixmap")))
1025 {
1026 unsigned int w, h;
1027 unsigned long new_pixmap = load_pixmap (f, attr_value, &w, &h);
1028 x_destroy_bitmap (f, face->stipple);
1029 face->stipple = (Pixmap) new_pixmap;
1030 face->pixmap_w = w;
1031 face->pixmap_h = h;
1032 garbaged = 1;
1033 }
1034 else if (EQ (attr_name, intern ("underline")))
1035 {
1036 int new = !NILP (attr_value);
1037 face->underline = new;
1038 }
1039 else
1040 error ("unknown face attribute");
1041
1042 if (id == 0 || id == 1)
1043 recompute_basic_faces (f);
1044
1045 /* We must redraw the frame whenever any face font or color changes,
1046 because it's possible that a merged (display) face
1047 contains the font or color we just replaced.
1048 And we must inhibit any Expose events until the redraw is done,
1049 since they would try to use the invalid display faces. */
1050 if (garbaged)
1051 SET_FRAME_GARBAGED (f);
1052
1053 return Qnil;
1054 }
1055
1056 DEFUN ("internal-next-face-id", Finternal_next_face_id, Sinternal_next_face_id,
1057 0, 0, 0, "")
1058 ()
1059 {
1060 return make_number (next_face_id++);
1061 }
1062
1063 /* Return the face id for name NAME on frame FRAME.
1064 (It should be the same for all frames,
1065 but it's as easy to use the "right" frame to look it up
1066 as to use any other one.) */
1067
1068 int
1069 face_name_id_number (f, name)
1070 FRAME_PTR f;
1071 Lisp_Object name;
1072 {
1073 Lisp_Object tem;
1074
1075 tem = Fcdr (assq_no_quit (name, f->face_alist));
1076 if (NILP (tem))
1077 return 0;
1078 CHECK_VECTOR (tem, 0);
1079 tem = XVECTOR (tem)->contents[2];
1080 CHECK_NUMBER (tem, 0);
1081 return XINT (tem);
1082 }
1083 \f
1084 /* Emacs initialization. */
1085
1086 void
1087 syms_of_w32faces ()
1088 {
1089 Qface = intern ("face");
1090 staticpro (&Qface);
1091 Qmouse_face = intern ("mouse-face");
1092 staticpro (&Qmouse_face);
1093 Qpixmap_spec_p = intern ("pixmap-spec-p");
1094 staticpro (&Qpixmap_spec_p);
1095
1096 DEFVAR_INT ("region-face", &region_face,
1097 "Face number to use to highlight the region\n\
1098 The region is highlighted with this face\n\
1099 when Transient Mark mode is enabled and the mark is active.");
1100
1101 defsubr (&Spixmap_spec_p);
1102 defsubr (&Sframe_face_alist);
1103 defsubr (&Sset_frame_face_alist);
1104 defsubr (&Smake_face_internal);
1105 defsubr (&Sset_face_attribute_internal);
1106 defsubr (&Sinternal_next_face_id);
1107 }