Mercurial > emacs
comparison src/xterm.c @ 17194:ae76b2a59dcc
(dumpglyphs): Set a clipping region when we draw glyphs
with a font of inappropriate size.
(x_list_fonts): Try alternate fonts if we can't find a font of an
appropriate size.
author | Kenichi Handa <handa@m17n.org> |
---|---|
date | Wed, 19 Mar 1997 16:33:48 +0000 |
parents | 4173a7215c5b |
children | d11d6c9a48e8 |
comparison
equal
deleted
inserted
replaced
17193:dc4562b0152a | 17194:ae76b2a59dcc |
---|---|
548 register int tlen = GLYPH_TABLE_LENGTH; | 548 register int tlen = GLYPH_TABLE_LENGTH; |
549 register Lisp_Object *tbase = GLYPH_TABLE_BASE; | 549 register Lisp_Object *tbase = GLYPH_TABLE_BASE; |
550 Window window = FRAME_X_WINDOW (f); | 550 Window window = FRAME_X_WINDOW (f); |
551 int orig_left = left; | 551 int orig_left = left; |
552 int gidx = 0; | 552 int gidx = 0; |
553 int pixel_width; | 553 int i; |
554 | 554 |
555 while (n > 0) | 555 while (n > 0) |
556 { | 556 { |
557 /* Get the face-code of the next GLYPH. */ | 557 /* Get the face-code of the next GLYPH. */ |
558 int cf, len; | 558 int cf, len; |
617 ++gp, --n; | 617 ++gp, --n; |
618 } | 618 } |
619 | 619 |
620 /* LEN gets the length of the run. */ | 620 /* LEN gets the length of the run. */ |
621 len = cp - buf; | 621 len = cp - buf; |
622 /* PIXEL_WIDTH get the pixcel width of the run. */ | |
623 pixel_width | |
624 = (FONT_WIDTH (f->output_data.x->font) | |
625 * (cmpcharp ? cmpcharp->width : len * CHARSET_WIDTH (charset))); | |
626 | |
627 /* Now output this run of chars, with the font and pixel values | 622 /* Now output this run of chars, with the font and pixel values |
628 determined by the face code CF. */ | 623 determined by the face code CF. */ |
629 { | 624 { |
630 struct face *face = FRAME_DEFAULT_FACE (f); | 625 struct face *face = FRAME_DEFAULT_FACE (f); |
631 XFontStruct *font = NULL; | 626 XFontStruct *font = NULL; |
632 GC gc; | 627 GC gc; |
633 int stippled = 0; | 628 int stippled = 0; |
629 int line_height = f->output_data.x->line_height; | |
630 /* Pixel width of each glyph in this run. */ | |
631 int glyph_width | |
632 = FONT_WIDTH (f->output_data.x->font) * CHARSET_WIDTH (charset); | |
633 /* Overall pixel width of this run. */ | |
634 int run_width | |
635 = (FONT_WIDTH (f->output_data.x->font) | |
636 * (cmpcharp ? cmpcharp->width : len * CHARSET_WIDTH (charset))); | |
634 /* A flag to tell if we have already filled background. We | 637 /* A flag to tell if we have already filled background. We |
635 fill background in advance in the following cases: | 638 fill background in advance in the following cases: |
636 1) A face has stipple. | 639 1) A face has stipple. |
637 2) A height of font is different from that of the current line. | 640 2) A height of font is shorter than LINE_HEIGHT. |
638 3) Drawing a composite character. | 641 3) Drawing a composite character. |
639 4) Font has non-zero _MULE_BASELINE_OFFSET property. | 642 4) Font has non-zero _MULE_BASELINE_OFFSET property. |
640 After filling background, we draw glyphs by XDrawString16. */ | 643 After filling background, we draw glyphs by XDrawString16. */ |
641 int background_filled; | 644 int background_filled; |
642 /* Baseline position of a character, offset from TOP. */ | 645 /* Baseline position of a character, offset from TOP. */ |
643 int baseline; | 646 int baseline; |
644 /* The property value of `_MULE_RELATIVE_COMPOSE' and | 647 /* The property value of `_MULE_RELATIVE_COMPOSE' and |
645 `_MULE_DEFAULT_ASCENT'. */ | 648 `_MULE_DEFAULT_ASCENT'. */ |
646 int relative_compose = 0, default_ascent = 0; | 649 int relative_compose = 0, default_ascent = 0; |
650 /* 1 if we find no font or a font of inappropriate size. */ | |
651 int require_clipping; | |
647 | 652 |
648 /* HL = 3 means use a mouse face previously chosen. */ | 653 /* HL = 3 means use a mouse face previously chosen. */ |
649 if (hl == 3) | 654 if (hl == 3) |
650 cf = FRAME_X_DISPLAY_INFO (f)->mouse_face_face_id; | 655 cf = FRAME_X_DISPLAY_INFO (f)->mouse_face_face_id; |
651 | 656 |
689 goto font_not_found; | 694 goto font_not_found; |
690 | 695 |
691 font = (XFontStruct *) (fontp->font); | 696 font = (XFontStruct *) (fontp->font); |
692 gc = FACE_NON_ASCII_GC (face); | 697 gc = FACE_NON_ASCII_GC (face); |
693 XSetFont (FRAME_X_DISPLAY (f), gc, font->fid); | 698 XSetFont (FRAME_X_DISPLAY (f), gc, font->fid); |
694 if (font->max_byte1 != 0) | 699 baseline |
695 baseline = (f->output_data.x->line_height | 700 = (font->max_byte1 != 0 |
696 + font->ascent - font->descent) / 2; | 701 ? (line_height + font->ascent - font->descent) / 2 |
697 else | 702 : f->output_data.x->font_baseline - fontp->baseline_offset); |
698 baseline = (f->output_data.x->font_baseline | |
699 - fontp->baseline_offset); | |
700 if (cmpcharp && cmpcharp->cmp_rule == NULL) | 703 if (cmpcharp && cmpcharp->cmp_rule == NULL) |
701 { | 704 { |
702 relative_compose = fontp->relative_compose; | 705 relative_compose = fontp->relative_compose; |
703 default_ascent = fontp->default_ascent; | 706 default_ascent = fontp->default_ascent; |
704 } | 707 } |
753 if (hl == 2) | 756 if (hl == 2) |
754 { | 757 { |
755 /* The cursor overrides stippling. */ | 758 /* The cursor overrides stippling. */ |
756 stippled = 0; | 759 stippled = 0; |
757 | 760 |
758 if (!cmpcharp | 761 if ((font == (XFontStruct *) FACE_DEFAULT |
759 && (!font | 762 || font == f->output_data.x->font) |
760 || font == (XFontStruct *) FACE_DEFAULT | |
761 || font == f->output_data.x->font) | |
762 && face->background == f->output_data.x->background_pixel | 763 && face->background == f->output_data.x->background_pixel |
763 && face->foreground == f->output_data.x->foreground_pixel) | 764 && face->foreground == f->output_data.x->foreground_pixel) |
764 { | 765 { |
765 gc = f->output_data.x->cursor_gc; | 766 gc = f->output_data.x->cursor_gc; |
766 } | 767 } |
811 } | 812 } |
812 | 813 |
813 if (font == (XFontStruct *) FACE_DEFAULT) | 814 if (font == (XFontStruct *) FACE_DEFAULT) |
814 font = f->output_data.x->font; | 815 font = f->output_data.x->font; |
815 | 816 |
817 if (font) | |
818 require_clipping = (FONT_HEIGHT (font) > line_height | |
819 || FONT_WIDTH (font) > glyph_width | |
820 || baseline != f->output_data.x->font_baseline); | |
821 | |
816 if (font && (just_foreground || (cmpcharp && gidx > 0))) | 822 if (font && (just_foreground || (cmpcharp && gidx > 0))) |
817 background_filled = 1; | 823 background_filled = 1; |
818 else if (!font | 824 else if (stippled) |
819 || stippled | |
820 || f->output_data.x->line_height != FONT_HEIGHT (font) | |
821 || cmpcharp | |
822 || baseline != f->output_data.x->font_baseline) | |
823 { | 825 { |
824 if (!stippled) | |
825 /* This is to fill a rectangle with background color. */ | |
826 XSetStipple (FRAME_X_DISPLAY (f), gc, | |
827 FRAME_X_DISPLAY_INFO (f)->null_pixel); | |
828 /* Turn stipple on. */ | 826 /* Turn stipple on. */ |
829 XSetFillStyle (FRAME_X_DISPLAY (f), gc, FillOpaqueStippled); | 827 XSetFillStyle (FRAME_X_DISPLAY (f), gc, FillOpaqueStippled); |
830 | 828 |
831 /* Draw stipple or background color on background. */ | 829 /* Draw stipple or background color on background. */ |
832 XFillRectangle (FRAME_X_DISPLAY (f), window, gc, | 830 XFillRectangle (FRAME_X_DISPLAY (f), window, gc, |
833 left, top, pixel_width, | 831 left, top, run_width, line_height); |
834 f->output_data.x->line_height); | |
835 | 832 |
836 /* Turn stipple off. */ | 833 /* Turn stipple off. */ |
837 XSetFillStyle (FRAME_X_DISPLAY (f), gc, FillSolid); | 834 XSetFillStyle (FRAME_X_DISPLAY (f), gc, FillSolid); |
835 | |
836 background_filled = 1; | |
837 } | |
838 else if (!font | |
839 || FONT_HEIGHT (font) < line_height | |
840 || FONT_WIDTH (font) < glyph_width | |
841 || baseline != f->output_data.x->font_baseline | |
842 || cmpcharp) | |
843 { | |
844 /* Fill a area for the current run in background pixle of GC. */ | |
845 XGCValues xgcv; | |
846 unsigned long mask = GCForeground | GCBackground; | |
847 unsigned long fore, back; | |
848 | |
849 /* The current code at first exchange foreground and | |
850 background of GC, fill the area, then recover the | |
851 original foreground and background of GC. | |
852 Aren't there more smart ways? */ | |
853 | |
854 XGetGCValues (FRAME_X_DISPLAY (f), gc, mask, &xgcv); | |
855 fore = xgcv.foreground, back = xgcv.background; | |
856 xgcv.foreground = back, xgcv.background = fore; | |
857 XChangeGC (FRAME_X_DISPLAY (f), gc, mask, &xgcv); | |
858 XFillRectangle (FRAME_X_DISPLAY (f), window, gc, | |
859 left, top, run_width, line_height); | |
860 xgcv.foreground = fore, xgcv.background = back; | |
861 XChangeGC (FRAME_X_DISPLAY (f), gc, mask, &xgcv); | |
838 | 862 |
839 background_filled = 1; | 863 background_filled = 1; |
840 if (cmpcharp) | 864 if (cmpcharp) |
841 /* To assure not to fill background while drawing | 865 /* To assure not to fill background while drawing |
842 remaining components. */ | 866 remaining components. */ |
845 else | 869 else |
846 background_filled = 0; | 870 background_filled = 0; |
847 | 871 |
848 if (font) | 872 if (font) |
849 { | 873 { |
850 if (cmpcharp) | 874 if (require_clipping) |
875 { | |
876 Region region; /* Region used for setting clip mask to GC. */ | |
877 XPoint x[4]; /* Data used for creating REGION. */ | |
878 | |
879 x[0].x = x[3].x = left, x[1].x = x[2].x = left + glyph_width; | |
880 x[0].y = x[1].y = top, x[2].y = x[3].y = top + line_height; | |
881 region = XPolygonRegion (x, 4, EvenOddRule); | |
882 XSetRegion (FRAME_X_DISPLAY (f), gc, region); | |
883 XDestroyRegion (region); | |
884 } | |
885 | |
886 if (!cmpcharp) | |
887 { | |
888 if (require_clipping) | |
889 for (i = 0; i < len; i++) | |
890 { | |
891 if (i > 0) | |
892 XSetClipOrigin (FRAME_X_DISPLAY (f), gc, | |
893 glyph_width * i, 0); | |
894 if (background_filled) | |
895 XDrawString16 (FRAME_X_DISPLAY (f), window, gc, | |
896 left + glyph_width * i, | |
897 top + baseline, buf + i, 1); | |
898 else | |
899 XDrawImageString16 (FRAME_X_DISPLAY (f), window, gc, | |
900 left + glyph_width * i, | |
901 top + baseline, buf + i, 1); | |
902 } | |
903 else | |
904 { | |
905 if (background_filled) | |
906 XDrawString16 (FRAME_X_DISPLAY (f), window, gc, | |
907 left, top + baseline, buf, len); | |
908 else | |
909 XDrawImageString16 (FRAME_X_DISPLAY (f), window, gc, | |
910 left, top + baseline, buf, len); | |
911 } | |
912 } | |
913 else | |
851 { | 914 { |
852 XCharStruct *pcm; /* Pointer to per char metric info. */ | 915 XCharStruct *pcm; /* Pointer to per char metric info. */ |
853 int i; | |
854 | 916 |
855 if ((cmpcharp->cmp_rule || relative_compose) | 917 if ((cmpcharp->cmp_rule || relative_compose) |
856 && gidx == 0) | 918 && gidx == 0) |
857 { | 919 { |
858 /* This is the first character. Initialize variables. | 920 /* This is the first character. Initialize variables. |
937 XDrawString16 (FRAME_X_DISPLAY (f), window, gc, | 999 XDrawString16 (FRAME_X_DISPLAY (f), window, gc, |
938 left + x_offset, top + baseline - y_offset, | 1000 left + x_offset, top + baseline - y_offset, |
939 buf + i, 1); | 1001 buf + i, 1); |
940 } | 1002 } |
941 } | 1003 } |
942 else if (background_filled) | 1004 if (require_clipping) |
943 XDrawString16 (FRAME_X_DISPLAY (f), window, gc, | 1005 XSetClipMask (FRAME_X_DISPLAY (f), gc, None); |
944 left, top + baseline, buf, len); | |
945 else | |
946 XDrawImageString16 (FRAME_X_DISPLAY (f), window, gc, | |
947 left, top + baseline, buf, len); | |
948 | |
949 /* Clear the rest of the line's height. */ | |
950 if (f->output_data.x->line_height > FONT_HEIGHT (font)) | |
951 XClearArea (FRAME_X_DISPLAY (f), window, left, | |
952 top + FONT_HEIGHT (font), | |
953 FONT_WIDTH (font) * len, | |
954 /* This is how many pixels of height | |
955 we have to clear. */ | |
956 f->output_data.x->line_height - FONT_HEIGHT (font), | |
957 False); | |
958 | 1006 |
959 #if 0 /* Doesn't work, because it uses FRAME_CURRENT_GLYPHS, | 1007 #if 0 /* Doesn't work, because it uses FRAME_CURRENT_GLYPHS, |
960 which often is not up to date yet. */ | 1008 which often is not up to date yet. */ |
961 if (!just_foreground) | 1009 if (!just_foreground) |
962 { | 1010 { |
967 redraw_following_char (f, PIXEL_TO_CHAR_COL (f, left + len * FONT_WIDTH (font)), | 1015 redraw_following_char (f, PIXEL_TO_CHAR_COL (f, left + len * FONT_WIDTH (font)), |
968 PIXEL_TO_CHAR_ROW (f, top), hl == 1); | 1016 PIXEL_TO_CHAR_ROW (f, top), hl == 1); |
969 } | 1017 } |
970 #endif | 1018 #endif |
971 } | 1019 } |
972 else | 1020 if (!font || require_clipping) |
973 { | 1021 { |
974 /* There's no appropriate font for this glyph. Just show | 1022 /* Show rectangles to show that we found no font or a font |
975 rectangles. */ | 1023 of inappropriate size. */ |
976 | 1024 |
977 if (cmpcharp) | 1025 if (cmpcharp) |
978 XDrawRectangle | 1026 XDrawRectangle |
979 (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc, | 1027 (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc, |
980 left, top + 1, | 1028 left, top, run_width - 1, line_height - 1); |
981 pixel_width - 2, f->output_data.x->line_height - 3); | |
982 else | 1029 else |
983 { | 1030 for (i = 0; i < len; i++) |
984 int left_offset; | 1031 XDrawRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc, |
985 int left_skip_step = (FONT_WIDTH (f->output_data.x->font) | 1032 left + glyph_width * i, top, |
986 * CHARSET_WIDTH (charset)); | 1033 glyph_width -1, line_height - 1); |
987 | |
988 for (left_offset = 0; left_offset < pixel_width; | |
989 left_offset += left_skip_step) | |
990 XDrawRectangle | |
991 (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc, | |
992 left + left_offset, top + 1, | |
993 left_skip_step - 2, f->output_data.x->line_height - 3); | |
994 } | |
995 } | 1034 } |
996 | 1035 |
997 /* We should probably check for XA_UNDERLINE_POSITION and | 1036 /* We should probably check for XA_UNDERLINE_POSITION and |
998 XA_UNDERLINE_THICKNESS properties on the font, but let's | 1037 XA_UNDERLINE_THICKNESS properties on the font, but let's |
999 just get the thing working, and come back to that. */ | 1038 just get the thing working, and come back to that. */ |
1002 current font results in shaky underline if it strides | 1041 current font results in shaky underline if it strides |
1003 over different fonts. So, we set the position based only | 1042 over different fonts. So, we set the position based only |
1004 on the default font of this frame. */ | 1043 on the default font of this frame. */ |
1005 int underline_position = f->output_data.x->font_baseline + 1; | 1044 int underline_position = f->output_data.x->font_baseline + 1; |
1006 | 1045 |
1007 if (underline_position >= f->output_data.x->line_height) | 1046 if (underline_position >= line_height) |
1008 underline_position = f->output_data.x->line_height - 1; | 1047 underline_position = line_height - 1; |
1009 | 1048 |
1010 if (face->underline) | 1049 if (face->underline) |
1011 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), | 1050 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), |
1012 FACE_GC (face), | 1051 FACE_GC (face), |
1013 left, top + underline_position, pixel_width, 1); | 1052 left, top + underline_position, run_width, 1); |
1014 } | 1053 } |
1015 | 1054 |
1016 if (!cmpcharp) | 1055 if (!cmpcharp) |
1017 left += pixel_width; | 1056 left += run_width; |
1018 } | 1057 } |
1019 } | 1058 } |
1020 | 1059 |
1021 return (left - orig_left); | 1060 return (left - orig_left); |
1022 } | 1061 } |
5169 return build_string (fontp->full_name); | 5208 return build_string (fontp->full_name); |
5170 } | 5209 } |
5171 | 5210 |
5172 /* Give frame F the fontset named FONTSETNAME as its default font, and | 5211 /* Give frame F the fontset named FONTSETNAME as its default font, and |
5173 return the full name of that fontset. FONTSETNAME may be a wildcard | 5212 return the full name of that fontset. FONTSETNAME may be a wildcard |
5174 pattern; in that case, we choose some font that fits the pattern. | 5213 pattern; in that case, we choose some fontset that fits the pattern. |
5175 The return value shows which font we chose. */ | 5214 The return value shows which fontset we chose. */ |
5176 | 5215 |
5177 Lisp_Object | 5216 Lisp_Object |
5178 x_new_fontset (f, fontsetname) | 5217 x_new_fontset (f, fontsetname) |
5179 struct frame *f; | 5218 struct frame *f; |
5180 char *fontsetname; | 5219 char *fontsetname; |
6126 FRAME_PTR f; | 6165 FRAME_PTR f; |
6127 Lisp_Object pattern; | 6166 Lisp_Object pattern; |
6128 int size; | 6167 int size; |
6129 int maxnames; | 6168 int maxnames; |
6130 { | 6169 { |
6131 Lisp_Object list, newlist, key; | 6170 Lisp_Object list, patterns = Qnil, newlist = Qnil, key, tem, second_best; |
6132 Display *dpy = f != NULL ? FRAME_X_DISPLAY (f) : x_display_list->display; | 6171 Display *dpy = f != NULL ? FRAME_X_DISPLAY (f) : x_display_list->display; |
6133 | 6172 |
6134 key = Fcons (pattern, make_number (maxnames)); | 6173 for (list = Valternative_fontname_alist; CONSP (list); |
6135 | 6174 list = XCONS (list)->cdr) |
6136 if (f == NULL) | 6175 { |
6137 list = Qnil; | 6176 tem = XCONS (list)->car; |
6138 else | 6177 if (CONSP (tem) |
6139 /* See if we cached the result for this particular query. */ | 6178 && STRINGP (XCONS (tem)->car) |
6140 list = Fassoc (key, | 6179 && !NILP (Fstring_equal (XCONS (tem)->car, pattern))) |
6141 XCONS (FRAME_X_DISPLAY_INFO (f)->name_list_element)->cdr); | 6180 { |
6142 | 6181 patterns = XCONS (tem)->cdr; |
6143 /* Now LIST has the form (KEY . FONT-DATA-LIST), where KEY is a | 6182 break; |
6144 pattern which matches font names in FONT-DATA-LIST, FONT-DATA-LIST | 6183 } |
6145 is a list of cons cells for the form (FONTNAME . FONTWIDTH). */ | 6184 } |
6146 | 6185 |
6147 if (!NILP (list)) | 6186 for (patterns = Fcons (pattern, patterns); CONSP (patterns); |
6148 list = XCONS (list)->cdr; | 6187 patterns = XCONS (patterns)->cdr, pattern = XCONS (patterns)->car) |
6149 else | 6188 { |
6150 { | |
6151 /* At first, put PATTERN in the cache. */ | |
6152 int num_fonts; | 6189 int num_fonts; |
6153 char **names; | 6190 char **names; |
6154 | 6191 |
6192 /* See if we cached the result for this particular query. */ | |
6193 if (f && (tem = XCONS (FRAME_X_DISPLAY_INFO (f)->name_list_element)->cdr, | |
6194 key = Fcons (pattern, make_number (maxnames)), | |
6195 !NILP (list = Fassoc (key, tem)))) | |
6196 { | |
6197 list = Fcdr_safe (list); | |
6198 /* We have a cashed list. Don't have to get the list again. */ | |
6199 goto label_cached; | |
6200 } | |
6201 | |
6202 /* At first, put PATTERN in the cache. */ | |
6155 BLOCK_INPUT; | 6203 BLOCK_INPUT; |
6156 names = XListFonts (dpy, XSTRING (pattern)->data, maxnames, &num_fonts); | 6204 names = XListFonts (dpy, XSTRING (pattern)->data, maxnames, &num_fonts); |
6157 UNBLOCK_INPUT; | 6205 UNBLOCK_INPUT; |
6158 | 6206 |
6159 if (names) | 6207 if (names) |
6160 { | 6208 { |
6161 int i; | 6209 int i; |
6162 Lisp_Object tem; | |
6163 | 6210 |
6164 /* Make a list of all the fonts we got back. | 6211 /* Make a list of all the fonts we got back. |
6165 Store that in the font cache for the display. */ | 6212 Store that in the font cache for the display. */ |
6166 for (i = 0; i < num_fonts; i++) | 6213 for (i = 0; i < num_fonts; i++) |
6167 { | 6214 { |
6168 char *p = names[i]; | 6215 char *p = names[i]; |
6169 int average_width = -1, dashes = 0, width = 0; | 6216 int average_width = -1, dashes = 0, width = 0; |
6170 | 6217 |
6171 /* Count the number of dashes in NAMES[I]. If there are | 6218 /* Count the number of dashes in NAMES[I]. If there are |
6172 14 dashes, and the field value following 12th dash | 6219 14 dashes, and the field value following 12th dash |
6173 (AVERAGE_WIDTH) is 0, this is a auto-scaled font | 6220 (AVERAGE_WIDTH) is 0, this is a auto-scaled font which |
6174 which is usually too ugly to be used for editing. | 6221 is usually too ugly to be used for editing. Let's |
6175 Let's ignore it. */ | 6222 ignore it. */ |
6176 while (*p) | 6223 while (*p) |
6177 if (*p++ == '-') | 6224 if (*p++ == '-') |
6178 { | 6225 { |
6179 dashes++; | 6226 dashes++; |
6180 if (dashes == 7) /* PIXEL_SIZE field */ | 6227 if (dashes == 7) /* PIXEL_SIZE field */ |
6190 if (STRINGP (Vx_pixel_size_width_font_regexp) | 6237 if (STRINGP (Vx_pixel_size_width_font_regexp) |
6191 && (fast_string_match_ignore_case | 6238 && (fast_string_match_ignore_case |
6192 (Vx_pixel_size_width_font_regexp, names[i]) | 6239 (Vx_pixel_size_width_font_regexp, names[i]) |
6193 >= 0)) | 6240 >= 0)) |
6194 /* We can set the value of PIXEL_SIZE to the | 6241 /* We can set the value of PIXEL_SIZE to the |
6195 width of this font. */ | 6242 width of this font. */ |
6196 list = Fcons (Fcons (tem, make_number (width)), list); | 6243 list = Fcons (Fcons (tem, make_number (width)), list); |
6197 else | 6244 else |
6198 /* For the moment, width is not known. */ | 6245 /* For the moment, width is not known. */ |
6199 list = Fcons (Fcons (tem, Qnil), list); | 6246 list = Fcons (Fcons (tem, Qnil), list); |
6200 } | 6247 } |
6201 } | 6248 } |
6202 } | 6249 } |
6203 XFreeFontNames (names); | 6250 XFreeFontNames (names); |
6204 } | 6251 } |
6205 | 6252 |
6253 /* Now store the result in the cache. */ | |
6206 if (f != NULL) | 6254 if (f != NULL) |
6207 XCONS (FRAME_X_DISPLAY_INFO (f)->name_list_element)->cdr | 6255 XCONS (FRAME_X_DISPLAY_INFO (f)->name_list_element)->cdr |
6208 = Fcons (Fcons (key, list), | 6256 = Fcons (Fcons (key, list), |
6209 XCONS (FRAME_X_DISPLAY_INFO (f)->name_list_element)->cdr); | 6257 XCONS (FRAME_X_DISPLAY_INFO (f)->name_list_element)->cdr); |
6210 } | 6258 |
6211 | 6259 label_cached: |
6212 if (NILP (list)) | 6260 if (NILP (list)) continue; /* Try the remaining alternatives. */ |
6213 return Qnil; | 6261 |
6214 | 6262 newlist = second_best = Qnil; |
6215 newlist = Qnil; | 6263 /* Make a list of the fonts that have the right width. */ |
6216 | 6264 for (; CONSP (list); list = XCONS (list)->cdr) |
6217 /* Make a list of the fonts that have the right width. */ | |
6218 for (; CONSP (list); list = XCONS (list)->cdr) | |
6219 { | |
6220 Lisp_Object tem = XCONS (list)->car; | |
6221 int keeper; | |
6222 | |
6223 if (!CONSP (tem) || NILP (XCONS (tem)->car)) | |
6224 continue; | |
6225 if (!size) | |
6226 keeper = 1; | |
6227 else | |
6228 { | 6265 { |
6266 tem = XCONS (list)->car; | |
6267 | |
6268 if (!CONSP (tem) || NILP (XCONS (tem)->car)) | |
6269 continue; | |
6270 if (!size) | |
6271 { | |
6272 newlist = Fcons (XCONS (tem)->car, newlist); | |
6273 continue; | |
6274 } | |
6275 | |
6229 if (!INTEGERP (XCONS (tem)->cdr)) | 6276 if (!INTEGERP (XCONS (tem)->cdr)) |
6230 { | 6277 { |
6278 /* Since we have not yet known the size of this font, we | |
6279 must try slow function call XLoadQueryFont. */ | |
6231 XFontStruct *thisinfo; | 6280 XFontStruct *thisinfo; |
6232 | 6281 |
6233 BLOCK_INPUT; | 6282 BLOCK_INPUT; |
6234 thisinfo = XLoadQueryFont (dpy, | 6283 thisinfo = XLoadQueryFont (dpy, |
6235 XSTRING (XCONS (tem)->car)->data); | 6284 XSTRING (XCONS (tem)->car)->data); |
6239 { | 6288 { |
6240 XCONS (tem)->cdr = make_number (thisinfo->max_bounds.width); | 6289 XCONS (tem)->cdr = make_number (thisinfo->max_bounds.width); |
6241 XFreeFont (dpy, thisinfo); | 6290 XFreeFont (dpy, thisinfo); |
6242 } | 6291 } |
6243 else | 6292 else |
6293 /* For unknown reason, the previous call of XListFont had | |
6294 retruned a font which can't be opened. Record the size | |
6295 as 0 not to try to open it again. */ | |
6244 XCONS (tem)->cdr = make_number (0); | 6296 XCONS (tem)->cdr = make_number (0); |
6245 } | 6297 } |
6246 keeper = XINT (XCONS (tem)->cdr) == size; | 6298 if (XINT (XCONS (tem)->cdr) == size) |
6299 newlist = Fcons (XCONS (tem)->car, newlist); | |
6300 else if (NILP (second_best)) | |
6301 second_best = tem; | |
6302 else if (XINT (XCONS (tem)->cdr) < size) | |
6303 { | |
6304 if (XINT (XCONS (second_best)->cdr) > size | |
6305 || XINT (XCONS (second_best)->cdr) < XINT (XCONS (tem)->cdr)) | |
6306 second_best = tem; | |
6307 } | |
6308 else | |
6309 { | |
6310 if (XINT (XCONS (second_best)->cdr) > size | |
6311 && XINT (XCONS (second_best)->cdr) > XINT (XCONS (tem)->cdr)) | |
6312 second_best = tem; | |
6313 } | |
6247 } | 6314 } |
6248 if (keeper) | 6315 if (!NILP (newlist)) |
6249 newlist = Fcons (XCONS (tem)->car, newlist); | 6316 break; |
6317 else if (!NILP (second_best)) | |
6318 { | |
6319 newlist = Fcons (XCONS (second_best)->car, Qnil); | |
6320 break; | |
6321 } | |
6250 } | 6322 } |
6251 | 6323 |
6252 return newlist; | 6324 return newlist; |
6253 } | 6325 } |
6254 | 6326 |
6296 fontname = XSTRING (XCONS (font_names)->car)->data; | 6368 fontname = XSTRING (XCONS (font_names)->car)->data; |
6297 | 6369 |
6298 BLOCK_INPUT; | 6370 BLOCK_INPUT; |
6299 font = (XFontStruct *) XLoadQueryFont (FRAME_X_DISPLAY (f), fontname); | 6371 font = (XFontStruct *) XLoadQueryFont (FRAME_X_DISPLAY (f), fontname); |
6300 UNBLOCK_INPUT; | 6372 UNBLOCK_INPUT; |
6301 if (!font || (size && font->max_bounds.width != size)) | 6373 if (!font) |
6302 return NULL; | 6374 return NULL; |
6303 | 6375 |
6304 /* Do we need to create the table? */ | 6376 /* Do we need to create the table? */ |
6305 if (dpyinfo->font_table_size == 0) | 6377 if (dpyinfo->font_table_size == 0) |
6306 { | 6378 { |