Mercurial > emacs
comparison src/xfaces.c @ 3074:96b4623fdeb3
* xterm.h: New section for declarations for xfaces.c.
(init_frame_faces, free_frame_faces, intern_face,
face_name_id_number, same_size_fonts, recompute_basic_faces,
compute_char_face, compute_glyph_face): Declare these here.
* xfaces.c (same_size_fonts): We can now remove this extern
declaration.
* xfns.c (face_name_id_number): Likewise.
* xterm.c (intern_face): Likewise.
* xfaces.c (build_face, unload_font, free_frame_faces): Don't
forget to block input while making X calls.
Treat faces as structures specifying modifications to the frame's
parameters, rather than things which need to specify a complete
set of parameters by themselves.
* xfaces.c (init_frame_faces): Don't set up the two frame display
faces by querying the GC - just leave all their fields blank, and
call recompute_basic_faces, letting build_face do the work of
consulting the frame when necessary.
(recompute_basic_faces): New function.
(compute_base_faces): New function for obtaining the "identity"
for compute_char_face and compute_glyph_face.
(compute_char_face, compute_glyph_face): Call it, instead of copying
FRAME_DEFAULT_FACE.
* xfns.c (x_make_gc): No need to call init_frame_faces here.
* xfaces.c (intern_frame_face): This can be static.
* dispextern.h (struct face): New field - `copy', to help us with
resource allocation.
* xfaces.c (free_frame_faces): Do free the first two faces; don't
free anything from a face that's a copy.
(intern_frame_face): Mark every face we intern as a copy; its
resources are actually a combination of the real faces.
(Fset_face_attribute_internal): No need to check if we're trying
to free one of the frame's GC's; they never enter into the
picture.
* xfns.c (Fx_list_fonts): New function.
(face_name_id_number): Add extern declaration for this.
* xfaces.c (face_name_id_number): Make this externally visible,
and make the FRAME argument a FRAME_PTR, not a Lisp_Object.
(compute_char_face): Call face_name_id_number properly.
author | Jim Blandy <jimb@redhat.com> |
---|---|
date | Tue, 25 May 1993 14:02:58 +0000 |
parents | fff06093b756 |
children | 564f748751ea |
comparison
equal
deleted
inserted
replaced
3073:905f9fda79b8 | 3074:96b4623fdeb3 |
---|---|
59 FONT, FOREGROUND, and BACKGROUND are strings naming the fonts and colors | 59 FONT, FOREGROUND, and BACKGROUND are strings naming the fonts and colors |
60 to use with the face, | 60 to use with the face, |
61 BACKGROUND-PIXMAP is the name of an x bitmap filename, which we don't | 61 BACKGROUND-PIXMAP is the name of an x bitmap filename, which we don't |
62 use right now, and | 62 use right now, and |
63 UNDERLINE-P is non-nil if the face should be underlined. | 63 UNDERLINE-P is non-nil if the face should be underlined. |
64 If any of these elements are nil, that allows the frame's parameters to | |
65 show through. | |
64 (lisp/faces.el maintains these association lists.) | 66 (lisp/faces.el maintains these association lists.) |
65 | 67 |
66 The frames' private alists hold the frame-local definitions for the | 68 The frames' private alists hold the frame-local definitions for the |
67 faces. The lisp variable global-face-data contains the global | 69 faces. The lisp variable global-face-data contains the global |
68 defaults for faces. (See lisp/faces.el for this too.) | 70 defaults for faces. (See lisp/faces.el for this too.) |
134 int next_face_id; | 136 int next_face_id; |
135 | 137 |
136 /* The number of the face to use to indicate the region. */ | 138 /* The number of the face to use to indicate the region. */ |
137 int region_face; | 139 int region_face; |
138 | 140 |
139 /* Return non-zero if FONT1 and FONT2 have the same size bounding box. | |
140 We assume that they're both character-cell fonts. */ | |
141 extern int same_size_fonts (); | |
142 | |
143 /* This is what appears in a slot in a face to signify that the face | 141 /* This is what appears in a slot in a face to signify that the face |
144 does not specify that display aspect. */ | 142 does not specify that display aspect. */ |
145 #define FACE_DEFAULT (~0) | 143 #define FACE_DEFAULT (~0) |
146 | 144 |
147 Lisp_Object Qface, Qwindow, Qpriority; | 145 Lisp_Object Qface, Qwindow, Qpriority; |
316 { | 314 { |
317 GC gc; | 315 GC gc; |
318 XGCValues xgcv; | 316 XGCValues xgcv; |
319 unsigned long mask; | 317 unsigned long mask; |
320 | 318 |
319 BLOCK_INPUT; | |
320 | |
321 if (face->foreground != FACE_DEFAULT) | 321 if (face->foreground != FACE_DEFAULT) |
322 xgcv.foreground = face->foreground; | 322 xgcv.foreground = face->foreground; |
323 else | 323 else |
324 xgcv. foreground = f->display.x->foreground_pixel; | 324 xgcv.foreground = f->display.x->foreground_pixel; |
325 | |
325 if (face->background != FACE_DEFAULT) | 326 if (face->background != FACE_DEFAULT) |
326 xgcv.background = face->background; | 327 xgcv.background = face->background; |
327 else | 328 else |
328 xgcv. background = f->display.x->background_pixel; | 329 xgcv.background = f->display.x->background_pixel; |
330 | |
329 if (face->font && (int) face->font != FACE_DEFAULT) | 331 if (face->font && (int) face->font != FACE_DEFAULT) |
330 xgcv.font = face->font->fid; | 332 xgcv.font = face->font->fid; |
331 else | 333 else |
332 xgcv.font = f->display.x->font->fid; | 334 xgcv.font = f->display.x->font->fid; |
335 | |
333 xgcv.graphics_exposures = 0; | 336 xgcv.graphics_exposures = 0; |
337 | |
334 mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures; | 338 mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures; |
335 gc = XCreateGC (x_current_display, FRAME_X_WINDOW (f), | 339 gc = XCreateGC (x_current_display, FRAME_X_WINDOW (f), |
336 mask, &xgcv); | 340 mask, &xgcv); |
341 | |
337 #if 0 | 342 #if 0 |
338 if (face->stipple && face->stipple != FACE_DEFAULT) | 343 if (face->stipple && face->stipple != FACE_DEFAULT) |
339 XSetStipple (x_current_display, gc, face->stipple); | 344 XSetStipple (x_current_display, gc, face->stipple); |
340 #endif | 345 #endif |
346 | |
341 face->gc = gc; | 347 face->gc = gc; |
348 | |
349 UNBLOCK_INPUT; | |
342 } | 350 } |
343 | 351 |
344 /* Allocating, freeing, and duplicating fonts, colors, and pixmaps. */ | 352 /* Allocating, freeing, and duplicating fonts, colors, and pixmaps. */ |
345 | 353 |
346 static XFontStruct * | 354 static XFontStruct * |
369 struct frame *f; | 377 struct frame *f; |
370 XFontStruct *font; | 378 XFontStruct *font; |
371 { | 379 { |
372 if (!font || font == ((XFontStruct *) FACE_DEFAULT)) | 380 if (!font || font == ((XFontStruct *) FACE_DEFAULT)) |
373 return; | 381 return; |
382 | |
383 BLOCK_INPUT; | |
374 XFreeFont (x_current_display, font); | 384 XFreeFont (x_current_display, font); |
385 UNBLOCK_INPUT; | |
375 } | 386 } |
376 | 387 |
377 static unsigned long | 388 static unsigned long |
378 load_color (f, name) | 389 load_color (f, name) |
379 struct frame *f; | 390 struct frame *f; |
430 #endif | 441 #endif |
431 } | 442 } |
432 | 443 |
433 /* Initializing face arrays for frames. */ | 444 /* Initializing face arrays for frames. */ |
434 | 445 |
435 /* Set up faces 0 and 1 based on the normal text and modeline GC's. | |
436 This gets called whenever the parameters stored in the frame itself | |
437 (i.e. font, background color, etcetera) change. | |
438 | |
439 Note that the first two faces just contain references to the | |
440 frame's own resources. We shouldn't free them. */ | |
441 void | 446 void |
442 init_frame_faces (f) | 447 init_frame_faces (f) |
443 struct frame *f; | 448 FRAME_PTR f; |
444 { | 449 { |
445 ensure_face_ready (f, 0); | 450 ensure_face_ready (f, 0); |
446 { | |
447 XGCValues gcv; | |
448 struct face *face = FRAME_FACES (f) [0]; | |
449 | |
450 XGetGCValues (x_current_display, f->display.x->normal_gc, | |
451 GCForeground | GCBackground | GCFont, &gcv); | |
452 face->gc = f->display.x->normal_gc; | |
453 face->foreground = gcv.foreground; | |
454 face->background = gcv.background; | |
455 face->font = f->display.x->font; | |
456 face->stipple = 0; | |
457 face->underline = 0; | |
458 } | |
459 | |
460 ensure_face_ready (f, 1); | 451 ensure_face_ready (f, 1); |
461 { | 452 |
462 XGCValues gcv; | 453 recompute_basic_faces (f); |
463 struct face *face = FRAME_FACES (f) [1]; | 454 } |
464 | 455 |
465 XGetGCValues (x_current_display, f->display.x->reverse_gc, | |
466 GCForeground | GCBackground | GCFont, &gcv); | |
467 face->gc = f->display.x->reverse_gc; | |
468 face->foreground = gcv.foreground; | |
469 face->background = gcv.background; | |
470 face->font = f->display.x->font; | |
471 face->stipple = 0; | |
472 face->underline = 0; | |
473 } | |
474 } | |
475 | 456 |
476 /* Called from Fdelete_frame. */ | 457 /* Called from Fdelete_frame. */ |
477 void | 458 void |
478 free_frame_faces (f) | 459 free_frame_faces (f) |
479 struct frame *f; | 460 struct frame *f; |
480 { | 461 { |
481 Display *dpy = x_current_display; | 462 Display *dpy = x_current_display; |
482 int i; | 463 int i; |
483 | 464 |
484 /* The first two faces on the frame are just made of resources which | 465 BLOCK_INPUT; |
485 we borrowed from the frame's GC's, so don't free them. Let | 466 |
486 them get freed by the x_destroy_window code. */ | 467 for (i = 0; i < FRAME_N_FACES (f); i++) |
487 for (i = 2; i < FRAME_N_FACES (f); i++) | |
488 { | 468 { |
489 struct face *face = FRAME_FACES (f) [i]; | 469 struct face *face = FRAME_FACES (f) [i]; |
490 if (! face) | 470 if (face) |
491 continue; | 471 { |
492 if (face->gc) | 472 if (face->gc) |
493 XFreeGC (dpy, face->gc); | 473 XFreeGC (dpy, face->gc); |
494 unload_font (f, face->font); | 474 if (! face->copy) |
495 unload_color (f, face->foreground); | 475 { |
496 unload_color (f, face->background); | 476 unload_font (f, face->font); |
477 unload_color (f, face->foreground); | |
478 unload_color (f, face->background); | |
497 #if 0 | 479 #if 0 |
498 unload_pixmap (f, face->stipple); | 480 unload_pixmap (f, face->stipple); |
499 #endif | 481 #endif |
500 xfree (face); | 482 } |
483 xfree (face); | |
484 } | |
501 } | 485 } |
502 xfree (FRAME_FACES (f)); | 486 xfree (FRAME_FACES (f)); |
503 FRAME_FACES (f) = 0; | 487 FRAME_FACES (f) = 0; |
504 FRAME_N_FACES (f) = 0; | 488 FRAME_N_FACES (f) = 0; |
489 | |
490 UNBLOCK_INPUT; | |
505 } | 491 } |
506 | 492 |
507 /* Interning faces in a frame's face array. */ | 493 /* Interning faces in a frame's face array. */ |
508 | 494 |
509 /* Find a match for NEW_FACE in a FRAME's face array, and add it if we don't | 495 /* Find a match for NEW_FACE in a FRAME's face array, and add it if we don't |
510 find one. */ | 496 find one. */ |
511 int | 497 static int |
512 intern_frame_face (frame, new_face) | 498 intern_frame_face (frame, new_face) |
513 struct frame *frame; | 499 struct frame *frame; |
514 struct face *new_face; | 500 struct face *new_face; |
515 { | 501 { |
516 int len = FRAME_N_FACES (frame); | 502 int len = FRAME_N_FACES (frame); |
528 /* We didn't find one; add a new one. */ | 514 /* We didn't find one; add a new one. */ |
529 i = next_face_id++; | 515 i = next_face_id++; |
530 | 516 |
531 ensure_face_ready (frame, i); | 517 ensure_face_ready (frame, i); |
532 bcopy (new_face, FRAME_FACES (frame)[i], sizeof (*new_face)); | 518 bcopy (new_face, FRAME_FACES (frame)[i], sizeof (*new_face)); |
519 FRAME_FACES (frame)[i]->copy = 1; | |
533 | 520 |
534 return i; | 521 return i; |
535 } | 522 } |
536 | 523 |
537 /* Make face id ID valid on frame F. */ | 524 /* Make face id ID valid on frame F. */ |
561 if (FRAME_FACES (f) [id] == 0) | 548 if (FRAME_FACES (f) [id] == 0) |
562 FRAME_FACES (f) [id] = allocate_face (); | 549 FRAME_FACES (f) [id] = allocate_face (); |
563 } | 550 } |
564 | 551 |
565 /* Computing faces appropriate for a given piece of text in a buffer. */ | 552 /* Computing faces appropriate for a given piece of text in a buffer. */ |
553 | |
554 /* Return non-zero if FONT1 and FONT2 have the same size bounding box. | |
555 We assume that they're both character-cell fonts. */ | |
556 int | |
557 same_size_fonts (font1, font2) | |
558 XFontStruct *font1, *font2; | |
559 { | |
560 XCharStruct *bounds1 = &font1->min_bounds; | |
561 XCharStruct *bounds2 = &font2->min_bounds; | |
562 | |
563 return (bounds1->width == bounds2->width | |
564 && bounds1->ascent == bounds2->ascent | |
565 && bounds1->descent == bounds2->descent); | |
566 } | |
566 | 567 |
567 /* Modify face TO by copying from FROM all properties which have | 568 /* Modify face TO by copying from FROM all properties which have |
568 nondefault settings. */ | 569 nondefault settings. */ |
569 static void | 570 static void |
570 merge_faces (from, to) | 571 merge_faces (from, to) |
582 to->stipple = from->stipple; | 583 to->stipple = from->stipple; |
583 if (from->underline) | 584 if (from->underline) |
584 to->underline = from->underline; | 585 to->underline = from->underline; |
585 } | 586 } |
586 | 587 |
588 /* Set up the basic set of facial parameters, based on the frame's | |
589 data; all faces are deltas applied to this. */ | |
590 static void | |
591 compute_base_face (f, face) | |
592 FRAME_PTR f; | |
593 struct face *face; | |
594 { | |
595 struct x_display *d = f->display.x; | |
596 | |
597 face->gc = 0; | |
598 face->foreground = d->foreground_pixel; | |
599 face->background = d->background_pixel; | |
600 face->font = d->font; | |
601 face->underline = 0; | |
602 } | |
603 | |
604 | |
587 struct sortvec | 605 struct sortvec |
588 { | 606 { |
589 Lisp_Object overlay; | 607 Lisp_Object overlay; |
590 int beg, end; | 608 int beg, end; |
591 int priority; | 609 int priority; |
678 /* Optimize the default case. */ | 696 /* Optimize the default case. */ |
679 if (noverlays == 0 && NILP (prop) | 697 if (noverlays == 0 && NILP (prop) |
680 && !(pos >= region_beg && pos < region_end)) | 698 && !(pos >= region_beg && pos < region_end)) |
681 return 0; | 699 return 0; |
682 | 700 |
683 bcopy (FRAME_DEFAULT_FACE (f), &face, sizeof (struct face)); | 701 compute_base_face (f, &face); |
684 face.gc = 0; | |
685 | 702 |
686 if (!NILP (prop)) | 703 if (!NILP (prop)) |
687 { | 704 { |
688 facecode = face_name_id_number (f, prop); | 705 facecode = face_name_id_number (f, prop); |
689 if (facecode >= 0 && facecode < FRAME_N_FACES (f) | 706 if (facecode >= 0 && facecode < FRAME_N_FACES (f) |
775 struct frame *f; | 792 struct frame *f; |
776 int face_code; | 793 int face_code; |
777 { | 794 { |
778 struct face face; | 795 struct face face; |
779 | 796 |
780 bcopy (FRAME_DEFAULT_FACE (f), &face, sizeof (face)); | 797 compute_base_face (f, &face); |
781 face.gc = 0; | |
782 | 798 |
783 if (face_code >= 0 && face_code < FRAME_N_FACES (f) | 799 if (face_code >= 0 && face_code < FRAME_N_FACES (f) |
784 && FRAME_FACES (f) [face_code] != 0) | 800 && FRAME_FACES (f) [face_code] != 0) |
785 merge_faces (FRAME_FACES (f) [face_code], &face); | 801 merge_faces (FRAME_FACES (f) [face_code], &face); |
786 | 802 |
787 return intern_frame_face (f, &face); | 803 return intern_frame_face (f, &face); |
788 } | 804 } |
805 | |
806 | |
807 /* Recompute the GC's for the default and modeline faces. | |
808 We call this after changing frame parameters on which those GC's | |
809 depend. */ | |
810 void | |
811 recompute_basic_faces (f) | |
812 FRAME_PTR f; | |
813 { | |
814 /* If the frame's faces haven't been initialized yet, don't worry about | |
815 this stuff. */ | |
816 if (FRAME_N_FACES (f) < 2) | |
817 return; | |
818 | |
819 BLOCK_INPUT; | |
820 | |
821 if (FRAME_DEFAULT_FACE (f)->gc) | |
822 XFreeGC (x_current_display, FRAME_DEFAULT_FACE (f)->gc); | |
823 build_face (f, FRAME_DEFAULT_FACE (f)); | |
824 | |
825 if (FRAME_MODE_LINE_FACE (f)->gc) | |
826 XFreeGC (x_current_display, FRAME_MODE_LINE_FACE (f)->gc); | |
827 build_face (f, FRAME_MODE_LINE_FACE (f)); | |
828 | |
829 UNBLOCK_INPUT; | |
830 } | |
831 | |
832 | |
789 | 833 |
790 /* Lisp interface. */ | 834 /* Lisp interface. */ |
791 | 835 |
792 DEFUN ("frame-face-alist", Fframe_face_alist, Sframe_face_alist, 1, 1, 0, | 836 DEFUN ("frame-face-alist", Fframe_face_alist, Sframe_face_alist, 1, 1, 0, |
793 "") | 837 "") |
898 error ("unknown face attribute"); | 942 error ("unknown face attribute"); |
899 | 943 |
900 if (id == 0) | 944 if (id == 0) |
901 { | 945 { |
902 BLOCK_INPUT; | 946 BLOCK_INPUT; |
903 if (FRAME_DEFAULT_FACE (f)->gc != 0 | 947 if (FRAME_DEFAULT_FACE (f)->gc != 0) |
904 && FRAME_DEFAULT_FACE (f)->gc != f->display.x->normal_gc | |
905 && FRAME_DEFAULT_FACE (f)->gc != f->display.x->reverse_gc) | |
906 XFreeGC (x_current_display, FRAME_DEFAULT_FACE (f)->gc); | 948 XFreeGC (x_current_display, FRAME_DEFAULT_FACE (f)->gc); |
907 build_face (f, FRAME_DEFAULT_FACE (f)); | 949 build_face (f, FRAME_DEFAULT_FACE (f)); |
908 UNBLOCK_INPUT; | 950 UNBLOCK_INPUT; |
909 } | 951 } |
910 | 952 |
911 if (id == 1) | 953 if (id == 1) |
912 { | 954 { |
913 BLOCK_INPUT; | 955 BLOCK_INPUT; |
914 if (FRAME_MODE_LINE_FACE (f)->gc != 0 | 956 if (FRAME_MODE_LINE_FACE (f)->gc != 0) |
915 && FRAME_MODE_LINE_FACE (f)->gc != f->display.x->normal_gc | |
916 && FRAME_MODE_LINE_FACE (f)->gc != f->display.x->reverse_gc) | |
917 XFreeGC (x_current_display, FRAME_MODE_LINE_FACE (f)->gc); | 957 XFreeGC (x_current_display, FRAME_MODE_LINE_FACE (f)->gc); |
918 build_face (f, FRAME_MODE_LINE_FACE (f)); | 958 build_face (f, FRAME_MODE_LINE_FACE (f)); |
919 UNBLOCK_INPUT; | 959 UNBLOCK_INPUT; |
920 } | 960 } |
921 | 961 |