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