diff options
| author | Richard M. Stallman | 1994-10-14 05:19:13 +0000 |
|---|---|---|
| committer | Richard M. Stallman | 1994-10-14 05:19:13 +0000 |
| commit | 42120bc769f1cd7335ed5070a9c70b40da7335b3 (patch) | |
| tree | e2406a43584f358c616f1fbb2666143622f49d68 /src | |
| parent | 8e3d10a98706b7d70c1d55a5052c0a69536988db (diff) | |
| download | emacs-42120bc769f1cd7335ed5070a9c70b40da7335b3.tar.gz emacs-42120bc769f1cd7335ed5070a9c70b40da7335b3.zip | |
Eliminate the "display faces"; store GCs in the "computed faces".
(face_vector, nfaces, nfaces_allocated): Vars deleted.
(free_frame_faces): Free GCs in the computed faces.
Free the computed faces themselves.
(clear_face_cache): Renamed from clear_face_vector
and completely rewritten to free GCs in the computed faces.
(get_cached_face): Function deleted.
(build_face): Function deleted; code moved into intern_face.
(intern_face): Don't treat default and modeline faces specially.
(recompute_basic_faces): Call intern_face, not build_face.
(intern_face, clear_face_vector, load_font, unload_font)
(load_color, free_frame_faces, recompute_basic_faces): Use FRAME_X_DISPLAY.
Diffstat (limited to 'src')
| -rw-r--r-- | src/xfaces.c | 237 |
1 files changed, 71 insertions, 166 deletions
diff --git a/src/xfaces.c b/src/xfaces.c index a96085ee2ba..250732aaefe 100644 --- a/src/xfaces.c +++ b/src/xfaces.c | |||
| @@ -106,12 +106,12 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ | |||
| 106 | characters. Elements 0 and 1 of computed_faces always describe the | 106 | characters. Elements 0 and 1 of computed_faces always describe the |
| 107 | default and mode-line faces. | 107 | default and mode-line faces. |
| 108 | 108 | ||
| 109 | Elements 0 and 1 of computed_faces have GC's; all the other faces | 109 | Computed faces have graphics contexts some of the time. |
| 110 | in computed_faces do not. The global array face_vector contains | 110 | intern_face builds a GC for a specified computed face |
| 111 | faces with their GC's set. Given a computed_face, the function | 111 | if it doesn't have one already. |
| 112 | intern_face finds (or adds) an element of face_vector with | 112 | clear_face_cache clears out the GCs of all computed faces. |
| 113 | equivalent parameters, and returns a pointer to that face, whose GC | 113 | This is done from time to time so that we don't hold on to |
| 114 | can then be used for display. | 114 | lots of GCs that are no longer needed. |
| 115 | 115 | ||
| 116 | Constraints: | 116 | Constraints: |
| 117 | 117 | ||
| @@ -132,35 +132,10 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ | |||
| 132 | to be valid on all frames. If they were the same array, then that | 132 | to be valid on all frames. If they were the same array, then that |
| 133 | array would grow very large on all frames, because any facial | 133 | array would grow very large on all frames, because any facial |
| 134 | combination displayed on any frame would need to be a valid entry | 134 | combination displayed on any frame would need to be a valid entry |
| 135 | on all frames. | 135 | on all frames. */ |
| 136 | |||
| 137 | Since face_vector is just a cache --- there are no pointers into it | ||
| 138 | from the rest of the code, and everyone accesses it through | ||
| 139 | intern_face --- we could just free its GC's and throw the whole | ||
| 140 | thing away without breaking anything. This gives us a simple way | ||
| 141 | to garbage-collect old GC's nobody's using any more - we can just | ||
| 142 | purge face_vector, and then let subsequent calls to intern_face | ||
| 143 | refill it as needed. The function clear_face_vector performs this | ||
| 144 | purge. | ||
| 145 | |||
| 146 | We're often applying intern_face to faces in computed_faces - | ||
| 147 | for example, we do this while sending GLYPHs from a struct | ||
| 148 | frame_glyphs to X during redisplay. It would be nice to avoid | ||
| 149 | searching all of face_vector every time we intern a frame's face. | ||
| 150 | So, when intern_face finds a match for FACE in face_vector, it | ||
| 151 | stores the index of the match in FACE's cached_index member, and | ||
| 152 | checks there first next time. */ | ||
| 153 | |||
| 154 | 136 | ||
| 155 | /* Definitions and declarations. */ | 137 | /* Definitions and declarations. */ |
| 156 | 138 | ||
| 157 | /* A table of display faces. */ | ||
| 158 | static struct face **face_vector; | ||
| 159 | /* The length in use of the table. */ | ||
| 160 | static int nfaces; | ||
| 161 | /* The allocated length of the table. */ | ||
| 162 | static int nfaces_allocated; | ||
| 163 | |||
| 164 | /* The number of face-id's in use (same for all frames). */ | 139 | /* The number of face-id's in use (same for all frames). */ |
| 165 | int next_face_id; | 140 | int next_face_id; |
| 166 | 141 | ||
| @@ -173,7 +148,6 @@ int region_face; | |||
| 173 | 148 | ||
| 174 | Lisp_Object Qface, Qmouse_face; | 149 | Lisp_Object Qface, Qmouse_face; |
| 175 | 150 | ||
| 176 | static void build_face ( /* FRAME_PTR, struct face * */ ); | ||
| 177 | int face_name_id_number ( /* FRAME_PTR, Lisp_Object name */ ); | 151 | int face_name_id_number ( /* FRAME_PTR, Lisp_Object name */ ); |
| 178 | 152 | ||
| 179 | struct face *intern_face ( /* FRAME_PTR, struct face * */ ); | 153 | struct face *intern_face ( /* FRAME_PTR, struct face * */ ); |
| @@ -224,134 +198,22 @@ face_eql (face1, face2) | |||
| 224 | && face1->underline == face2->underline); | 198 | && face1->underline == face2->underline); |
| 225 | } | 199 | } |
| 226 | 200 | ||
| 227 | /* Interning faces in the `face_vector' cache, and clearing that cache. */ | 201 | /* Managing graphics contexts of faces. */ |
| 228 | 202 | ||
| 229 | /* Return the unique display face corresponding to the user-level face FACE. | 203 | /* Given a computed face, construct its graphics context if necessary. */ |
| 230 | If there isn't one, make one, and find a slot in the face_vector to | ||
| 231 | put it in. */ | ||
| 232 | static struct face * | ||
| 233 | get_cached_face (f, face) | ||
| 234 | struct frame *f; | ||
| 235 | struct face *face; | ||
| 236 | { | ||
| 237 | int i, empty = -1; | ||
| 238 | struct face *result; | ||
| 239 | |||
| 240 | /* Perhaps FACE->cached_index is valid; this could happen if FACE is | ||
| 241 | in a frame's face list. */ | ||
| 242 | if (face->cached_index >= 0 | ||
| 243 | && face->cached_index < nfaces | ||
| 244 | && face_eql (face_vector[face->cached_index], face)) | ||
| 245 | return face_vector[face->cached_index]; | ||
| 246 | |||
| 247 | /* Look for an existing display face that does the job. | ||
| 248 | Also find an empty slot if any. */ | ||
| 249 | for (i = 0; i < nfaces; i++) | ||
| 250 | { | ||
| 251 | if (face_eql (face_vector[i], face)) | ||
| 252 | { | ||
| 253 | face->cached_index = i; | ||
| 254 | return face_vector[i]; | ||
| 255 | } | ||
| 256 | if (face_vector[i] == 0) | ||
| 257 | empty = i; | ||
| 258 | } | ||
| 259 | |||
| 260 | /* If no empty slots, make one. */ | ||
| 261 | if (empty < 0 && nfaces == nfaces_allocated) | ||
| 262 | { | ||
| 263 | int newsize = nfaces + 20; | ||
| 264 | face_vector | ||
| 265 | = (struct face **) xrealloc (face_vector, | ||
| 266 | newsize * sizeof (struct face *)); | ||
| 267 | nfaces_allocated = newsize; | ||
| 268 | } | ||
| 269 | |||
| 270 | if (empty < 0) | ||
| 271 | empty = nfaces++; | ||
| 272 | |||
| 273 | /* Put a new display face in the empty slot. */ | ||
| 274 | result = copy_face (face); | ||
| 275 | face_vector[empty] = result; | ||
| 276 | |||
| 277 | /* Make a graphics context for it. */ | ||
| 278 | build_face (f, result); | ||
| 279 | |||
| 280 | face->cached_index = empty; | ||
| 281 | return result; | ||
| 282 | } | ||
| 283 | |||
| 284 | /* Given a computed face, return an equivalent display face | ||
| 285 | (one which has a graphics context). */ | ||
| 286 | 204 | ||
| 287 | struct face * | 205 | struct face * |
| 288 | intern_face (f, face) | 206 | intern_face (f, face) |
| 289 | struct frame *f; | 207 | struct frame *f; |
| 290 | struct face *face; | 208 | struct face *face; |
| 291 | { | 209 | { |
| 292 | /* If it's equivalent to the default face, use that. */ | ||
| 293 | if (face_eql (face, FRAME_DEFAULT_FACE (f))) | ||
| 294 | { | ||
| 295 | if (!FRAME_DEFAULT_FACE (f)->gc) | ||
| 296 | build_face (f, FRAME_DEFAULT_FACE (f)); | ||
| 297 | return FRAME_DEFAULT_FACE (f); | ||
| 298 | } | ||
| 299 | |||
| 300 | /* If it's equivalent to the mode line face, use that. */ | ||
| 301 | if (face_eql (face, FRAME_MODE_LINE_FACE (f))) | ||
| 302 | { | ||
| 303 | if (!FRAME_MODE_LINE_FACE (f)->gc) | ||
| 304 | build_face (f, FRAME_MODE_LINE_FACE (f)); | ||
| 305 | return FRAME_MODE_LINE_FACE (f); | ||
| 306 | } | ||
| 307 | |||
| 308 | /* If it's not one of the frame's default faces, it shouldn't have a GC. */ | ||
| 309 | if (face->gc) | ||
| 310 | abort (); | ||
| 311 | |||
| 312 | /* Get a specialized display face. */ | ||
| 313 | return get_cached_face (f, face); | ||
| 314 | } | ||
| 315 | |||
| 316 | /* Clear out face_vector and start anew. | ||
| 317 | This should be done from time to time just to avoid | ||
| 318 | keeping too many graphics contexts in face_vector | ||
| 319 | that are no longer needed. */ | ||
| 320 | |||
| 321 | void | ||
| 322 | clear_face_vector () | ||
| 323 | { | ||
| 324 | Lisp_Object rest; | ||
| 325 | Display *dpy = x_current_display; | ||
| 326 | int i; | ||
| 327 | |||
| 328 | BLOCK_INPUT; | ||
| 329 | /* Free the display faces in the face_vector. */ | ||
| 330 | for (i = 0; i < nfaces; i++) | ||
| 331 | { | ||
| 332 | struct face *face = face_vector[i]; | ||
| 333 | if (face->gc) | ||
| 334 | XFreeGC (dpy, face->gc); | ||
| 335 | xfree (face); | ||
| 336 | } | ||
| 337 | nfaces = 0; | ||
| 338 | |||
| 339 | UNBLOCK_INPUT; | ||
| 340 | } | ||
| 341 | |||
| 342 | /* Allocating and freeing X resources for display faces. */ | ||
| 343 | |||
| 344 | /* Make a graphics context for face FACE, which is on frame F, | ||
| 345 | if that can be done. */ | ||
| 346 | static void | ||
| 347 | build_face (f, face) | ||
| 348 | struct frame *f; | ||
| 349 | struct face *face; | ||
| 350 | { | ||
| 351 | GC gc; | 210 | GC gc; |
| 352 | XGCValues xgcv; | 211 | XGCValues xgcv; |
| 353 | unsigned long mask; | 212 | unsigned long mask; |
| 354 | 213 | ||
| 214 | if (face->gc) | ||
| 215 | return face; | ||
| 216 | |||
| 355 | BLOCK_INPUT; | 217 | BLOCK_INPUT; |
| 356 | 218 | ||
| 357 | if (face->foreground != FACE_DEFAULT) | 219 | if (face->foreground != FACE_DEFAULT) |
| @@ -372,19 +234,53 @@ build_face (f, face) | |||
| 372 | xgcv.graphics_exposures = 0; | 234 | xgcv.graphics_exposures = 0; |
| 373 | 235 | ||
| 374 | mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures; | 236 | mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures; |
| 375 | gc = XCreateGC (x_current_display, FRAME_X_WINDOW (f), | 237 | gc = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), |
| 376 | mask, &xgcv); | 238 | mask, &xgcv); |
| 377 | 239 | ||
| 378 | #if 0 | 240 | #if 0 |
| 379 | if (face->stipple && face->stipple != FACE_DEFAULT) | 241 | if (face->stipple && face->stipple != FACE_DEFAULT) |
| 380 | XSetStipple (x_current_display, gc, face->stipple); | 242 | XSetStipple (FRAME_X_DISPLAY (f), gc, face->stipple); |
| 381 | #endif | 243 | #endif |
| 382 | 244 | ||
| 383 | face->gc = gc; | 245 | face->gc = gc; |
| 384 | 246 | ||
| 385 | UNBLOCK_INPUT; | 247 | UNBLOCK_INPUT; |
| 248 | |||
| 249 | return face; | ||
| 386 | } | 250 | } |
| 387 | 251 | ||
| 252 | /* Clear out all graphics contexts for all computed faces | ||
| 253 | except for the default and mode line faces. | ||
| 254 | This should be done from time to time just to avoid | ||
| 255 | keeping too many graphics contexts that are no longer needed. */ | ||
| 256 | |||
| 257 | void | ||
| 258 | clear_face_cache () | ||
| 259 | { | ||
| 260 | Lisp_Object tail, frame; | ||
| 261 | |||
| 262 | BLOCK_INPUT; | ||
| 263 | FOR_EACH_FRAME (tail, frame) | ||
| 264 | { | ||
| 265 | FRAME_PTR f = XFRAME (frame); | ||
| 266 | if (FRAME_X_P (f)) | ||
| 267 | { | ||
| 268 | int i; | ||
| 269 | Display *dpy = FRAME_X_DISPLAY (f); | ||
| 270 | |||
| 271 | for (i = 2; i < FRAME_N_COMPUTED_FACES (f); i++) | ||
| 272 | { | ||
| 273 | struct face *face = FRAME_COMPUTED_FACES (f) [i]; | ||
| 274 | if (face->gc) | ||
| 275 | XFreeGC (dpy, face->gc); | ||
| 276 | face->gc = 0; | ||
| 277 | } | ||
| 278 | } | ||
| 279 | } | ||
| 280 | |||
| 281 | UNBLOCK_INPUT; | ||
| 282 | } | ||
| 283 | |||
| 388 | /* Allocating, freeing, and duplicating fonts, colors, and pixmaps. */ | 284 | /* Allocating, freeing, and duplicating fonts, colors, and pixmaps. */ |
| 389 | 285 | ||
| 390 | static XFontStruct * | 286 | static XFontStruct * |
| @@ -399,7 +295,7 @@ load_font (f, name) | |||
| 399 | 295 | ||
| 400 | CHECK_STRING (name, 0); | 296 | CHECK_STRING (name, 0); |
| 401 | BLOCK_INPUT; | 297 | BLOCK_INPUT; |
| 402 | font = XLoadQueryFont (x_current_display, (char *) XSTRING (name)->data); | 298 | font = XLoadQueryFont (FRAME_X_DISPLAY (f), (char *) XSTRING (name)->data); |
| 403 | UNBLOCK_INPUT; | 299 | UNBLOCK_INPUT; |
| 404 | 300 | ||
| 405 | if (! font) | 301 | if (! font) |
| @@ -417,7 +313,7 @@ unload_font (f, font) | |||
| 417 | return; | 313 | return; |
| 418 | 314 | ||
| 419 | BLOCK_INPUT; | 315 | BLOCK_INPUT; |
| 420 | XFreeFont (x_current_display, font); | 316 | XFreeFont (FRAME_X_DISPLAY (f), font); |
| 421 | UNBLOCK_INPUT; | 317 | UNBLOCK_INPUT; |
| 422 | } | 318 | } |
| 423 | 319 | ||
| @@ -426,7 +322,7 @@ load_color (f, name) | |||
| 426 | struct frame *f; | 322 | struct frame *f; |
| 427 | Lisp_Object name; | 323 | Lisp_Object name; |
| 428 | { | 324 | { |
| 429 | Display *dpy = x_current_display; | 325 | Display *dpy = FRAME_X_DISPLAY (f); |
| 430 | Colormap cmap; | 326 | Colormap cmap; |
| 431 | XColor color; | 327 | XColor color; |
| 432 | int result; | 328 | int result; |
| @@ -434,7 +330,7 @@ load_color (f, name) | |||
| 434 | if (NILP (name)) | 330 | if (NILP (name)) |
| 435 | return FACE_DEFAULT; | 331 | return FACE_DEFAULT; |
| 436 | 332 | ||
| 437 | cmap = DefaultColormapOfScreen (DefaultScreenOfDisplay (x_current_display)); | 333 | cmap = DefaultColormapOfScreen (DefaultScreenOfDisplay (dpy)); |
| 438 | 334 | ||
| 439 | CHECK_STRING (name, 0); | 335 | CHECK_STRING (name, 0); |
| 440 | BLOCK_INPUT; | 336 | BLOCK_INPUT; |
| @@ -465,12 +361,12 @@ unload_color (f, pixel) | |||
| 465 | we'll get the same pixel. */ | 361 | we'll get the same pixel. */ |
| 466 | #if 0 | 362 | #if 0 |
| 467 | Colormap cmap; | 363 | Colormap cmap; |
| 468 | Display *dpy = x_current_display; | 364 | Display *dpy = FRAME_X_DISPLAY (f); |
| 469 | if (pixel == FACE_DEFAULT | 365 | if (pixel == FACE_DEFAULT |
| 470 | || pixel == BLACK_PIX_DEFAULT | 366 | || pixel == BLACK_PIX_DEFAULT |
| 471 | || pixel == WHITE_PIX_DEFAULT) | 367 | || pixel == WHITE_PIX_DEFAULT) |
| 472 | return; | 368 | return; |
| 473 | cmap = DefaultColormapOfScreen (DefaultScreenOfDisplay (x_current_display)); | 369 | cmap = DefaultColormapOfScreen (DefaultScreenOfDisplay (dpy)); |
| 474 | BLOCK_INPUT; | 370 | BLOCK_INPUT; |
| 475 | XFreeColors (dpy, cmap, &pixel, 1, 0); | 371 | XFreeColors (dpy, cmap, &pixel, 1, 0); |
| 476 | UNBLOCK_INPUT; | 372 | UNBLOCK_INPUT; |
| @@ -529,7 +425,7 @@ void | |||
| 529 | free_frame_faces (f) | 425 | free_frame_faces (f) |
| 530 | struct frame *f; | 426 | struct frame *f; |
| 531 | { | 427 | { |
| 532 | Display *dpy = x_current_display; | 428 | Display *dpy = FRAME_X_DISPLAY (f); |
| 533 | int i; | 429 | int i; |
| 534 | 430 | ||
| 535 | BLOCK_INPUT; | 431 | BLOCK_INPUT; |
| @@ -539,8 +435,6 @@ free_frame_faces (f) | |||
| 539 | struct face *face = FRAME_PARAM_FACES (f) [i]; | 435 | struct face *face = FRAME_PARAM_FACES (f) [i]; |
| 540 | if (face) | 436 | if (face) |
| 541 | { | 437 | { |
| 542 | if (face->gc) | ||
| 543 | XFreeGC (dpy, face->gc); | ||
| 544 | unload_font (f, face->font); | 438 | unload_font (f, face->font); |
| 545 | unload_color (f, face->foreground); | 439 | unload_color (f, face->foreground); |
| 546 | unload_color (f, face->background); | 440 | unload_color (f, face->background); |
| @@ -555,7 +449,18 @@ free_frame_faces (f) | |||
| 555 | FRAME_N_PARAM_FACES (f) = 0; | 449 | FRAME_N_PARAM_FACES (f) = 0; |
| 556 | 450 | ||
| 557 | /* All faces in FRAME_COMPUTED_FACES use resources copied from | 451 | /* All faces in FRAME_COMPUTED_FACES use resources copied from |
| 558 | FRAME_PARAM_FACES; we can free them without fuss. */ | 452 | FRAME_PARAM_FACES; we can free them without fuss. |
| 453 | But we do free the GCs and the face objects themselves. */ | ||
| 454 | for (i = 0; i < FRAME_N_COMPUTED_FACES (f); i++) | ||
| 455 | { | ||
| 456 | struct face *face = FRAME_COMPUTED_FACES (f) [i]; | ||
| 457 | if (face) | ||
| 458 | { | ||
| 459 | if (face->gc) | ||
| 460 | XFreeGC (dpy, face->gc); | ||
| 461 | xfree (face); | ||
| 462 | } | ||
| 463 | } | ||
| 559 | xfree (FRAME_COMPUTED_FACES (f)); | 464 | xfree (FRAME_COMPUTED_FACES (f)); |
| 560 | FRAME_COMPUTED_FACES (f) = 0; | 465 | FRAME_COMPUTED_FACES (f) = 0; |
| 561 | FRAME_N_COMPUTED_FACES (f) = 0; | 466 | FRAME_N_COMPUTED_FACES (f) = 0; |
| @@ -971,9 +876,9 @@ recompute_basic_faces (f) | |||
| 971 | BLOCK_INPUT; | 876 | BLOCK_INPUT; |
| 972 | 877 | ||
| 973 | if (FRAME_DEFAULT_FACE (f)->gc) | 878 | if (FRAME_DEFAULT_FACE (f)->gc) |
| 974 | XFreeGC (x_current_display, FRAME_DEFAULT_FACE (f)->gc); | 879 | XFreeGC (FRAME_X_DISPLAY (f), FRAME_DEFAULT_FACE (f)->gc); |
| 975 | if (FRAME_MODE_LINE_FACE (f)->gc) | 880 | if (FRAME_MODE_LINE_FACE (f)->gc) |
| 976 | XFreeGC (x_current_display, FRAME_MODE_LINE_FACE (f)->gc); | 881 | XFreeGC (FRAME_X_DISPLAY (f), FRAME_MODE_LINE_FACE (f)->gc); |
| 977 | 882 | ||
| 978 | compute_base_face (f, FRAME_DEFAULT_FACE (f)); | 883 | compute_base_face (f, FRAME_DEFAULT_FACE (f)); |
| 979 | compute_base_face (f, FRAME_MODE_LINE_FACE (f)); | 884 | compute_base_face (f, FRAME_MODE_LINE_FACE (f)); |
| @@ -981,8 +886,8 @@ recompute_basic_faces (f) | |||
| 981 | merge_faces (FRAME_DEFAULT_PARAM_FACE (f), FRAME_DEFAULT_FACE (f)); | 886 | merge_faces (FRAME_DEFAULT_PARAM_FACE (f), FRAME_DEFAULT_FACE (f)); |
| 982 | merge_faces (FRAME_MODE_LINE_PARAM_FACE (f), FRAME_MODE_LINE_FACE (f)); | 887 | merge_faces (FRAME_MODE_LINE_PARAM_FACE (f), FRAME_MODE_LINE_FACE (f)); |
| 983 | 888 | ||
| 984 | build_face (f, FRAME_DEFAULT_FACE (f)); | 889 | intern_face (f, FRAME_DEFAULT_FACE (f)); |
| 985 | build_face (f, FRAME_MODE_LINE_FACE (f)); | 890 | intern_face (f, FRAME_MODE_LINE_FACE (f)); |
| 986 | 891 | ||
| 987 | UNBLOCK_INPUT; | 892 | UNBLOCK_INPUT; |
| 988 | } | 893 | } |