Mercurial > hg > xemacs-beta
annotate src/faces.c @ 5125:b5df3737028a ben-lisp-object
merge
author | Ben Wing <ben@xemacs.org> |
---|---|
date | Wed, 24 Feb 2010 01:58:04 -0600 |
parents | 623d57b7fbe8 d95c102a96d3 |
children | 2a462149bd6a |
rev | line source |
---|---|
428 | 1 /* "Face" primitives |
2 Copyright (C) 1994 Free Software Foundation, Inc. | |
3 Copyright (C) 1995 Board of Trustees, University of Illinois. | |
5015
d95c102a96d3
cleanups for specifier font stages, from ben-unicode-internal (preparation for eliminating shadowed warnings)
Ben Wing <ben@xemacs.org>
parents:
5013
diff
changeset
|
4 Copyright (C) 1995, 1996, 2001, 2002, 2005, 2010 Ben Wing. |
428 | 5 Copyright (C) 1995 Sun Microsystems, Inc. |
6 | |
7 This file is part of XEmacs. | |
8 | |
9 XEmacs is free software; you can redistribute it and/or modify it | |
10 under the terms of the GNU General Public License as published by the | |
11 Free Software Foundation; either version 2, or (at your option) any | |
12 later version. | |
13 | |
14 XEmacs is distributed in the hope that it will be useful, but WITHOUT | |
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
17 for more details. | |
18 | |
19 You should have received a copy of the GNU General Public License | |
20 along with XEmacs; see the file COPYING. If not, write to | |
21 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
22 Boston, MA 02111-1307, USA. */ | |
23 | |
24 /* Synched up with: Not in FSF. */ | |
25 | |
26 /* Written by Chuck Thompson and Ben Wing, | |
27 based loosely on old face code by Jamie Zawinski. */ | |
28 | |
29 #include <config.h> | |
30 #include "lisp.h" | |
31 | |
32 #include "buffer.h" | |
872 | 33 #include "device-impl.h" |
428 | 34 #include "elhash.h" |
872 | 35 #include "extents-impl.h" /* for extent_face */ |
428 | 36 #include "faces.h" |
872 | 37 #include "frame-impl.h" |
428 | 38 #include "glyphs.h" |
872 | 39 #include "objects-impl.h" |
428 | 40 #include "specifier.h" |
41 #include "window.h" | |
42 | |
43 Lisp_Object Qfacep; | |
44 Lisp_Object Qforeground, Qbackground, Qdisplay_table; | |
45 Lisp_Object Qbackground_pixmap, Qunderline, Qdim; | |
46 Lisp_Object Qblinking, Qstrikethru; | |
47 | |
48 Lisp_Object Qinit_face_from_resources; | |
49 Lisp_Object Qinit_frame_faces; | |
50 Lisp_Object Qinit_device_faces; | |
51 Lisp_Object Qinit_global_faces; | |
52 | |
53 /* These faces are used directly internally. We use these variables | |
54 to be able to reference them directly and save the overhead of | |
55 calling Ffind_face. */ | |
56 Lisp_Object Vdefault_face, Vmodeline_face, Vgui_element_face; | |
57 Lisp_Object Vleft_margin_face, Vright_margin_face, Vtext_cursor_face; | |
58 Lisp_Object Vpointer_face, Vvertical_divider_face, Vtoolbar_face, Vwidget_face; | |
59 | |
440 | 60 /* Qdefault, Qhighlight, Qleft_margin, Qright_margin defined in general.c */ |
61 Lisp_Object Qmodeline, Qgui_element, Qtext_cursor, Qvertical_divider; | |
428 | 62 |
2867 | 63 Lisp_Object Qface_alias, Qcyclic_face_alias; |
2865 | 64 |
428 | 65 /* In the old implementation Vface_list was a list of the face names, |
66 not the faces themselves. We now distinguish between permanent and | |
67 temporary faces. Permanent faces are kept in a regular hash table, | |
68 temporary faces in a weak hash table. */ | |
69 Lisp_Object Vpermanent_faces_cache; | |
70 Lisp_Object Vtemporary_faces_cache; | |
71 | |
72 Lisp_Object Vbuilt_in_face_specifiers; | |
73 | |
74 | |
3659 | 75 #ifdef DEBUG_XEMACS |
76 Fixnum debug_x_faces; | |
77 #endif | |
78 | |
4187 | 79 #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901) |
3659 | 80 |
81 #ifdef DEBUG_XEMACS | |
82 # define DEBUG_FACES(FORMAT, ...) \ | |
83 do { if (debug_x_faces) stderr_out(FORMAT, __VA_ARGS__); } while (0) | |
84 #else /* DEBUG_XEMACS */ | |
85 # define DEBUG_FACES(format, ...) | |
86 #endif /* DEBUG_XEMACS */ | |
87 | |
88 #elif defined(__GNUC__) | |
89 | |
90 #ifdef DEBUG_XEMACS | |
91 # define DEBUG_FACES(format, args...) \ | |
92 do { if (debug_x_faces) stderr_out(format, args ); } while (0) | |
93 #else /* DEBUG_XEMACS */ | |
94 # define DEBUG_FACES(format, args...) | |
95 #endif /* DEBUG_XEMACS */ | |
96 | |
97 #else /* defined(__STDC_VERSION__) [...] */ | |
98 # define DEBUG_FACES (void) | |
99 #endif | |
428 | 100 |
101 static Lisp_Object | |
102 mark_face (Lisp_Object obj) | |
103 { | |
440 | 104 Lisp_Face *face = XFACE (obj); |
428 | 105 |
106 mark_object (face->name); | |
107 mark_object (face->doc_string); | |
108 | |
109 mark_object (face->foreground); | |
110 mark_object (face->background); | |
111 mark_object (face->font); | |
112 mark_object (face->display_table); | |
113 mark_object (face->background_pixmap); | |
114 mark_object (face->underline); | |
115 mark_object (face->strikethru); | |
116 mark_object (face->highlight); | |
117 mark_object (face->dim); | |
118 mark_object (face->blinking); | |
119 mark_object (face->reverse); | |
120 | |
121 mark_object (face->charsets_warned_about); | |
122 | |
123 return face->plist; | |
124 } | |
125 | |
126 static void | |
2286 | 127 print_face (Lisp_Object obj, Lisp_Object printcharfun, int UNUSED (escapeflag)) |
428 | 128 { |
440 | 129 Lisp_Face *face = XFACE (obj); |
428 | 130 |
131 if (print_readably) | |
132 { | |
800 | 133 write_fmt_string_lisp (printcharfun, "#s(face name %S)", 1, face->name); |
428 | 134 } |
135 else | |
136 { | |
800 | 137 write_fmt_string_lisp (printcharfun, "#<face %S", 1, face->name); |
428 | 138 if (!NILP (face->doc_string)) |
800 | 139 write_fmt_string_lisp (printcharfun, " %S", 1, face->doc_string); |
4952
19a72041c5ed
Mule-izing, various fixes related to char * arguments
Ben Wing <ben@xemacs.org>
parents:
4862
diff
changeset
|
140 write_ascstring (printcharfun, ">"); |
428 | 141 } |
142 } | |
143 | |
144 /* Faces are equal if all of their display attributes are equal. We | |
145 don't compare names or doc-strings, because that would make equal | |
146 be eq. | |
147 | |
148 This isn't concerned with "unspecified" attributes, that's what | |
149 #'face-differs-from-default-p is for. */ | |
150 static int | |
4906
6ef8256a020a
implement equalp in C, fix case-folding, add equal() method for keymaps
Ben Wing <ben@xemacs.org>
parents:
4862
diff
changeset
|
151 face_equal (Lisp_Object obj1, Lisp_Object obj2, int depth, |
6ef8256a020a
implement equalp in C, fix case-folding, add equal() method for keymaps
Ben Wing <ben@xemacs.org>
parents:
4862
diff
changeset
|
152 int UNUSED (foldcase)) |
428 | 153 { |
440 | 154 Lisp_Face *f1 = XFACE (obj1); |
155 Lisp_Face *f2 = XFACE (obj2); | |
428 | 156 |
157 depth++; | |
158 | |
159 return | |
160 (internal_equal (f1->foreground, f2->foreground, depth) && | |
161 internal_equal (f1->background, f2->background, depth) && | |
162 internal_equal (f1->font, f2->font, depth) && | |
163 internal_equal (f1->display_table, f2->display_table, depth) && | |
164 internal_equal (f1->background_pixmap, f2->background_pixmap, depth) && | |
165 internal_equal (f1->underline, f2->underline, depth) && | |
166 internal_equal (f1->strikethru, f2->strikethru, depth) && | |
167 internal_equal (f1->highlight, f2->highlight, depth) && | |
168 internal_equal (f1->dim, f2->dim, depth) && | |
169 internal_equal (f1->blinking, f2->blinking, depth) && | |
170 internal_equal (f1->reverse, f2->reverse, depth) && | |
171 | |
4906
6ef8256a020a
implement equalp in C, fix case-folding, add equal() method for keymaps
Ben Wing <ben@xemacs.org>
parents:
4862
diff
changeset
|
172 ! plists_differ (f1->plist, f2->plist, 0, 0, depth + 1, 0)); |
428 | 173 } |
174 | |
665 | 175 static Hashcode |
428 | 176 face_hash (Lisp_Object obj, int depth) |
177 { | |
440 | 178 Lisp_Face *f = XFACE (obj); |
428 | 179 |
180 depth++; | |
181 | |
182 /* No need to hash all of the elements; that would take too long. | |
183 Just hash the most common ones. */ | |
184 return HASH3 (internal_hash (f->foreground, depth), | |
185 internal_hash (f->background, depth), | |
186 internal_hash (f->font, depth)); | |
187 } | |
188 | |
189 static Lisp_Object | |
190 face_getprop (Lisp_Object obj, Lisp_Object prop) | |
191 { | |
440 | 192 Lisp_Face *f = XFACE (obj); |
428 | 193 |
194 return | |
195 (EQ (prop, Qforeground) ? f->foreground : | |
196 EQ (prop, Qbackground) ? f->background : | |
197 EQ (prop, Qfont) ? f->font : | |
198 EQ (prop, Qdisplay_table) ? f->display_table : | |
199 EQ (prop, Qbackground_pixmap) ? f->background_pixmap : | |
200 EQ (prop, Qunderline) ? f->underline : | |
201 EQ (prop, Qstrikethru) ? f->strikethru : | |
202 EQ (prop, Qhighlight) ? f->highlight : | |
203 EQ (prop, Qdim) ? f->dim : | |
204 EQ (prop, Qblinking) ? f->blinking : | |
205 EQ (prop, Qreverse) ? f->reverse : | |
206 EQ (prop, Qdoc_string) ? f->doc_string : | |
207 external_plist_get (&f->plist, prop, 0, ERROR_ME)); | |
208 } | |
209 | |
210 static int | |
211 face_putprop (Lisp_Object obj, Lisp_Object prop, Lisp_Object value) | |
212 { | |
440 | 213 Lisp_Face *f = XFACE (obj); |
428 | 214 |
215 if (EQ (prop, Qforeground) || | |
216 EQ (prop, Qbackground) || | |
217 EQ (prop, Qfont) || | |
218 EQ (prop, Qdisplay_table) || | |
219 EQ (prop, Qbackground_pixmap) || | |
220 EQ (prop, Qunderline) || | |
221 EQ (prop, Qstrikethru) || | |
222 EQ (prop, Qhighlight) || | |
223 EQ (prop, Qdim) || | |
224 EQ (prop, Qblinking) || | |
225 EQ (prop, Qreverse)) | |
226 return 0; | |
227 | |
228 if (EQ (prop, Qdoc_string)) | |
229 { | |
230 if (!NILP (value)) | |
231 CHECK_STRING (value); | |
232 f->doc_string = value; | |
233 return 1; | |
234 } | |
235 | |
236 external_plist_put (&f->plist, prop, value, 0, ERROR_ME); | |
237 return 1; | |
238 } | |
239 | |
240 static int | |
241 face_remprop (Lisp_Object obj, Lisp_Object prop) | |
242 { | |
440 | 243 Lisp_Face *f = XFACE (obj); |
428 | 244 |
245 if (EQ (prop, Qforeground) || | |
246 EQ (prop, Qbackground) || | |
247 EQ (prop, Qfont) || | |
248 EQ (prop, Qdisplay_table) || | |
249 EQ (prop, Qbackground_pixmap) || | |
250 EQ (prop, Qunderline) || | |
251 EQ (prop, Qstrikethru) || | |
252 EQ (prop, Qhighlight) || | |
253 EQ (prop, Qdim) || | |
254 EQ (prop, Qblinking) || | |
255 EQ (prop, Qreverse)) | |
256 return -1; | |
257 | |
258 if (EQ (prop, Qdoc_string)) | |
259 { | |
260 f->doc_string = Qnil; | |
261 return 1; | |
262 } | |
263 | |
264 return external_remprop (&f->plist, prop, 0, ERROR_ME); | |
265 } | |
266 | |
267 static Lisp_Object | |
268 face_plist (Lisp_Object obj) | |
269 { | |
440 | 270 Lisp_Face *face = XFACE (obj); |
428 | 271 Lisp_Object result = face->plist; |
272 | |
273 result = cons3 (Qreverse, face->reverse, result); | |
274 result = cons3 (Qblinking, face->blinking, result); | |
275 result = cons3 (Qdim, face->dim, result); | |
276 result = cons3 (Qhighlight, face->highlight, result); | |
277 result = cons3 (Qstrikethru, face->strikethru, result); | |
278 result = cons3 (Qunderline, face->underline, result); | |
279 result = cons3 (Qbackground_pixmap, face->background_pixmap, result); | |
280 result = cons3 (Qdisplay_table, face->display_table, result); | |
281 result = cons3 (Qfont, face->font, result); | |
282 result = cons3 (Qbackground, face->background, result); | |
283 result = cons3 (Qforeground, face->foreground, result); | |
284 | |
285 return result; | |
286 } | |
287 | |
1204 | 288 static const struct memory_description face_description[] = { |
440 | 289 { XD_LISP_OBJECT, offsetof (Lisp_Face, name) }, |
290 { XD_LISP_OBJECT, offsetof (Lisp_Face, doc_string) }, | |
291 { XD_LISP_OBJECT, offsetof (Lisp_Face, foreground) }, | |
292 { XD_LISP_OBJECT, offsetof (Lisp_Face, background) }, | |
293 { XD_LISP_OBJECT, offsetof (Lisp_Face, font) }, | |
294 { XD_LISP_OBJECT, offsetof (Lisp_Face, display_table) }, | |
295 { XD_LISP_OBJECT, offsetof (Lisp_Face, background_pixmap) }, | |
296 { XD_LISP_OBJECT, offsetof (Lisp_Face, underline) }, | |
297 { XD_LISP_OBJECT, offsetof (Lisp_Face, strikethru) }, | |
298 { XD_LISP_OBJECT, offsetof (Lisp_Face, highlight) }, | |
299 { XD_LISP_OBJECT, offsetof (Lisp_Face, dim) }, | |
300 { XD_LISP_OBJECT, offsetof (Lisp_Face, blinking) }, | |
301 { XD_LISP_OBJECT, offsetof (Lisp_Face, reverse) }, | |
302 { XD_LISP_OBJECT, offsetof (Lisp_Face, plist) }, | |
303 { XD_LISP_OBJECT, offsetof (Lisp_Face, charsets_warned_about) }, | |
428 | 304 { XD_END } |
305 }; | |
306 | |
5124
623d57b7fbe8
separate regular and disksave finalization, print method fixes.
Ben Wing <ben@xemacs.org>
parents:
5119
diff
changeset
|
307 DEFINE_DUMPABLE_GENERAL_LISP_OBJECT ("face", face, |
623d57b7fbe8
separate regular and disksave finalization, print method fixes.
Ben Wing <ben@xemacs.org>
parents:
5119
diff
changeset
|
308 mark_face, print_face, 0, face_equal, |
623d57b7fbe8
separate regular and disksave finalization, print method fixes.
Ben Wing <ben@xemacs.org>
parents:
5119
diff
changeset
|
309 face_hash, face_description, |
623d57b7fbe8
separate regular and disksave finalization, print method fixes.
Ben Wing <ben@xemacs.org>
parents:
5119
diff
changeset
|
310 face_getprop, |
623d57b7fbe8
separate regular and disksave finalization, print method fixes.
Ben Wing <ben@xemacs.org>
parents:
5119
diff
changeset
|
311 face_putprop, face_remprop, |
623d57b7fbe8
separate regular and disksave finalization, print method fixes.
Ben Wing <ben@xemacs.org>
parents:
5119
diff
changeset
|
312 face_plist, 0 /* no disksaver */, |
623d57b7fbe8
separate regular and disksave finalization, print method fixes.
Ben Wing <ben@xemacs.org>
parents:
5119
diff
changeset
|
313 Lisp_Face); |
428 | 314 |
315 /************************************************************************/ | |
316 /* face read syntax */ | |
317 /************************************************************************/ | |
318 | |
319 static int | |
2286 | 320 face_name_validate (Lisp_Object UNUSED (keyword), Lisp_Object value, |
578 | 321 Error_Behavior errb) |
428 | 322 { |
323 if (ERRB_EQ (errb, ERROR_ME)) | |
324 { | |
325 CHECK_SYMBOL (value); | |
326 return 1; | |
327 } | |
328 | |
329 return SYMBOLP (value); | |
330 } | |
331 | |
332 static int | |
578 | 333 face_validate (Lisp_Object data, Error_Behavior errb) |
428 | 334 { |
335 int name_seen = 0; | |
336 Lisp_Object valw = Qnil; | |
337 | |
338 data = Fcdr (data); /* skip over Qface */ | |
339 while (!NILP (data)) | |
340 { | |
341 Lisp_Object keyw = Fcar (data); | |
342 | |
343 data = Fcdr (data); | |
344 valw = Fcar (data); | |
345 data = Fcdr (data); | |
346 if (EQ (keyw, Qname)) | |
347 name_seen = 1; | |
348 else | |
2500 | 349 ABORT (); |
428 | 350 } |
351 | |
352 if (!name_seen) | |
353 { | |
563 | 354 maybe_sferror ("No face name given", Qunbound, Qface, errb); |
428 | 355 return 0; |
356 } | |
357 | |
358 if (NILP (Ffind_face (valw))) | |
359 { | |
563 | 360 maybe_invalid_argument ("No such face", valw, Qface, errb); |
428 | 361 return 0; |
362 } | |
363 | |
364 return 1; | |
365 } | |
366 | |
367 static Lisp_Object | |
368 face_instantiate (Lisp_Object data) | |
369 { | |
370 return Fget_face (Fcar (Fcdr (data))); | |
371 } | |
372 | |
373 | |
374 /**************************************************************************** | |
375 * utility functions * | |
376 ****************************************************************************/ | |
377 | |
378 static void | |
440 | 379 reset_face (Lisp_Face *f) |
428 | 380 { |
381 f->name = Qnil; | |
382 f->doc_string = Qnil; | |
383 f->dirty = 0; | |
384 f->foreground = Qnil; | |
385 f->background = Qnil; | |
386 f->font = Qnil; | |
387 f->display_table = Qnil; | |
388 f->background_pixmap = Qnil; | |
389 f->underline = Qnil; | |
390 f->strikethru = Qnil; | |
391 f->highlight = Qnil; | |
392 f->dim = Qnil; | |
393 f->blinking = Qnil; | |
394 f->reverse = Qnil; | |
395 f->plist = Qnil; | |
396 f->charsets_warned_about = Qnil; | |
397 } | |
398 | |
440 | 399 static Lisp_Face * |
428 | 400 allocate_face (void) |
401 { | |
5117
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3017
diff
changeset
|
402 Lisp_Object obj = ALLOC_LISP_OBJECT (face); |
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3017
diff
changeset
|
403 Lisp_Face *result = XFACE (obj); |
428 | 404 |
405 reset_face (result); | |
406 return result; | |
407 } | |
408 | |
409 | |
410 /* We store the faces in hash tables with the names as the key and the | |
411 actual face object as the value. Occasionally we need to use them | |
412 in a list format. These routines provide us with that. */ | |
413 struct face_list_closure | |
414 { | |
415 Lisp_Object *face_list; | |
416 }; | |
417 | |
418 static int | |
2286 | 419 add_face_to_list_mapper (Lisp_Object UNUSED (key), Lisp_Object value, |
428 | 420 void *face_list_closure) |
421 { | |
422 /* This function can GC */ | |
423 struct face_list_closure *fcl = | |
424 (struct face_list_closure *) face_list_closure; | |
425 | |
426 *(fcl->face_list) = Fcons (XFACE (value)->name, (*fcl->face_list)); | |
427 return 0; | |
428 } | |
429 | |
430 static Lisp_Object | |
431 faces_list_internal (Lisp_Object list) | |
432 { | |
433 Lisp_Object face_list = Qnil; | |
434 struct gcpro gcpro1; | |
435 struct face_list_closure face_list_closure; | |
436 | |
437 GCPRO1 (face_list); | |
438 face_list_closure.face_list = &face_list; | |
439 elisp_maphash (add_face_to_list_mapper, list, &face_list_closure); | |
440 UNGCPRO; | |
441 | |
442 return face_list; | |
443 } | |
444 | |
445 static Lisp_Object | |
446 permanent_faces_list (void) | |
447 { | |
448 return faces_list_internal (Vpermanent_faces_cache); | |
449 } | |
450 | |
451 static Lisp_Object | |
452 temporary_faces_list (void) | |
453 { | |
454 return faces_list_internal (Vtemporary_faces_cache); | |
455 } | |
456 | |
457 | |
458 static int | |
2286 | 459 mark_face_as_clean_mapper (Lisp_Object UNUSED (key), Lisp_Object value, |
428 | 460 void *flag_closure) |
461 { | |
462 /* This function can GC */ | |
463 int *flag = (int *) flag_closure; | |
464 XFACE (value)->dirty = *flag; | |
465 return 0; | |
466 } | |
467 | |
468 static void | |
469 mark_all_faces_internal (int flag) | |
470 { | |
471 elisp_maphash (mark_face_as_clean_mapper, Vpermanent_faces_cache, &flag); | |
472 elisp_maphash (mark_face_as_clean_mapper, Vtemporary_faces_cache, &flag); | |
473 } | |
474 | |
475 void | |
476 mark_all_faces_as_clean (void) | |
477 { | |
478 mark_all_faces_internal (0); | |
479 } | |
480 | |
481 /* Currently unused (see the comment in face_property_was_changed()). */ | |
482 #if 0 | |
483 /* #### OBSOLETE ME, PLEASE. Maybe. Maybe this is just as good as | |
484 any other solution. */ | |
485 struct face_inheritance_closure | |
486 { | |
487 Lisp_Object face; | |
488 Lisp_Object property; | |
489 }; | |
490 | |
491 static void | |
492 update_inheritance_mapper_internal (Lisp_Object cur_face, | |
493 Lisp_Object inh_face, | |
494 Lisp_Object property) | |
495 { | |
496 /* #### fix this function */ | |
497 Lisp_Object elt = Qnil; | |
498 struct gcpro gcpro1; | |
499 | |
500 GCPRO1 (elt); | |
501 | |
502 for (elt = FACE_PROPERTY_SPEC_LIST (cur_face, property, Qall); | |
503 !NILP (elt); | |
504 elt = XCDR (elt)) | |
505 { | |
506 Lisp_Object values = XCDR (XCAR (elt)); | |
507 | |
508 for (; !NILP (values); values = XCDR (values)) | |
509 { | |
510 Lisp_Object value = XCDR (XCAR (values)); | |
511 if (VECTORP (value) && XVECTOR_LENGTH (value)) | |
512 { | |
513 if (EQ (Ffind_face (XVECTOR_DATA (value)[0]), inh_face)) | |
514 Fset_specifier_dirty_flag | |
515 (FACE_PROPERTY_SPECIFIER (inh_face, property)); | |
516 } | |
517 } | |
518 } | |
519 | |
520 UNGCPRO; | |
521 } | |
522 | |
523 static int | |
442 | 524 update_face_inheritance_mapper (const void *hash_key, void *hash_contents, |
428 | 525 void *face_inheritance_closure) |
526 { | |
527 Lisp_Object key, contents; | |
528 struct face_inheritance_closure *fcl = | |
529 (struct face_inheritance_closure *) face_inheritance_closure; | |
530 | |
5013 | 531 key = GET_LISP_FROM_VOID (hash_key); |
532 contents = GET_LISP_FROM_VOID (hash_contents); | |
428 | 533 |
534 if (EQ (fcl->property, Qfont)) | |
535 { | |
536 update_inheritance_mapper_internal (contents, fcl->face, Qfont); | |
537 } | |
538 else if (EQ (fcl->property, Qforeground) || | |
539 EQ (fcl->property, Qbackground)) | |
540 { | |
541 update_inheritance_mapper_internal (contents, fcl->face, Qforeground); | |
542 update_inheritance_mapper_internal (contents, fcl->face, Qbackground); | |
543 } | |
544 else if (EQ (fcl->property, Qunderline) || | |
545 EQ (fcl->property, Qstrikethru) || | |
546 EQ (fcl->property, Qhighlight) || | |
547 EQ (fcl->property, Qdim) || | |
548 EQ (fcl->property, Qblinking) || | |
549 EQ (fcl->property, Qreverse)) | |
550 { | |
551 update_inheritance_mapper_internal (contents, fcl->face, Qunderline); | |
552 update_inheritance_mapper_internal (contents, fcl->face, Qstrikethru); | |
553 update_inheritance_mapper_internal (contents, fcl->face, Qhighlight); | |
554 update_inheritance_mapper_internal (contents, fcl->face, Qdim); | |
555 update_inheritance_mapper_internal (contents, fcl->face, Qblinking); | |
556 update_inheritance_mapper_internal (contents, fcl->face, Qreverse); | |
557 } | |
558 return 0; | |
559 } | |
560 | |
561 static void | |
562 update_faces_inheritance (Lisp_Object face, Lisp_Object property) | |
563 { | |
564 struct face_inheritance_closure face_inheritance_closure; | |
565 struct gcpro gcpro1, gcpro2; | |
566 | |
567 GCPRO2 (face, property); | |
568 face_inheritance_closure.face = face; | |
569 face_inheritance_closure.property = property; | |
570 | |
571 elisp_maphash (update_face_inheritance_mapper, Vpermanent_faces_cache, | |
572 &face_inheritance_closure); | |
573 elisp_maphash (update_face_inheritance_mapper, Vtemporary_faces_cache, | |
574 &face_inheritance_closure); | |
575 | |
576 UNGCPRO; | |
577 } | |
578 #endif /* 0 */ | |
579 | |
580 Lisp_Object | |
581 face_property_matching_instance (Lisp_Object face, Lisp_Object property, | |
582 Lisp_Object charset, Lisp_Object domain, | |
578 | 583 Error_Behavior errb, int no_fallback, |
3659 | 584 Lisp_Object depth, |
585 enum font_specifier_matchspec_stages stage) | |
428 | 586 { |
771 | 587 Lisp_Object retval; |
872 | 588 Lisp_Object matchspec = Qunbound; |
589 struct gcpro gcpro1; | |
771 | 590 |
872 | 591 if (!NILP (charset)) |
4187 | 592 matchspec = noseeum_cons (charset, |
5015
d95c102a96d3
cleanups for specifier font stages, from ben-unicode-internal (preparation for eliminating shadowed warnings)
Ben Wing <ben@xemacs.org>
parents:
5013
diff
changeset
|
593 stage == STAGE_INITIAL ? Qinitial : Qfinal); |
3659 | 594 |
872 | 595 GCPRO1 (matchspec); |
5015
d95c102a96d3
cleanups for specifier font stages, from ben-unicode-internal (preparation for eliminating shadowed warnings)
Ben Wing <ben@xemacs.org>
parents:
5013
diff
changeset
|
596 /* This call to specifier_instance_no_quit(), will end up calling |
d95c102a96d3
cleanups for specifier font stages, from ben-unicode-internal (preparation for eliminating shadowed warnings)
Ben Wing <ben@xemacs.org>
parents:
5013
diff
changeset
|
597 font_instantiate() if the property in a question is a font (currently, |
d95c102a96d3
cleanups for specifier font stages, from ben-unicode-internal (preparation for eliminating shadowed warnings)
Ben Wing <ben@xemacs.org>
parents:
5013
diff
changeset
|
598 this means EQ (property, Qfont), because only the face property named |
d95c102a96d3
cleanups for specifier font stages, from ben-unicode-internal (preparation for eliminating shadowed warnings)
Ben Wing <ben@xemacs.org>
parents:
5013
diff
changeset
|
599 `font' contains a font object). See the comments there. */ |
872 | 600 retval = specifier_instance_no_quit (Fget (face, property, Qnil), matchspec, |
771 | 601 domain, errb, no_fallback, depth); |
872 | 602 UNGCPRO; |
603 if (CONSP (matchspec)) | |
604 free_cons (matchspec); | |
428 | 605 |
5015
d95c102a96d3
cleanups for specifier font stages, from ben-unicode-internal (preparation for eliminating shadowed warnings)
Ben Wing <ben@xemacs.org>
parents:
5013
diff
changeset
|
606 if (UNBOUNDP (retval) && !no_fallback && STAGE_FINAL == stage) |
428 | 607 { |
608 if (EQ (property, Qfont)) | |
609 { | |
610 if (NILP (memq_no_quit (charset, | |
611 XFACE (face)->charsets_warned_about))) | |
612 { | |
793 | 613 if (!UNBOUNDP (charset)) |
428 | 614 warn_when_safe |
793 | 615 (Qfont, Qnotice, |
616 "Unable to instantiate font for charset %s, face %s", | |
617 XSTRING_DATA (symbol_name | |
618 (XSYMBOL (XCHARSET_NAME (charset)))), | |
619 XSTRING_DATA (symbol_name | |
620 (XSYMBOL (XFACE (face)->name)))); | |
428 | 621 XFACE (face)->charsets_warned_about = |
622 Fcons (charset, XFACE (face)->charsets_warned_about); | |
623 } | |
624 retval = Vthe_null_font_instance; | |
625 } | |
626 } | |
627 | |
628 return retval; | |
629 } | |
630 | |
631 | |
632 DEFUN ("facep", Ffacep, 1, 1, 0, /* | |
444 | 633 Return t if OBJECT is a face. |
428 | 634 */ |
635 (object)) | |
636 { | |
637 return FACEP (object) ? Qt : Qnil; | |
638 } | |
639 | |
640 DEFUN ("find-face", Ffind_face, 1, 1, 0, /* | |
641 Retrieve the face of the given name. | |
642 If FACE-OR-NAME is a face object, it is simply returned. | |
643 Otherwise, FACE-OR-NAME should be a symbol. If there is no such face, | |
644 nil is returned. Otherwise the associated face object is returned. | |
645 */ | |
646 (face_or_name)) | |
647 { | |
648 Lisp_Object retval; | |
2865 | 649 Lisp_Object face_name; |
650 Lisp_Object face_alias; | |
651 int i; | |
428 | 652 |
653 if (FACEP (face_or_name)) | |
654 return face_or_name; | |
2865 | 655 |
656 face_name = face_or_name; | |
657 CHECK_SYMBOL (face_name); | |
658 | |
2867 | 659 # define FACE_ALIAS_MAX_DEPTH 32 |
2865 | 660 |
661 i = 0; | |
662 while (! NILP ((face_alias = Fget (face_name, Qface_alias, Qnil))) | |
2867 | 663 && i < FACE_ALIAS_MAX_DEPTH) |
2865 | 664 { |
665 face_name = face_alias; | |
666 CHECK_SYMBOL (face_alias); | |
667 i += 1; | |
668 } | |
669 | |
670 /* #### This test actually makes the aliasing max depth to 30, which is more | |
671 #### than enough IMO. -- dvl */ | |
2867 | 672 if (i == FACE_ALIAS_MAX_DEPTH) |
673 signal_error (Qcyclic_face_alias, | |
2865 | 674 "Max face aliasing depth reached", |
675 face_name); | |
676 | |
2867 | 677 # undef FACE_ALIAS_MAX_DEPTH |
428 | 678 |
679 /* Check if the name represents a permanent face. */ | |
2865 | 680 retval = Fgethash (face_name, Vpermanent_faces_cache, Qnil); |
428 | 681 if (!NILP (retval)) |
682 return retval; | |
683 | |
684 /* Check if the name represents a temporary face. */ | |
2865 | 685 return Fgethash (face_name, Vtemporary_faces_cache, Qnil); |
428 | 686 } |
687 | |
688 DEFUN ("get-face", Fget_face, 1, 1, 0, /* | |
689 Retrieve the face of the given name. | |
690 Same as `find-face' except an error is signalled if there is no such | |
691 face instead of returning nil. | |
692 */ | |
693 (name)) | |
694 { | |
695 Lisp_Object face = Ffind_face (name); | |
696 | |
697 if (NILP (face)) | |
563 | 698 invalid_argument ("No such face", name); |
428 | 699 return face; |
700 } | |
701 | |
702 DEFUN ("face-name", Fface_name, 1, 1, 0, /* | |
703 Return the name of the given face. | |
704 */ | |
705 (face)) | |
706 { | |
707 return XFACE (Fget_face (face))->name; | |
708 } | |
709 | |
710 DEFUN ("built-in-face-specifiers", Fbuilt_in_face_specifiers, 0, 0, 0, /* | |
711 Return a list of all built-in face specifier properties. | |
4534
f32c7f843961
#'built-in-face-specifiers; document that we're returning a copy.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4532
diff
changeset
|
712 |
f32c7f843961
#'built-in-face-specifiers; document that we're returning a copy.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4532
diff
changeset
|
713 This is a copy; there is no way to modify XEmacs' idea of the built-in face |
f32c7f843961
#'built-in-face-specifiers; document that we're returning a copy.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4532
diff
changeset
|
714 specifier properties from Lisp. |
428 | 715 */ |
716 ()) | |
717 { | |
4532
16906fefc8df
Return a list copy in #'built-in-face-specifiers, pre-empting modification.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4210
diff
changeset
|
718 return Fcopy_list(Vbuilt_in_face_specifiers); |
428 | 719 } |
720 | |
721 /* These values are retrieved so often that we make a special | |
722 function. | |
723 */ | |
724 | |
725 void | |
726 default_face_font_info (Lisp_Object domain, int *ascent, int *descent, | |
727 int *height, int *width, int *proportional_p) | |
728 { | |
729 Lisp_Object font_instance; | |
3707 | 730 struct face_cachel *cachel; |
731 struct window *w = NULL; | |
428 | 732 |
733 if (noninteractive) | |
734 { | |
735 if (ascent) | |
4187 | 736 *ascent = 1; |
428 | 737 if (descent) |
4187 | 738 *descent = 0; |
428 | 739 if (height) |
4187 | 740 *height = 1; |
428 | 741 if (width) |
4187 | 742 *width = 1; |
428 | 743 if (proportional_p) |
4187 | 744 *proportional_p = 0; |
428 | 745 return; |
746 } | |
747 | |
3707 | 748 /* We use ASCII here. This is reasonable because the people calling this |
749 function are using the resulting values to come up with overall sizes | |
4187 | 750 for windows and frames. |
3707 | 751 |
752 It's possible for this function to get called when the face cachels | |
753 have not been initialized--put a call to debug-print in | |
754 init-locale-at-early-startup to see it happen. */ | |
755 | |
756 if (WINDOWP (domain) && (w = XWINDOW (domain)) && w->face_cachels) | |
428 | 757 { |
758 if (!Dynarr_length (w->face_cachels)) | |
4187 | 759 reset_face_cachels (w); |
428 | 760 cachel = WINDOW_FACE_CACHEL (w, DEFAULT_INDEX); |
761 font_instance = FACE_CACHEL_FONT (cachel, Vcharset_ascii); | |
762 } | |
763 else | |
764 { | |
765 font_instance = FACE_FONT (Vdefault_face, domain, Vcharset_ascii); | |
766 } | |
767 | |
3707 | 768 if (UNBOUNDP (font_instance)) |
769 { | |
770 return; | |
771 } | |
772 | |
428 | 773 if (height) |
774 *height = XFONT_INSTANCE (font_instance)->height; | |
775 if (width) | |
776 *width = XFONT_INSTANCE (font_instance)->width; | |
777 if (ascent) | |
778 *ascent = XFONT_INSTANCE (font_instance)->ascent; | |
779 if (descent) | |
780 *descent = XFONT_INSTANCE (font_instance)->descent; | |
781 if (proportional_p) | |
782 *proportional_p = XFONT_INSTANCE (font_instance)->proportional_p; | |
783 } | |
784 | |
785 void | |
786 default_face_height_and_width (Lisp_Object domain, | |
787 int *height, int *width) | |
788 { | |
789 default_face_font_info (domain, 0, 0, height, width, 0); | |
790 } | |
791 | |
792 void | |
793 default_face_height_and_width_1 (Lisp_Object domain, | |
794 int *height, int *width) | |
795 { | |
796 if (window_system_pixelated_geometry (domain)) | |
797 { | |
798 if (height) | |
799 *height = 1; | |
800 if (width) | |
801 *width = 1; | |
802 } | |
803 else | |
804 default_face_height_and_width (domain, height, width); | |
805 } | |
806 | |
807 DEFUN ("face-list", Fface_list, 0, 1, 0, /* | |
808 Return a list of the names of all defined faces. | |
809 If TEMPORARY is nil, only the permanent faces are included. | |
810 If it is t, only the temporary faces are included. If it is any | |
811 other non-nil value both permanent and temporary are included. | |
812 */ | |
813 (temporary)) | |
814 { | |
815 Lisp_Object face_list = Qnil; | |
816 | |
817 /* Added the permanent faces, if requested. */ | |
818 if (NILP (temporary) || !EQ (Qt, temporary)) | |
819 face_list = permanent_faces_list (); | |
820 | |
821 if (!NILP (temporary)) | |
822 { | |
823 struct gcpro gcpro1; | |
824 GCPRO1 (face_list); | |
825 face_list = nconc2 (face_list, temporary_faces_list ()); | |
826 UNGCPRO; | |
827 } | |
828 | |
829 return face_list; | |
830 } | |
831 | |
832 DEFUN ("make-face", Fmake_face, 1, 3, 0, /* | |
444 | 833 Define a new face with name NAME (a symbol), described by DOC-STRING. |
834 You can modify the font, color, etc. of a face with the set-face-* functions. | |
428 | 835 If the face already exists, it is unmodified. |
836 If TEMPORARY is non-nil, this face will cease to exist if not in use. | |
837 */ | |
838 (name, doc_string, temporary)) | |
839 { | |
840 /* This function can GC if initialized is non-zero */ | |
440 | 841 Lisp_Face *f; |
428 | 842 Lisp_Object face; |
843 | |
844 CHECK_SYMBOL (name); | |
845 if (!NILP (doc_string)) | |
846 CHECK_STRING (doc_string); | |
847 | |
848 face = Ffind_face (name); | |
849 if (!NILP (face)) | |
850 return face; | |
851 | |
852 f = allocate_face (); | |
793 | 853 face = wrap_face (f); |
428 | 854 |
855 f->name = name; | |
856 f->doc_string = doc_string; | |
857 f->foreground = Fmake_specifier (Qcolor); | |
858 set_color_attached_to (f->foreground, face, Qforeground); | |
859 f->background = Fmake_specifier (Qcolor); | |
860 set_color_attached_to (f->background, face, Qbackground); | |
861 f->font = Fmake_specifier (Qfont); | |
862 set_font_attached_to (f->font, face, Qfont); | |
863 f->background_pixmap = Fmake_specifier (Qimage); | |
864 set_image_attached_to (f->background_pixmap, face, Qbackground_pixmap); | |
865 f->display_table = Fmake_specifier (Qdisplay_table); | |
866 f->underline = Fmake_specifier (Qface_boolean); | |
867 set_face_boolean_attached_to (f->underline, face, Qunderline); | |
868 f->strikethru = Fmake_specifier (Qface_boolean); | |
869 set_face_boolean_attached_to (f->strikethru, face, Qstrikethru); | |
870 f->highlight = Fmake_specifier (Qface_boolean); | |
871 set_face_boolean_attached_to (f->highlight, face, Qhighlight); | |
872 f->dim = Fmake_specifier (Qface_boolean); | |
873 set_face_boolean_attached_to (f->dim, face, Qdim); | |
874 f->blinking = Fmake_specifier (Qface_boolean); | |
875 set_face_boolean_attached_to (f->blinking, face, Qblinking); | |
876 f->reverse = Fmake_specifier (Qface_boolean); | |
877 set_face_boolean_attached_to (f->reverse, face, Qreverse); | |
878 if (!NILP (Vdefault_face)) | |
879 { | |
880 /* If the default face has already been created, set it as | |
881 the default fallback specifier for all the specifiers we | |
882 just created. This implements the standard "all faces | |
883 inherit from default" behavior. */ | |
884 set_specifier_fallback (f->foreground, | |
885 Fget (Vdefault_face, Qforeground, Qunbound)); | |
886 set_specifier_fallback (f->background, | |
887 Fget (Vdefault_face, Qbackground, Qunbound)); | |
888 set_specifier_fallback (f->font, | |
889 Fget (Vdefault_face, Qfont, Qunbound)); | |
890 set_specifier_fallback (f->background_pixmap, | |
891 Fget (Vdefault_face, Qbackground_pixmap, | |
892 Qunbound)); | |
893 set_specifier_fallback (f->display_table, | |
894 Fget (Vdefault_face, Qdisplay_table, Qunbound)); | |
895 set_specifier_fallback (f->underline, | |
896 Fget (Vdefault_face, Qunderline, Qunbound)); | |
897 set_specifier_fallback (f->strikethru, | |
898 Fget (Vdefault_face, Qstrikethru, Qunbound)); | |
899 set_specifier_fallback (f->highlight, | |
900 Fget (Vdefault_face, Qhighlight, Qunbound)); | |
901 set_specifier_fallback (f->dim, | |
902 Fget (Vdefault_face, Qdim, Qunbound)); | |
903 set_specifier_fallback (f->blinking, | |
904 Fget (Vdefault_face, Qblinking, Qunbound)); | |
905 set_specifier_fallback (f->reverse, | |
906 Fget (Vdefault_face, Qreverse, Qunbound)); | |
907 } | |
908 | |
909 /* Add the face to the appropriate list. */ | |
910 if (NILP (temporary)) | |
911 Fputhash (name, face, Vpermanent_faces_cache); | |
912 else | |
913 Fputhash (name, face, Vtemporary_faces_cache); | |
914 | |
915 /* Note that it's OK if we dump faces. | |
916 When we start up again when we're not noninteractive, | |
917 `init-global-faces' is called and it resources all | |
918 existing faces. */ | |
919 if (initialized && !noninteractive) | |
920 { | |
921 struct gcpro gcpro1, gcpro2; | |
922 | |
923 GCPRO2 (name, face); | |
924 call1 (Qinit_face_from_resources, name); | |
925 UNGCPRO; | |
926 } | |
927 | |
928 return face; | |
929 } | |
930 | |
931 | |
932 /***************************************************************************** | |
933 initialization code | |
934 ****************************************************************************/ | |
935 | |
936 void | |
937 init_global_faces (struct device *d) | |
938 { | |
939 /* When making the initial terminal device, there is no Lisp code | |
940 loaded, so we can't do this. */ | |
941 if (initialized && !noninteractive) | |
872 | 942 call_critical_lisp_code (d, Qinit_global_faces, wrap_device (d)); |
428 | 943 } |
944 | |
945 void | |
946 init_device_faces (struct device *d) | |
947 { | |
948 /* This function can call lisp */ | |
949 | |
950 /* When making the initial terminal device, there is no Lisp code | |
951 loaded, so we can't do this. */ | |
952 if (initialized) | |
872 | 953 call_critical_lisp_code (d, Qinit_device_faces, wrap_device (d)); |
428 | 954 } |
955 | |
956 void | |
957 init_frame_faces (struct frame *frm) | |
958 { | |
959 /* When making the initial terminal device, there is no Lisp code | |
960 loaded, so we can't do this. */ | |
961 if (initialized) | |
962 { | |
793 | 963 Lisp_Object tframe = wrap_frame (frm); |
964 | |
428 | 965 |
966 /* DO NOT change the selected frame here. If the debugger goes off | |
4187 | 967 it will try and display on the frame being created, but it is not |
968 ready for that yet and a horrible death will occur. Any random | |
969 code depending on the selected-frame as an implicit arg should be | |
970 tracked down and shot. For the benefit of the one known, | |
971 xpm-color-symbols, make-frame sets the variable | |
972 Vframe_being_created to the frame it is making and sets it to nil | |
973 when done. Internal functions that this could trigger which are | |
974 currently depending on selected-frame should use this instead. It | |
975 is not currently visible at the lisp level. */ | |
428 | 976 call_critical_lisp_code (XDEVICE (FRAME_DEVICE (frm)), |
977 Qinit_frame_faces, tframe); | |
978 } | |
979 } | |
980 | |
981 | |
982 /**************************************************************************** | |
983 * face cache element functions * | |
984 ****************************************************************************/ | |
985 | |
986 /* | |
987 | |
988 #### Here is a description of how the face cache elements ought | |
989 to be redone. It is *NOT* how they work currently: | |
990 | |
991 However, when I started to go about implementing this, I realized | |
992 that there are all sorts of subtle problems with cache coherency | |
993 that are coming up. As it turns out, these problems don't | |
994 manifest themselves now due to the brute-force "kill 'em all" | |
995 approach to cache invalidation when faces change; but if this | |
996 is ever made smarter, these problems are going to come up, and | |
997 some of them are very non-obvious. | |
998 | |
999 I'm thinking of redoing the cache code a bit to avoid these | |
1000 coherency problems. The bulk of the problems will arise because | |
1001 the current display structures have simple indices into the | |
1002 face cache, but the cache can be changed at various times, | |
1003 which could make the current display structures incorrect. | |
1004 I guess the dirty and updated flags are an attempt to fix | |
1005 this, but this approach doesn't really work. | |
1006 | |
1007 Here's an approach that should keep things clean and unconfused: | |
1008 | |
1009 1) Imagine a "virtual face cache" that can grow arbitrarily | |
1010 big and for which the only thing allowed is to add new | |
1011 elements. Existing elements cannot be removed or changed. | |
1012 This way, any pointers in the existing redisplay structure | |
1013 into the cache never get screwed up. (This is important | |
1014 because even if a cache element is out of date, if there's | |
1015 a pointer to it then its contents still accurately describe | |
1016 the way the text currently looks on the screen.) | |
1017 2) Each element in the virtual cache either describes exactly | |
1018 one face, or describes the merger of a number of faces | |
1019 by some process. In order to simplify things, for mergers | |
1020 we do not record which faces or ordering was used, but | |
1021 simply that this cache element is the result of merging. | |
1022 Unlike the current implementation, it's important that a | |
1023 single cache element not be used to both describe a | |
1024 single face and describe a merger, even if all the property | |
1025 values are the same. | |
1026 3) Each cache element can be clean or dirty. "Dirty" means | |
1027 that the face that the element points to has been changed; | |
1028 this gets set at the time the face is changed. This | |
1029 way, when looking up a value in the cache, you can determine | |
1030 whether it's out of date or not. For merged faces it | |
1031 does not matter -- we don't record the faces or priority | |
1032 used to create the merger, so it's impossible to look up | |
1033 one of these faces. We have to recompute it each time. | |
1034 Luckily, this is fine -- doing the merge is much | |
1035 less expensive than recomputing the properties of a | |
1036 single face. | |
1037 4) For each cache element, we keep a hash value. (In order | |
1038 to hash the boolean properties, we convert each of them | |
1039 into a different large prime number so that the hashing works | |
1040 well.) This allows us, when comparing runes, to properly | |
1041 determine whether the face for that rune has changed. | |
1042 This will be especially important for TTY's, where there | |
1043 aren't that many faces and minimizing redraw is very | |
1044 important. | |
1045 5) We can't actually keep an infinite cache, but that doesn't | |
1046 really matter that much. The only elements we care about | |
1047 are those that are used by either the current or desired | |
1048 display structs. Therefore, we keep a per-window | |
1049 redisplay iteration number, and mark each element with | |
1050 that number as we use it. Just after outputting the | |
1051 window and synching the redisplay structs, we go through | |
1052 the cache and invalidate all elements that are not clean | |
1053 elements referring to a particular face and that do not | |
1054 have an iteration number equal to the current one. We | |
1055 keep them in a chain, and use them to allocate new | |
1056 elements when possible instead of increasing the Dynarr. | |
1057 | |
872 | 1058 --ben (?? At least I think I wrote this!) |
428 | 1059 */ |
1060 | |
1061 /* mark for GC a dynarr of face cachels. */ | |
1062 | |
1063 void | |
1064 mark_face_cachels (face_cachel_dynarr *elements) | |
1065 { | |
1066 int elt; | |
1067 | |
1068 if (!elements) | |
1069 return; | |
1070 | |
1071 for (elt = 0; elt < Dynarr_length (elements); elt++) | |
1072 { | |
1073 struct face_cachel *cachel = Dynarr_atp (elements, elt); | |
1074 | |
1075 { | |
1076 int i; | |
1077 | |
1078 for (i = 0; i < NUM_LEADING_BYTES; i++) | |
1079 if (!NILP (cachel->font[i]) && !UNBOUNDP (cachel->font[i])) | |
1080 mark_object (cachel->font[i]); | |
1081 } | |
1082 mark_object (cachel->face); | |
1083 mark_object (cachel->foreground); | |
1084 mark_object (cachel->background); | |
1085 mark_object (cachel->display_table); | |
1086 mark_object (cachel->background_pixmap); | |
1087 } | |
1088 } | |
1089 | |
1090 /* ensure that the given cachel contains an updated font value for | |
3094 | 1091 the given charset. Return the updated font value (which can be |
1092 Qunbound, so this value must not be passed unchecked to Lisp). | |
1093 | |
1094 #### Xft: This function will need to be updated for new font model. */ | |
428 | 1095 |
1096 Lisp_Object | |
1097 ensure_face_cachel_contains_charset (struct face_cachel *cachel, | |
1098 Lisp_Object domain, Lisp_Object charset) | |
1099 { | |
1100 Lisp_Object new_val; | |
1101 Lisp_Object face = cachel->face; | |
3659 | 1102 int bound = 1, final_stage = 0; |
428 | 1103 int offs = XCHARSET_LEADING_BYTE (charset) - MIN_LEADING_BYTE; |
1104 | |
4187 | 1105 if (!UNBOUNDP (cachel->font[offs]) && |
3659 | 1106 bit_vector_bit(FACE_CACHEL_FONT_UPDATED (cachel), offs)) |
428 | 1107 return cachel->font[offs]; |
1108 | |
1109 if (UNBOUNDP (face)) | |
1110 { | |
1111 /* a merged face. */ | |
1112 int i; | |
1113 struct window *w = XWINDOW (domain); | |
1114 | |
1115 new_val = Qunbound; | |
3659 | 1116 set_bit_vector_bit(FACE_CACHEL_FONT_SPECIFIED(cachel), offs, 0); |
1117 | |
428 | 1118 for (i = 0; i < cachel->nfaces; i++) |
1119 { | |
1120 struct face_cachel *oth; | |
1121 | |
1122 oth = Dynarr_atp (w->face_cachels, | |
1123 FACE_CACHEL_FINDEX_UNSAFE (cachel, i)); | |
1124 /* Tout le monde aime la recursion */ | |
1125 ensure_face_cachel_contains_charset (oth, domain, charset); | |
1126 | |
3659 | 1127 if (bit_vector_bit(FACE_CACHEL_FONT_SPECIFIED(oth), offs)) |
428 | 1128 { |
1129 new_val = oth->font[offs]; | |
3659 | 1130 set_bit_vector_bit(FACE_CACHEL_FONT_SPECIFIED(cachel), offs, 1); |
1131 set_bit_vector_bit | |
4187 | 1132 (FACE_CACHEL_FONT_FINAL_STAGE(cachel), offs, |
3659 | 1133 bit_vector_bit(FACE_CACHEL_FONT_FINAL_STAGE(oth), offs)); |
428 | 1134 break; |
1135 } | |
1136 } | |
1137 | |
3659 | 1138 if (!bit_vector_bit(FACE_CACHEL_FONT_SPECIFIED(cachel), offs)) |
428 | 1139 /* need to do the default face. */ |
1140 { | |
1141 struct face_cachel *oth = | |
1142 Dynarr_atp (w->face_cachels, DEFAULT_INDEX); | |
1143 ensure_face_cachel_contains_charset (oth, domain, charset); | |
1144 | |
1145 new_val = oth->font[offs]; | |
1146 } | |
1147 | |
4187 | 1148 if (!UNBOUNDP (cachel->font[offs]) && |
3659 | 1149 !EQ (cachel->font[offs], new_val)) |
428 | 1150 cachel->dirty = 1; |
3659 | 1151 set_bit_vector_bit(FACE_CACHEL_FONT_UPDATED(cachel), offs, 1); |
428 | 1152 cachel->font[offs] = new_val; |
3659 | 1153 DEBUG_FACES("just recursed on the unbound face, returning " |
1154 "something %s\n", UNBOUNDP(new_val) ? "not bound" | |
1155 : "bound"); | |
428 | 1156 return new_val; |
1157 } | |
1158 | |
3659 | 1159 do { |
1160 | |
1161 /* Lookup the face, specifying the initial stage and that fallbacks | |
1162 shouldn't happen. */ | |
1163 new_val = face_property_matching_instance (face, Qfont, charset, domain, | |
1164 /* ERROR_ME_DEBUG_WARN is | |
1165 fine here. */ | |
1166 ERROR_ME_DEBUG_WARN, 1, Qzero, | |
5015
d95c102a96d3
cleanups for specifier font stages, from ben-unicode-internal (preparation for eliminating shadowed warnings)
Ben Wing <ben@xemacs.org>
parents:
5013
diff
changeset
|
1167 STAGE_INITIAL); |
3659 | 1168 DEBUG_FACES("just called f_p_m_i on face %s, charset %s, initial, " |
4187 | 1169 "result was something %s\n", |
1170 XSTRING_DATA(XSYMBOL_NAME(XFACE(cachel->face)->name)), | |
3659 | 1171 XSTRING_DATA(XSYMBOL_NAME(XCHARSET_NAME(charset))), |
1172 UNBOUNDP(new_val) ? "not bound" : "bound"); | |
1173 | |
1174 if (!UNBOUNDP (new_val)) break; | |
1175 | |
1176 bound = 0; | |
1177 /* Lookup the face again, this time allowing the fallback. If this | |
1178 succeeds, it'll give a font intended for the script in question, | |
1179 which is preferable to translating to ISO10646-1 and using the | |
4667
cbe5d2169270
Fix typos in face.c.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4534
diff
changeset
|
1180 fixed-width fallback. |
cbe5d2169270
Fix typos in face.c.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4534
diff
changeset
|
1181 |
cbe5d2169270
Fix typos in face.c.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4534
diff
changeset
|
1182 #### This is questionable. The problem is that unusual scripts |
cbe5d2169270
Fix typos in face.c.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4534
diff
changeset
|
1183 will typically fallback to the hard-coded values as the user is |
cbe5d2169270
Fix typos in face.c.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4534
diff
changeset
|
1184 unlikely to have specified them herself, a common complaint. */ |
3659 | 1185 new_val = face_property_matching_instance (face, Qfont, |
1186 charset, domain, | |
1187 ERROR_ME_DEBUG_WARN, 0, | |
4187 | 1188 Qzero, |
5015
d95c102a96d3
cleanups for specifier font stages, from ben-unicode-internal (preparation for eliminating shadowed warnings)
Ben Wing <ben@xemacs.org>
parents:
5013
diff
changeset
|
1189 STAGE_INITIAL); |
3659 | 1190 |
5015
d95c102a96d3
cleanups for specifier font stages, from ben-unicode-internal (preparation for eliminating shadowed warnings)
Ben Wing <ben@xemacs.org>
parents:
5013
diff
changeset
|
1191 DEBUG_FACES ("just called f_p_m_i on face %s, charset %s, initial, " |
d95c102a96d3
cleanups for specifier font stages, from ben-unicode-internal (preparation for eliminating shadowed warnings)
Ben Wing <ben@xemacs.org>
parents:
5013
diff
changeset
|
1192 "allow fallback, result was something %s\n", |
d95c102a96d3
cleanups for specifier font stages, from ben-unicode-internal (preparation for eliminating shadowed warnings)
Ben Wing <ben@xemacs.org>
parents:
5013
diff
changeset
|
1193 XSTRING_DATA (XSYMBOL_NAME (XFACE (cachel->face)->name)), |
d95c102a96d3
cleanups for specifier font stages, from ben-unicode-internal (preparation for eliminating shadowed warnings)
Ben Wing <ben@xemacs.org>
parents:
5013
diff
changeset
|
1194 XSTRING_DATA (XSYMBOL_NAME (XCHARSET_NAME (charset))), |
d95c102a96d3
cleanups for specifier font stages, from ben-unicode-internal (preparation for eliminating shadowed warnings)
Ben Wing <ben@xemacs.org>
parents:
5013
diff
changeset
|
1195 UNBOUNDP (new_val) ? "not bound" : "bound"); |
3659 | 1196 |
5015
d95c102a96d3
cleanups for specifier font stages, from ben-unicode-internal (preparation for eliminating shadowed warnings)
Ben Wing <ben@xemacs.org>
parents:
5013
diff
changeset
|
1197 if (!UNBOUNDP (new_val)) |
3659 | 1198 { |
1199 break; | |
1200 } | |
1201 | |
1202 bound = 1; | |
1203 /* Try the face itself with the final-stage specifiers. */ | |
1204 new_val = face_property_matching_instance (face, Qfont, | |
1205 charset, domain, | |
1206 ERROR_ME_DEBUG_WARN, 1, | |
4187 | 1207 Qzero, |
5015
d95c102a96d3
cleanups for specifier font stages, from ben-unicode-internal (preparation for eliminating shadowed warnings)
Ben Wing <ben@xemacs.org>
parents:
5013
diff
changeset
|
1208 STAGE_FINAL); |
3659 | 1209 |
1210 DEBUG_FACES("just called f_p_m_i on face %s, charset %s, final, " | |
4187 | 1211 "result was something %s\n", |
1212 XSTRING_DATA(XSYMBOL_NAME(XFACE(cachel->face)->name)), | |
3659 | 1213 XSTRING_DATA(XSYMBOL_NAME(XCHARSET_NAME(charset))), |
1214 UNBOUNDP(new_val) ? "not bound" : "bound"); | |
1215 /* Tell X11 redisplay that it should translate to iso10646-1. */ | |
5015
d95c102a96d3
cleanups for specifier font stages, from ben-unicode-internal (preparation for eliminating shadowed warnings)
Ben Wing <ben@xemacs.org>
parents:
5013
diff
changeset
|
1216 if (!UNBOUNDP (new_val)) |
3659 | 1217 { |
1218 final_stage = 1; | |
1219 break; | |
1220 } | |
1221 | |
1222 bound = 0; | |
1223 | |
1224 /* Lookup the face again, this time both allowing the fallback and | |
1225 allowing its final stage to be used. */ | |
1226 new_val = face_property_matching_instance (face, Qfont, | |
1227 charset, domain, | |
1228 ERROR_ME_DEBUG_WARN, 0, | |
4187 | 1229 Qzero, |
5015
d95c102a96d3
cleanups for specifier font stages, from ben-unicode-internal (preparation for eliminating shadowed warnings)
Ben Wing <ben@xemacs.org>
parents:
5013
diff
changeset
|
1230 STAGE_FINAL); |
3659 | 1231 |
5015
d95c102a96d3
cleanups for specifier font stages, from ben-unicode-internal (preparation for eliminating shadowed warnings)
Ben Wing <ben@xemacs.org>
parents:
5013
diff
changeset
|
1232 DEBUG_FACES ("just called f_p_m_i on face %s, charset %s, initial, " |
d95c102a96d3
cleanups for specifier font stages, from ben-unicode-internal (preparation for eliminating shadowed warnings)
Ben Wing <ben@xemacs.org>
parents:
5013
diff
changeset
|
1233 "allow fallback, result was something %s\n", |
d95c102a96d3
cleanups for specifier font stages, from ben-unicode-internal (preparation for eliminating shadowed warnings)
Ben Wing <ben@xemacs.org>
parents:
5013
diff
changeset
|
1234 XSTRING_DATA (XSYMBOL_NAME (XFACE (cachel->face)->name)), |
d95c102a96d3
cleanups for specifier font stages, from ben-unicode-internal (preparation for eliminating shadowed warnings)
Ben Wing <ben@xemacs.org>
parents:
5013
diff
changeset
|
1235 XSTRING_DATA (XSYMBOL_NAME (XCHARSET_NAME (charset))), |
d95c102a96d3
cleanups for specifier font stages, from ben-unicode-internal (preparation for eliminating shadowed warnings)
Ben Wing <ben@xemacs.org>
parents:
5013
diff
changeset
|
1236 UNBOUNDP (new_val) ? "not bound" : "bound"); |
3659 | 1237 if (!UNBOUNDP(new_val)) |
1238 { | |
1239 /* Tell X11 redisplay that it should translate to iso10646-1. */ | |
1240 final_stage = 1; | |
1241 break; | |
1242 } | |
1243 } while (0); | |
1244 | |
428 | 1245 if (!UNBOUNDP (cachel->font[offs]) && !EQ (new_val, cachel->font[offs])) |
1246 cachel->dirty = 1; | |
3659 | 1247 |
1248 set_bit_vector_bit(FACE_CACHEL_FONT_UPDATED(cachel), offs, 1); | |
1249 set_bit_vector_bit(FACE_CACHEL_FONT_FINAL_STAGE(cachel), offs, | |
1250 final_stage); | |
4187 | 1251 set_bit_vector_bit(FACE_CACHEL_FONT_SPECIFIED(cachel), offs, |
3659 | 1252 (bound || EQ (face, Vdefault_face))); |
428 | 1253 cachel->font[offs] = new_val; |
1254 return new_val; | |
1255 } | |
1256 | |
1257 /* Ensure that the given cachel contains updated fonts for all | |
1258 the charsets specified. */ | |
1259 | |
1260 void | |
1261 ensure_face_cachel_complete (struct face_cachel *cachel, | |
1262 Lisp_Object domain, unsigned char *charsets) | |
1263 { | |
1264 int i; | |
1265 | |
1266 for (i = 0; i < NUM_LEADING_BYTES; i++) | |
1267 if (charsets[i]) | |
1268 { | |
826 | 1269 Lisp_Object charset = charset_by_leading_byte (i + MIN_LEADING_BYTE); |
428 | 1270 assert (CHARSETP (charset)); |
1271 ensure_face_cachel_contains_charset (cachel, domain, charset); | |
1272 } | |
1273 } | |
1274 | |
1275 void | |
1276 face_cachel_charset_font_metric_info (struct face_cachel *cachel, | |
1277 unsigned char *charsets, | |
1278 struct font_metric_info *fm) | |
1279 { | |
1280 int i; | |
1281 | |
1282 fm->width = 1; | |
1283 fm->height = fm->ascent = 1; | |
1284 fm->descent = 0; | |
1285 fm->proportional_p = 0; | |
1286 | |
1287 for (i = 0; i < NUM_LEADING_BYTES; i++) | |
1288 { | |
1289 if (charsets[i]) | |
1290 { | |
826 | 1291 Lisp_Object charset = charset_by_leading_byte (i + MIN_LEADING_BYTE); |
428 | 1292 Lisp_Object font_instance = FACE_CACHEL_FONT (cachel, charset); |
440 | 1293 Lisp_Font_Instance *fi = XFONT_INSTANCE (font_instance); |
428 | 1294 |
1295 assert (CHARSETP (charset)); | |
1296 assert (FONT_INSTANCEP (font_instance)); | |
1297 | |
1298 if (fm->ascent < (int) fi->ascent) fm->ascent = (int) fi->ascent; | |
1299 if (fm->descent < (int) fi->descent) fm->descent = (int) fi->descent; | |
1300 fm->height = fm->ascent + fm->descent; | |
1301 if (fi->proportional_p) | |
1302 fm->proportional_p = 1; | |
1303 if (EQ (charset, Vcharset_ascii)) | |
1304 fm->width = fi->width; | |
1305 } | |
1306 } | |
1307 } | |
1308 | |
1309 #define FROB(field) \ | |
1310 do { \ | |
1311 Lisp_Object new_val = \ | |
1312 FACE_PROPERTY_INSTANCE (face, Q##field, domain, 1, Qzero); \ | |
1313 int bound = 1; \ | |
1314 if (UNBOUNDP (new_val)) \ | |
1315 { \ | |
1316 bound = 0; \ | |
1317 new_val = FACE_PROPERTY_INSTANCE (face, Q##field, domain, 0, Qzero); \ | |
1318 } \ | |
1319 if (!EQ (new_val, cachel->field)) \ | |
1320 { \ | |
1321 cachel->field = new_val; \ | |
1322 cachel->dirty = 1; \ | |
1323 } \ | |
1324 cachel->field##_specified = (bound || default_face); \ | |
1325 } while (0) | |
1326 | |
446 | 1327 /* |
1328 * A face's background pixmap will override the face's | |
1329 * background color. But the background pixmap of the | |
1330 * default face should not override the background color of | |
1331 * a face if the background color has been specified or | |
1332 * inherited. | |
1333 * | |
1334 * To accomplish this we remove the background pixmap of the | |
1335 * cachel and mark it as having been specified so that cachel | |
1336 * merging won't override it later. | |
1337 */ | |
1338 #define MAYBE_UNFROB_BACKGROUND_PIXMAP \ | |
1339 do \ | |
1340 { \ | |
1341 if (! default_face \ | |
1342 && cachel->background_specified \ | |
1343 && ! cachel->background_pixmap_specified) \ | |
1344 { \ | |
1345 cachel->background_pixmap = Qunbound; \ | |
1346 cachel->background_pixmap_specified = 1; \ | |
1347 } \ | |
1348 } while (0) | |
1349 | |
1350 | |
1351 /* Add a cachel for the given face to the given window's cache. */ | |
1352 | |
1353 static void | |
1354 add_face_cachel (struct window *w, Lisp_Object face) | |
1355 { | |
1356 int must_finish_frobbing = ! WINDOW_FACE_CACHEL (w, DEFAULT_INDEX); | |
1357 struct face_cachel new_cachel; | |
1358 Lisp_Object domain; | |
1359 | |
1360 reset_face_cachel (&new_cachel); | |
793 | 1361 domain = wrap_window (w); |
446 | 1362 update_face_cachel_data (&new_cachel, domain, face); |
1363 Dynarr_add (w->face_cachels, new_cachel); | |
1364 | |
1365 /* The face's background pixmap have not yet been frobbed (see comment | |
4667
cbe5d2169270
Fix typos in face.c.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4534
diff
changeset
|
1366 in update_face_cachel_data), so we have to do it now */ |
446 | 1367 if (must_finish_frobbing) |
1368 { | |
1369 int default_face = EQ (face, Vdefault_face); | |
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4827
diff
changeset
|
1370 struct face_cachel *cachel = Dynarr_lastp (w->face_cachels); |
446 | 1371 |
1372 FROB (background_pixmap); | |
1373 MAYBE_UNFROB_BACKGROUND_PIXMAP; | |
1374 } | |
1375 } | |
1376 | |
1377 /* Called when the updated flag has been cleared on a cachel. | |
1378 This function returns 1 if the caller must finish the update (see comment | |
1379 below), 0 otherwise. | |
1380 */ | |
1381 | |
1382 void | |
1383 update_face_cachel_data (struct face_cachel *cachel, | |
1384 Lisp_Object domain, | |
1385 Lisp_Object face) | |
1386 { | |
1387 if (XFACE (face)->dirty || UNBOUNDP (cachel->face)) | |
1388 { | |
1389 int default_face = EQ (face, Vdefault_face); | |
1390 cachel->face = face; | |
1391 | |
1392 /* We normally only set the _specified flags if the value was | |
4187 | 1393 actually bound. The exception is for the default face where |
1394 we always set it since it is the ultimate fallback. */ | |
446 | 1395 |
428 | 1396 FROB (foreground); |
1397 FROB (background); | |
1398 FROB (display_table); | |
446 | 1399 |
1400 /* #### WARNING: the background pixmap property of faces is currently | |
1401 the only one dealing with images. The problem we have here is that | |
1402 frobbing the background pixmap might lead to image instantiation | |
1403 which in turn might require that the cache we're building be up to | |
1404 date, hence a crash. Here's a typical scenario of this: | |
1405 | |
4667
cbe5d2169270
Fix typos in face.c.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4534
diff
changeset
|
1406 - a new window is created and its face cache elements are |
446 | 1407 initialized through a call to reset_face_cachels[1]. At that point, |
1408 the cache for the default and modeline faces (normaly taken care of | |
1409 by redisplay itself) are null. | |
1410 - the default face has a background pixmap which needs to be | |
1411 instantiated right here, as a consequence of cache initialization. | |
1412 - the background pixmap image happens to be instantiated as a string | |
1413 (this happens on tty's for instance). | |
1414 - In order to do this, we need to compute the string geometry. | |
1415 - In order to do this, we might have to access the window's default | |
1416 face cache. But this is the cache we're building right now, it is | |
1417 null. | |
1418 - BARF !!!!! | |
428 | 1419 |
446 | 1420 To sum up, this means that it is in general unsafe to instantiate |
1421 images before face cache updating is complete (appart from image | |
1422 related face attributes). The solution we use below is to actually | |
1423 detect whether we're building the window's face_cachels for the first | |
1424 time, and simply NOT frob the background pixmap in that case. If | |
1425 other image-related face attributes are ever implemented, they should | |
1426 be protected the same way right here. | |
1427 | |
1428 One note: | |
1429 * See comment in `default_face_font_info' in face.c. Who wrote it ? | |
1430 Maybe we have the begining of an answer here ? | |
1431 | |
1432 Footnotes: | |
1433 [1] See comment at the top of `allocate_window' in window.c. | |
1434 | |
1435 -- didier | |
1436 */ | |
1437 if (! WINDOWP (domain) | |
1438 || WINDOW_FACE_CACHEL (DOMAIN_XWINDOW (domain), DEFAULT_INDEX)) | |
428 | 1439 { |
446 | 1440 FROB (background_pixmap); |
1441 MAYBE_UNFROB_BACKGROUND_PIXMAP; | |
428 | 1442 } |
1443 #undef FROB | |
446 | 1444 #undef MAYBE_UNFROB_BACKGROUND_PIXMAP |
428 | 1445 |
1446 ensure_face_cachel_contains_charset (cachel, domain, Vcharset_ascii); | |
1447 | |
1448 #define FROB(field) \ | |
1449 do { \ | |
1450 Lisp_Object new_val = \ | |
1451 FACE_PROPERTY_INSTANCE (face, Q##field, domain, 1, Qzero); \ | |
1452 int bound = 1; \ | |
1453 unsigned int new_val_int; \ | |
1454 if (UNBOUNDP (new_val)) \ | |
1455 { \ | |
1456 bound = 0; \ | |
1457 new_val = FACE_PROPERTY_INSTANCE (face, Q##field, domain, 0, Qzero); \ | |
1458 } \ | |
1459 new_val_int = EQ (new_val, Qt); \ | |
1460 if (cachel->field != new_val_int) \ | |
1461 { \ | |
1462 cachel->field = new_val_int; \ | |
1463 cachel->dirty = 1; \ | |
1464 } \ | |
1465 cachel->field##_specified = bound; \ | |
1466 } while (0) | |
1467 | |
1468 FROB (underline); | |
1469 FROB (strikethru); | |
1470 FROB (highlight); | |
1471 FROB (dim); | |
1472 FROB (reverse); | |
1473 FROB (blinking); | |
1474 #undef FROB | |
1475 } | |
1476 | |
1477 cachel->updated = 1; | |
1478 } | |
1479 | |
1480 /* Merge the cachel identified by FINDEX in window W into the given | |
1481 cachel. */ | |
1482 | |
1483 static void | |
1484 merge_face_cachel_data (struct window *w, face_index findex, | |
1485 struct face_cachel *cachel) | |
1486 { | |
3659 | 1487 int offs; |
1488 | |
428 | 1489 #define FINDEX_FIELD(field) \ |
1490 Dynarr_atp (w->face_cachels, findex)->field | |
1491 | |
1492 #define FROB(field) \ | |
1493 do { \ | |
1494 if (!cachel->field##_specified && FINDEX_FIELD (field##_specified)) \ | |
1495 { \ | |
1496 cachel->field = FINDEX_FIELD (field); \ | |
1497 cachel->field##_specified = 1; \ | |
1498 cachel->dirty = 1; \ | |
1499 } \ | |
1500 } while (0) | |
1501 | |
1502 FROB (foreground); | |
1503 FROB (background); | |
1504 FROB (display_table); | |
1505 FROB (background_pixmap); | |
1506 FROB (underline); | |
1507 FROB (strikethru); | |
1508 FROB (highlight); | |
1509 FROB (dim); | |
1510 FROB (reverse); | |
1511 FROB (blinking); | |
1512 | |
3659 | 1513 for (offs = 0; offs < NUM_LEADING_BYTES; ++offs) |
1514 { | |
1515 if (!(bit_vector_bit(FACE_CACHEL_FONT_SPECIFIED(cachel), offs)) | |
1516 && bit_vector_bit(FACE_CACHEL_FONT_SPECIFIED | |
1517 (Dynarr_atp(w->face_cachels, findex)), offs)) | |
1518 { | |
1519 cachel->font[offs] = FINDEX_FIELD (font[offs]); | |
1520 set_bit_vector_bit(FACE_CACHEL_FONT_SPECIFIED(cachel), offs, 1); | |
1521 /* Also propagate whether we're translating to Unicode for the | |
1522 given face. */ | |
4187 | 1523 set_bit_vector_bit(FACE_CACHEL_FONT_FINAL_STAGE(cachel), offs, |
3659 | 1524 bit_vector_bit(FACE_CACHEL_FONT_FINAL_STAGE |
1525 (Dynarr_atp(w->face_cachels, | |
1526 findex)), offs)); | |
1527 cachel->dirty = 1; | |
1528 } | |
1529 } | |
428 | 1530 #undef FROB |
1531 #undef FINDEX_FIELD | |
1532 | |
1533 cachel->updated = 1; | |
1534 } | |
1535 | |
1536 /* Initialize a cachel. */ | |
3094 | 1537 /* #### Xft: this function will need to be changed for new font model. */ |
428 | 1538 |
1539 void | |
1540 reset_face_cachel (struct face_cachel *cachel) | |
1541 { | |
1542 xzero (*cachel); | |
1543 cachel->face = Qunbound; | |
1544 cachel->nfaces = 0; | |
1545 cachel->merged_faces = 0; | |
1546 cachel->foreground = Qunbound; | |
1547 cachel->background = Qunbound; | |
1548 { | |
1549 int i; | |
1550 | |
1551 for (i = 0; i < NUM_LEADING_BYTES; i++) | |
1552 cachel->font[i] = Qunbound; | |
1553 } | |
1554 cachel->display_table = Qunbound; | |
1555 cachel->background_pixmap = Qunbound; | |
3659 | 1556 FACE_CACHEL_FONT_SPECIFIED (cachel)->size = sizeof(cachel->font_specified); |
1557 FACE_CACHEL_FONT_UPDATED (cachel)->size = sizeof(cachel->font_updated); | |
428 | 1558 } |
1559 | |
1560 /* Retrieve the index to a cachel for window W that corresponds to | |
1561 the specified face. If necessary, add a new element to the | |
1562 cache. */ | |
1563 | |
1564 face_index | |
1565 get_builtin_face_cache_index (struct window *w, Lisp_Object face) | |
1566 { | |
1567 int elt; | |
1568 | |
1569 if (noninteractive) | |
1570 return 0; | |
1571 | |
1572 for (elt = 0; elt < Dynarr_length (w->face_cachels); elt++) | |
1573 { | |
1574 struct face_cachel *cachel = WINDOW_FACE_CACHEL (w, elt); | |
1575 | |
1576 if (EQ (cachel->face, face)) | |
1577 { | |
793 | 1578 Lisp_Object window = wrap_window (w); |
1579 | |
428 | 1580 if (!cachel->updated) |
1581 update_face_cachel_data (cachel, window, face); | |
1582 return elt; | |
1583 } | |
1584 } | |
1585 | |
1586 /* If we didn't find the face, add it and then return its index. */ | |
1587 add_face_cachel (w, face); | |
1588 return elt; | |
1589 } | |
1590 | |
1591 void | |
1592 reset_face_cachels (struct window *w) | |
1593 { | |
1594 /* #### Not initialized in batch mode for the stream device. */ | |
1595 if (w->face_cachels) | |
1596 { | |
1597 int i; | |
4208 | 1598 face_index fi; |
428 | 1599 |
1600 for (i = 0; i < Dynarr_length (w->face_cachels); i++) | |
1601 { | |
1602 struct face_cachel *cachel = Dynarr_atp (w->face_cachels, i); | |
1603 if (cachel->merged_faces) | |
1604 Dynarr_free (cachel->merged_faces); | |
1605 } | |
1606 Dynarr_reset (w->face_cachels); | |
4187 | 1607 /* #### NOTE: be careful with the order ! |
1608 The cpp macros DEFAULT_INDEX and MODELINE_INDEX defined in | |
4208 | 1609 redisplay.h depend on the code below. Please make sure to assert the |
1610 correct values if you ever add new built-in faces here. | |
4187 | 1611 -- dvl */ |
4208 | 1612 fi = get_builtin_face_cache_index (w, Vdefault_face); |
4210 | 1613 assert (noninteractive || fi == DEFAULT_INDEX); |
4208 | 1614 fi = get_builtin_face_cache_index (w, Vmodeline_face); |
4210 | 1615 assert (noninteractive || fi == MODELINE_INDEX); |
428 | 1616 XFRAME (w->frame)->window_face_cache_reset = 1; |
1617 } | |
1618 } | |
1619 | |
1620 void | |
1621 mark_face_cachels_as_clean (struct window *w) | |
1622 { | |
1623 int elt; | |
1624 | |
1625 for (elt = 0; elt < Dynarr_length (w->face_cachels); elt++) | |
1626 Dynarr_atp (w->face_cachels, elt)->dirty = 0; | |
1627 } | |
1628 | |
3094 | 1629 /* #### Xft: this function will need to be changed for new font model. */ |
428 | 1630 void |
1631 mark_face_cachels_as_not_updated (struct window *w) | |
1632 { | |
1633 int elt; | |
1634 | |
1635 for (elt = 0; elt < Dynarr_length (w->face_cachels); elt++) | |
1636 { | |
1637 struct face_cachel *cachel = Dynarr_atp (w->face_cachels, elt); | |
1638 | |
1639 cachel->updated = 0; | |
4187 | 1640 memset(FACE_CACHEL_FONT_UPDATED(cachel)->bits, 0, |
3659 | 1641 BIT_VECTOR_LONG_STORAGE (NUM_LEADING_BYTES)); |
428 | 1642 } |
1643 } | |
1644 | |
1645 #ifdef MEMORY_USAGE_STATS | |
1646 | |
1647 int | |
1648 compute_face_cachel_usage (face_cachel_dynarr *face_cachels, | |
1649 struct overhead_stats *ovstats) | |
1650 { | |
1651 int total = 0; | |
1652 | |
1653 if (face_cachels) | |
1654 { | |
1655 int i; | |
1656 | |
1657 total += Dynarr_memory_usage (face_cachels, ovstats); | |
1658 for (i = 0; i < Dynarr_length (face_cachels); i++) | |
1659 { | |
1660 int_dynarr *merged = Dynarr_at (face_cachels, i).merged_faces; | |
1661 if (merged) | |
1662 total += Dynarr_memory_usage (merged, ovstats); | |
1663 } | |
1664 } | |
1665 | |
1666 return total; | |
1667 } | |
1668 | |
1669 #endif /* MEMORY_USAGE_STATS */ | |
1670 | |
1671 | |
1672 /***************************************************************************** | |
1673 * merged face functions * | |
1674 *****************************************************************************/ | |
1675 | |
1676 /* Compare two merged face cachels to determine whether we have to add | |
1677 a new entry to the face cache. | |
1678 | |
1679 Note that we do not compare the attributes, but just the faces the | |
1680 cachels are based on. If they are the same, then the cachels certainly | |
1681 ought to have the same attributes, except in the case where fonts | |
1682 for different charsets have been determined in the two -- and in that | |
1683 case this difference is fine. */ | |
1684 | |
1685 static int | |
1686 compare_merged_face_cachels (struct face_cachel *cachel1, | |
1687 struct face_cachel *cachel2) | |
1688 { | |
1689 int i; | |
1690 | |
1691 if (!EQ (cachel1->face, cachel2->face) | |
1692 || cachel1->nfaces != cachel2->nfaces) | |
1693 return 0; | |
1694 | |
1695 for (i = 0; i < cachel1->nfaces; i++) | |
1696 if (FACE_CACHEL_FINDEX_UNSAFE (cachel1, i) | |
1697 != FACE_CACHEL_FINDEX_UNSAFE (cachel2, i)) | |
1698 return 0; | |
1699 | |
1700 return 1; | |
1701 } | |
1702 | |
1703 /* Retrieve the index to a cachel for window W that corresponds to | |
1704 the specified cachel. If necessary, add a new element to the | |
1705 cache. This is similar to get_builtin_face_cache_index() but | |
1706 is intended for merged cachels rather than for cachels representing | |
1707 just a face. | |
1708 | |
1709 Note that a merged cachel for just one face is not the same as | |
1710 the simple cachel for that face, because it is also merged with | |
1711 the default face. */ | |
1712 | |
1713 static face_index | |
1714 get_merged_face_cache_index (struct window *w, | |
1715 struct face_cachel *merged_cachel) | |
1716 { | |
1717 int elt; | |
1718 int cache_size = Dynarr_length (w->face_cachels); | |
1719 | |
1720 for (elt = 0; elt < cache_size; elt++) | |
1721 { | |
1722 struct face_cachel *cachel = | |
1723 Dynarr_atp (w->face_cachels, elt); | |
1724 | |
1725 if (compare_merged_face_cachels (cachel, merged_cachel)) | |
1726 return elt; | |
1727 } | |
1728 | |
1729 /* We didn't find it so add this instance to the cache. */ | |
1730 merged_cachel->updated = 1; | |
1731 merged_cachel->dirty = 1; | |
1732 Dynarr_add (w->face_cachels, *merged_cachel); | |
1733 return cache_size; | |
1734 } | |
1735 | |
1736 face_index | |
1737 get_extent_fragment_face_cache_index (struct window *w, | |
1738 struct extent_fragment *ef) | |
1739 { | |
1740 struct face_cachel cachel; | |
1741 int len = Dynarr_length (ef->extents); | |
1742 face_index findex = 0; | |
1743 | |
1744 /* Optimize the default case. */ | |
1745 if (len == 0) | |
1746 return DEFAULT_INDEX; | |
1747 else | |
1748 { | |
1749 int i; | |
1750 | |
1751 /* Merge the faces of the extents together in order. */ | |
1752 | |
1753 reset_face_cachel (&cachel); | |
1754 | |
1755 for (i = len - 1; i >= 0; i--) | |
1756 { | |
1757 EXTENT current = Dynarr_at (ef->extents, i); | |
1758 int has_findex = 0; | |
1759 Lisp_Object face = extent_face (current); | |
1760 | |
1761 if (FACEP (face)) | |
1762 { | |
1763 findex = get_builtin_face_cache_index (w, face); | |
1764 has_findex = 1; | |
1765 merge_face_cachel_data (w, findex, &cachel); | |
1766 } | |
1767 /* remember, we're called from within redisplay | |
1768 so we can't error. */ | |
1769 else while (CONSP (face)) | |
1770 { | |
1771 Lisp_Object one_face = XCAR (face); | |
1772 if (FACEP (one_face)) | |
1773 { | |
1774 findex = get_builtin_face_cache_index (w, one_face); | |
1775 merge_face_cachel_data (w, findex, &cachel); | |
1776 | |
1777 /* code duplication here but there's no clean | |
1778 way to avoid it. */ | |
1779 if (cachel.nfaces >= NUM_STATIC_CACHEL_FACES) | |
1780 { | |
1781 if (!cachel.merged_faces) | |
1782 cachel.merged_faces = Dynarr_new (int); | |
1783 Dynarr_add (cachel.merged_faces, findex); | |
1784 } | |
1785 else | |
1786 cachel.merged_faces_static[cachel.nfaces] = findex; | |
1787 cachel.nfaces++; | |
1788 } | |
1789 face = XCDR (face); | |
1790 } | |
1791 | |
1792 if (has_findex) | |
1793 { | |
1794 if (cachel.nfaces >= NUM_STATIC_CACHEL_FACES) | |
1795 { | |
1796 if (!cachel.merged_faces) | |
1797 cachel.merged_faces = Dynarr_new (int); | |
1798 Dynarr_add (cachel.merged_faces, findex); | |
1799 } | |
1800 else | |
1801 cachel.merged_faces_static[cachel.nfaces] = findex; | |
1802 cachel.nfaces++; | |
1803 } | |
1804 } | |
1805 | |
1806 /* Now finally merge in the default face. */ | |
1807 findex = get_builtin_face_cache_index (w, Vdefault_face); | |
1808 merge_face_cachel_data (w, findex, &cachel); | |
1809 | |
444 | 1810 findex = get_merged_face_cache_index (w, &cachel); |
1811 if (cachel.merged_faces && | |
1812 /* merged_faces did not get stored and available via return value */ | |
1813 Dynarr_at (w->face_cachels, findex).merged_faces != | |
1814 cachel.merged_faces) | |
1815 { | |
1816 Dynarr_free (cachel.merged_faces); | |
1817 cachel.merged_faces = 0; | |
1818 } | |
1819 return findex; | |
428 | 1820 } |
1821 } | |
1822 | |
3094 | 1823 /* Return a cache index for window W from merging the faces in FACE_LIST. |
1824 COUNT is the number of faces in the list. | |
1825 | |
1826 The default face should not be included in the list, as it is always | |
1827 implicitly merged into the cachel. | |
1828 | |
1829 WARNING: this interface may change. */ | |
1830 | |
1831 face_index | |
1832 merge_face_list_to_cache_index (struct window *w, | |
1833 Lisp_Object *face_list, int count) | |
1834 { | |
1835 int i; | |
1836 face_index findex = 0; | |
1837 struct face_cachel cachel; | |
1838 | |
1839 reset_face_cachel (&cachel); | |
1840 | |
1841 for (i = 0; i < count; i++) | |
1842 { | |
1843 Lisp_Object face = face_list[i]; | |
1844 | |
1845 if (!NILP (face)) | |
1846 { | |
1847 CHECK_FACE(face); /* #### presumably unnecessary */ | |
1848 findex = get_builtin_face_cache_index (w, face); | |
1849 merge_face_cachel_data (w, findex, &cachel); | |
1850 } | |
1851 } | |
1852 | |
1853 /* Now finally merge in the default face. */ | |
1854 findex = get_builtin_face_cache_index (w, Vdefault_face); | |
1855 merge_face_cachel_data (w, findex, &cachel); | |
1856 | |
1857 return get_merged_face_cache_index (w, &cachel); | |
1858 } | |
1859 | |
428 | 1860 |
1861 /***************************************************************************** | |
1862 interface functions | |
1863 ****************************************************************************/ | |
1864 | |
1865 static void | |
1866 update_EmacsFrame (Lisp_Object frame, Lisp_Object name) | |
1867 { | |
1868 struct frame *frm = XFRAME (frame); | |
1869 | |
3676 | 1870 if (!FRAME_LIVE_P(frm)) |
1871 return; | |
1872 | |
428 | 1873 if (EQ (name, Qfont)) |
1874 MARK_FRAME_SIZE_SLIPPED (frm); | |
1875 | |
1876 MAYBE_FRAMEMETH (frm, update_frame_external_traits, (frm, name)); | |
1877 } | |
1878 | |
1879 static void | |
1880 update_EmacsFrames (Lisp_Object locale, Lisp_Object name) | |
1881 { | |
1882 if (FRAMEP (locale)) | |
1883 { | |
1884 update_EmacsFrame (locale, name); | |
1885 } | |
1886 else if (DEVICEP (locale)) | |
1887 { | |
1888 Lisp_Object frmcons; | |
1889 | |
1890 DEVICE_FRAME_LOOP (frmcons, XDEVICE (locale)) | |
1891 update_EmacsFrame (XCAR (frmcons), name); | |
1892 } | |
1893 else if (EQ (locale, Qglobal) || EQ (locale, Qfallback)) | |
1894 { | |
1895 Lisp_Object frmcons, devcons, concons; | |
1896 | |
1897 FRAME_LOOP_NO_BREAK (frmcons, devcons, concons) | |
1898 update_EmacsFrame (XCAR (frmcons), name); | |
1899 } | |
1900 } | |
1901 | |
1902 void | |
1903 update_frame_face_values (struct frame *f) | |
1904 { | |
793 | 1905 Lisp_Object frm = wrap_frame (f); |
428 | 1906 |
1907 update_EmacsFrame (frm, Qforeground); | |
1908 update_EmacsFrame (frm, Qbackground); | |
1909 update_EmacsFrame (frm, Qfont); | |
1910 } | |
1911 | |
1912 void | |
1913 face_property_was_changed (Lisp_Object face, Lisp_Object property, | |
1914 Lisp_Object locale) | |
1915 { | |
1916 int default_face = EQ (face, Vdefault_face); | |
1917 | |
1918 /* If the locale could affect the frame value, then call | |
1919 update_EmacsFrames just in case. */ | |
1920 if (default_face && | |
1921 (EQ (property, Qforeground) || | |
1922 EQ (property, Qbackground) || | |
1923 EQ (property, Qfont))) | |
1924 update_EmacsFrames (locale, property); | |
1925 | |
1926 if (WINDOWP (locale)) | |
1927 { | |
1928 MARK_FRAME_FACES_CHANGED (XFRAME (XWINDOW (locale)->frame)); | |
1929 } | |
1930 else if (FRAMEP (locale)) | |
1931 { | |
1932 MARK_FRAME_FACES_CHANGED (XFRAME (locale)); | |
1933 } | |
1934 else if (DEVICEP (locale)) | |
1935 { | |
1936 MARK_DEVICE_FRAMES_FACES_CHANGED (XDEVICE (locale)); | |
1937 } | |
1938 else | |
1939 { | |
1940 Lisp_Object devcons, concons; | |
1941 DEVICE_LOOP_NO_BREAK (devcons, concons) | |
1942 MARK_DEVICE_FRAMES_FACES_CHANGED (XDEVICE (XCAR (devcons))); | |
1943 } | |
1944 | |
1945 /* | |
1946 * This call to update_faces_inheritance isn't needed and makes | |
1947 * creating and modifying faces _very_ slow. The point of | |
1948 * update_face_inheritances is to find all faces that inherit | |
1949 * directly from this face property and set the specifier "dirty" | |
1950 * flag on the corresponding specifier. This forces recaching of | |
1951 * cached specifier values in frame and window struct slots. But | |
1952 * currently no face properties are cached in frame and window | |
1953 * struct slots, so calling this function does nothing useful! | |
1954 * | |
1955 * Further, since update_faces_inheritance maps over the whole | |
1956 * face table every time it is called, it gets terribly slow when | |
1957 * there are many faces. Creating 500 faces on a 50Mhz 486 took | |
1958 * 433 seconds when update_faces_inheritance was called. With the | |
1959 * call commented out, creating those same 500 faces took 0.72 | |
1960 * seconds. | |
1961 */ | |
1962 /* update_faces_inheritance (face, property);*/ | |
1963 XFACE (face)->dirty = 1; | |
1964 } | |
1965 | |
1966 DEFUN ("copy-face", Fcopy_face, 2, 6, 0, /* | |
1967 Define and return a new face which is a copy of an existing one, | |
1968 or makes an already-existing face be exactly like another. | |
1969 LOCALE, TAG-SET, EXACT-P, and HOW-TO-ADD are as in `copy-specifier'. | |
1970 */ | |
1971 (old_face, new_name, locale, tag_set, exact_p, how_to_add)) | |
1972 { | |
440 | 1973 Lisp_Face *fold, *fnew; |
428 | 1974 Lisp_Object new_face = Qnil; |
1975 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; | |
1976 | |
1977 old_face = Fget_face (old_face); | |
1978 | |
1979 /* We GCPRO old_face because it might be temporary, and GCing could | |
1980 occur in various places below. */ | |
1981 GCPRO4 (tag_set, locale, old_face, new_face); | |
1982 /* check validity of how_to_add now. */ | |
1983 decode_how_to_add_specification (how_to_add); | |
1984 /* and of tag_set. */ | |
1985 tag_set = decode_specifier_tag_set (tag_set); | |
1986 /* and of locale. */ | |
1987 locale = decode_locale_list (locale); | |
1988 | |
1989 new_face = Ffind_face (new_name); | |
1990 if (NILP (new_face)) | |
1991 { | |
1992 Lisp_Object temp; | |
1993 | |
1994 CHECK_SYMBOL (new_name); | |
1995 | |
1996 /* Create the new face with the same status as the old face. */ | |
1997 temp = (NILP (Fgethash (old_face, Vtemporary_faces_cache, Qnil)) | |
1998 ? Qnil | |
1999 : Qt); | |
2000 | |
2001 new_face = Fmake_face (new_name, Qnil, temp); | |
2002 } | |
2003 | |
2004 fold = XFACE (old_face); | |
2005 fnew = XFACE (new_face); | |
2006 | |
2007 #define COPY_PROPERTY(property) \ | |
2008 Fcopy_specifier (fold->property, fnew->property, \ | |
4187 | 2009 locale, tag_set, exact_p, how_to_add); |
428 | 2010 |
2011 COPY_PROPERTY (foreground); | |
2012 COPY_PROPERTY (background); | |
2013 COPY_PROPERTY (font); | |
2014 COPY_PROPERTY (display_table); | |
2015 COPY_PROPERTY (background_pixmap); | |
2016 COPY_PROPERTY (underline); | |
2017 COPY_PROPERTY (strikethru); | |
2018 COPY_PROPERTY (highlight); | |
2019 COPY_PROPERTY (dim); | |
2020 COPY_PROPERTY (blinking); | |
2021 COPY_PROPERTY (reverse); | |
2022 #undef COPY_PROPERTY | |
2023 /* #### should it copy the individual specifiers, if they exist? */ | |
2024 fnew->plist = Fcopy_sequence (fold->plist); | |
2025 | |
2026 UNGCPRO; | |
2027 | |
2028 return new_name; | |
2029 } | |
2030 | |
3659 | 2031 #ifdef MULE |
2032 | |
3918 | 2033 Lisp_Object Qone_dimensional, Qtwo_dimensional, Qx_coverage_instantiator; |
3659 | 2034 |
4187 | 2035 DEFUN ("specifier-tag-one-dimensional-p", |
2036 Fspecifier_tag_one_dimensional_p, | |
5015
d95c102a96d3
cleanups for specifier font stages, from ben-unicode-internal (preparation for eliminating shadowed warnings)
Ben Wing <ben@xemacs.org>
parents:
5013
diff
changeset
|
2037 1, 1, 0, /* |
3659 | 2038 Return non-nil if (charset-dimension CHARSET) is 1. |
2039 | |
2040 Used by the X11 platform font code; see `define-specifier-tag'. You | |
2041 shouldn't ever need to call this yourself. | |
2042 */ | |
5015
d95c102a96d3
cleanups for specifier font stages, from ben-unicode-internal (preparation for eliminating shadowed warnings)
Ben Wing <ben@xemacs.org>
parents:
5013
diff
changeset
|
2043 (charset)) |
3659 | 2044 { |
5015
d95c102a96d3
cleanups for specifier font stages, from ben-unicode-internal (preparation for eliminating shadowed warnings)
Ben Wing <ben@xemacs.org>
parents:
5013
diff
changeset
|
2045 CHECK_CHARSET (charset); |
d95c102a96d3
cleanups for specifier font stages, from ben-unicode-internal (preparation for eliminating shadowed warnings)
Ben Wing <ben@xemacs.org>
parents:
5013
diff
changeset
|
2046 return (1 == XCHARSET_DIMENSION (charset)) ? Qt : Qnil; |
3659 | 2047 } |
2048 | |
4187 | 2049 DEFUN ("specifier-tag-two-dimensional-p", |
2050 Fspecifier_tag_two_dimensional_p, | |
5015
d95c102a96d3
cleanups for specifier font stages, from ben-unicode-internal (preparation for eliminating shadowed warnings)
Ben Wing <ben@xemacs.org>
parents:
5013
diff
changeset
|
2051 1, 1, 0, /* |
3659 | 2052 Return non-nil if (charset-dimension CHARSET) is 2. |
2053 | |
2054 Used by the X11 platform font code; see `define-specifier-tag'. You | |
2055 shouldn't ever need to call this yourself. | |
2056 */ | |
5015
d95c102a96d3
cleanups for specifier font stages, from ben-unicode-internal (preparation for eliminating shadowed warnings)
Ben Wing <ben@xemacs.org>
parents:
5013
diff
changeset
|
2057 (charset)) |
3659 | 2058 { |
5015
d95c102a96d3
cleanups for specifier font stages, from ben-unicode-internal (preparation for eliminating shadowed warnings)
Ben Wing <ben@xemacs.org>
parents:
5013
diff
changeset
|
2059 CHECK_CHARSET (charset); |
d95c102a96d3
cleanups for specifier font stages, from ben-unicode-internal (preparation for eliminating shadowed warnings)
Ben Wing <ben@xemacs.org>
parents:
5013
diff
changeset
|
2060 return (2 == XCHARSET_DIMENSION (charset)) ? Qt : Qnil; |
3659 | 2061 } |
2062 | |
4187 | 2063 DEFUN ("specifier-tag-final-stage-p", |
2064 Fspecifier_tag_final_stage_p, | |
3659 | 2065 2, 2, 0, /* |
2066 Return non-nil if STAGE is 'final. | |
2067 | |
2068 Used by the X11 platform font code for giving fallbacks; see | |
4187 | 2069 `define-specifier-tag'. You shouldn't ever need to call this. |
3659 | 2070 */ |
5015
d95c102a96d3
cleanups for specifier font stages, from ben-unicode-internal (preparation for eliminating shadowed warnings)
Ben Wing <ben@xemacs.org>
parents:
5013
diff
changeset
|
2071 (UNUSED (charset), stage)) |
3659 | 2072 { |
5015
d95c102a96d3
cleanups for specifier font stages, from ben-unicode-internal (preparation for eliminating shadowed warnings)
Ben Wing <ben@xemacs.org>
parents:
5013
diff
changeset
|
2073 return EQ (stage, Qfinal) ? Qt : Qnil; |
3659 | 2074 } |
2075 | |
4187 | 2076 DEFUN ("specifier-tag-initial-stage-p", |
2077 Fspecifier_tag_initial_stage_p, | |
3659 | 2078 2, 2, 0, /* |
2079 Return non-nil if STAGE is 'initial. | |
2080 | |
2081 Used by the X11 platform font code for giving fallbacks; see | |
4187 | 2082 `define-specifier-tag'. You shouldn't ever need to call this. |
3659 | 2083 */ |
2084 (UNUSED(charset), stage)) | |
2085 { | |
2086 return EQ(stage, Qinitial) ? Qt : Qnil; | |
2087 } | |
2088 | |
4187 | 2089 DEFUN ("specifier-tag-encode-as-utf-8-p", |
2090 Fspecifier_tag_encode_as_utf_8_p, | |
3659 | 2091 2, 2, 0, /* |
2092 Return t if and only if (charset-property CHARSET 'encode-as-utf-8)). | |
2093 | |
2094 Used by the X11 platform font code; see `define-specifier-tag'. You | |
2095 shouldn't ever need to call this. | |
2096 */ | |
2097 (charset, UNUSED(stage))) | |
2098 { | |
2099 /* Used to check that the stage was initial too. */ | |
2100 CHECK_CHARSET(charset); | |
2101 return XCHARSET_ENCODE_AS_UTF_8(charset) ? Qt : Qnil; | |
2102 } | |
2103 | |
2104 #endif /* MULE */ | |
2105 | |
428 | 2106 |
2107 void | |
2108 syms_of_faces (void) | |
2109 { | |
5117
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3017
diff
changeset
|
2110 INIT_LISP_OBJECT (face); |
442 | 2111 |
440 | 2112 /* Qdefault, Qwidget, Qleft_margin, Qright_margin defined in general.c */ |
563 | 2113 DEFSYMBOL (Qmodeline); |
2114 DEFSYMBOL (Qgui_element); | |
2115 DEFSYMBOL (Qtext_cursor); | |
2116 DEFSYMBOL (Qvertical_divider); | |
428 | 2117 |
2118 DEFSUBR (Ffacep); | |
2119 DEFSUBR (Ffind_face); | |
2120 DEFSUBR (Fget_face); | |
2121 DEFSUBR (Fface_name); | |
2122 DEFSUBR (Fbuilt_in_face_specifiers); | |
2123 DEFSUBR (Fface_list); | |
2124 DEFSUBR (Fmake_face); | |
2125 DEFSUBR (Fcopy_face); | |
2126 | |
3659 | 2127 #ifdef MULE |
2128 DEFSYMBOL (Qone_dimensional); | |
2129 DEFSYMBOL (Qtwo_dimensional); | |
3918 | 2130 DEFSYMBOL (Qx_coverage_instantiator); |
2131 | |
3659 | 2132 /* I would much prefer these were in Lisp. */ |
2133 DEFSUBR (Fspecifier_tag_one_dimensional_p); | |
2134 DEFSUBR (Fspecifier_tag_two_dimensional_p); | |
2135 DEFSUBR (Fspecifier_tag_initial_stage_p); | |
2136 DEFSUBR (Fspecifier_tag_final_stage_p); | |
2137 DEFSUBR (Fspecifier_tag_encode_as_utf_8_p); | |
2138 #endif /* MULE */ | |
2139 | |
563 | 2140 DEFSYMBOL (Qfacep); |
2141 DEFSYMBOL (Qforeground); | |
2142 DEFSYMBOL (Qbackground); | |
428 | 2143 /* Qfont defined in general.c */ |
563 | 2144 DEFSYMBOL (Qdisplay_table); |
2145 DEFSYMBOL (Qbackground_pixmap); | |
2146 DEFSYMBOL (Qunderline); | |
2147 DEFSYMBOL (Qstrikethru); | |
428 | 2148 /* Qhighlight, Qreverse defined in general.c */ |
563 | 2149 DEFSYMBOL (Qdim); |
2150 DEFSYMBOL (Qblinking); | |
428 | 2151 |
2865 | 2152 DEFSYMBOL (Qface_alias); |
2867 | 2153 DEFERROR_STANDARD (Qcyclic_face_alias, Qinvalid_state); |
2865 | 2154 |
563 | 2155 DEFSYMBOL (Qinit_face_from_resources); |
2156 DEFSYMBOL (Qinit_global_faces); | |
2157 DEFSYMBOL (Qinit_device_faces); | |
2158 DEFSYMBOL (Qinit_frame_faces); | |
428 | 2159 } |
2160 | |
2161 void | |
2162 structure_type_create_faces (void) | |
2163 { | |
2164 struct structure_type *st; | |
2165 | |
2166 st = define_structure_type (Qface, face_validate, face_instantiate); | |
2167 | |
2168 define_structure_type_keyword (st, Qname, face_name_validate); | |
2169 } | |
2170 | |
2171 void | |
2172 vars_of_faces (void) | |
2173 { | |
2174 staticpro (&Vpermanent_faces_cache); | |
771 | 2175 Vpermanent_faces_cache = |
2176 make_lisp_hash_table (10, HASH_TABLE_NON_WEAK, HASH_TABLE_EQ); | |
428 | 2177 staticpro (&Vtemporary_faces_cache); |
771 | 2178 Vtemporary_faces_cache = |
2179 make_lisp_hash_table (0, HASH_TABLE_WEAK, HASH_TABLE_EQ); | |
428 | 2180 |
2181 staticpro (&Vdefault_face); | |
2182 Vdefault_face = Qnil; | |
2183 staticpro (&Vgui_element_face); | |
2184 Vgui_element_face = Qnil; | |
2185 staticpro (&Vwidget_face); | |
2186 Vwidget_face = Qnil; | |
2187 staticpro (&Vmodeline_face); | |
2188 Vmodeline_face = Qnil; | |
2189 staticpro (&Vtoolbar_face); | |
2190 Vtoolbar_face = Qnil; | |
2191 | |
2192 staticpro (&Vvertical_divider_face); | |
2193 Vvertical_divider_face = Qnil; | |
2194 staticpro (&Vleft_margin_face); | |
2195 Vleft_margin_face = Qnil; | |
2196 staticpro (&Vright_margin_face); | |
2197 Vright_margin_face = Qnil; | |
2198 staticpro (&Vtext_cursor_face); | |
2199 Vtext_cursor_face = Qnil; | |
2200 staticpro (&Vpointer_face); | |
2201 Vpointer_face = Qnil; | |
2202 | |
3659 | 2203 #ifdef DEBUG_XEMACS |
2204 DEFVAR_INT ("debug-x-faces", &debug_x_faces /* | |
2205 If non-zero, display debug information about X faces | |
2206 */ ); | |
2207 debug_x_faces = 0; | |
2208 #endif | |
2209 | |
428 | 2210 { |
2211 Lisp_Object syms[20]; | |
2212 int n = 0; | |
2213 | |
2214 syms[n++] = Qforeground; | |
2215 syms[n++] = Qbackground; | |
2216 syms[n++] = Qfont; | |
2217 syms[n++] = Qdisplay_table; | |
2218 syms[n++] = Qbackground_pixmap; | |
2219 syms[n++] = Qunderline; | |
2220 syms[n++] = Qstrikethru; | |
2221 syms[n++] = Qhighlight; | |
2222 syms[n++] = Qdim; | |
2223 syms[n++] = Qblinking; | |
2224 syms[n++] = Qreverse; | |
2225 | |
2226 Vbuilt_in_face_specifiers = Flist (n, syms); | |
2227 staticpro (&Vbuilt_in_face_specifiers); | |
2228 } | |
2229 } | |
2230 | |
2231 void | |
2232 complex_vars_of_faces (void) | |
2233 { | |
2234 /* Create the default face now so we know what it is immediately. */ | |
2235 | |
2236 Vdefault_face = Qnil; /* so that Fmake_face() doesn't set up a bogus | |
2237 default value */ | |
4952
19a72041c5ed
Mule-izing, various fixes related to char * arguments
Ben Wing <ben@xemacs.org>
parents:
4862
diff
changeset
|
2238 Vdefault_face = Fmake_face (Qdefault, build_defer_string ("default face"), |
428 | 2239 Qnil); |
2240 | |
2241 /* Provide some last-resort fallbacks to avoid utter fuckage if | |
2242 someone provides invalid values for the global specifications. */ | |
2243 | |
2244 { | |
2245 Lisp_Object fg_fb = Qnil, bg_fb = Qnil; | |
2246 | |
462 | 2247 #ifdef HAVE_GTK |
4952
19a72041c5ed
Mule-izing, various fixes related to char * arguments
Ben Wing <ben@xemacs.org>
parents:
4862
diff
changeset
|
2248 fg_fb = acons (list1 (Qgtk), build_ascstring ("black"), fg_fb); |
19a72041c5ed
Mule-izing, various fixes related to char * arguments
Ben Wing <ben@xemacs.org>
parents:
4862
diff
changeset
|
2249 bg_fb = acons (list1 (Qgtk), build_ascstring ("white"), bg_fb); |
462 | 2250 #endif |
428 | 2251 #ifdef HAVE_X_WINDOWS |
4952
19a72041c5ed
Mule-izing, various fixes related to char * arguments
Ben Wing <ben@xemacs.org>
parents:
4862
diff
changeset
|
2252 fg_fb = acons (list1 (Qx), build_ascstring ("black"), fg_fb); |
19a72041c5ed
Mule-izing, various fixes related to char * arguments
Ben Wing <ben@xemacs.org>
parents:
4862
diff
changeset
|
2253 bg_fb = acons (list1 (Qx), build_ascstring ("gray80"), bg_fb); |
428 | 2254 #endif |
2255 #ifdef HAVE_TTY | |
2256 fg_fb = acons (list1 (Qtty), Fvector (0, 0), fg_fb); | |
2257 bg_fb = acons (list1 (Qtty), Fvector (0, 0), bg_fb); | |
2258 #endif | |
2259 #ifdef HAVE_MS_WINDOWS | |
4952
19a72041c5ed
Mule-izing, various fixes related to char * arguments
Ben Wing <ben@xemacs.org>
parents:
4862
diff
changeset
|
2260 fg_fb = acons (list1 (Qmsprinter), build_ascstring ("black"), fg_fb); |
19a72041c5ed
Mule-izing, various fixes related to char * arguments
Ben Wing <ben@xemacs.org>
parents:
4862
diff
changeset
|
2261 bg_fb = acons (list1 (Qmsprinter), build_ascstring ("white"), bg_fb); |
19a72041c5ed
Mule-izing, various fixes related to char * arguments
Ben Wing <ben@xemacs.org>
parents:
4862
diff
changeset
|
2262 fg_fb = acons (list1 (Qmswindows), build_ascstring ("black"), fg_fb); |
19a72041c5ed
Mule-izing, various fixes related to char * arguments
Ben Wing <ben@xemacs.org>
parents:
4862
diff
changeset
|
2263 bg_fb = acons (list1 (Qmswindows), build_ascstring ("white"), bg_fb); |
428 | 2264 #endif |
2265 set_specifier_fallback (Fget (Vdefault_face, Qforeground, Qnil), fg_fb); | |
2266 set_specifier_fallback (Fget (Vdefault_face, Qbackground, Qnil), bg_fb); | |
2267 } | |
2268 | |
2269 { | |
2270 Lisp_Object inst_list = Qnil; | |
462 | 2271 |
872 | 2272 #if defined (HAVE_X_WINDOWS) || defined (HAVE_GTK) |
2865 | 2273 |
3659 | 2274 #ifdef HAVE_GTK |
2275 Lisp_Object device_symbol = Qgtk; | |
2276 #else | |
2277 Lisp_Object device_symbol = Qx; | |
2278 #endif | |
2279 | |
4916
a6c778975d7d
split USE_XFT into HAVE_XFT/USE_XFT
Ben Wing <ben@xemacs.org>
parents:
4906
diff
changeset
|
2280 #if defined (HAVE_XFT) || defined (MULE) |
3802 | 2281 const Ascbyte **fontptr; |
3659 | 2282 |
2367 | 2283 const Ascbyte *fonts[] = |
428 | 2284 { |
4916
a6c778975d7d
split USE_XFT into HAVE_XFT/USE_XFT
Ben Wing <ben@xemacs.org>
parents:
4906
diff
changeset
|
2285 #ifdef HAVE_XFT |
3094 | 2286 /************** Xft fonts *************/ |
2287 | |
2288 /* Note that fontconfig can search for several font families in one | |
2289 call. We should use this facility. */ | |
3659 | 2290 "Monospace-12", |
3094 | 2291 /* do we need to worry about non-Latin characters for monospace? |
4187 | 2292 No, at least in Debian's implementation of Xft. |
3094 | 2293 We should recommend that "gothic" and "mincho" aliases be created? */ |
3659 | 2294 "Sazanami Mincho-12", |
2295 /* Japanese #### add encoding info? */ | |
4187 | 2296 /* Arphic for Chinese? */ |
2297 /* Korean */ | |
3094 | 2298 #else |
3659 | 2299 /* The default Japanese fonts installed with XFree86 4.0 use this |
2300 point size, and the -misc-fixed fonts (which look really bad with | |
2301 Han characters) don't. We need to prefer the former. */ | |
2302 "-*-*-medium-r-*-*-*-150-*-*-c-*-*-*", | |
2303 /* And the Chinese ones, maddeningly, use this one. (But on 4.0, while | |
2304 XListFonts returns them, XLoadQueryFont on the fully-specified XLFD | |
2305 corresponding to one of them fails!) */ | |
2306 "-*-*-medium-r-*-*-*-160-*-*-c-*-*-*", | |
2307 "-*-*-medium-r-*-*-*-170-*-*-c-*-*-*", | |
3094 | 2308 #endif |
428 | 2309 }; |
4916
a6c778975d7d
split USE_XFT into HAVE_XFT/USE_XFT
Ben Wing <ben@xemacs.org>
parents:
4906
diff
changeset
|
2310 #endif /* defined (HAVE_XFT) || defined (MULE) */ |
3802 | 2311 |
2312 #ifdef MULE | |
428 | 2313 |
3659 | 2314 /* Define some specifier tags for classes of character sets. Combining |
2315 these allows for distinct fallback fonts for distinct dimensions of | |
2316 character sets and stages. */ | |
2317 | |
2318 define_specifier_tag(Qtwo_dimensional, Qnil, | |
2319 intern ("specifier-tag-two-dimensional-p")); | |
2320 | |
2321 define_specifier_tag(Qone_dimensional, Qnil, | |
2322 intern ("specifier-tag-one-dimensional-p")); | |
2323 | |
4187 | 2324 define_specifier_tag(Qinitial, Qnil, |
3659 | 2325 intern ("specifier-tag-initial-stage-p")); |
2326 | |
4187 | 2327 define_specifier_tag(Qfinal, Qnil, |
3659 | 2328 intern ("specifier-tag-final-stage-p")); |
2329 | |
2330 define_specifier_tag (Qencode_as_utf_8, Qnil, | |
2331 intern("specifier-tag-encode-as-utf-8-p")); | |
3918 | 2332 |
2333 /* This tag is used to group those instantiators made available in the | |
2334 fallback for the sake of coverage of obscure characters, notably | |
2335 Markus Kuhn's misc-fixed fonts. They will be copied from the fallback | |
2336 when the default face is determined from X resources at startup. */ | |
2337 define_specifier_tag (Qx_coverage_instantiator, Qnil, Qnil); | |
2338 | |
3659 | 2339 #endif /* MULE */ |
2340 | |
4916
a6c778975d7d
split USE_XFT into HAVE_XFT/USE_XFT
Ben Wing <ben@xemacs.org>
parents:
4906
diff
changeset
|
2341 #ifdef HAVE_XFT |
3747 | 2342 for (fontptr = fonts + countof(fonts) - 1; fontptr >= fonts; fontptr--) |
2343 inst_list = Fcons (Fcons (list1 (device_symbol), | |
4953
304aebb79cd3
function renamings to track names of char typedefs
Ben Wing <ben@xemacs.org>
parents:
4952
diff
changeset
|
2344 build_cistring (*fontptr)), |
3747 | 2345 inst_list); |
2346 | |
4916
a6c778975d7d
split USE_XFT into HAVE_XFT/USE_XFT
Ben Wing <ben@xemacs.org>
parents:
4906
diff
changeset
|
2347 #else /* !HAVE_XFT */ |
3659 | 2348 inst_list = |
4187 | 2349 Fcons |
3659 | 2350 (Fcons |
4187 | 2351 (list1 (device_symbol), |
4766
32b358a240b0
Avoid calling Xft if not built in.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4759
diff
changeset
|
2352 /* grrr. This really does need to be "*", not an XLFD. |
32b358a240b0
Avoid calling Xft if not built in.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4759
diff
changeset
|
2353 An unspecified XLFD won't pick up stuff like 10x20. */ |
4952
19a72041c5ed
Mule-izing, various fixes related to char * arguments
Ben Wing <ben@xemacs.org>
parents:
4862
diff
changeset
|
2354 build_ascstring ("*")), |
3659 | 2355 inst_list); |
4187 | 2356 #ifdef MULE |
3659 | 2357 |
2358 /* For Han characters and Ethiopic, we want the misc-fixed font used to | |
2359 be distinct from that for alphabetic scripts, because the font | |
2360 specified below is distractingly ugly when used for Han characters | |
2361 (this is slightly less so) and because its coverage isn't up to | |
2362 handling them (well, chiefly, it's not up to handling Ethiopic--we do | |
2363 have charset-specific fallbacks for the East Asian charsets.) */ | |
4187 | 2364 inst_list = |
3659 | 2365 Fcons |
2366 (Fcons | |
4187 | 2367 (list4(device_symbol, Qtwo_dimensional, Qfinal, Qx_coverage_instantiator), |
4952
19a72041c5ed
Mule-izing, various fixes related to char * arguments
Ben Wing <ben@xemacs.org>
parents:
4862
diff
changeset
|
2368 build_ascstring |
3659 | 2369 ("-misc-fixed-medium-r-normal--15-140-75-75-c-90-iso10646-1")), |
2370 inst_list); | |
2371 | |
2372 /* Use Markus Kuhn's version of misc-fixed as the font for the font for | |
2373 when a given charset's registries can't be found and redisplay for | |
2374 that charset falls back to iso10646-1. */ | |
428 | 2375 |
4187 | 2376 inst_list = |
3659 | 2377 Fcons |
2378 (Fcons | |
4187 | 2379 (list4(device_symbol, Qone_dimensional, Qfinal, Qx_coverage_instantiator), |
4952
19a72041c5ed
Mule-izing, various fixes related to char * arguments
Ben Wing <ben@xemacs.org>
parents:
4862
diff
changeset
|
2380 build_ascstring |
4187 | 2381 ("-misc-fixed-medium-r-semicondensed--13-120-75-75-c-60-iso10646-1")), |
3659 | 2382 inst_list); |
2383 | |
462 | 2384 for (fontptr = fonts + countof(fonts) - 1; fontptr >= fonts; fontptr--) |
4187 | 2385 inst_list = Fcons (Fcons (list3 (device_symbol, |
3659 | 2386 Qtwo_dimensional, Qinitial), |
4953
304aebb79cd3
function renamings to track names of char typedefs
Ben Wing <ben@xemacs.org>
parents:
4952
diff
changeset
|
2387 build_cistring (*fontptr)), |
462 | 2388 inst_list); |
3659 | 2389 |
2390 /* We need to set the font for the JIT-ucs-charsets separately from the | |
2391 final stage, since otherwise it picks up the two-dimensional | |
2392 specification (see specifier-tag-two-dimensional-initial-stage-p | |
2393 above). They also use Markus Kuhn's ISO 10646-1 fixed fonts for | |
2394 redisplay. */ | |
2395 | |
4187 | 2396 inst_list = |
3659 | 2397 Fcons |
2398 (Fcons | |
4187 | 2399 (list4(device_symbol, Qencode_as_utf_8, Qinitial, Qx_coverage_instantiator), |
4952
19a72041c5ed
Mule-izing, various fixes related to char * arguments
Ben Wing <ben@xemacs.org>
parents:
4862
diff
changeset
|
2400 build_ascstring |
4187 | 2401 ("-misc-fixed-medium-r-semicondensed--13-120-75-75-c-60-iso10646-1")), |
3659 | 2402 inst_list); |
2403 | |
2404 #endif /* MULE */ | |
2405 | |
2406 /* Needed to make sure that charsets with non-specified fonts don't | |
2407 use bold and oblique first if medium and regular are available. */ | |
2408 inst_list = | |
4187 | 2409 Fcons |
3659 | 2410 (Fcons |
4187 | 2411 (list1 (device_symbol), |
4952
19a72041c5ed
Mule-izing, various fixes related to char * arguments
Ben Wing <ben@xemacs.org>
parents:
4862
diff
changeset
|
2412 build_ascstring ("-*-*-medium-r-*-*-*-120-*-*-c-*-*-*")), |
3659 | 2413 inst_list); |
2414 | |
2415 /* With a Cygwin XFree86 install, this returns the best (clearest, | |
2416 most readable) font I can find when scaling of bitmap fonts is | |
2417 turned on, as it is by default. (WHO IN THE NAME OF CHRIST THOUGHT | |
2418 THAT WAS A GOOD IDEA?!?!) The other fonts that used to be specified | |
2419 here gave horrendous results. */ | |
2420 | |
2421 inst_list = | |
4187 | 2422 Fcons |
3659 | 2423 (Fcons |
4187 | 2424 (list1 (device_symbol), |
4952
19a72041c5ed
Mule-izing, various fixes related to char * arguments
Ben Wing <ben@xemacs.org>
parents:
4862
diff
changeset
|
2425 build_ascstring ("-*-lucidatypewriter-medium-r-*-*-*-120-*-*-*-*-*-*")), |
3659 | 2426 inst_list); |
2427 | |
4916
a6c778975d7d
split USE_XFT into HAVE_XFT/USE_XFT
Ben Wing <ben@xemacs.org>
parents:
4906
diff
changeset
|
2428 #endif /* !HAVE_XFT */ |
3747 | 2429 |
462 | 2430 #endif /* HAVE_X_WINDOWS || HAVE_GTK */ |
2431 | |
428 | 2432 #ifdef HAVE_TTY |
4952
19a72041c5ed
Mule-izing, various fixes related to char * arguments
Ben Wing <ben@xemacs.org>
parents:
4862
diff
changeset
|
2433 inst_list = Fcons (Fcons (list1 (Qtty), build_ascstring ("normal")), |
428 | 2434 inst_list); |
2435 #endif /* HAVE_TTY */ | |
440 | 2436 |
771 | 2437 #ifdef HAVE_MS_WINDOWS |
2438 { | |
2367 | 2439 const Ascbyte *mswfonts[] = |
4187 | 2440 { |
2441 "Courier New:Regular:10::", | |
2442 "Courier:Regular:10::", | |
2443 ":Regular:10::" | |
2444 }; | |
2367 | 2445 const Ascbyte **mswfontptr; |
2865 | 2446 |
771 | 2447 for (mswfontptr = mswfonts + countof (mswfonts) - 1; |
2448 mswfontptr >= mswfonts; mswfontptr--) | |
4187 | 2449 { |
2450 /* display device */ | |
2451 inst_list = Fcons (Fcons (list1 (Qmswindows), | |
4952
19a72041c5ed
Mule-izing, various fixes related to char * arguments
Ben Wing <ben@xemacs.org>
parents:
4862
diff
changeset
|
2452 build_ascstring (*mswfontptr)), |
4187 | 2453 inst_list); |
2454 /* printer device */ | |
2455 inst_list = Fcons (Fcons (list1 (Qmsprinter), | |
4952
19a72041c5ed
Mule-izing, various fixes related to char * arguments
Ben Wing <ben@xemacs.org>
parents:
4862
diff
changeset
|
2456 build_ascstring (*mswfontptr)), |
4187 | 2457 inst_list); |
2458 } | |
793 | 2459 /* Use Lucida Console rather than Courier New if it exists -- the |
4187 | 2460 line spacing is much less, so many more lines fit with the same |
2461 size font. (And it's specifically designed for screens.) */ | |
2865 | 2462 inst_list = Fcons (Fcons (list1 (Qmswindows), |
4952
19a72041c5ed
Mule-izing, various fixes related to char * arguments
Ben Wing <ben@xemacs.org>
parents:
4862
diff
changeset
|
2463 build_ascstring ("Lucida Console:Regular:10::")), |
793 | 2464 inst_list); |
771 | 2465 } |
428 | 2466 #endif /* HAVE_MS_WINDOWS */ |
771 | 2467 |
428 | 2468 set_specifier_fallback (Fget (Vdefault_face, Qfont, Qnil), inst_list); |
2469 } | |
2470 | |
2471 set_specifier_fallback (Fget (Vdefault_face, Qunderline, Qnil), | |
2472 list1 (Fcons (Qnil, Qnil))); | |
2473 set_specifier_fallback (Fget (Vdefault_face, Qstrikethru, Qnil), | |
2474 list1 (Fcons (Qnil, Qnil))); | |
2475 set_specifier_fallback (Fget (Vdefault_face, Qhighlight, Qnil), | |
2476 list1 (Fcons (Qnil, Qnil))); | |
2477 set_specifier_fallback (Fget (Vdefault_face, Qdim, Qnil), | |
2478 list1 (Fcons (Qnil, Qnil))); | |
2479 set_specifier_fallback (Fget (Vdefault_face, Qblinking, Qnil), | |
2480 list1 (Fcons (Qnil, Qnil))); | |
2481 set_specifier_fallback (Fget (Vdefault_face, Qreverse, Qnil), | |
2482 list1 (Fcons (Qnil, Qnil))); | |
2483 | |
2484 /* gui-element is the parent face of all gui elements such as | |
2485 modeline, vertical divider and toolbar. */ | |
2486 Vgui_element_face = Fmake_face (Qgui_element, | |
4952
19a72041c5ed
Mule-izing, various fixes related to char * arguments
Ben Wing <ben@xemacs.org>
parents:
4862
diff
changeset
|
2487 build_defer_string ("gui element face"), |
428 | 2488 Qnil); |
2489 | |
2490 /* Provide some last-resort fallbacks for gui-element face which | |
2491 mustn't default to default. */ | |
2492 { | |
2493 Lisp_Object fg_fb = Qnil, bg_fb = Qnil; | |
2494 | |
3094 | 2495 /* #### gui-element face doesn't have a font property? |
2496 But it gets referred to later! */ | |
462 | 2497 #ifdef HAVE_GTK |
2498 /* We need to put something in there, or error checking gets | |
2499 #%!@#ed up before the styles are set, which override the | |
2500 fallbacks. */ | |
4952
19a72041c5ed
Mule-izing, various fixes related to char * arguments
Ben Wing <ben@xemacs.org>
parents:
4862
diff
changeset
|
2501 fg_fb = acons (list1 (Qgtk), build_ascstring ("black"), fg_fb); |
19a72041c5ed
Mule-izing, various fixes related to char * arguments
Ben Wing <ben@xemacs.org>
parents:
4862
diff
changeset
|
2502 bg_fb = acons (list1 (Qgtk), build_ascstring ("Gray80"), bg_fb); |
462 | 2503 #endif |
428 | 2504 #ifdef HAVE_X_WINDOWS |
4952
19a72041c5ed
Mule-izing, various fixes related to char * arguments
Ben Wing <ben@xemacs.org>
parents:
4862
diff
changeset
|
2505 fg_fb = acons (list1 (Qx), build_ascstring ("black"), fg_fb); |
19a72041c5ed
Mule-izing, various fixes related to char * arguments
Ben Wing <ben@xemacs.org>
parents:
4862
diff
changeset
|
2506 bg_fb = acons (list1 (Qx), build_ascstring ("Gray80"), bg_fb); |
428 | 2507 #endif |
2508 #ifdef HAVE_TTY | |
2509 fg_fb = acons (list1 (Qtty), Fvector (0, 0), fg_fb); | |
2510 bg_fb = acons (list1 (Qtty), Fvector (0, 0), bg_fb); | |
2511 #endif | |
2512 #ifdef HAVE_MS_WINDOWS | |
4952
19a72041c5ed
Mule-izing, various fixes related to char * arguments
Ben Wing <ben@xemacs.org>
parents:
4862
diff
changeset
|
2513 fg_fb = acons (list1 (Qmsprinter), build_ascstring ("black"), fg_fb); |
19a72041c5ed
Mule-izing, various fixes related to char * arguments
Ben Wing <ben@xemacs.org>
parents:
4862
diff
changeset
|
2514 bg_fb = acons (list1 (Qmsprinter), build_ascstring ("white"), bg_fb); |
19a72041c5ed
Mule-izing, various fixes related to char * arguments
Ben Wing <ben@xemacs.org>
parents:
4862
diff
changeset
|
2515 fg_fb = acons (list1 (Qmswindows), build_ascstring ("black"), fg_fb); |
19a72041c5ed
Mule-izing, various fixes related to char * arguments
Ben Wing <ben@xemacs.org>
parents:
4862
diff
changeset
|
2516 bg_fb = acons (list1 (Qmswindows), build_ascstring ("Gray75"), bg_fb); |
428 | 2517 #endif |
2518 set_specifier_fallback (Fget (Vgui_element_face, Qforeground, Qnil), fg_fb); | |
2519 set_specifier_fallback (Fget (Vgui_element_face, Qbackground, Qnil), bg_fb); | |
2520 } | |
2521 | |
2522 /* Now create the other faces that redisplay needs to refer to | |
2523 directly. We could create them in Lisp but it's simpler this | |
2524 way since we need to get them anyway. */ | |
2525 | |
2526 /* modeline is gui element. */ | |
4952
19a72041c5ed
Mule-izing, various fixes related to char * arguments
Ben Wing <ben@xemacs.org>
parents:
4862
diff
changeset
|
2527 Vmodeline_face = Fmake_face (Qmodeline, build_defer_string ("modeline face"), |
428 | 2528 Qnil); |
2529 | |
2530 set_specifier_fallback (Fget (Vmodeline_face, Qforeground, Qunbound), | |
2531 Fget (Vgui_element_face, Qforeground, Qunbound)); | |
2532 set_specifier_fallback (Fget (Vmodeline_face, Qbackground, Qunbound), | |
2533 Fget (Vgui_element_face, Qbackground, Qunbound)); | |
2534 set_specifier_fallback (Fget (Vmodeline_face, Qbackground_pixmap, Qnil), | |
2535 Fget (Vgui_element_face, Qbackground_pixmap, | |
2536 Qunbound)); | |
2537 | |
2538 /* toolbar is another gui element */ | |
2539 Vtoolbar_face = Fmake_face (Qtoolbar, | |
4952
19a72041c5ed
Mule-izing, various fixes related to char * arguments
Ben Wing <ben@xemacs.org>
parents:
4862
diff
changeset
|
2540 build_defer_string ("toolbar face"), |
428 | 2541 Qnil); |
2542 set_specifier_fallback (Fget (Vtoolbar_face, Qforeground, Qunbound), | |
2543 Fget (Vgui_element_face, Qforeground, Qunbound)); | |
2544 set_specifier_fallback (Fget (Vtoolbar_face, Qbackground, Qunbound), | |
2545 Fget (Vgui_element_face, Qbackground, Qunbound)); | |
2546 set_specifier_fallback (Fget (Vtoolbar_face, Qbackground_pixmap, Qnil), | |
2547 Fget (Vgui_element_face, Qbackground_pixmap, | |
2548 Qunbound)); | |
2549 | |
2550 /* vertical divider is another gui element */ | |
2551 Vvertical_divider_face = Fmake_face (Qvertical_divider, | |
4952
19a72041c5ed
Mule-izing, various fixes related to char * arguments
Ben Wing <ben@xemacs.org>
parents:
4862
diff
changeset
|
2552 build_defer_string ("vertical divider face"), |
428 | 2553 Qnil); |
2554 | |
2555 set_specifier_fallback (Fget (Vvertical_divider_face, Qforeground, Qunbound), | |
2556 Fget (Vgui_element_face, Qforeground, Qunbound)); | |
2557 set_specifier_fallback (Fget (Vvertical_divider_face, Qbackground, Qunbound), | |
2558 Fget (Vgui_element_face, Qbackground, Qunbound)); | |
2559 set_specifier_fallback (Fget (Vvertical_divider_face, Qbackground_pixmap, | |
2560 Qunbound), | |
2561 Fget (Vgui_element_face, Qbackground_pixmap, | |
2562 Qunbound)); | |
2563 | |
2564 /* widget is another gui element */ | |
2565 Vwidget_face = Fmake_face (Qwidget, | |
4952
19a72041c5ed
Mule-izing, various fixes related to char * arguments
Ben Wing <ben@xemacs.org>
parents:
4862
diff
changeset
|
2566 build_defer_string ("widget face"), |
428 | 2567 Qnil); |
3094 | 2568 /* #### weird ... the gui-element face doesn't have its own font yet */ |
442 | 2569 set_specifier_fallback (Fget (Vwidget_face, Qfont, Qunbound), |
2570 Fget (Vgui_element_face, Qfont, Qunbound)); | |
428 | 2571 set_specifier_fallback (Fget (Vwidget_face, Qforeground, Qunbound), |
2572 Fget (Vgui_element_face, Qforeground, Qunbound)); | |
2573 set_specifier_fallback (Fget (Vwidget_face, Qbackground, Qunbound), | |
2574 Fget (Vgui_element_face, Qbackground, Qunbound)); | |
442 | 2575 /* We don't want widgets to have a default background pixmap. */ |
428 | 2576 |
2577 Vleft_margin_face = Fmake_face (Qleft_margin, | |
4952
19a72041c5ed
Mule-izing, various fixes related to char * arguments
Ben Wing <ben@xemacs.org>
parents:
4862
diff
changeset
|
2578 build_defer_string ("left margin face"), |
428 | 2579 Qnil); |
2580 Vright_margin_face = Fmake_face (Qright_margin, | |
4952
19a72041c5ed
Mule-izing, various fixes related to char * arguments
Ben Wing <ben@xemacs.org>
parents:
4862
diff
changeset
|
2581 build_defer_string ("right margin face"), |
428 | 2582 Qnil); |
2583 Vtext_cursor_face = Fmake_face (Qtext_cursor, | |
4952
19a72041c5ed
Mule-izing, various fixes related to char * arguments
Ben Wing <ben@xemacs.org>
parents:
4862
diff
changeset
|
2584 build_defer_string ("face for text cursor"), |
428 | 2585 Qnil); |
2586 Vpointer_face = | |
2587 Fmake_face (Qpointer, | |
4952
19a72041c5ed
Mule-izing, various fixes related to char * arguments
Ben Wing <ben@xemacs.org>
parents:
4862
diff
changeset
|
2588 build_defer_string |
428 | 2589 ("face for foreground/background colors of mouse pointer"), |
2590 Qnil); | |
2591 } |