428
+ − 1 /* Face data structures.
+ − 2 Copyright (C) 1995 Board of Trustees, University of Illinois.
771
+ − 3 Copyright (C) 1995, 2002 Ben Wing
428
+ − 4
+ − 5 This file is part of XEmacs.
+ − 6
+ − 7 XEmacs is free software; you can redistribute it and/or modify it
+ − 8 under the terms of the GNU General Public License as published by the
+ − 9 Free Software Foundation; either version 2, or (at your option) any
+ − 10 later version.
+ − 11
+ − 12 XEmacs is distributed in the hope that it will be useful, but WITHOUT
+ − 13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ − 14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ − 15 for more details.
+ − 16
+ − 17 You should have received a copy of the GNU General Public License
+ − 18 along with XEmacs; see the file COPYING. If not, write to
+ − 19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ − 20 Boston, MA 02111-1307, USA. */
+ − 21
+ − 22 /* Synched up with: Not in FSF. */
+ − 23
440
+ − 24 #ifndef INCLUDED_faces_h_
+ − 25 #define INCLUDED_faces_h_
428
+ − 26
771
+ − 27 #include "charset.h" /* for NUM_LEADING_BYTES */
3659
+ − 28 #include "specifier.h"
428
+ − 29
440
+ − 30 /* a Lisp_Face is the C object corresponding to a face. There is one
+ − 31 of these per face. It basically contains all of the specifiers for
+ − 32 the built-in face properties, plus the plist of user-specified
428
+ − 33 properties. */
+ − 34
+ − 35 struct Lisp_Face
+ − 36 {
3017
+ − 37 struct LCRECORD_HEADER header;
428
+ − 38
+ − 39 Lisp_Object name;
+ − 40 Lisp_Object doc_string;
+ − 41 unsigned int dirty :1; /* Set whenever a face property is changed on
+ − 42 a face. */
+ − 43
+ − 44 Lisp_Object foreground;
+ − 45 Lisp_Object background;
+ − 46 Lisp_Object font;
+ − 47
+ − 48 Lisp_Object display_table;
+ − 49 Lisp_Object background_pixmap;
+ − 50
+ − 51 Lisp_Object underline;
+ − 52 Lisp_Object strikethru;
+ − 53 Lisp_Object highlight;
+ − 54 Lisp_Object dim;
+ − 55 Lisp_Object blinking;
+ − 56 Lisp_Object reverse;
+ − 57
+ − 58 Lisp_Object plist;
+ − 59
+ − 60 Lisp_Object charsets_warned_about;
+ − 61 };
+ − 62
+ − 63 /*
+ − 64
+ − 65 A face cache element caches the results of instantiating the
+ − 66 properties of a face in a particular window. (Instantiation can
+ − 67 take a long time so this is very important.) Each window contains
+ − 68 an array of face cache elements (called the "face cache"), one for
+ − 69 each face that has been seen in the window so far.
+ − 70
+ − 71 Some tricky stuff is done to make sure the face cache does not
+ − 72 become inconsistent:
+ − 73
+ − 74 1) Switching buffers in a window clears the face cache for that
+ − 75 window, because this can change the way any property is
+ − 76 instantiated in the window.
+ − 77 2) Setting a face property causes that face to be marked as
+ − 78 dirty. This causes various stuff to happen to make sure
+ − 79 the appropriate face cache elements are invalidated.
+ − 80 (#### Actually this doesn't work quite right, and errs
+ − 81 too much on the side of invalidating unnecessary stuff.)
+ − 82
+ − 83 There are also face cache elements for "merged faces", which are the
+ − 84 result of merging all the faces that overlap a particular buffer
+ − 85 position. The merging is always done in the context of a particular
+ − 86 domain (specifically, a window), and the face cache element is
+ − 87 specific to a particular window. (Face cache elements are contained
+ − 88 in an array that is attached to each struct_window.) The reason that
+ − 89 the merging takes place in the context of a particular window has
+ − 90 to do with the way the merging works:
+ − 91
+ − 92 1) All extents overlying the buffer position are sorted by descending
+ − 93 priority.
+ − 94 2) The property of a particular merged face comes from the highest-
+ − 95 priority face that specifies a value for that particular property.
+ − 96 3) The way to determine whether a face specifies a value for a
+ − 97 particular property is to instantiate that face's property in
+ − 98 the window in question with the no-fallback option set, to
+ − 99 see if we got anything.
+ − 100
+ − 101 For Mule, things get a bit trickier because there can be multiple
+ − 102 fonts per face/window combination -- the charset is an argument
+ − 103 to specifier-instance.
+ − 104
+ − 105 We have two possible data structure representations:
+ − 106
+ − 107 1) Keep the original "one font per face cache element" representation
+ − 108 and use a different face cache element for each charset.
+ − 109 2) Allow multiple fonts to be in a single face cache element.
+ − 110
+ − 111 I've chosen to use (2) -- the data structure gets more complicated
+ − 112 but the algorithms for maintaining face cache elements end up
+ − 113 simpler.
+ − 114 */
+ − 115
+ − 116 #define NUM_STATIC_CACHEL_FACES 4
+ − 117
+ − 118 typedef struct face_cachel face_cachel;
+ − 119 struct face_cachel
+ − 120 {
3092
+ − 121 #ifdef NEW_GC
+ − 122 struct lrecord_header header;
3263
+ − 123 #endif /* NEW_GC */
428
+ − 124 /* There are two kinds of cachels; those created from a single face
+ − 125 and those created by merging more than one face. In the former
+ − 126 case, the FACE element specifies the face used. In the latter
+ − 127 case, the MERGED_FACES_STATIC and MERGED_FACES elements specify
+ − 128 the faces used for merging by giving the indices of the
+ − 129 corresponding single-face cachels.
+ − 130
+ − 131 Formerly we didn't bother to keep track of the faces used for
442
+ − 132 merging. We do now because we need to do so because there is no
428
+ − 133 other way to properly handle multiple charsets for Mule in the
+ − 134 presence of display tables short of always computing the values
+ − 135 for all charsets, which is very expensive. Instead, we use a
+ − 136 lazy scheme where we only compute the font for a particular charset
+ − 137 when it is needed. (The exception is the font for the ASCII charset.
+ − 138 We always compute it, just like the other attributes, because
+ − 139 many places in the C code refer to the font of the ASCII charset
+ − 140 and expect it to always be there.)
+ − 141
+ − 142 We store the first four faces in a static array, and use a
+ − 143 Dynarr for the rest. This has the advantage that the space used
+ − 144 is small but the Dynarr will almost never be created, so we
+ − 145 won't spend much time in malloc()/free().
+ − 146
+ − 147 The order of the faces here is decreasing extent priority. */
+ − 148 Lisp_Object face;
+ − 149 int merged_faces_static[NUM_STATIC_CACHEL_FACES];
+ − 150 int_dynarr *merged_faces;
+ − 151 int nfaces;
+ − 152
+ − 153 /* The values stored here are computed by calling specifier_instance()
+ − 154 on the appropriate specifiers. This means that we will have either
+ − 155 a value computed from the face itself or a value computed from the
+ − 156 default face. We need to distinguish the two so that merging works
+ − 157 properly -- a value that comes from the default face is treated
+ − 158 as "unspecified" during merging and is overridden by lower-priority
+ − 159 faces. This is what the _specified flags below are for. */
+ − 160
+ − 161 Lisp_Object foreground;
+ − 162 Lisp_Object background;
771
+ − 163 /* There are currently 128 or 129 possible charsets under Mule. For the
428
+ − 164 moment we just take the easy way out and allocate space for each
+ − 165 of them. This avoids messing with Dynarrs.
+ − 166
+ − 167 #### We should look into this and probably clean it up
3094
+ − 168 to use Dynarrs. This may be a big space hog as is.
+ − 169 sjt sez: doesn't look like it, my total face cache is 170KB.
+ − 170 Could be reduced to maybe 50KB. */
428
+ − 171 Lisp_Object font[NUM_LEADING_BYTES];
+ − 172
+ − 173 Lisp_Object display_table;
+ − 174 Lisp_Object background_pixmap;
+ − 175
+ − 176 unsigned int underline :1;
+ − 177 unsigned int strikethru :1;
+ − 178 unsigned int highlight :1;
+ − 179 unsigned int dim :1;
+ − 180 unsigned int blinking :1;
+ − 181 unsigned int reverse :1;
+ − 182
+ − 183 /* Used when merging to tell if the above field represents an actual
+ − 184 value of this face or a fallback value. */
3659
+ − 185 DECLARE_INLINE_LISP_BIT_VECTOR(NUM_LEADING_BYTES) font_specified;
+ − 186
428
+ − 187 unsigned int foreground_specified :1;
+ − 188 unsigned int background_specified :1;
+ − 189 unsigned int display_table_specified :1;
+ − 190 unsigned int background_pixmap_specified :1;
+ − 191
+ − 192 unsigned int strikethru_specified :1;
+ − 193 unsigned int underline_specified :1;
+ − 194 unsigned int highlight_specified :1;
+ − 195 unsigned int dim_specified :1;
+ − 196 unsigned int blinking_specified :1;
+ − 197 unsigned int reverse_specified :1;
+ − 198
+ − 199 /* The updated flag is set after we calculate the values for the
+ − 200 face cachel and cleared whenever a face changes, to indicate
+ − 201 that the values stored here might be wrong. The next time
+ − 202 we go to access the values, we recompute them; if any values
+ − 203 change, we set the DIRTY flag, which tells the output routines
+ − 204 that a face value has in fact changed and the sections of text
+ − 205 using this face need to be redrawn.
+ − 206
+ − 207 It is trickier with fonts because we don't automatically
+ − 208 recompute the fonts but do it only when it is necessary.
+ − 209 (The ASCII font is an exception, of course; see above).
+ − 210
+ − 211 In the case of fonts, we maintain a separate updated flag
+ − 212 for each font. Whenever we need to access the font for
+ − 213 a particular charset, we recalculate it if either its
+ − 214 value is Qunbound (meaning it's never been computed at all)
+ − 215 or the updated flag is not set. We set the dirty flag if
+ − 216 the value is not the same as before and the previous value
+ − 217 was not Qunbound.
+ − 218
+ − 219 #### Note that we don't yet deal with the case of the new
+ − 220 value being Qunbound, as could happen if no fonts of the
+ − 221 right sort are available on the system. In this case, the
+ − 222 whole program will just crash. For the moment, this is
+ − 223 OK (for debugging purposes) but we should fix this by
+ − 224 storing a "blank font" if the instantiation fails. */
+ − 225 unsigned int dirty :1;
+ − 226 unsigned int updated :1;
3659
+ − 227
+ − 228 DECLARE_INLINE_LISP_BIT_VECTOR(NUM_LEADING_BYTES) font_updated;
+ − 229
+ − 230 /* Whether the font for the charset in question was determined in the
+ − 231 "final stage"; that is, the last stage Lisp code could specify it,
+ − 232 after the initial stage and before the fallback. */
+ − 233 DECLARE_INLINE_LISP_BIT_VECTOR(NUM_LEADING_BYTES) font_final_stage;
428
+ − 234 };
+ − 235
3092
+ − 236 #ifdef NEW_GC
+ − 237 typedef struct face_cachel Lisp_Face_Cachel;
+ − 238
+ − 239 DECLARE_LRECORD (face_cachel, Lisp_Face_Cachel);
+ − 240
+ − 241 #define XFACE_CACHEL(x) \
+ − 242 XRECORD (x, face_cachel, Lisp_Face_Cachel)
+ − 243 #define wrap_face_cachel(p) wrap_record (p, face_cachel)
+ − 244 #define FACE_CACHEL_P(x) RECORDP (x, face_cachel)
+ − 245 #define CHECK_FACE_CACHEL(x) CHECK_RECORD (x, face_cachel)
+ − 246 #define CONCHECK_FACE_CACHEL(x) CONCHECK_RECORD (x, face_cachel)
+ − 247 #endif /* NEW_GC */
+ − 248
440
+ − 249 DECLARE_LRECORD (face, Lisp_Face);
+ − 250 #define XFACE(x) XRECORD (x, face, Lisp_Face)
617
+ − 251 #define wrap_face(p) wrap_record (p, face)
428
+ − 252 #define FACEP(x) RECORDP (x, face)
+ − 253 #define CHECK_FACE(x) CHECK_RECORD (x, face)
+ − 254
+ − 255 Lisp_Object ensure_face_cachel_contains_charset (struct face_cachel *cachel,
+ − 256 Lisp_Object domain,
+ − 257 Lisp_Object charset);
+ − 258 void ensure_face_cachel_complete (struct face_cachel *cachel,
+ − 259 Lisp_Object domain,
+ − 260 unsigned char *charsets);
+ − 261 void update_face_cachel_data (struct face_cachel *cachel,
+ − 262 Lisp_Object domain,
+ − 263 Lisp_Object face);
+ − 264 void face_cachel_charset_font_metric_info (struct face_cachel *cachel,
+ − 265 unsigned char *charsets,
+ − 266 struct font_metric_info *fm);
+ − 267 void mark_face_cachels (face_cachel_dynarr *elements);
+ − 268 void mark_face_cachels_as_clean (struct window *w);
+ − 269 void mark_face_cachels_as_not_updated (struct window *w);
+ − 270 void reset_face_cachel (struct face_cachel *inst);
+ − 271 void reset_face_cachels (struct window *w);
+ − 272 face_index get_builtin_face_cache_index (struct window *w,
+ − 273 Lisp_Object face);
3094
+ − 274 /* WARNING: this interface may change. */
+ − 275 face_index merge_face_list_to_cache_index (struct window *w,
+ − 276 Lisp_Object *face_list, int count);
+ − 277
428
+ − 278 #ifdef MEMORY_USAGE_STATS
+ − 279 int compute_face_cachel_usage (face_cachel_dynarr *face_cachels,
+ − 280 struct overhead_stats *ovstats);
+ − 281 #endif /* MEMORY_USAGE_STATS */
+ − 282
+ − 283 EXFUN (Fface_name, 1);
+ − 284 EXFUN (Ffind_face, 1);
+ − 285 EXFUN (Fget_face, 1);
+ − 286
+ − 287 extern Lisp_Object Qstrikethru, Vbuilt_in_face_specifiers, Vdefault_face;
+ − 288 extern Lisp_Object Vleft_margin_face, Vpointer_face, Vright_margin_face;
432
+ − 289 extern Lisp_Object Vtext_cursor_face, Vvertical_divider_face;
428
+ − 290 extern Lisp_Object Vtoolbar_face, Vgui_element_face, Vwidget_face;
+ − 291
+ − 292 void mark_all_faces_as_clean (void);
+ − 293 void init_frame_faces (struct frame *f);
+ − 294 void init_device_faces (struct device *d);
+ − 295 void init_global_faces (struct device *d);
+ − 296 face_index get_extent_fragment_face_cache_index (struct window *w,
+ − 297 struct extent_fragment *ef);
+ − 298 void update_frame_face_values (struct frame *f);
+ − 299 void face_property_was_changed (Lisp_Object face, Lisp_Object property,
+ − 300 Lisp_Object locale);
+ − 301 void default_face_font_info (Lisp_Object domain, int *ascent,
+ − 302 int *descent, int *height, int *width,
+ − 303 int *proportional_p);
+ − 304 void default_face_height_and_width (Lisp_Object domain,
+ − 305 int *height, int *width);
+ − 306 void default_face_height_and_width_1 (Lisp_Object domain,
+ − 307 int *height, int *width);
+ − 308
+ − 309 #define FACE_CACHEL_FONT(cachel, charset) \
771
+ − 310 (cachel->font[XCHARSET_LEADING_BYTE (charset) - MIN_LEADING_BYTE])
428
+ − 311
3659
+ − 312 #define FACE_CACHEL_FONT_UPDATED(x) \
+ − 313 ((struct Lisp_Bit_Vector *)(&((x)->font_updated)))
+ − 314 #define FACE_CACHEL_FONT_SPECIFIED(x) \
+ − 315 ((struct Lisp_Bit_Vector *)(&((x)->font_specified)))
+ − 316 #define FACE_CACHEL_FONT_FINAL_STAGE(x) \
+ − 317 ((struct Lisp_Bit_Vector *)(&((x)->font_final_stage)))
+ − 318
428
+ − 319 #define WINDOW_FACE_CACHEL(window, index) \
+ − 320 Dynarr_atp ((window)->face_cachels, index)
+ − 321
+ − 322 #define FACE_CACHEL_FINDEX_UNSAFE(cachel, offset) \
+ − 323 ((offset) < NUM_STATIC_CACHEL_FACES \
+ − 324 ? (cachel)->merged_faces_static[offset] \
+ − 325 : Dynarr_at ((cachel)->merged_faces, (offset) - NUM_STATIC_CACHEL_FACES))
+ − 326
+ − 327 #define WINDOW_FACE_CACHEL_FACE(window, index) \
+ − 328 (WINDOW_FACE_CACHEL (window, index)->face)
+ − 329 #define WINDOW_FACE_CACHEL_FOREGROUND(window, index) \
+ − 330 (WINDOW_FACE_CACHEL (window, index)->foreground)
+ − 331 #define WINDOW_FACE_CACHEL_BACKGROUND(window, index) \
+ − 332 (WINDOW_FACE_CACHEL (window, index)->background)
+ − 333 /* #### This can be referenced by various functions,
+ − 334 but face_cachels isn't initialized for the stream device.
+ − 335 Since it doesn't need the value we just return nil here to avoid
+ − 336 blowing up in multiple places. */
+ − 337 #define WINDOW_FACE_CACHEL_FONT(window, index, charset) \
+ − 338 ((window)->face_cachels \
+ − 339 ? FACE_CACHEL_FONT (WINDOW_FACE_CACHEL (window, index), charset) \
+ − 340 : Qnil)
+ − 341 #define WINDOW_FACE_CACHEL_DISPLAY_TABLE(window, index) \
+ − 342 (WINDOW_FACE_CACHEL (window, index)->display_table)
+ − 343 #define WINDOW_FACE_CACHEL_BACKGROUND_PIXMAP(window, index) \
+ − 344 (WINDOW_FACE_CACHEL (window, index)->background_pixmap)
+ − 345 #define WINDOW_FACE_CACHEL_DIRTY(window, index) \
+ − 346 (WINDOW_FACE_CACHEL (window, index)->dirty)
+ − 347 #define WINDOW_FACE_CACHEL_UNDERLINE_P(window, index) \
+ − 348 (WINDOW_FACE_CACHEL (window, index)->underline)
+ − 349 #define WINDOW_FACE_CACHEL_HIGHLIGHT_P(window, index) \
+ − 350 (WINDOW_FACE_CACHEL (window, index)->highlight)
+ − 351 #define WINDOW_FACE_CACHEL_DIM_P(window, index) \
+ − 352 (WINDOW_FACE_CACHEL (window, index)->dim)
+ − 353 #define WINDOW_FACE_CACHEL_BLINKING_P(window, index) \
+ − 354 (WINDOW_FACE_CACHEL (window, index)->blinking)
+ − 355 #define WINDOW_FACE_CACHEL_REVERSE_P(window, index) \
+ − 356 (WINDOW_FACE_CACHEL (window, index)->reverse)
+ − 357
+ − 358 #define FACE_PROPERTY_SPECIFIER(face, property) Fget (face, property, Qnil)
+ − 359
+ − 360 #define FACE_PROPERTY_INSTANCE_1(face, property, domain, errb, no_fallback, depth) \
+ − 361 specifier_instance (FACE_PROPERTY_SPECIFIER (face, property), Qunbound, \
+ − 362 domain, errb, 1, no_fallback, depth)
+ − 363
+ − 364 #define FACE_PROPERTY_INSTANCE(face, property, domain, no_fallback, depth) \
793
+ − 365 FACE_PROPERTY_INSTANCE_1 (face, property, domain, ERROR_ME_DEBUG_WARN, \
428
+ − 366 no_fallback, depth)
+ − 367
3659
+ − 368 Lisp_Object face_property_matching_instance
+ − 369 (Lisp_Object face,
+ − 370 Lisp_Object property,
+ − 371 Lisp_Object charset,
+ − 372 Lisp_Object domain,
+ − 373 Error_Behavior errb,
+ − 374 int no_fallback,
+ − 375 Lisp_Object depth,
+ − 376 enum font_specifier_matchspec_stages stages);
428
+ − 377
+ − 378 #define FACE_PROPERTY_SPEC_LIST(face, property, locale) \
+ − 379 Fspecifier_spec_list (FACE_PROPERTY_SPECIFIER (face, property), \
+ − 380 locale, Qnil, Qnil)
498
+ − 381 #define SET_FACE_PROPERTY(face, property, value, locale, tag, how_to_add) \
428
+ − 382 Fadd_spec_to_specifier (FACE_PROPERTY_SPECIFIER (face, property), \
498
+ − 383 value, locale, tag, how_to_add)
428
+ − 384
+ − 385 #define FACE_FOREGROUND(face, domain) \
+ − 386 FACE_PROPERTY_INSTANCE (face, Qforeground, domain, 0, Qzero)
+ − 387 #define FACE_BACKGROUND(face, domain) \
+ − 388 FACE_PROPERTY_INSTANCE (face, Qbackground, domain, 0, Qzero)
3676
+ − 389
+ − 390 /* Calling this function on the default face with the ASCII character set
+ − 391 may delete any X11 frames; see the code at the end of
+ − 392 x_find_charset_font. */
428
+ − 393 #define FACE_FONT(face, domain, charset) \
+ − 394 face_property_matching_instance (face, Qfont, charset, domain, \
3659
+ − 395 ERROR_ME_DEBUG_WARN, 0, Qzero, \
+ − 396 initial)
428
+ − 397 #define FACE_DISPLAY_TABLE(face, domain) \
+ − 398 FACE_PROPERTY_INSTANCE (face, Qdisplay_table, domain, 0, Qzero)
+ − 399 #define FACE_BACKGROUND_PIXMAP(face, domain) \
+ − 400 FACE_PROPERTY_INSTANCE (face, Qbackground_pixmap, domain, 0, Qzero)
+ − 401 #define FACE_UNDERLINE_P(face, domain) \
+ − 402 (!NILP (FACE_PROPERTY_INSTANCE (face, Qunderline, domain, 0, Qzero)))
440
+ − 403 #define FACE_STRIKETHRU_P(face, domain) \
+ − 404 (!NILP (FACE_PROPERTY_INSTANCE (face, Qstrikethru, domain, 0, Qzero)))
428
+ − 405 #define FACE_HIGHLIGHT_P(face, domain) \
+ − 406 (!NILP (FACE_PROPERTY_INSTANCE (face, Qhighlight, domain, 0, Qzero)))
+ − 407 #define FACE_DIM_P(face, domain) \
+ − 408 (!NILP (FACE_PROPERTY_INSTANCE (face, Qdim, domain, 0, Qzero)))
+ − 409 #define FACE_BLINKING_P(face, domain) \
+ − 410 (!NILP (FACE_PROPERTY_INSTANCE (face, Qblinking, domain, 0, Qzero)))
+ − 411 #define FACE_REVERSE_P(face, domain) \
+ − 412 (!NILP (FACE_PROPERTY_INSTANCE (face, Qreverse, domain, 0, Qzero)))
+ − 413
440
+ − 414 #endif /* INCLUDED_faces_h_ */