comparison src/redisplay-x.c @ 3094:ad2f4ae9895b

[xemacs-hg @ 2005-11-26 11:45:47 by stephent] Xft merge. <87k6ev4p8q.fsf@tleepslib.sk.tsukuba.ac.jp>
author stephent
date Sat, 26 Nov 2005 11:46:25 +0000
parents 3d8143fc88e1
children d1754e7f0cea
comparison
equal deleted inserted replaced
3093:769dc945b085 3094:ad2f4ae9895b
56 #include "sysproc.h" /* for select() */ 56 #include "sysproc.h" /* for select() */
57 57
58 #include <X11/bitmaps/gray> 58 #include <X11/bitmaps/gray>
59 59
60 /* Number of pixels below each line. */ 60 /* Number of pixels below each line. */
61 int x_interline_space; /* #### implement me */ 61 int x_interline_space; /* #### this needs to be implemented, but per-font */
62 62
63 #define EOL_CURSOR_WIDTH 5 63 #define EOL_CURSOR_WIDTH 5
64 64
65 static void x_output_vertical_divider (struct window *w, int clear); 65 static void x_output_vertical_divider (struct window *w, int clear);
66 static void x_output_blank (struct window *w, struct display_line *dl, 66 static void x_output_blank (struct window *w, struct display_line *dl,
71 static void x_output_eol_cursor (struct window *w, struct display_line *dl, 71 static void x_output_eol_cursor (struct window *w, struct display_line *dl,
72 int xpos, face_index findex); 72 int xpos, face_index findex);
73 static void x_clear_frame (struct frame *f); 73 static void x_clear_frame (struct frame *f);
74 static void x_clear_frame_windows (Lisp_Object window); 74 static void x_clear_frame_windows (Lisp_Object window);
75 75
76 #ifdef USE_XFT
77 #define MINL(x,y) ((((unsigned long) (x)) < ((unsigned long) (y))) \
78 ? ((unsigned long) (x)) : ((unsigned long) (y)))
79 #endif /* USE_XFT */
80
76 81
77 /* Note: We do not use the Xmb*() functions and XFontSets. 82 /* Note: We do not use the Xmb*() functions and XFontSets.
78 Those functions are generally losing for a number of reasons: 83 Those functions are generally losing for a number of reasons:
79 84
80 1) They only support one locale (e.g. you could display 85 1) They only support one locale (e.g. you could display
81 Japanese and ASCII text, but not mixed Japanese/Chinese 86 Japanese and ASCII text, but not mixed Japanese/Chinese
82 text). You could maybe call setlocale() frequently 87 text). You could maybe call setlocale() frequently
83 to try to deal with this, but that would generally 88 to try to deal with this, but that would generally
84 fail because an XFontSet is tied to one locale and 89 fail because an XFontSet is tied to one locale and
85 won't have the other character sets in it. 90 won't have the other character sets in it.
91
92 The following aren't true any more, but that doesn't make Xmb*()
93 usable. One wonders about Xft and Pango, etc, tho'. Except they
94 aren't cross-platform solutions. FMH, as jwz would say. -- sjt
95 [[
86 2) Not all (or even very many) OS's support the useful 96 2) Not all (or even very many) OS's support the useful
87 locales. For example, as far as I know SunOS and 97 locales. For example, as far as I know SunOS and
88 Solaris only support the Japanese locale if you get the 98 Solaris only support the Japanese locale if you get the
89 special Asian-language version of the OS. Yuck yuck 99 special Asian-language version of the OS. Yuck yuck
90 yuck. Linux doesn't support the Japanese locale at 100 yuck. Linux doesn't support the Japanese locale at
96 specific) is even the same for the same locale on 106 specific) is even the same for the same locale on
97 different OS's? It's not even documented anywhere that 107 different OS's? It's not even documented anywhere that
98 I can find what the multi-byte text format for the 108 I can find what the multi-byte text format for the
99 Japanese locale under SunOS and Solaris is, but I assume 109 Japanese locale under SunOS and Solaris is, but I assume
100 it's EUC. 110 it's EUC.
111 ]]
101 */ 112 */
102 113
114 /* #### Break me out into a separate header */
103 struct textual_run 115 struct textual_run
104 { 116 {
105 Lisp_Object charset; 117 Lisp_Object charset;
106 unsigned char *ptr; 118 unsigned char *ptr;
107 int len; 119 int len;
118 of TEXT_STORAGE and (len * sizeof (struct textual_run)) bytes of 130 of TEXT_STORAGE and (len * sizeof (struct textual_run)) bytes of
119 RUN_STORAGE, where LEN is the length of the dynarr. 131 RUN_STORAGE, where LEN is the length of the dynarr.
120 132
121 Returns the number of runs actually used. */ 133 Returns the number of runs actually used. */
122 134
135 /* Notes on Xft implementation
136
137 - Xft Reloaded, v.4, uses a function like that in redisplay-msw.c to
138 handle all characters. However, instead of using an appropriate
139 character width for each run, it just uses UTF-8 for all runs. This
140 is not obviously a bad idea, but (for Han characters etc) the estimate
141 of TEXT_STORAGE allocation needed is (3 * len), and for characters not
142 in the BMP, it's (4 * len).
143 - With Unicode, we're no longer going to have repertoires reified as
144 charsets. (Not that we ever really did, what with corporate variants,
145 and so on.) So we really should be querying the face for the desired
146 font, rather than the character for the charset, and that's what would
147 determine the separation into runs.
148 - The widechar versions of fontconfig (and therefore Xft) functions
149 seem to be just bigendian Unicode. So there's actually no need to use
150 the 8-bit versions in computing runs and runes, it would seem.
151 - Mule won't "just work"; substantially more effort seems needed.
152 */
153
123 static int 154 static int
124 separate_textual_runs (unsigned char *text_storage, 155 separate_textual_runs (unsigned char *text_storage,
125 struct textual_run *run_storage, 156 struct textual_run *run_storage,
126 const Ichar *str, Charcount len) 157 const Ichar *str, Charcount len)
127 { 158 {
137 168
138 for (i = 0; i < len; i++) 169 for (i = 0; i < len; i++)
139 { 170 {
140 Ichar ch = str[i]; 171 Ichar ch = str[i];
141 Lisp_Object charset; 172 Lisp_Object charset;
142 int byte1, byte2; 173 int byte1, byte2; /* #### why aren't these UExtbytes? */
143 int dimension; 174 int dimension;
144 int graphic; 175 int graphic;
145 176
146 BREAKUP_ICHAR (ch, charset, byte1, byte2); 177 BREAKUP_ICHAR (ch, charset, byte1, byte2);
147 dimension = XCHARSET_DIMENSION (charset); 178 dimension = XCHARSET_DIMENSION (charset);
149 180
150 if (!EQ (charset, prev_charset)) 181 if (!EQ (charset, prev_charset))
151 { 182 {
152 run_storage[runs_so_far].ptr = text_storage; 183 run_storage[runs_so_far].ptr = text_storage;
153 run_storage[runs_so_far].charset = charset; 184 run_storage[runs_so_far].charset = charset;
185 #ifdef USE_XFT
186 run_storage[runs_so_far].dimension = 2;
187 #else
154 run_storage[runs_so_far].dimension = dimension; 188 run_storage[runs_so_far].dimension = dimension;
189 #endif
155 190
156 if (runs_so_far) 191 if (runs_so_far)
157 { 192 {
158 run_storage[runs_so_far - 1].len = 193 run_storage[runs_so_far - 1].len =
159 text_storage - run_storage[runs_so_far - 1].ptr; 194 text_storage - run_storage[runs_so_far - 1].ptr;
170 need_ccl_conversion = 1; 205 need_ccl_conversion = 1;
171 } 206 }
172 #endif 207 #endif
173 } 208 }
174 209
210 #ifndef USE_XFT
175 if (graphic == 0) 211 if (graphic == 0)
176 { 212 {
177 byte1 &= 0x7F; 213 byte1 &= 0x7F;
178 byte2 &= 0x7F; 214 byte2 &= 0x7F;
179 } 215 }
190 char_converter.reg[2] = byte2; 226 char_converter.reg[2] = byte2;
191 ccl_driver (&char_converter, 0, 0, 0, 0, CCL_MODE_ENCODING); 227 ccl_driver (&char_converter, 0, 0, 0, 0, CCL_MODE_ENCODING);
192 byte1 = char_converter.reg[1]; 228 byte1 = char_converter.reg[1];
193 byte2 = char_converter.reg[2]; 229 byte2 = char_converter.reg[2];
194 } 230 }
195 #endif 231 #endif /* MULE */
196 *text_storage++ = (unsigned char) byte1; 232 *text_storage++ = (unsigned char) byte1;
197 if (dimension == 2) 233 if (dimension == 2)
198 *text_storage++ = (unsigned char) byte2; 234 *text_storage++ = (unsigned char) byte2;
235 #else /* USE_XFT */
236 /* #### This is bogus as hell. XftChar16, aka FcChar16, is actually
237 unsigned short, and therefore is not suitable for indexing matrix
238 fonts such as the JIS fonts supplied with X11. But if this were
239 consistent, the XftDraw*8 and XftDraw*16 functions are pretty
240 incoherent, as then we not should allow anything but ISO 8859/1
241 (ie, the first 256 code points of Unicode) in XftDraw*8. So it
242 looks like this depends on the font, not the charset. */
243 {
244 XftChar16 xftchar16 = 0xFFFD; /* unsigned short */
245 #ifndef MULE
246 int unicode = ch;
247 #else
248 int unicode = ichar_to_unicode (ch);
249 if (unicode < 0)
250 /* abort(); */ /* #### serious error, tables are corrupt
251 Unfortunately, not a valid assumption; this can happen with
252 composite characters. Fake it. */
253 unicode = 0xFFFD; /* REPLACEMENT CHARACTER, can't represent */
254 else if (need_ccl_conversion)
255 /* #### maybe we should just ignore this and hope the font wins? */
256 unicode = 0xFFFD; /* REPLACEMENT CHARACTER, can't represent */
257 else if (unicode > 65535)
258 unicode = 0xFFFD; /* REPLACEMENT CHARACTER, can't represent */
259 else
260 #endif
261 xftchar16 = (XftChar16) unicode;
262 /* #### endianness dependency? No,
263 apparently xft handles endianness for us;
264 the "big-endian" code works on Intel and PPC */
265 #if 1
266 /* big-endian or auto-endian */
267 byte1 = ((unsigned char *) (&xftchar16))[0];
268 byte2 = ((unsigned char *) (&xftchar16))[1];
269 #else
270 /* little-endian */
271 byte1 = ((unsigned char *) (&xftchar16))[1];
272 byte2 = ((unsigned char *) (&xftchar16))[0];
273 #endif
274 }
275 *text_storage++ = (unsigned char) byte1;
276 *text_storage++ = (unsigned char) byte2;
277 #endif /* USE_XFT */
199 } 278 }
200 279
201 if (runs_so_far) 280 if (runs_so_far)
202 { 281 {
203 run_storage[runs_so_far - 1].len = 282 run_storage[runs_so_far - 1].len =
214 /* X output routines */ 293 /* X output routines */
215 /* */ 294 /* */
216 /****************************************************************************/ 295 /****************************************************************************/
217 296
218 static int 297 static int
219 x_text_width_single_run (struct face_cachel *cachel, struct textual_run *run) 298 x_text_width_single_run (struct frame * USED_IF_XFT (f),
299 struct face_cachel *cachel, struct textual_run *run)
220 { 300 {
221 Lisp_Object font_inst = FACE_CACHEL_FONT (cachel, run->charset); 301 Lisp_Object font_inst = FACE_CACHEL_FONT (cachel, run->charset);
222 Lisp_Font_Instance *fi = XFONT_INSTANCE (font_inst); 302 Lisp_Font_Instance *fi = XFONT_INSTANCE (font_inst);
223 if (!fi->proportional_p) 303 if (!fi->proportional_p)
224 return fi->width * run->len; 304 return fi->width * run->len;
225 else 305 #ifdef USE_XFT
306 else if (FONT_INSTANCE_X_XFTFONT(fi))
307 {
308 static XGlyphInfo glyphinfo;
309 struct device *d = XDEVICE (f->device);
310 Display *dpy = DEVICE_X_DISPLAY (d);
311
312 if (run->dimension == 2) {
313 XftTextExtents16 (dpy,
314 FONT_INSTANCE_X_XFTFONT(fi),
315 (XftChar16 *) run->ptr, run->len, &glyphinfo);
316 } else {
317 XftTextExtents8 (dpy,
318 FONT_INSTANCE_X_XFTFONT(fi),
319 run->ptr, run->len, &glyphinfo);
320 }
321
322 return glyphinfo.xOff;
323 }
324 #endif
325 else if (FONT_INSTANCE_X_FONT (fi))
226 { 326 {
227 if (run->dimension == 2) 327 if (run->dimension == 2)
228 return XTextWidth16 (FONT_INSTANCE_X_FONT (fi), 328 return XTextWidth16 (FONT_INSTANCE_X_FONT (fi),
229 (XChar2b *) run->ptr, run->len); 329 (XChar2b *) run->ptr, run->len);
230 else 330 else
231 return XTextWidth (FONT_INSTANCE_X_FONT (fi), 331 return XTextWidth (FONT_INSTANCE_X_FONT (fi),
232 (char *) run->ptr, run->len); 332 (char *) run->ptr, run->len);
233 } 333 }
334 else
335 abort();
336 return 0; /* shut up GCC */
234 } 337 }
235 338
236 /* 339 /*
237 x_text_width 340 x_text_width
238 341
239 Given a string and a face, return the string's length in pixels when 342 Given a string and a merged face, return the string's length in pixels
240 displayed in the font associated with the face. 343 when displayed in the fonts associated with the face.
241 */ 344 */
242 345
243 static int 346 /* #### Break me out into a separate header */
244 x_text_width (struct frame *UNUSED (f), struct face_cachel *cachel, 347 int x_text_width (struct frame *f, struct face_cachel *cachel,
348 const Ichar *str, Charcount len);
349 int
350 x_text_width (struct frame *f, struct face_cachel *cachel,
245 const Ichar *str, Charcount len) 351 const Ichar *str, Charcount len)
246 { 352 {
247 /* !!#### Needs review */ 353 /* !!#### Needs review */
248 int width_so_far = 0; 354 int width_so_far = 0;
249 unsigned char *text_storage = (unsigned char *) ALLOCA (2 * len); 355 unsigned char *text_storage = (unsigned char *) ALLOCA (2 * len);
252 int i; 358 int i;
253 359
254 nruns = separate_textual_runs (text_storage, runs, str, len); 360 nruns = separate_textual_runs (text_storage, runs, str, len);
255 361
256 for (i = 0; i < nruns; i++) 362 for (i = 0; i < nruns; i++)
257 width_so_far += x_text_width_single_run (cachel, runs + i); 363 width_so_far += x_text_width_single_run (f, cachel, runs + i);
258 364
259 return width_so_far; 365 return width_so_far;
260 } 366 }
261 367
262 /***************************************************************************** 368 /*****************************************************************************
317 static void 423 static void
318 x_output_display_block (struct window *w, struct display_line *dl, int block, 424 x_output_display_block (struct window *w, struct display_line *dl, int block,
319 int start, int end, int start_pixpos, int cursor_start, 425 int start, int end, int start_pixpos, int cursor_start,
320 int cursor_width, int cursor_height) 426 int cursor_width, int cursor_height)
321 { 427 {
428 #ifndef USE_XFT
322 struct frame *f = XFRAME (w->frame); 429 struct frame *f = XFRAME (w->frame);
430 #endif
323 Ichar_dynarr *buf = Dynarr_new (Ichar); 431 Ichar_dynarr *buf = Dynarr_new (Ichar);
324 Lisp_Object window; 432 Lisp_Object window;
325 433
326 struct display_block *db = Dynarr_atp (dl->display_blocks, block); 434 struct display_block *db = Dynarr_atp (dl->display_blocks, block);
327 rune_dynarr *rba = db->runes; 435 rune_dynarr *rba = db->runes;
500 608
501 if (Dynarr_length (buf)) 609 if (Dynarr_length (buf))
502 x_output_string (w, dl, buf, xpos, 0, start_pixpos, width, findex, 610 x_output_string (w, dl, buf, xpos, 0, start_pixpos, width, findex,
503 0, cursor_start, cursor_width, cursor_height); 611 0, cursor_start, cursor_width, cursor_height);
504 612
505 /* #### This is really conditionalized well for optimized
506 performance. */
507 if (dl->modeline 613 if (dl->modeline
508 && !EQ (Qzero, w->modeline_shadow_thickness) 614 && !EQ (Qzero, w->modeline_shadow_thickness)
615 #ifndef USE_XFT
616 /* This optimization doesn't work right with some Xft fonts, which
617 leave antialiasing turds at the boundary. I don't know if this
618 is an Xft bug or not, but I think it is. See x_output_string. */
509 && (f->clear 619 && (f->clear
510 || f->windows_structure_changed 620 || f->windows_structure_changed
511 || w->shadow_thickness_changed)) 621 || w->shadow_thickness_changed)
622 #endif
623 )
512 bevel_modeline (w, dl); 624 bevel_modeline (w, dl);
513 625
514 Dynarr_free (buf); 626 Dynarr_free (buf);
515 } 627 }
516 628
660 gcv.clip_y_origin = 0; 772 gcv.clip_y_origin = 0;
661 gcv.fill_style = FillSolid; 773 gcv.fill_style = FillSolid;
662 mask = GCGraphicsExposures | GCClipMask | GCClipXOrigin | GCClipYOrigin; 774 mask = GCGraphicsExposures | GCClipMask | GCClipXOrigin | GCClipYOrigin;
663 mask |= GCFillStyle; 775 mask |= GCFillStyle;
664 776
665 if (!NILP (font)) 777 if (!NILP (font)
778 #ifdef USE_XFT
779 /* Only set the font if it's a core font */
780 /* the renderfont will be set elsewhere (not part of gc) */
781 && !FONT_INSTANCE_X_XFTFONT (XFONT_INSTANCE (font))
782 #endif
783 )
666 { 784 {
667 gcv.font = FONT_INSTANCE_X_FONT (XFONT_INSTANCE (font))->fid; 785 gcv.font = FONT_INSTANCE_X_FONT (XFONT_INSTANCE (font))->fid;
668 mask |= GCFont; 786 mask |= GCFont;
669 } 787 }
670 788
671 /* evil kludge! */ 789 /* evil kludge! */
672 if (!NILP (fg) && !COLOR_INSTANCEP (fg) && !INTP (fg)) 790 if (!NILP (fg) && !COLOR_INSTANCEP (fg) && !INTP (fg))
673 { 791 {
674 /* #### I fixed once case where this was getting it. It was a 792 /* #### I fixed one case where this was getting hit. It was a
675 bad macro expansion (compiler bug). */ 793 bad macro expansion (compiler bug). */
676 stderr_out ("Help! x_get_gc got a bogus fg value! fg = "); 794 stderr_out ("Help! x_get_gc got a bogus fg value! fg = ");
677 debug_print (fg); 795 debug_print (fg);
678 fg = Qnil; 796 fg = Qnil;
679 } 797 }
727 { 845 {
728 gcv.line_width = XINT (lwidth); 846 gcv.line_width = XINT (lwidth);
729 mask |= GCLineWidth; 847 mask |= GCLineWidth;
730 } 848 }
731 849
850 #if 0
851 debug_out ("\nx_get_gc: calling gc_cache_lookup\n");
852 #endif
732 return gc_cache_lookup (DEVICE_X_GC_CACHE (d), &gcv, mask); 853 return gc_cache_lookup (DEVICE_X_GC_CACHE (d), &gcv, mask);
733 } 854 }
734 855
735 /***************************************************************************** 856 /*****************************************************************************
736 x_output_string 857 x_output_string
772 int cursor_start, int cursor_width, int cursor_height) 893 int cursor_start, int cursor_width, int cursor_height)
773 { 894 {
774 /* General variables */ 895 /* General variables */
775 struct frame *f = XFRAME (w->frame); 896 struct frame *f = XFRAME (w->frame);
776 struct device *d = XDEVICE (f->device); 897 struct device *d = XDEVICE (f->device);
777 Lisp_Object window; 898 Lisp_Object window = wrap_window (w);
778 Display *dpy = DEVICE_X_DISPLAY (d); 899 Display *dpy = DEVICE_X_DISPLAY (d);
779 Window x_win = XtWindow (FRAME_X_TEXT_WIDGET (f)); 900 Window x_win = XtWindow (FRAME_X_TEXT_WIDGET (f));
780 901
781 int clip_end; 902 int clip_end;
782 903
788 struct face_cachel *cursor_cachel = 0; 909 struct face_cachel *cursor_cachel = 0;
789 910
790 /* Text-related variables */ 911 /* Text-related variables */
791 Lisp_Object bg_pmap; 912 Lisp_Object bg_pmap;
792 GC bgc, gc; 913 GC bgc, gc;
793 int height; 914 int height = DISPLAY_LINE_HEIGHT (dl);
915 int ypos = DISPLAY_LINE_YPOS (dl);
794 int len = Dynarr_length (buf); 916 int len = Dynarr_length (buf);
795 unsigned char *text_storage = (unsigned char *) ALLOCA (2 * len); 917 unsigned char *text_storage = (unsigned char *) ALLOCA (2 * len);
796 struct textual_run *runs = alloca_array (struct textual_run, len); 918 struct textual_run *runs = alloca_array (struct textual_run, len);
797 int nruns; 919 int nruns;
798 int i; 920 int i;
799 struct face_cachel *cachel = WINDOW_FACE_CACHEL (w, findex); 921 struct face_cachel *cachel = WINDOW_FACE_CACHEL (w, findex);
800 922
801 window = wrap_window (w); 923 int use_x_font = 1; /* #### bogus!!
924 The logic of this function needs review! */
925 #ifdef USE_XFT
926 Colormap cmap = DEVICE_X_COLORMAP (d);
927 Visual *visual = DEVICE_X_VISUAL (d);
928 static XftColor fg, bg;
929 XftDraw *xftDraw;
930
931 /* Lazily initialize frame's xftDraw member. */
932 if (!FRAME_X_XFTDRAW (f)) {
933 FRAME_X_XFTDRAW (f) = XftDrawCreate (dpy, x_win, visual, cmap);
934 }
935 xftDraw = FRAME_X_XFTDRAW (f);
936
937 /* #### This will probably cause asserts when passed a Lisp integer for a
938 color. See ca. line 759 this file.
939 #### Maybe xft_convert_color should take an XColor, not a pixel. */
940 #define XFT_FROB_LISP_COLOR(color, dim) \
941 xft_convert_color (dpy, cmap, visual, \
942 COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (color)).pixel, \
943 (dim))
944 #endif
802 945
803 if (width < 0) 946 if (width < 0)
804 width = x_text_width (f, cachel, Dynarr_atp (buf, 0), Dynarr_length (buf)); 947 width = x_text_width (f, cachel, Dynarr_atp (buf, 0), Dynarr_length (buf));
805 height = DISPLAY_LINE_HEIGHT (dl);
806 948
807 /* Regularize the variables passed in. */ 949 /* Regularize the variables passed in. */
808 950
809 if (clip_start < xpos) 951 if (clip_start < xpos)
810 clip_start = xpos; 952 clip_start = xpos;
814 return; 956 return;
815 957
816 xpos -= xoffset; 958 xpos -= xoffset;
817 959
818 /* make sure the area we are about to display is subwindow free. */ 960 /* make sure the area we are about to display is subwindow free. */
819 redisplay_unmap_subwindows_maybe (f, clip_start, DISPLAY_LINE_YPOS (dl), 961 redisplay_unmap_subwindows_maybe (f, clip_start, ypos,
820 clip_end - clip_start, DISPLAY_LINE_HEIGHT (dl)); 962 clip_end - clip_start, height);
821
822 nruns = separate_textual_runs (text_storage, runs, Dynarr_atp (buf, 0),
823 Dynarr_length (buf));
824 963
825 cursor_clip = (cursor_start >= clip_start && 964 cursor_clip = (cursor_start >= clip_start &&
826 cursor_start < clip_end); 965 cursor_start < clip_end);
827 966
828 /* This cursor code is really a mess. */ 967 /* This cursor code is really a mess. */
856 995
857 if ((cursor && focus && NILP (bar_cursor_value) 996 if ((cursor && focus && NILP (bar_cursor_value)
858 && !NILP (w->text_cursor_visible_p)) || NILP (bg_pmap)) 997 && !NILP (w->text_cursor_visible_p)) || NILP (bg_pmap))
859 bgc = 0; 998 bgc = 0;
860 else 999 else
861 bgc = x_get_gc (d, Qnil, cachel->foreground, cachel->background, 1000 {
862 bg_pmap, Qnil); 1001 bgc = x_get_gc (d, Qnil, cachel->foreground, cachel->background,
1002 bg_pmap, Qnil);
1003 }
863 1004
864 if (bgc) 1005 if (bgc)
865 XFillRectangle (dpy, x_win, bgc, clip_start, 1006 {
866 DISPLAY_LINE_YPOS (dl), clip_end - clip_start, 1007 XFillRectangle (dpy, x_win, bgc, clip_start,
867 height); 1008 ypos, clip_end - clip_start,
1009 height);
1010 }
1011
1012 nruns = separate_textual_runs (text_storage, runs, Dynarr_atp (buf, 0),
1013 Dynarr_length (buf));
868 1014
869 for (i = 0; i < nruns; i++) 1015 for (i = 0; i < nruns; i++)
870 { 1016 {
871 Lisp_Object font = FACE_CACHEL_FONT (cachel, runs[i].charset); 1017 Lisp_Object font = FACE_CACHEL_FONT (cachel, runs[i].charset);
872 Lisp_Font_Instance *fi = XFONT_INSTANCE (font); 1018 Lisp_Font_Instance *fi = XFONT_INSTANCE (font);
874 int need_clipping; 1020 int need_clipping;
875 1021
876 if (EQ (font, Vthe_null_font_instance)) 1022 if (EQ (font, Vthe_null_font_instance))
877 continue; 1023 continue;
878 1024
879 this_width = x_text_width_single_run (cachel, runs + i); 1025 this_width = x_text_width_single_run (f, cachel, runs + i);
880 need_clipping = (dl->clip || clip_start > xpos || 1026 need_clipping = (dl->clip || clip_start > xpos ||
881 clip_end < xpos + this_width); 1027 clip_end < xpos + this_width);
882 1028
883 /* XDrawImageString only clears the area equal to the height of 1029 /* XDrawImageString only clears the area equal to the height of
884 the given font. It is possible that a font is being displayed 1030 the given font. It is possible that a font is being displayed
893 { 1039 {
894 int ypos1_line, ypos1_string, ypos2_line, ypos2_string; 1040 int ypos1_line, ypos1_string, ypos2_line, ypos2_string;
895 1041
896 ypos1_string = dl->ypos - fi->ascent; 1042 ypos1_string = dl->ypos - fi->ascent;
897 ypos2_string = dl->ypos + fi->descent; 1043 ypos2_string = dl->ypos + fi->descent;
898 ypos1_line = DISPLAY_LINE_YPOS (dl); 1044 ypos1_line = ypos;
899 ypos2_line = ypos1_line + DISPLAY_LINE_HEIGHT (dl); 1045 ypos2_line = ypos1_line + height;
900 1046
901 /* Make sure we don't clear below the real bottom of the 1047 /* Make sure we don't clear below the real bottom of the
902 line. */ 1048 line. */
903 if (ypos1_string > ypos2_line) 1049 if (ypos1_string > ypos2_line)
904 ypos1_string = ypos2_line; 1050 ypos1_string = ypos2_line;
920 } 1066 }
921 } 1067 }
922 else 1068 else
923 { 1069 {
924 redisplay_clear_region (window, findex, clear_start, 1070 redisplay_clear_region (window, findex, clear_start,
925 DISPLAY_LINE_YPOS (dl), clear_end - clear_start, 1071 ypos, clear_end - clear_start,
926 height); 1072 height);
927 } 1073 }
928 } 1074 }
929 1075
930 if (cursor && cursor_cachel && focus && NILP (bar_cursor_value)) 1076 if (cursor && cursor_cachel && focus && NILP (bar_cursor_value))
931 gc = x_get_gc (d, font, cursor_cachel->foreground, 1077 {
932 cursor_cachel->background, Qnil, Qnil); 1078 #ifdef USE_XFT
1079 fg = XFT_FROB_LISP_COLOR (cursor_cachel->foreground, 0);
1080 bg = XFT_FROB_LISP_COLOR (cursor_cachel->background, 0);
1081 #endif
1082 gc = x_get_gc (d, font, cursor_cachel->foreground,
1083 cursor_cachel->background, Qnil, Qnil);
1084 }
933 else if (cachel->dim) 1085 else if (cachel->dim)
934 { 1086 {
935 /* Ensure the gray bitmap exists */ 1087 /* Ensure the gray bitmap exists */
936 if (DEVICE_X_GRAY_PIXMAP (d) == None) 1088 if (DEVICE_X_GRAY_PIXMAP (d) == None)
937 DEVICE_X_GRAY_PIXMAP (d) = 1089 DEVICE_X_GRAY_PIXMAP (d) =
938 XCreateBitmapFromData (dpy, x_win, (char *)gray_bits, 1090 XCreateBitmapFromData (dpy, x_win, (char *)gray_bits,
939 gray_width, gray_height); 1091 gray_width, gray_height);
940 1092
941 /* Request a GC with the gray stipple pixmap to draw dimmed text */ 1093 /* Request a GC with the gray stipple pixmap to draw dimmed text */
1094 #ifdef USE_XFT
1095 fg = XFT_FROB_LISP_COLOR (cachel->foreground, 1);
1096 bg = XFT_FROB_LISP_COLOR (cachel->background, 0);
1097 #endif
942 gc = x_get_gc (d, font, cachel->foreground, cachel->background, 1098 gc = x_get_gc (d, font, cachel->foreground, cachel->background,
943 Qdim, Qnil); 1099 Qdim, Qnil);
944 } 1100 }
945 else 1101 else
946 gc = x_get_gc (d, font, cachel->foreground, cachel->background, 1102 {
947 Qnil, Qnil); 1103 #ifdef USE_XFT
948 1104 fg = XFT_FROB_LISP_COLOR (cachel->foreground, 0);
949 if (need_clipping) 1105 bg = XFT_FROB_LISP_COLOR (cachel->background, 0);
950 { 1106 #endif
951 XRectangle clip_box[1]; 1107 gc = x_get_gc (d, font, cachel->foreground, cachel->background,
952 1108 Qnil, Qnil);
953 clip_box[0].x = 0; 1109 }
954 clip_box[0].y = 0; 1110 #ifdef USE_XFT
955 clip_box[0].width = clip_end - clip_start; 1111 {
956 clip_box[0].height = height; 1112 XftFont *rf = FONT_INSTANCE_X_XFTFONT (fi);
957 1113
958 XSetClipRectangles (dpy, gc, clip_start, DISPLAY_LINE_YPOS (dl), 1114 if (rf)
959 clip_box, 1, Unsorted); 1115 {
960 } 1116 use_x_font = 0;
961 1117 if (need_clipping)
962 if (runs[i].dimension == 1) 1118 {
963 (bgc ? XDrawString : XDrawImageString) (dpy, x_win, gc, xpos, 1119 Region clip_reg = XCreateRegion();
964 dl->ypos, (char *) runs[i].ptr, 1120 XRectangle clip_box = { clip_start, ypos,
965 runs[i].len); 1121 clip_end - clip_start, height };
966 else 1122
967 (bgc ? XDrawString16 : XDrawImageString16) (dpy, x_win, gc, xpos, 1123 XUnionRectWithRegion (&clip_box, clip_reg, clip_reg);
968 dl->ypos, 1124 XftDrawSetClip(xftDraw, clip_reg);
969 (XChar2b *) runs[i].ptr, 1125 XDestroyRegion(clip_reg);
970 runs[i].len); 1126 }
1127
1128 if (!bgc)
1129 {
1130 /* #### Neither rect_height nor XftTextExtents as computed
1131 below handles the vertical space taken up by antialiasing,
1132 which for some fonts (eg, Bitstream Vera Sans Mono-16 on
1133 my Mac PowerBook G4) leaves behind orphaned dots on
1134 insertion or deletion earlier in the line, especially in
1135 the case of the underscore character.
1136 Interestingly, insertion or deletion of a single character
1137 immediately after a refresh does not leave any droppings,
1138 but any further insertions or deletions do.
1139 While adding a pixel to rect_height (mostly) takes care of
1140 this, it trashes aggressively laid-out elements like the
1141 modeline (overwriting part of the bevel).
1142 OK, unconditionally redraw the bevel, and increment
1143 rect_height by 1. See x_output_display_block. -- sjt */
1144 struct textual_run *run = &runs[i];
1145 int rect_width = x_text_width_single_run (f, cachel, run);
1146 #ifndef USE_XFTTEXTENTS_TO_AVOID_FONT_DROPPINGS
1147 int rect_height = FONT_INSTANCE_ASCENT(fi)
1148 + FONT_INSTANCE_DESCENT(fi) + 1;
1149 #else
1150 int rect_height = FONT_INSTANCE_ASCENT(fi)
1151 + FONT_INSTANCE_DESCENT(fi);
1152 XGlyphInfo gi;
1153 if (run->dimension == 2) {
1154 XftTextExtents16 (dpy,
1155 FONT_INSTANCE_X_XFTFONT(fi),
1156 (XftChar16 *) run->ptr, run->len, &gi);
1157 } else {
1158 XftTextExtents8 (dpy,
1159 FONT_INSTANCE_X_XFTFONT(fi),
1160 run->ptr, run->len, &gi);
1161 }
1162 rect_height = rect_height > gi.height
1163 ? rect_height : gi.height;
1164 #endif
1165
1166 XftDrawRect (xftDraw, &bg,
1167 xpos, ypos, rect_width, rect_height);
1168 }
1169
1170 if (runs[i].dimension == 1)
1171 XftDrawString8 (xftDraw, &fg, rf, xpos, dl->ypos,
1172 runs[i].ptr, runs[i].len);
1173 else
1174 XftDrawString16 (xftDraw, &fg, rf, xpos, dl->ypos,
1175 (XftChar16 *) runs[i].ptr, runs[i].len);
1176 }
1177 }
1178 #endif
1179 {
1180 if (use_x_font)
1181 {
1182 if (need_clipping)
1183 {
1184 XRectangle clip_box[1];
1185
1186 clip_box[0].x = 0;
1187 clip_box[0].y = 0;
1188 clip_box[0].width = clip_end - clip_start;
1189 clip_box[0].height = height;
1190
1191 XSetClipRectangles (dpy, gc, clip_start, ypos,
1192 clip_box, 1, YXBanded);
1193 }
1194
1195 if (runs[i].dimension == 1)
1196 (bgc ? XDrawString : XDrawImageString)
1197 (dpy, x_win, gc, xpos, dl->ypos,
1198 (char *) runs[i].ptr, runs[i].len);
1199 else
1200 (bgc ? XDrawString16 : XDrawImageString16)
1201 (dpy, x_win, gc, xpos, dl->ypos,
1202 (XChar2b *) runs[i].ptr, runs[i].len);
1203 }
1204 }
971 1205
972 /* We draw underlines in the same color as the text. */ 1206 /* We draw underlines in the same color as the text. */
973 if (cachel->underline) 1207 if (cachel->underline)
974 { 1208 {
975 int upos, uthick; 1209 int upos, uthick;
976 unsigned long upos_ext, uthick_ext; 1210 unsigned long upos_ext, uthick_ext;
977 XFontStruct *xfont; 1211 XFontStruct *fs =
978 1212 use_x_font ? FONT_INSTANCE_X_FONT (XFONT_INSTANCE (font)) : 0;
979 xfont = FONT_INSTANCE_X_FONT (XFONT_INSTANCE (font)); 1213 /* #### the logic of the next two may be suboptimal: we may want
980 if (!XGetFontProperty (xfont, XA_UNDERLINE_POSITION, &upos_ext)) 1214 to use the POSITION and/or THICKNESS information with Xft */
1215 if (fs && XGetFontProperty (fs, XA_UNDERLINE_POSITION, &upos_ext))
1216 upos = (int) upos_ext;
1217 else
981 upos = dl->descent / 2; 1218 upos = dl->descent / 2;
1219 if (fs && XGetFontProperty (fs, XA_UNDERLINE_THICKNESS, &uthick_ext))
1220 uthick = (int) uthick_ext;
982 else 1221 else
983 upos = (int) upos_ext;
984 if (!XGetFontProperty (xfont, XA_UNDERLINE_THICKNESS, &uthick_ext))
985 uthick = 1; 1222 uthick = 1;
986 else
987 uthick = (int) uthick_ext;
988
989 if (dl->ypos + upos < dl->ypos + dl->descent - dl->clip) 1223 if (dl->ypos + upos < dl->ypos + dl->descent - dl->clip)
990 { 1224 {
991 if (dl->ypos + upos + uthick > dl->ypos + dl->descent - dl->clip) 1225 if (dl->ypos + upos + uthick > dl->ypos + dl->descent - dl->clip)
992 uthick = dl->descent - dl->clip - upos; 1226 uthick = dl->descent - dl->clip - upos;
993 1227
1006 1240
1007 if (cachel->strikethru) 1241 if (cachel->strikethru)
1008 { 1242 {
1009 int ascent, descent, upos, uthick; 1243 int ascent, descent, upos, uthick;
1010 unsigned long ascent_ext, descent_ext, uthick_ext; 1244 unsigned long ascent_ext, descent_ext, uthick_ext;
1011 XFontStruct *xfont; 1245 XFontStruct *fs = FONT_INSTANCE_X_FONT (fi);
1012
1013 xfont = FONT_INSTANCE_X_FONT (XFONT_INSTANCE (font));
1014 1246
1015 if (!XGetFontProperty (xfont, XA_STRIKEOUT_ASCENT, &ascent_ext)) 1247 if (!use_x_font)
1016 ascent = xfont->ascent; 1248 {
1249 ascent = dl->ascent;
1250 descent = dl->descent;
1251 uthick = 1;
1252 }
1017 else 1253 else
1018 ascent = (int) ascent_ext; 1254 {
1019 if (!XGetFontProperty (xfont, XA_STRIKEOUT_DESCENT, &descent_ext)) 1255 if (!XGetFontProperty (fs, XA_STRIKEOUT_ASCENT, &ascent_ext))
1020 descent = xfont->descent; 1256 ascent = fs->ascent;
1021 else 1257 else
1022 descent = (int) descent_ext; 1258 ascent = (int) ascent_ext;
1023 if (!XGetFontProperty (xfont, XA_UNDERLINE_THICKNESS, &uthick_ext)) 1259 if (!XGetFontProperty (fs, XA_STRIKEOUT_DESCENT, &descent_ext))
1024 uthick = 1; 1260 descent = fs->descent;
1025 else 1261 else
1026 uthick = (int) uthick_ext; 1262 descent = (int) descent_ext;
1263 if (!XGetFontProperty (fs, XA_UNDERLINE_THICKNESS, &uthick_ext))
1264 uthick = 1;
1265 else
1266 uthick = (int) uthick_ext;
1267 }
1027 1268
1028 upos = ascent - ((ascent + descent) / 2) + 1; 1269 upos = ascent - ((ascent + descent) / 2) + 1;
1029 1270
1030 /* Generally, upos will be positive (above the baseline),so 1271 /* Generally, upos will be positive (above the baseline),so
1031 subtract */ 1272 subtract */
1044 } 1285 }
1045 1286
1046 /* Restore the GC */ 1287 /* Restore the GC */
1047 if (need_clipping) 1288 if (need_clipping)
1048 { 1289 {
1049 XSetClipMask (dpy, gc, None); 1290 #ifdef USE_XFT
1050 XSetClipOrigin (dpy, gc, 0, 0); 1291 if (!use_x_font)
1292 {
1293 XftDrawSetClip(xftDraw, 0);
1294 }
1295 else
1296 {
1297 #endif
1298 XSetClipMask (dpy, gc, None);
1299 XSetClipOrigin (dpy, gc, 0, 0);
1300 #ifdef USE_XFT
1301 }
1302 #endif
1051 } 1303 }
1052 1304
1053 /* If we are actually superimposing the cursor then redraw with just 1305 /* If we are actually superimposing the cursor then redraw with just
1054 the appropriate section highlighted. */ 1306 the appropriate section highlighted. */
1055 if (cursor_clip && !cursor && focus && cursor_cachel) 1307 if (cursor_clip && !cursor && focus && cursor_cachel)
1056 { 1308 {
1057 GC cgc; 1309 #ifdef USE_XFT
1058 XRectangle clip_box[1]; 1310 if (!use_x_font) /* Xft */
1059 1311 {
1060 cgc = x_get_gc (d, font, cursor_cachel->foreground, 1312 XftFont *rf = FONT_INSTANCE_X_XFTFONT (fi);
1061 cursor_cachel->background, Qnil, Qnil); 1313
1062 1314 { /* set up clipping */
1063 clip_box[0].x = 0; 1315 Region clip_reg = XCreateRegion();
1064 clip_box[0].y = 0; 1316 XRectangle clip_box = { cursor_start, ypos,
1065 clip_box[0].width = cursor_width; 1317 cursor_width, height };
1066 clip_box[0].height = height; 1318
1067 1319 XUnionRectWithRegion (&clip_box, clip_reg, clip_reg);
1068 XSetClipRectangles (dpy, cgc, cursor_start, DISPLAY_LINE_YPOS (dl), 1320 XftDrawSetClip(xftDraw, clip_reg);
1069 clip_box, 1, Unsorted); 1321 XDestroyRegion(clip_reg);
1070 1322 }
1071 if (runs[i].dimension == 1) 1323 { /* draw background rectangle & draw text */
1072 XDrawImageString (dpy, x_win, cgc, xpos, dl->ypos, 1324 int rect_height = FONT_INSTANCE_ASCENT(fi)
1073 (char *) runs[i].ptr, runs[i].len); 1325 + FONT_INSTANCE_DESCENT(fi);
1074 else 1326 int rect_width = x_text_width_single_run(f, cachel, &runs[i]);
1075 XDrawImageString16 (dpy, x_win, cgc, xpos, dl->ypos, 1327 XftColor xft_color;
1076 (XChar2b *) runs[i].ptr, runs[i].len); 1328
1077 1329 xft_color = XFT_FROB_LISP_COLOR (cursor_cachel->background, 0);
1078 XSetClipMask (dpy, cgc, None); 1330 XftDrawRect (xftDraw, &xft_color,
1079 XSetClipOrigin (dpy, cgc, 0, 0); 1331 xpos, ypos, rect_width, rect_height);
1332
1333 xft_color = XFT_FROB_LISP_COLOR (cursor_cachel->foreground, 0);
1334 if (runs[i].dimension == 1)
1335 XftDrawString8 (xftDraw, &xft_color, rf, xpos, dl->ypos,
1336 runs[i].ptr, runs[i].len);
1337 else
1338 XftDrawString16 (xftDraw, &xft_color, rf, xpos, dl->ypos,
1339 (XftChar16 *) runs[i].ptr, runs[i].len);
1340 }
1341
1342 XftDrawSetClip(xftDraw, 0);
1343 }
1344 else /* core font, not Xft */
1345 {
1346 #endif
1347 GC cgc;
1348 XRectangle clip_box[1];
1349
1350 cgc = x_get_gc (d, font, cursor_cachel->foreground,
1351 cursor_cachel->background, Qnil, Qnil);
1352
1353 clip_box[0].x = 0;
1354 clip_box[0].y = 0;
1355 clip_box[0].width = cursor_width;
1356 clip_box[0].height = height;
1357
1358 XSetClipRectangles (dpy, cgc, cursor_start, ypos,
1359 clip_box, 1, YXBanded);
1360 if (runs[i].dimension == 1)
1361 XDrawImageString (dpy, x_win, cgc, xpos, dl->ypos,
1362 (char *) runs[i].ptr, runs[i].len);
1363 else
1364 XDrawImageString16 (dpy, x_win, cgc, xpos, dl->ypos,
1365 (XChar2b *) runs[i].ptr, runs[i].len);
1366
1367 XSetClipMask (dpy, cgc, None);
1368 XSetClipOrigin (dpy, cgc, 0, 0);
1369 #ifdef USE_XFT
1370 }
1371 #endif
1080 } 1372 }
1081 1373
1082 xpos += this_width; 1374 xpos += this_width;
1083 } 1375 }
1084 1376
1100 be called with exactly one character, so we know we 1392 be called with exactly one character, so we know we
1101 can always use runs[0]. 1393 can always use runs[0].
1102 1394
1103 This is bogus as all hell, however. The cursor handling in 1395 This is bogus as all hell, however. The cursor handling in
1104 this function is way bogus and desperately needs to be 1396 this function is way bogus and desperately needs to be
1105 cleaned up. (In particular, the drawing of the cursor should 1397 cleaned up. (In particular, the drawing of the cursor should
1106 really really be separated out of this function. This may be 1398 really really be separated out of this function. This may be
1107 a bit tricky now because this function itself does way too 1399 a bit tricky now because this function itself does way too
1108 much stuff, a lot of which needs to be moved into 1400 much stuff, a lot of which needs to be moved into
1109 redisplay.c) This is the only way to be able to easily add 1401 redisplay.c.) This is the only way to be able to easily add
1110 new cursor types or (e.g.) make the bar cursor be able to 1402 new cursor types or (e.g.) make the bar cursor be able to
1111 span two characters instead of overlaying just one. */ 1403 span two characters instead of overlaying just one. */
1112 int bogusly_obtained_ascent_value = 1404 int bogusly_obtained_ascent_value =
1113 XFONT_INSTANCE (FACE_CACHEL_FONT (cachel, runs[0].charset))->ascent; 1405 XFONT_INSTANCE (FACE_CACHEL_FONT (cachel, runs[0].charset))->ascent;
1114 1406
1123 Qnil, Qnil, Qnil); 1415 Qnil, Qnil, Qnil);
1124 } 1416 }
1125 1417
1126 tmp_y = dl->ypos - bogusly_obtained_ascent_value; 1418 tmp_y = dl->ypos - bogusly_obtained_ascent_value;
1127 tmp_height = cursor_height; 1419 tmp_height = cursor_height;
1128 if (tmp_y + tmp_height > (int) (DISPLAY_LINE_YPOS(dl) + height)) 1420 if (tmp_y + tmp_height > (int) (ypos + height))
1129 { 1421 {
1130 tmp_y = DISPLAY_LINE_YPOS (dl) + height - tmp_height; 1422 tmp_y = ypos + height - tmp_height;
1131 if (tmp_y < (int) DISPLAY_LINE_YPOS (dl)) 1423 if (tmp_y < (int) ypos)
1132 tmp_y = DISPLAY_LINE_YPOS (dl); 1424 tmp_y = ypos;
1133 tmp_height = DISPLAY_LINE_YPOS (dl) + height - tmp_y; 1425 tmp_height = ypos + height - tmp_y;
1134 } 1426 }
1135 1427
1136 if (need_clipping) 1428 if (need_clipping)
1137 { 1429 {
1138 XRectangle clip_box[1]; 1430 XRectangle clip_box[1];
1139 clip_box[0].x = 0; 1431 clip_box[0].x = 0;
1140 clip_box[0].y = 0; 1432 clip_box[0].y = 0;
1141 clip_box[0].width = clip_end - clip_start; 1433 clip_box[0].width = clip_end - clip_start;
1142 clip_box[0].height = tmp_height; 1434 clip_box[0].height = tmp_height;
1143 XSetClipRectangles (dpy, gc, clip_start, tmp_y, 1435 XSetClipRectangles (dpy, gc, clip_start, tmp_y,
1144 clip_box, 1, Unsorted); 1436 /* #### why not Unsorted? */
1437 clip_box, 1, YXBanded);
1145 } 1438 }
1146 1439
1147 if (!focus && NILP (bar_cursor_value)) 1440 if (!focus && NILP (bar_cursor_value))
1148 { 1441 {
1149 XDrawRectangle (dpy, x_win, gc, cursor_start, tmp_y, 1442 XDrawRectangle (dpy, x_win, gc, cursor_start, tmp_y,
1160 { 1453 {
1161 XSetClipMask (dpy, gc, None); 1454 XSetClipMask (dpy, gc, None);
1162 XSetClipOrigin (dpy, gc, 0, 0); 1455 XSetClipOrigin (dpy, gc, 0, 0);
1163 } 1456 }
1164 } 1457 }
1458
1459 #ifdef USE_XFT
1460 #undef XFT_FROB_LISP_COLOR
1461 #endif
1462
1165 } 1463 }
1166 1464
1167 void 1465 void
1168 x_output_x_pixmap (struct frame *f, Lisp_Image_Instance *p, int x, 1466 x_output_x_pixmap (struct frame *f, Lisp_Image_Instance *p, int x,
1169 int y, int xoffset, int yoffset, 1467 int y, int xoffset, int yoffset,
1623 XQueryColor (dpy, cmap, &topc); 1921 XQueryColor (dpy, cmap, &topc);
1624 /* don't overflow/wrap! */ 1922 /* don't overflow/wrap! */
1625 topc.red = MINL (65535, (unsigned long) topc.red * 6 / 5); 1923 topc.red = MINL (65535, (unsigned long) topc.red * 6 / 5);
1626 topc.green = MINL (65535, (unsigned long) topc.green * 6 / 5); 1924 topc.green = MINL (65535, (unsigned long) topc.green * 6 / 5);
1627 topc.blue = MINL (65535, (unsigned long) topc.blue * 6 / 5); 1925 topc.blue = MINL (65535, (unsigned long) topc.blue * 6 / 5);
1628 if (allocate_nearest_color (dpy, cmap, visual, &topc)) 1926 if (x_allocate_nearest_color (dpy, cmap, visual, &topc))
1629 { 1927 {
1630 *top_shadow = topc.pixel; 1928 *top_shadow = topc.pixel;
1631 top_frobbed = 1; 1929 top_frobbed = 1;
1632 } 1930 }
1633 } 1931 }
1639 botc.pixel = background; 1937 botc.pixel = background;
1640 XQueryColor (dpy, cmap, &botc); 1938 XQueryColor (dpy, cmap, &botc);
1641 botc.red = (unsigned short) ((unsigned long) botc.red * 3 / 5); 1939 botc.red = (unsigned short) ((unsigned long) botc.red * 3 / 5);
1642 botc.green = (unsigned short) ((unsigned long) botc.green * 3 / 5); 1940 botc.green = (unsigned short) ((unsigned long) botc.green * 3 / 5);
1643 botc.blue = (unsigned short) ((unsigned long) botc.blue * 3 / 5); 1941 botc.blue = (unsigned short) ((unsigned long) botc.blue * 3 / 5);
1644 if (allocate_nearest_color (dpy, cmap, visual, &botc)) 1942 if (x_allocate_nearest_color (dpy, cmap, visual, &botc))
1645 { 1943 {
1646 *bottom_shadow = botc.pixel; 1944 *bottom_shadow = botc.pixel;
1647 bottom_frobbed = 1; 1945 bottom_frobbed = 1;
1648 } 1946 }
1649 } 1947 }