Mercurial > hg > xemacs-beta
comparison src/redisplay-xlike-inc.c @ 4882:eab9498ecc0e
merge most of rest of redisplay-x.c and redisplay-gtk.c into redisplay-xlike-inc.c
-------------------- ChangeLog entries follow: --------------------
src/ChangeLog addition:
2010-01-18 Ben Wing <ben@xemacs.org>
* redisplay-gtk.c:
* redisplay-gtk.c (gtk_bevel_area):
* redisplay-x.c:
* redisplay-x.c (THIS_IS_X):
* redisplay-xlike-inc.c:
* redisplay-xlike-inc.c (XLIKE_text_width_single_run):
* redisplay-xlike-inc.c (XLIKE_text_width):
* redisplay-xlike-inc.c (XLIKE_output_display_block):
* redisplay-xlike-inc.c (XLIKE_get_gc):
* redisplay-xlike-inc.c (XLIKE_output_string):
* redisplay-xlike-inc.c (XLIKE_OUTPUT_XLIKE_PIXMAP):
* redisplay-xlike-inc.c (XLIKE_output_pixmap):
* redisplay-xlike-inc.c (XLIKE_output_vertical_divider):
* redisplay-xlike-inc.c (XLIKE_output_blank):
* redisplay-xlike-inc.c (XLIKE_output_horizontal_line):
* redisplay-xlike-inc.c (XLIKE_clear_region):
* redisplay-xlike-inc.c (XLIKE_output_eol_cursor):
* redisplay-xlike-inc.c (XLIKE_clear_frame_window):
* redisplay-xlike-inc.c (XLIKE_clear_frame):
* redisplay-xlike-inc.c (XLIKE_flash):
* redisplay-xlike-inc.c (console_type_create_redisplay_XLIKE):
Move lots more code into redisplay-xlike-inc.c. Use macros to
isolate the code that differs among X vs. GTK, to reduce the need
for ifdefs in the middle of the code. Now, redisplay-x.c and
redisplay-gtk.c only contain a few functions whose implementation
is completely different from one to the other, or which are not
present at all in one of them.
GTK code not currently tested, but it has bitrotted somewhat
any. Doing this will help keep it less bitrotty.
* depend: Regenerate.
author | Ben Wing <ben@xemacs.org> |
---|---|
date | Mon, 18 Jan 2010 08:44:49 -0600 |
parents | a4322ac49e37 |
children | b3ce27ca7647 ea701c23ed84 |
comparison
equal
deleted
inserted
replaced
4881:a4322ac49e37 | 4882:eab9498ecc0e |
---|---|
1 /* Common code between X and GTK. | 1 /* Common code between X and GTK. |
2 Copyright (C) 1994, 1995 Board of Trustees, University of Illinois. | 2 Copyright (C) 1994, 1995 Board of Trustees, University of Illinois. |
3 Copyright (C) 1994 Lucid, Inc. | 3 Copyright (C) 1994 Lucid, Inc. |
4 Copyright (C) 1995 Sun Microsystems, Inc. | 4 Copyright (C) 1995 Sun Microsystems, Inc. |
5 Copyright (C) 2002, 2003, 2005 Ben Wing. | 5 Copyright (C) 2002, 2003, 2005, 2009, 2010 Ben Wing. |
6 | 6 |
7 This file is part of XEmacs. | 7 This file is part of XEmacs. |
8 | 8 |
9 XEmacs is free software; you can redistribute it and/or modify it | 9 XEmacs is free software; you can redistribute it and/or modify it |
10 under the terms of the GNU General Public License as published by the | 10 under the terms of the GNU General Public License as published by the |
20 along with XEmacs; see the file COPYING. If not, write to | 20 along with XEmacs; see the file COPYING. If not, write to |
21 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | 21 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
22 Boston, MA 02111-1307, USA. */ | 22 Boston, MA 02111-1307, USA. */ |
23 | 23 |
24 /* Synched up with: Not in FSF. */ | 24 /* Synched up with: Not in FSF. */ |
25 | |
26 /* Author: Chuck Thompson */ | |
27 /* Gtk flavor by William Perry */ | |
28 /* X and GTK code merged by Ben Wing, 1-10 */ | |
29 | |
30 /* Lots of work done by Ben Wing for Mule */ | |
31 | |
32 #include <config.h> | |
33 #include "lisp.h" | |
34 | |
35 #include "buffer.h" | |
36 #include "debug.h" | |
37 #include "device-impl.h" | |
38 #include "faces.h" | |
39 #include "file-coding.h" | |
40 #include "frame-impl.h" | |
41 #include "gutter.h" | |
42 #include "redisplay.h" | |
43 #include "sysdep.h" | |
44 #include "window.h" | |
45 | |
46 #ifdef MULE | |
47 #include "mule-ccl.h" | |
48 #endif | |
49 #include "charset.h" | |
50 | |
51 #ifdef THIS_IS_X | |
52 #include "console-x-impl.h" | |
53 #include "glyphs-x.h" | |
54 #include "objects-x-impl.h" | |
55 #include "xgccache.h" | |
56 #else /* THIS_IS_GTK */ | |
57 #include "console-gtk-impl.h" | |
58 #include "gccache-gtk.h" | |
59 #include "glyphs-gtk.h" | |
60 #include "objects-gtk-impl.h" | |
61 #endif /* THIS_IS_GTK */ | |
62 | |
63 #include "EmacsFrame.h" | |
64 #include "EmacsFrameP.h" | |
65 | |
66 #include "sysproc.h" /* for select() */ | |
67 | |
68 #ifdef THIS_IS_X | |
69 #include <X11/bitmaps/gray> | |
70 #endif /* THIS_IS_X */ | |
71 | |
72 #define EOL_CURSOR_WIDTH 5 | |
73 | |
74 /* About some of the types below: | |
75 | |
76 X has two ways of representing a color: (a) as an unsigned long | |
77 representing a color pixel value, i.e. the actual value stored in memory | |
78 or a file at a particular pixel location to indicate that the pixel | |
79 takes on a specific color; and (b) an XColor structure, which | |
80 encapsulates both the RGB components of a color and the associated color | |
81 pixel value. | |
82 | |
83 We call the former type XLIKE_PIXCOLOR and the latter XLIKE_COLOR. | |
84 GTK uses the same GdkColor structure for both, and normally passes in | |
85 a pointer. We provide routines to handle the two logical color types. */ | |
86 | |
87 #ifdef THIS_IS_X | |
88 | |
89 /***************************************************************************/ | |
90 /* Definitions implementing X flavor of XLIKE */ | |
91 /***************************************************************************/ | |
92 | |
93 #define XLIKE_NAME x | |
94 #define USED_IF_X(var) var | |
95 | |
96 /* types */ | |
97 #define XLIKE_DISPLAY Display * | |
98 #define XLIKE_WINDOW Window | |
99 #define XLIKE_GC GC | |
100 #define XLIKE_RECTANGLE XRectangle | |
101 #define XLIKE_GCVALUES XGCValues | |
102 #define XLIKE_COLOR XColor | |
103 #define XLIKE_PIXCOLOR unsigned long | |
104 | |
105 /* constants */ | |
106 #define XLIKE_NONE None | |
107 #define XLIKE_FALSE False | |
108 | |
109 #define XLIKE_GC_BACKGROUND GCBackground | |
110 #define XLIKE_GC_CLIP_MASK GCClipMask | |
111 #define XLIKE_GC_CLIP_X_ORIGIN GCClipXOrigin | |
112 #define XLIKE_GC_CLIP_Y_ORIGIN GCClipYOrigin | |
113 #define XLIKE_GC_EXPOSURES GCGraphicsExposures | |
114 #define XLIKE_GC_FILL GCFillStyle | |
115 #define XLIKE_GC_FONT GCFont | |
116 #define XLIKE_GC_FOREGROUND GCForeground | |
117 #define XLIKE_GC_FUNCTION GCFunction | |
118 #define XLIKE_GC_LINE_WIDTH GCLineWidth | |
119 #define XLIKE_GC_STIPPLE GCStipple | |
120 #define XLIKE_GC_TILE GCTile | |
121 | |
122 #define XLIKE_GX_COPY GXcopy | |
123 #define XLIKE_GX_XOR GXxor | |
124 | |
125 #define XLIKE_FILL_MEMBER fill_style | |
126 #define XLIKE_FILL_STIPPLED FillStippled | |
127 #define XLIKE_FILL_OPAQUE_STIPPLED FillOpaqueStippled | |
128 #define XLIKE_FILL_TILED FillTiled | |
129 #define XLIKE_FILL_SOLID FillSolid | |
130 | |
131 /* functions */ | |
132 #define GET_XLIKE_DISPLAY(d) DEVICE_X_DISPLAY (d) | |
133 #define GET_XLIKE_WINDOW(w) XtWindow (FRAME_X_TEXT_WIDGET (f)) | |
134 #define XLIKE_FILL_RECTANGLE(dpy, x_win, gc, x, y, width, height) \ | |
135 XFillRectangle (dpy, x_win, gc, x, y, width, height) | |
136 #define XLIKE_DRAW_RECTANGLE(dpy, x_win, gc, x, y, width, height) \ | |
137 XDrawRectangle (dpy, x_win, gc, x, y, width, height) | |
138 #define XLIKE_DRAW_LINE(dpy, x_win, gc, x1, y1, x2, y2) \ | |
139 XDrawLine (dpy, x_win, gc, x1, y1, x2, y2) | |
140 #define XLIKE_OUTPUT_XLIKE_PIXMAP x_output_x_pixmap | |
141 | |
142 #define XLIKE_DISPLAY_LINE_HEIGHT(dl) DISPLAY_LINE_HEIGHT (dl) | |
143 #define XLIKE_DISPLAY_LINE_YPOS(dl) DISPLAY_LINE_YPOS (dl) | |
144 #define XLIKE_DISPLAY_LINE_TOP_CLIP(dl) ((dl)->top_clip) | |
145 #define XLIKE_SET_CLIP_RECTANGLE(dpy, gc, xorig, yorig, prect) \ | |
146 /* #### why not Unsorted? */ \ | |
147 XSetClipRectangles (dpy, gc, xorig, yorig, prect, 1, YXBanded) | |
148 #define XLIKE_CLEAR_CLIP_MASK(dpy, gc) \ | |
149 do \ | |
150 { \ | |
151 XSetClipMask (dpy, gc, None); \ | |
152 XSetClipOrigin (dpy, gc, 0, 0); \ | |
153 } \ | |
154 while (0) | |
155 #define XLIKE_FLUSH(dpy) XSync (dpy, False) | |
156 #define XLIKE_CLEAR_AREA(dpy, win, x, y, width, height) \ | |
157 XClearArea (dpy, win, x, y, width, height, False) | |
158 | |
159 #define IMAGE_INSTANCE_XLIKE_MASK IMAGE_INSTANCE_X_MASK | |
160 #define XIMAGE_INSTANCE_XLIKE_PIXMAP XIMAGE_INSTANCE_X_PIXMAP | |
161 #define COLOR_INSTANCE_XLIKE_COLOR COLOR_INSTANCE_X_COLOR | |
162 #define FONT_INSTANCE_XLIKE_FONT FONT_INSTANCE_X_FONT | |
163 #define DEVICE_XLIKE_GC_CACHE DEVICE_X_GC_CACHE | |
164 #define DEVICE_XLIKE_GRAY_PIXMAP DEVICE_X_GRAY_PIXMAP | |
165 #define XLIKE_COLOR_TO_PIXCOLOR(ci) ((ci).pixel) | |
166 #define XLIKE_SET_PIXCOLOR_COPY(lval, rval) ((lval) = (rval)) | |
167 #define XLIKE_SET_PIXCOLOR_NUM(lval, rval) ((lval) = (rval)) | |
168 #define XLIKE_FONT_NUM(val) ((val)->fid) | |
169 | |
170 #define XLIKE_OUTPUT_XLIKE_PIXMAP x_output_x_pixmap | |
171 | |
172 /************ End X flavor of XLIKE **********/ | |
173 | |
174 | |
175 | |
176 | |
177 #else /* THIS_IS_GTK */ | |
178 | |
179 /***************************************************************************/ | |
180 /* Definitions implementing GTK flavor of XLIKE */ | |
181 /***************************************************************************/ | |
182 | |
183 #define XLIKE_NAME gtk | |
184 #define USED_IF_X(var) UNUSED (var) | |
185 | |
186 /*types */ | |
187 #define XLIKE_DISPLAY void * | |
188 #define XLIKE_WINDOW GdkWindow * | |
189 #define XLIKE_GC GdkGC * | |
190 #define XLIKE_RECTANGLE GdkRectangle | |
191 #define XLIKE_GCVALUES GdkGCValues | |
192 #define XLIKE_COLOR GdkColor * | |
193 #define XLIKE_PIXCOLOR GdkColor * | |
194 | |
195 /* constants */ | |
196 #define XLIKE_NONE 0 | |
197 #define XLIKE_FALSE FALSE | |
198 | |
199 #define XLIKE_GC_BACKGROUND GDK_GC_BACKGROUND | |
200 #define XLIKE_GC_CLIP_MASK GDK_GC_CLIP_MASK | |
201 #define XLIKE_GC_CLIP_X_ORIGIN GDK_GC_CLIP_X_ORIGIN | |
202 #define XLIKE_GC_CLIP_Y_ORIGIN GDK_GC_CLIP_Y_ORIGIN | |
203 #define XLIKE_GC_EXPOSURES GDK_GC_EXPOSURES | |
204 #define XLIKE_GC_FILL GDK_GC_FILL | |
205 #define XLIKE_GC_FONT GDK_GC_FONT | |
206 #define XLIKE_GC_FOREGROUND GDK_GC_FOREGROUND | |
207 #define XLIKE_GC_FUNCTION GDK_GC_FUNCTION | |
208 #define XLIKE_GC_LINE_WIDTH GDK_GC_LINE_WIDTH | |
209 #define XLIKE_GC_STIPPLE GDK_GC_STIPPLE | |
210 #define XLIKE_GC_TILE GDK_GC_TILE | |
211 | |
212 #define XLIKE_GX_COPY GDK_COPY | |
213 #define XLIKE_GX_XOR GDK_XOR | |
214 | |
215 #define XLIKE_FILL_MEMBER fill | |
216 #define XLIKE_FILL_STIPPLED GDK_STIPPLED | |
217 #define XLIKE_FILL_OPAQUE_STIPPLED GDK_OPAQUE_STIPPLED | |
218 #define XLIKE_FILL_TILED GDK_TILED | |
219 #define XLIKE_FILL_SOLID GDK_SOLID | |
220 | |
221 /* functions */ | |
222 | |
223 #define GET_XLIKE_DISPLAY(d) NULL | |
224 #define GET_XLIKE_WINDOW(w) GET_GTK_WIDGET_WINDOW (FRAME_GTK_TEXT_WIDGET (w)) | |
225 #define XLIKE_FILL_RECTANGLE(dpy, x_win, gc, x, y, width, height) \ | |
226 gdk_draw_rectangle (GDK_DRAWABLE (x_win), gc, TRUE, x, y, width, height) | |
227 #define XLIKE_DRAW_RECTANGLE(dpy, x_win, gc, x, y, width, height) \ | |
228 gdk_draw_rectangle (GDK_DRAWABLE (x_win), gc, FALSE, x, y, width, height) | |
229 #define XLIKE_DRAW_LINE(dpy, x_win, gc, x1, y1, x2, y2) \ | |
230 gdk_draw_line (GDK_DRAWABLE (x_win), gc, x1, y1, x2, y2) | |
231 #define XLIKE_OUTPUT_XLIKE_PIXMAP gtk_output_gdk_pixmap | |
232 | |
233 /* FIXME: This is totally bogus. It removes dl->top_clip from the | |
234 equations. If there is a bug involving this, fix it properly! | |
235 Or just ensure that top_clip is 0. */ | |
236 #define XLIKE_DISPLAY_LINE_HEIGHT(dl) \ | |
237 ((dl)->ascent + ((dl)->descent - (dl)->clip) | |
238 #define XLIKE_DISPLAY_LINE_YPOS(dl) ((dl)->ypos - (dl)->ascent) | |
239 #define XLIKE_DISPLAY_LINE_TOP_CLIP(dl) ((0) | |
240 #define XLIKE_SET_CLIP_RECTANGLE(dpy, gc, xorig, yorig, prect) \ | |
241 do \ | |
242 { \ | |
243 gdk_gc_set_clip_rectangle (gc, prect); \ | |
244 gdk_gc_set_clip_origin (gc, xorig, yorig); \ | |
245 } \ | |
246 while (0) | |
247 #define XLIKE_CLEAR_CLIP_MASK(dpy, gc) \ | |
248 do \ | |
249 { \ | |
250 gdk_gc_set_clip_rectangle (gc, NULL); \ | |
251 gdk_gc_set_clip_origin (gc, 0, 0); \ | |
252 } \ | |
253 while (0) | |
254 #define XLIKE_FLUSH(dpy) gdk_flush () | |
255 #define XLIKE_CLEAR_AREA(dpy, win, x, y, width, height) \ | |
256 gdk_window_clear_area (win, x, y, width, height) | |
257 | |
258 #define IMAGE_INSTANCE_XLIKE_MASK IMAGE_INSTANCE_GTK_MASK | |
259 #define XIMAGE_INSTANCE_XLIKE_PIXMAP XIMAGE_INSTANCE_GTK_PIXMAP | |
260 #define COLOR_INSTANCE_XLIKE_COLOR COLOR_INSTANCE_GTK_COLOR | |
261 #define FONT_INSTANCE_XLIKE_FONT FONT_INSTANCE_GTK_FONT | |
262 #define DEVICE_XLIKE_GRAY_PIXMAP DEVICE_GTK_GRAY_PIXMAP | |
263 #define DEVICE_XLIKE_GC_CACHE DEVICE_GTK_GC_CACHE | |
264 #define XLIKE_COLOR_TO_PIXCOLOR(ci) (ci) | |
265 #define XLIKE_SET_PIXCOLOR_COPY(lval, rval) ((lval) = *(rval)) | |
266 #define XLIKE_SET_PIXCOLOR_NUM(lval, rval) ((lval).pixel = (rval)) | |
267 #define XLIKE_FONT_NUM(val) (val) | |
268 | |
269 #define XLIKE_OUTPUT_XLIKE_PIXMAP gtk_output_gdk_pixmap | |
270 | |
271 static void gtk_output_pixmap (struct window *w, | |
272 Lisp_Object image_instance, | |
273 struct display_box *db, | |
274 struct display_glyph_area *dga, | |
275 face_index findex, | |
276 int cursor_start, | |
277 int cursor_width, | |
278 int cursor_height, | |
279 int bgpixmap); | |
280 static void gtk_clear_region (Lisp_Object locale, struct device* d, | |
281 struct frame* f, face_index findex, int x, int y, | |
282 int width, int height, Lisp_Object fcolor, | |
283 Lisp_Object bcolor, | |
284 Lisp_Object background_pixmap); | |
285 static void gtk_bevel_modeline (struct window *w, struct display_line *dl); | |
286 | |
287 #if 0 | |
288 static void __describe_gc (GdkGC *); | |
289 #endif | |
290 | |
291 /************ End GTK flavor of XLIKE **********/ | |
292 | |
293 #endif /* (not) THIS_IS_X */ | |
294 | |
295 | |
296 | |
297 /***************************************************************************/ | |
298 /* Common definitions */ | |
299 /***************************************************************************/ | |
300 | |
301 #define XCOLOR_INSTANCE_XLIKE_COLOR(x) \ | |
302 COLOR_INSTANCE_XLIKE_COLOR (XCOLOR_INSTANCE (x)) | |
303 | |
304 #define XLIKE_PASTE_1(a,b) a##_##b | |
305 #define XLIKE_PASTE(a,b) XLIKE_PASTE_1(a,b) | |
306 #define XLIKE_CONSOLE_HAS_METHOD_1(xlike, name) CONSOLE_HAS_METHOD (xlike, name) | |
307 #define XLIKE_CONSOLE_HAS_METHOD(name) \ | |
308 XLIKE_CONSOLE_HAS_METHOD_1 (XLIKE_NAME, name) | |
309 | |
310 /* Device methods */ | |
311 | |
312 #define XLIKE_text_width XLIKE_PASTE (XLIKE_NAME, text_width) | |
313 #define XLIKE_output_display_block XLIKE_PASTE (XLIKE_NAME, output_display_block) | |
314 #define XLIKE_divider_height XLIKE_PASTE (XLIKE_NAME, divider_height) | |
315 #define XLIKE_eol_cursor_width XLIKE_PASTE (XLIKE_NAME, eol_cursor_width) | |
316 #define XLIKE_output_vertical_divider XLIKE_PASTE (XLIKE_NAME, output_vertical_divider) | |
317 #define XLIKE_clear_region XLIKE_PASTE (XLIKE_NAME, clear_region) | |
318 #define XLIKE_clear_frame XLIKE_PASTE (XLIKE_NAME, clear_frame) | |
319 #define XLIKE_flash XLIKE_PASTE (XLIKE_NAME, flash) | |
320 #define XLIKE_ring_bell XLIKE_PASTE (XLIKE_NAME, ring_bell) | |
321 #define XLIKE_bevel_area XLIKE_PASTE (XLIKE_NAME, bevel_area) | |
322 #define XLIKE_output_string XLIKE_PASTE (XLIKE_NAME, output_string) | |
323 #define XLIKE_output_pixmap XLIKE_PASTE (XLIKE_NAME, output_pixmap) | |
324 #define XLIKE_window_output_begin XLIKE_PASTE (XLIKE_NAME, window_output_begin) | |
325 #define XLIKE_window_output_end XLIKE_PASTE (XLIKE_NAME, window_output_end) | |
326 | |
327 /* Miscellaneous split functions */ | |
328 | |
329 #define console_type_create_redisplay_XLIKE XLIKE_PASTE (console_type_create_redisplay, XLIKE_NAME) | |
330 #define XLIKE_get_gc XLIKE_PASTE (XLIKE_NAME, get_gc) | |
331 #define XLIKE_output_blank XLIKE_PASTE (XLIKE_NAME, output_blank) | |
332 #define XLIKE_text_width_single_run XLIKE_PASTE (XLIKE_NAME, text_width_single_run) | |
333 | |
334 static void XLIKE_output_blank (struct window *w, struct display_line *dl, | |
335 struct rune *rb, int start_pixpos, | |
336 int cursor_start, int cursor_width); | |
337 static void XLIKE_output_horizontal_line (struct window *w, | |
338 struct display_line *dl, | |
339 struct rune *rb); | |
340 | |
341 static void XLIKE_output_vertical_divider (struct window *w, int clear); | |
342 | |
343 static void XLIKE_output_eol_cursor (struct window *w, | |
344 struct display_line *dl, | |
345 int xpos, face_index findex); | |
346 static void XLIKE_clear_frame (struct frame *f); | |
347 static void XLIKE_clear_frame_windows (Lisp_Object window); | |
348 static void XLIKE_window_output_begin (struct window *w); | |
349 static void XLIKE_window_output_end (struct window *w); | |
350 static void XLIKE_bevel_area (struct window *w, face_index findex, | |
351 int x, int y, int width, int height, | |
352 int shadow_thickness, int edges, | |
353 enum edge_style style); | |
354 static void XLIKE_ring_bell (struct device *d, int volume, int pitch, | |
355 int duration); | |
356 | |
357 /****************************************************************************/ | |
358 /* */ | |
359 /* Separate textual runs */ | |
360 /* */ | |
361 /****************************************************************************/ | |
362 | |
25 | 363 |
26 /* Note: We do not use the Xmb*() functions and XFontSets, nor the | 364 /* Note: We do not use the Xmb*() functions and XFontSets, nor the |
27 Motif XFontLists and CompoundStrings. | 365 Motif XFontLists and CompoundStrings. |
28 Those functions are generally losing for a number of reasons. | 366 Those functions are generally losing for a number of reasons. |
29 Most important, they only support one locale (e.g. you could | 367 Most important, they only support one locale (e.g. you could |
351 #if !defined(USE_XFT) && !defined(MULE) | 689 #if !defined(USE_XFT) && !defined(MULE) |
352 return separate_textual_runs_nomule (text_storage, run_storage, | 690 return separate_textual_runs_nomule (text_storage, run_storage, |
353 str, len, cachel); | 691 str, len, cachel); |
354 #endif | 692 #endif |
355 } | 693 } |
694 | |
695 /****************************************************************************/ | |
696 /* */ | |
697 /* Xlike output routines */ | |
698 /* */ | |
699 /****************************************************************************/ | |
700 | |
701 static int | |
702 XLIKE_text_width_single_run (struct frame * USED_IF_XFT (f), | |
703 struct face_cachel *cachel, | |
704 struct textual_run *run) | |
705 { | |
706 Lisp_Object font_inst = FACE_CACHEL_FONT (cachel, run->charset); | |
707 Lisp_Font_Instance *fi = XFONT_INSTANCE (font_inst); | |
708 | |
709 if (!fi->proportional_p) | |
710 return fi->width * run->len; | |
711 #ifdef USE_XFT | |
712 else if (FONT_INSTANCE_X_XFTFONT (fi)) | |
713 { | |
714 static XGlyphInfo glyphinfo; | |
715 struct device *d = XDEVICE (f->device); | |
716 Display *dpy = DEVICE_X_DISPLAY (d); | |
717 | |
718 if (run->dimension == 2) | |
719 { | |
720 XftTextExtents16 (dpy, | |
721 FONT_INSTANCE_X_XFTFONT (fi), | |
722 (XftChar16 *) run->ptr, run->len, &glyphinfo); | |
723 } | |
724 else | |
725 { | |
726 XftTextExtents8 (dpy, | |
727 FONT_INSTANCE_X_XFTFONT (fi), | |
728 run->ptr, run->len, &glyphinfo); | |
729 } | |
730 | |
731 return glyphinfo.xOff; | |
732 } | |
733 #endif | |
734 else if (FONT_INSTANCE_XLIKE_FONT (fi)) | |
735 { | |
736 if (run->dimension == 2) | |
737 { | |
738 #ifdef THIS_IS_X | |
739 return XTextWidth16 (FONT_INSTANCE_X_FONT (fi), | |
740 (XChar2b *) run->ptr, run->len); | |
741 #else /* THIS_IS_GTK */ | |
742 /* stderr_out ("Measuring wide characters\n"); */ | |
743 return gdk_text_width_wc (FONT_INSTANCE_GTK_FONT (fi), | |
744 (GdkWChar *) run->ptr, run->len); | |
745 #endif /* THIS_IS_GTK */ | |
746 } | |
747 else | |
748 { | |
749 #ifdef THIS_IS_X | |
750 return XTextWidth (FONT_INSTANCE_X_FONT (fi), | |
751 (char *) run->ptr, run->len); | |
752 #else /* THIS_IS_GTK */ | |
753 return gdk_text_width (FONT_INSTANCE_GTK_FONT (fi), | |
754 (char *) run->ptr, run->len); | |
755 #endif /* THIS_IS_GTK */ | |
756 } | |
757 } | |
758 else | |
759 abort(); | |
760 return 0; /* shut up GCC */ | |
761 } | |
762 | |
763 /* | |
764 XLIKE_text_width | |
765 | |
766 Given a string and a merged face, return the string's length in pixels | |
767 when displayed in the fonts associated with the face. | |
768 */ | |
769 | |
770 /* #### Break me out into a separate header */ | |
771 int XLIKE_text_width (struct frame *USED_IF_X (f), struct face_cachel *cachel, | |
772 const Ichar *str, Charcount len); | |
773 int | |
774 XLIKE_text_width (struct frame *USED_IF_X (f), struct face_cachel *cachel, | |
775 const Ichar *str, Charcount len) | |
776 { | |
777 /* !!#### Needs review */ | |
778 int width_so_far = 0; | |
779 unsigned char *text_storage = (unsigned char *) ALLOCA (2 * len); | |
780 struct textual_run *runs = alloca_array (struct textual_run, len); | |
781 int nruns; | |
782 int i; | |
783 | |
784 nruns = separate_textual_runs (text_storage, runs, str, len, | |
785 cachel); | |
786 | |
787 for (i = 0; i < nruns; i++) | |
788 width_so_far += XLIKE_text_width_single_run (f, cachel, runs + i); | |
789 | |
790 return width_so_far; | |
791 } | |
792 | |
793 /***************************************************************************** | |
794 XLIKE_divider_height | |
795 | |
796 Return the height of the horizontal divider. This is a function because | |
797 divider_height is a device method. | |
798 | |
799 #### If we add etched horizontal divider lines this will have to get | |
800 smarter. | |
801 ****************************************************************************/ | |
802 static int | |
803 XLIKE_divider_height (void) | |
804 { | |
805 #ifdef THIS_IS_X | |
806 return 1; | |
807 #else /* THIS_IS_GTK */ | |
808 return 2; | |
809 #endif /* THIS_IS_GTK */ | |
810 } | |
811 | |
812 /***************************************************************************** | |
813 XLIKE_eol_cursor_width | |
814 | |
815 Return the width of the end-of-line cursor. This is a function | |
816 because eol_cursor_width is a device method. | |
817 ****************************************************************************/ | |
818 static int | |
819 XLIKE_eol_cursor_width (void) | |
820 { | |
821 return EOL_CURSOR_WIDTH; | |
822 } | |
823 | |
824 /***************************************************************************** | |
825 XLIKE_output_display_block | |
826 | |
827 Given a display line, a block number for that start line, output all | |
828 runes between start and end in the specified display block. | |
829 ****************************************************************************/ | |
830 static void | |
831 XLIKE_output_display_block (struct window *w, struct display_line *dl, | |
832 int block, int start, int end, int start_pixpos, | |
833 int cursor_start, int cursor_width, | |
834 int cursor_height) | |
835 { | |
836 #ifndef USE_XFT | |
837 struct frame *f = XFRAME (w->frame); | |
838 #endif | |
839 Ichar_dynarr *buf; | |
840 Lisp_Object window; | |
841 | |
842 struct display_block *db = Dynarr_atp (dl->display_blocks, block); | |
843 rune_dynarr *rba = db->runes; | |
844 struct rune *rb; | |
845 | |
846 int elt = start; | |
847 face_index findex; | |
848 int xpos, width = 0; | |
849 Lisp_Object charset = Qunbound; /* Qnil is a valid charset when | |
850 MULE is not defined */ | |
851 | |
852 window = wrap_window (w); | |
853 rb = Dynarr_atp (rba, start); | |
854 | |
855 if (!rb) | |
856 /* Nothing to do so don't do anything. */ | |
857 return; | |
858 | |
859 findex = rb->findex; | |
860 xpos = rb->xpos; | |
861 if (rb->type == RUNE_CHAR) | |
862 charset = ichar_charset (rb->object.chr.ch); | |
863 | |
864 if (end < 0) | |
865 end = Dynarr_length (rba); | |
866 buf = Dynarr_new (Ichar); | |
867 | |
868 while (elt < end) | |
869 { | |
870 rb = Dynarr_atp (rba, elt); | |
871 | |
872 if (rb->findex == findex && rb->type == RUNE_CHAR | |
873 && rb->object.chr.ch != '\n' && rb->cursor_type != CURSOR_ON | |
874 && EQ (charset, ichar_charset (rb->object.chr.ch))) | |
875 { | |
876 Dynarr_add (buf, rb->object.chr.ch); | |
877 width += rb->width; | |
878 elt++; | |
879 } | |
880 else | |
881 { | |
882 if (Dynarr_length (buf)) | |
883 { | |
884 XLIKE_output_string (w, dl, buf, xpos, 0, start_pixpos, width, | |
885 findex, 0, cursor_start, cursor_width, | |
886 cursor_height); | |
887 xpos = rb->xpos; | |
888 width = 0; | |
889 } | |
890 Dynarr_reset (buf); | |
891 width = 0; | |
892 | |
893 if (rb->type == RUNE_CHAR) | |
894 { | |
895 findex = rb->findex; | |
896 xpos = rb->xpos; | |
897 charset = ichar_charset (rb->object.chr.ch); | |
898 | |
899 if (rb->cursor_type == CURSOR_ON) | |
900 { | |
901 if (rb->object.chr.ch == '\n') | |
902 { | |
903 XLIKE_output_eol_cursor (w, dl, xpos, findex); | |
904 } | |
905 else | |
906 { | |
907 Dynarr_add (buf, rb->object.chr.ch); | |
908 XLIKE_output_string (w, dl, buf, xpos, 0, start_pixpos, | |
909 rb->width, findex, 1, | |
910 cursor_start, cursor_width, | |
911 cursor_height); | |
912 Dynarr_reset (buf); | |
913 } | |
914 | |
915 xpos += rb->width; | |
916 elt++; | |
917 } | |
918 else if (rb->object.chr.ch == '\n') | |
919 { | |
920 /* Clear in case a cursor was formerly here. */ | |
921 redisplay_clear_region (window, findex, xpos, | |
922 XLIKE_DISPLAY_LINE_YPOS (dl), | |
923 rb->width, | |
924 XLIKE_DISPLAY_LINE_HEIGHT (dl)); | |
925 elt++; | |
926 } | |
927 } | |
928 else if (rb->type == RUNE_BLANK || rb->type == RUNE_HLINE) | |
929 { | |
930 if (rb->type == RUNE_BLANK) | |
931 XLIKE_output_blank (w, dl, rb, start_pixpos, cursor_start, | |
932 cursor_width); | |
933 else | |
934 { | |
935 /* #### Our flagging of when we need to redraw the | |
936 modeline shadows sucks. Since RUNE_HLINE is only used | |
937 by the modeline at the moment it is a good bet | |
938 that if it gets redrawn then we should also | |
939 redraw the shadows. This won't be true forever. | |
940 We borrow the shadow_thickness_changed flag for | |
941 now. */ | |
942 w->shadow_thickness_changed = 1; | |
943 XLIKE_output_horizontal_line (w, dl, rb); | |
944 } | |
945 | |
946 elt++; | |
947 if (elt < end) | |
948 { | |
949 rb = Dynarr_atp (rba, elt); | |
950 | |
951 findex = rb->findex; | |
952 xpos = rb->xpos; | |
953 } | |
954 } | |
955 else if (rb->type == RUNE_DGLYPH) | |
956 { | |
957 Lisp_Object instance; | |
958 struct display_box dbox; | |
959 struct display_glyph_area dga; | |
960 | |
961 redisplay_calculate_display_boxes (dl, rb->xpos, rb->object.dglyph.xoffset, | |
962 rb->object.dglyph.yoffset, start_pixpos, | |
963 rb->width, &dbox, &dga); | |
964 | |
965 window = wrap_window (w); | |
966 instance = glyph_image_instance (rb->object.dglyph.glyph, | |
967 window, ERROR_ME_DEBUG_WARN, 1); | |
968 findex = rb->findex; | |
969 | |
970 if (IMAGE_INSTANCEP (instance)) | |
971 { | |
972 switch (XIMAGE_INSTANCE_TYPE (instance)) | |
973 { | |
974 case IMAGE_TEXT: | |
975 #ifdef THIS_IS_GTK | |
976 { | |
977 /* !!#### Examine for Mule-izing */ | |
978 /* #### This is way losing. See the comment in | |
979 add_glyph_rune(). */ | |
980 Lisp_Object string = | |
981 XIMAGE_INSTANCE_TEXT_STRING (instance); | |
982 convert_ibyte_string_into_ichar_dynarr | |
983 (XSTRING_DATA (string), XSTRING_LENGTH (string), | |
984 buf); | |
985 | |
986 gtk_output_string (w, dl, buf, xpos, | |
987 rb->object.dglyph.xoffset, | |
988 start_pixpos, -1, findex, | |
989 (rb->cursor_type == CURSOR_ON), | |
990 cursor_start, cursor_width, | |
991 cursor_height); | |
992 Dynarr_reset (buf); | |
993 } | |
994 break; | |
995 #else | |
996 ABORT (); | |
997 #endif /* THIS_IS_GTK */ | |
998 case IMAGE_MONO_PIXMAP: | |
999 case IMAGE_COLOR_PIXMAP: | |
1000 redisplay_output_pixmap (w, instance, &dbox, &dga, | |
1001 findex, cursor_start, | |
1002 cursor_width, | |
1003 cursor_height, 0); | |
1004 break; | |
1005 | |
1006 case IMAGE_WIDGET: | |
1007 if (EQ (XIMAGE_INSTANCE_WIDGET_TYPE (instance), | |
1008 Qlayout)) | |
1009 { | |
1010 redisplay_output_layout (window, instance, &dbox, | |
1011 &dga, findex, | |
1012 cursor_start, cursor_width, | |
1013 cursor_height); | |
1014 break; | |
1015 } | |
1016 | |
1017 case IMAGE_SUBWINDOW: | |
1018 redisplay_output_subwindow (w, instance, &dbox, &dga, | |
1019 findex, cursor_start, | |
1020 cursor_width, cursor_height); | |
1021 break; | |
1022 | |
1023 case IMAGE_NOTHING: | |
1024 /* nothing is as nothing does */ | |
1025 break; | |
1026 | |
1027 case IMAGE_POINTER: | |
1028 default: | |
1029 ABORT (); | |
1030 } | |
1031 IMAGE_INSTANCE_OPTIMIZE_OUTPUT | |
1032 (XIMAGE_INSTANCE (instance)) = 0; | |
1033 } | |
1034 | |
1035 xpos += rb->width; | |
1036 elt++; | |
1037 } | |
1038 else | |
1039 ABORT (); | |
1040 } | |
1041 } | |
1042 | |
1043 if (Dynarr_length (buf)) | |
1044 XLIKE_output_string (w, dl, buf, xpos, 0, start_pixpos, width, findex, | |
1045 0, cursor_start, cursor_width, cursor_height); | |
1046 | |
1047 if (dl->modeline | |
1048 && !EQ (Qzero, w->modeline_shadow_thickness) | |
1049 #ifndef USE_XFT | |
1050 /* This optimization doesn't work right with some Xft fonts, which | |
1051 leave antialiasing turds at the boundary. I don't know if this | |
1052 is an Xft bug or not, but I think it is. See x_output_string. */ | |
1053 && (f->clear | |
1054 || f->windows_structure_changed | |
1055 || w->shadow_thickness_changed) | |
1056 #endif | |
1057 ) | |
1058 bevel_modeline (w, dl); | |
1059 | |
1060 Dynarr_free (buf); | |
1061 } | |
1062 | |
1063 /***************************************************************************** | |
1064 XLIKE_get_gc | |
1065 | |
1066 Given a number of parameters return a GC with those properties. | |
1067 ****************************************************************************/ | |
1068 static XLIKE_GC | |
1069 XLIKE_get_gc (struct device *d, Lisp_Object font, Lisp_Object fg, | |
1070 Lisp_Object bg, Lisp_Object bg_pmap, Lisp_Object lwidth) | |
1071 { | |
1072 XLIKE_GCVALUES gcv; | |
1073 unsigned long mask; | |
1074 | |
1075 memset (&gcv, ~0, sizeof (gcv)); | |
1076 gcv.graphics_exposures = XLIKE_FALSE; | |
1077 /* Make absolutely sure that we don't pick up a clipping region in | |
1078 the GC returned by this function. */ | |
1079 gcv.clip_mask = XLIKE_NONE; | |
1080 gcv.clip_x_origin = 0; | |
1081 gcv.clip_y_origin = 0; | |
1082 gcv.XLIKE_FILL_MEMBER = XLIKE_FILL_SOLID; | |
1083 mask = XLIKE_GC_EXPOSURES | XLIKE_GC_CLIP_MASK | XLIKE_GC_CLIP_X_ORIGIN | XLIKE_GC_CLIP_Y_ORIGIN; | |
1084 mask |= XLIKE_GC_FILL; | |
1085 | |
1086 if (!NILP (font) | |
1087 #ifdef USE_XFT | |
1088 /* Only set the font if it's a core font */ | |
1089 /* the renderfont will be set elsewhere (not part of gc) */ | |
1090 && !FONT_INSTANCE_X_XFTFONT (XFONT_INSTANCE (font)) | |
1091 #endif | |
1092 ) | |
1093 { | |
1094 gcv.font = | |
1095 XLIKE_FONT_NUM (FONT_INSTANCE_XLIKE_FONT (XFONT_INSTANCE (font))); | |
1096 mask |= XLIKE_GC_FONT; | |
1097 } | |
1098 | |
1099 /* evil kludge! */ | |
1100 if (!NILP (fg) && !COLOR_INSTANCEP (fg) && !INTP (fg)) | |
1101 { | |
1102 /* #### I fixed one case where this was getting hit. It was a | |
1103 bad macro expansion (compiler bug). */ | |
1104 stderr_out ("Help! x_get_gc got a bogus fg value! fg = "); | |
1105 debug_print (fg); | |
1106 fg = Qnil; | |
1107 } | |
1108 | |
1109 if (!NILP (fg)) | |
1110 { | |
1111 if (COLOR_INSTANCEP (fg)) | |
1112 XLIKE_SET_PIXCOLOR_COPY | |
1113 (gcv.foreground, | |
1114 XLIKE_COLOR_TO_PIXCOLOR (XCOLOR_INSTANCE_XLIKE_COLOR (fg))); | |
1115 else | |
1116 XLIKE_SET_PIXCOLOR_NUM (gcv.foreground, XINT (fg)); | |
1117 mask |= XLIKE_GC_FOREGROUND; | |
1118 } | |
1119 | |
1120 if (!NILP (bg)) | |
1121 { | |
1122 if (COLOR_INSTANCEP (bg)) | |
1123 XLIKE_SET_PIXCOLOR_COPY | |
1124 (gcv.background, | |
1125 XLIKE_COLOR_TO_PIXCOLOR (XCOLOR_INSTANCE_XLIKE_COLOR (bg))); | |
1126 else | |
1127 XLIKE_SET_PIXCOLOR_NUM (gcv.background, XINT (bg)); | |
1128 mask |= XLIKE_GC_BACKGROUND; | |
1129 } | |
1130 | |
1131 /* This special case comes from a request to draw text with a face which has | |
1132 the dim property. We'll use a stippled foreground GC. */ | |
1133 if (EQ (bg_pmap, Qdim)) | |
1134 { | |
1135 assert (DEVICE_XLIKE_GRAY_PIXMAP (d) != XLIKE_NONE); | |
1136 | |
1137 gcv.XLIKE_FILL_MEMBER = XLIKE_FILL_STIPPLED; | |
1138 gcv.stipple = DEVICE_XLIKE_GRAY_PIXMAP (d); | |
1139 mask |= (XLIKE_GC_FILL | XLIKE_GC_STIPPLE); | |
1140 } | |
1141 else if (IMAGE_INSTANCEP (bg_pmap) | |
1142 && IMAGE_INSTANCE_PIXMAP_TYPE_P (XIMAGE_INSTANCE (bg_pmap))) | |
1143 { | |
1144 if (XIMAGE_INSTANCE_PIXMAP_DEPTH (bg_pmap) == 0) | |
1145 { | |
1146 gcv.XLIKE_FILL_MEMBER = XLIKE_FILL_OPAQUE_STIPPLED; | |
1147 gcv.stipple = XIMAGE_INSTANCE_XLIKE_PIXMAP (bg_pmap); | |
1148 mask |= (XLIKE_GC_STIPPLE | XLIKE_GC_FILL); | |
1149 } | |
1150 else | |
1151 { | |
1152 gcv.XLIKE_FILL_MEMBER = XLIKE_FILL_TILED; | |
1153 gcv.tile = XIMAGE_INSTANCE_XLIKE_PIXMAP (bg_pmap); | |
1154 mask |= (XLIKE_GC_TILE | XLIKE_GC_FILL); | |
1155 } | |
1156 } | |
1157 | |
1158 if (!NILP (lwidth)) | |
1159 { | |
1160 gcv.line_width = XINT (lwidth); | |
1161 mask |= XLIKE_GC_LINE_WIDTH; | |
1162 } | |
1163 | |
1164 #if 0 | |
1165 debug_out ("\nx_get_gc: calling gc_cache_lookup\n"); | |
1166 #endif | |
1167 return gc_cache_lookup (DEVICE_XLIKE_GC_CACHE (d), &gcv, mask); | |
1168 } | |
1169 | |
1170 /***************************************************************************** | |
1171 XLIKE_output_string | |
1172 | |
1173 Given a string and a starting position, output that string in the | |
1174 given face. If cursor is true, draw a cursor around the string. | |
1175 Correctly handles multiple charsets in the string. | |
1176 | |
1177 The meaning of the parameters is something like this: | |
1178 | |
1179 W Window that the text is to be displayed in. | |
1180 DL Display line that this text is on. The values in the | |
1181 structure are used to determine the vertical position and | |
1182 clipping range of the text. | |
1183 BUF Dynamic array of Ichars specifying what is actually to be | |
1184 drawn. | |
1185 XPOS X position in pixels where the text should start being drawn. | |
1186 XOFFSET Number of pixels to be chopped off the left side of the | |
1187 text. The effect is as if the text were shifted to the | |
1188 left this many pixels and clipped at XPOS. | |
1189 CLIP_START Clip everything left of this X position. | |
1190 WIDTH Clip everything right of XPOS + WIDTH. | |
1191 FINDEX Index for the face cache element describing how to display | |
1192 the text. | |
1193 CURSOR #### I don't understand this. There's something | |
1194 strange and overcomplexified with this variable. | |
1195 Chuck, explain please? | |
1196 CURSOR_START Starting X position of cursor. | |
1197 CURSOR_WIDTH Width of cursor in pixels. | |
1198 CURSOR_HEIGHT Height of cursor in pixels. | |
1199 | |
1200 Starting Y position of cursor is the top of the text line. | |
1201 The cursor is drawn sometimes whether or not CURSOR is set. ??? | |
1202 ****************************************************************************/ | |
1203 #ifdef THIS_IS_GTK | |
1204 static | |
1205 void gdk_draw_text_image (GdkDrawable *drawable, | |
1206 GdkFont *font, | |
1207 GdkGC *gc, | |
1208 gint x, | |
1209 gint y, | |
1210 const gchar *text, | |
1211 gint text_length); | |
1212 | |
1213 #endif /* THIS_IS_GTK */ | |
1214 void | |
1215 XLIKE_output_string (struct window *w, struct display_line *dl, | |
1216 Ichar_dynarr *buf, int xpos, int xoffset, int clip_start, | |
1217 int width, face_index findex, int cursor, | |
1218 int cursor_start, int cursor_width, int cursor_height) | |
1219 { | |
1220 /* General variables */ | |
1221 struct frame *f = XFRAME (w->frame); | |
1222 struct device *d = XDEVICE (f->device); | |
1223 XLIKE_DISPLAY dpy = GET_XLIKE_DISPLAY (d); | |
1224 XLIKE_WINDOW x_win = GET_XLIKE_WINDOW (f); | |
1225 Lisp_Object window = wrap_window (w); | |
1226 | |
1227 int clip_end; | |
1228 | |
1229 /* Cursor-related variables */ | |
1230 int focus = EQ (w->frame, DEVICE_FRAME_WITH_FOCUS_REAL (d)); | |
1231 int cursor_clip; | |
1232 Lisp_Object bar_cursor_value = symbol_value_in_buffer (Qbar_cursor, | |
1233 WINDOW_BUFFER (w)); | |
1234 struct face_cachel *cursor_cachel = 0; | |
1235 | |
1236 /* Text-related variables */ | |
1237 Lisp_Object bg_pmap; | |
1238 XLIKE_GC bgc, gc; | |
1239 int height = XLIKE_DISPLAY_LINE_HEIGHT (dl); | |
1240 int ypos = XLIKE_DISPLAY_LINE_YPOS (dl); | |
1241 int len = Dynarr_length (buf); | |
1242 unsigned char *text_storage = (unsigned char *) ALLOCA (2 * len); | |
1243 struct textual_run *runs = alloca_array (struct textual_run, len); | |
1244 int nruns; | |
1245 int i; | |
1246 struct face_cachel *cachel = WINDOW_FACE_CACHEL (w, findex); | |
1247 | |
1248 #ifdef THIS_IS_X | |
1249 int use_x_font = 1; /* #### bogus!! | |
1250 The logic of this function needs review! */ | |
1251 #endif | |
1252 #ifdef USE_XFT | |
1253 Colormap cmap = DEVICE_X_COLORMAP (d); | |
1254 Visual *visual = DEVICE_X_VISUAL (d); | |
1255 static XftColor fg, bg; | |
1256 XftDraw *xftDraw; | |
1257 | |
1258 /* Lazily initialize frame's xftDraw member. */ | |
1259 if (!FRAME_X_XFTDRAW (f)) { | |
1260 FRAME_X_XFTDRAW (f) = XftDrawCreate (dpy, x_win, visual, cmap); | |
1261 } | |
1262 xftDraw = FRAME_X_XFTDRAW (f); | |
1263 | |
1264 /* #### This will probably cause asserts when passed a Lisp integer for a | |
1265 color. See ca. line 759 this file. | |
1266 #### Maybe xft_convert_color should take an XColor, not a pixel. */ | |
1267 #define XFT_FROB_LISP_COLOR(color, dim) \ | |
1268 xft_convert_color (dpy, cmap, visual, \ | |
1269 COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (color)).pixel, \ | |
1270 (dim)) | |
1271 #endif /* USE_XFT */ | |
1272 | |
1273 if (width < 0) | |
1274 width = XLIKE_text_width (f, cachel, Dynarr_atp (buf, 0), | |
1275 Dynarr_length (buf)); | |
1276 | |
1277 /* Regularize the variables passed in. */ | |
1278 | |
1279 if (clip_start < xpos) | |
1280 clip_start = xpos; | |
1281 clip_end = xpos + width; | |
1282 if (clip_start >= clip_end) | |
1283 /* It's all clipped out. */ | |
1284 return; | |
1285 | |
1286 xpos -= xoffset; | |
1287 | |
1288 /* make sure the area we are about to display is subwindow free. */ | |
1289 redisplay_unmap_subwindows_maybe (f, clip_start, ypos, | |
1290 clip_end - clip_start, height); | |
1291 | |
1292 cursor_clip = (cursor_start >= clip_start && | |
1293 cursor_start < clip_end); | |
1294 | |
1295 /* This cursor code is really a mess. */ | |
1296 if (!NILP (w->text_cursor_visible_p) | |
1297 && (cursor | |
1298 || cursor_clip | |
1299 || (cursor_width | |
1300 && (cursor_start + cursor_width >= clip_start) | |
1301 && !NILP (bar_cursor_value)))) | |
1302 { | |
1303 /* These have to be in separate statements in order to avoid a | |
1304 compiler bug. */ | |
1305 face_index sucks = get_builtin_face_cache_index (w, Vtext_cursor_face); | |
1306 cursor_cachel = WINDOW_FACE_CACHEL (w, sucks); | |
1307 | |
1308 /* We have to reset this since any call to WINDOW_FACE_CACHEL | |
1309 may cause the cache to resize and any pointers to it to | |
1310 become invalid. */ | |
1311 cachel = WINDOW_FACE_CACHEL (w, findex); | |
1312 } | |
1313 | |
1314 #ifdef HAVE_XIM | |
1315 if (cursor && focus && (cursor_start == clip_start) && cursor_height) | |
1316 XIM_SetSpotLocation (f, xpos - 2, dl->ypos + dl->descent - 2); | |
1317 #endif /* HAVE_XIM */ | |
1318 | |
1319 bg_pmap = cachel->background_pixmap; | |
1320 if (!IMAGE_INSTANCEP (bg_pmap) | |
1321 || !IMAGE_INSTANCE_PIXMAP_TYPE_P (XIMAGE_INSTANCE (bg_pmap))) | |
1322 bg_pmap = Qnil; | |
1323 | |
1324 if ((cursor && focus && NILP (bar_cursor_value) | |
1325 && !NILP (w->text_cursor_visible_p)) || NILP (bg_pmap)) | |
1326 bgc = 0; | |
1327 else | |
1328 bgc = XLIKE_get_gc (d, Qnil, cachel->foreground, cachel->background, | |
1329 bg_pmap, Qnil); | |
1330 | |
1331 if (bgc) | |
1332 { | |
1333 XLIKE_FILL_RECTANGLE (dpy, x_win, bgc, clip_start, | |
1334 ypos, clip_end - clip_start, | |
1335 height); | |
1336 } | |
1337 | |
1338 nruns = separate_textual_runs (text_storage, runs, Dynarr_atp (buf, 0), | |
1339 Dynarr_length (buf), cachel); | |
1340 | |
1341 for (i = 0; i < nruns; i++) | |
1342 { | |
1343 Lisp_Object font = FACE_CACHEL_FONT (cachel, runs[i].charset); | |
1344 Lisp_Font_Instance *fi = XFONT_INSTANCE (font); | |
1345 int this_width; | |
1346 int need_clipping; | |
1347 | |
1348 if (EQ (font, Vthe_null_font_instance)) | |
1349 continue; | |
1350 | |
1351 this_width = XLIKE_text_width_single_run (f, cachel, runs + i); | |
1352 need_clipping = (dl->clip || clip_start > xpos || | |
1353 clip_end < xpos + this_width); | |
1354 | |
1355 /* XDrawImageString only clears the area equal to the height of | |
1356 the given font. It is possible that a font is being displayed | |
1357 on a line taller than it is, so this would cause us to fail to | |
1358 clear some areas. */ | |
1359 if ((int) fi->height < (int) (height + dl->clip + | |
1360 XLIKE_DISPLAY_LINE_TOP_CLIP (dl))) | |
1361 { | |
1362 int clear_start = max (xpos, clip_start); | |
1363 int clear_end = min (xpos + this_width, clip_end); | |
1364 | |
1365 if (cursor) | |
1366 { | |
1367 int ypos1_line, ypos1_string, ypos2_line, ypos2_string; | |
1368 | |
1369 ypos1_string = dl->ypos - fi->ascent; | |
1370 ypos2_string = dl->ypos + fi->descent; | |
1371 ypos1_line = ypos; | |
1372 ypos2_line = ypos1_line + height; | |
1373 | |
1374 /* Make sure we don't clear below the real bottom of the | |
1375 line. */ | |
1376 if (ypos1_string > ypos2_line) | |
1377 ypos1_string = ypos2_line; | |
1378 if (ypos2_string > ypos2_line) | |
1379 ypos2_string = ypos2_line; | |
1380 | |
1381 if (ypos1_line < ypos1_string) | |
1382 { | |
1383 redisplay_clear_region (window, findex, clear_start, ypos1_line, | |
1384 clear_end - clear_start, | |
1385 ypos1_string - ypos1_line); | |
1386 } | |
1387 | |
1388 if (ypos2_line > ypos2_string) | |
1389 { | |
1390 redisplay_clear_region (window, findex, clear_start, ypos2_string, | |
1391 clear_end - clear_start, | |
1392 ypos2_line - ypos2_string); | |
1393 } | |
1394 } | |
1395 else | |
1396 { | |
1397 redisplay_clear_region (window, findex, clear_start, | |
1398 ypos, clear_end - clear_start, | |
1399 height); | |
1400 } | |
1401 } | |
1402 | |
1403 if (cursor && cursor_cachel && focus && NILP (bar_cursor_value)) | |
1404 { | |
1405 #ifdef USE_XFT | |
1406 fg = XFT_FROB_LISP_COLOR (cursor_cachel->foreground, 0); | |
1407 bg = XFT_FROB_LISP_COLOR (cursor_cachel->background, 0); | |
1408 #endif | |
1409 gc = XLIKE_get_gc (d, font, cursor_cachel->foreground, | |
1410 cursor_cachel->background, Qnil, Qnil); | |
1411 } | |
1412 else if (cachel->dim) | |
1413 { | |
1414 /* Ensure the gray bitmap exists */ | |
1415 if (DEVICE_XLIKE_GRAY_PIXMAP (d) == XLIKE_NONE) | |
1416 DEVICE_XLIKE_GRAY_PIXMAP (d) = | |
1417 #ifdef THIS_IS_X | |
1418 XCreateBitmapFromData (dpy, x_win, (char *)gray_bits, | |
1419 gray_width, gray_height) | |
1420 #else | |
1421 /* #### FIXME! Implement me! */ | |
1422 XLIKE_NONE | |
1423 #endif | |
1424 ; | |
1425 | |
1426 /* Request a GC with the gray stipple pixmap to draw dimmed text */ | |
1427 #ifdef USE_XFT | |
1428 fg = XFT_FROB_LISP_COLOR (cachel->foreground, 1); | |
1429 bg = XFT_FROB_LISP_COLOR (cachel->background, 0); | |
1430 #endif | |
1431 gc = XLIKE_get_gc (d, font, cachel->foreground, cachel->background, | |
1432 Qdim, Qnil); | |
1433 } | |
1434 else | |
1435 { | |
1436 #ifdef USE_XFT | |
1437 fg = XFT_FROB_LISP_COLOR (cachel->foreground, 0); | |
1438 bg = XFT_FROB_LISP_COLOR (cachel->background, 0); | |
1439 #endif | |
1440 gc = XLIKE_get_gc (d, font, cachel->foreground, cachel->background, | |
1441 Qnil, Qnil); | |
1442 } | |
1443 #ifdef USE_XFT | |
1444 { | |
1445 XftFont *rf = FONT_INSTANCE_X_XFTFONT (fi); | |
1446 | |
1447 if (rf) | |
1448 { | |
1449 use_x_font = 0; | |
1450 if (need_clipping) | |
1451 { | |
1452 Region clip_reg = XCreateRegion(); | |
1453 XRectangle clip_box = { clip_start, ypos, | |
1454 clip_end - clip_start, height }; | |
1455 | |
1456 XUnionRectWithRegion (&clip_box, clip_reg, clip_reg); | |
1457 XftDrawSetClip(xftDraw, clip_reg); | |
1458 XDestroyRegion(clip_reg); | |
1459 } | |
1460 | |
1461 if (!bgc) | |
1462 { | |
1463 /* #### Neither rect_height nor XftTextExtents as computed | |
1464 below handles the vertical space taken up by antialiasing, | |
1465 which for some fonts (eg, Bitstream Vera Sans Mono-16 on | |
1466 my Mac PowerBook G4) leaves behind orphaned dots on | |
1467 insertion or deletion earlier in the line, especially in | |
1468 the case of the underscore character. | |
1469 Interestingly, insertion or deletion of a single character | |
1470 immediately after a refresh does not leave any droppings, | |
1471 but any further insertions or deletions do. | |
1472 While adding a pixel to rect_height (mostly) takes care of | |
1473 this, it trashes aggressively laid-out elements like the | |
1474 modeline (overwriting part of the bevel). | |
1475 OK, unconditionally redraw the bevel, and increment | |
1476 rect_height by 1. See x_output_display_block. -- sjt */ | |
1477 struct textual_run *run = &runs[i]; | |
1478 int rect_width = x_text_width_single_run (f, cachel, run); | |
1479 #ifndef USE_XFTTEXTENTS_TO_AVOID_FONT_DROPPINGS | |
1480 int rect_height = FONT_INSTANCE_ASCENT(fi) | |
1481 + FONT_INSTANCE_DESCENT(fi) + 1; | |
1482 #else | |
1483 int rect_height = FONT_INSTANCE_ASCENT(fi) | |
1484 + FONT_INSTANCE_DESCENT(fi); | |
1485 XGlyphInfo gi; | |
1486 if (run->dimension == 2) { | |
1487 XftTextExtents16 (dpy, | |
1488 FONT_INSTANCE_X_XFTFONT(fi), | |
1489 (XftChar16 *) run->ptr, run->len, &gi); | |
1490 } else { | |
1491 XftTextExtents8 (dpy, | |
1492 FONT_INSTANCE_X_XFTFONT(fi), | |
1493 run->ptr, run->len, &gi); | |
1494 } | |
1495 rect_height = rect_height > gi.height | |
1496 ? rect_height : gi.height; | |
1497 #endif | |
1498 | |
1499 XftDrawRect (xftDraw, &bg, | |
1500 xpos, ypos, rect_width, rect_height); | |
1501 } | |
1502 | |
1503 if (runs[i].dimension == 1) | |
1504 XftDrawString8 (xftDraw, &fg, rf, xpos, dl->ypos, | |
1505 runs[i].ptr, runs[i].len); | |
1506 else | |
1507 XftDrawString16 (xftDraw, &fg, rf, xpos, dl->ypos, | |
1508 (XftChar16 *) runs[i].ptr, runs[i].len); | |
1509 } | |
1510 } | |
1511 #endif /* USE_XFT */ | |
1512 | |
1513 #ifdef THIS_IS_X | |
1514 if (use_x_font) | |
1515 #endif | |
1516 { | |
1517 if (need_clipping) | |
1518 { | |
1519 XLIKE_RECTANGLE clip_box; | |
1520 | |
1521 clip_box.x = 0; | |
1522 clip_box.y = 0; | |
1523 clip_box.width = clip_end - clip_start; | |
1524 clip_box.height = height; | |
1525 | |
1526 XLIKE_SET_CLIP_RECTANGLE (dpy, gc, clip_start, ypos, &clip_box); | |
1527 } | |
1528 | |
1529 #ifdef THIS_IS_X | |
1530 if (runs[i].dimension == 1) | |
1531 (bgc ? XDrawString : XDrawImageString) | |
1532 (dpy, x_win, gc, xpos, dl->ypos, | |
1533 (char *) runs[i].ptr, runs[i].len); | |
1534 else | |
1535 (bgc ? XDrawString16 : XDrawImageString16) | |
1536 (dpy, x_win, gc, xpos, dl->ypos, | |
1537 (XChar2b *) runs[i].ptr, runs[i].len); | |
1538 #else /* THIS_IS_GTK */ | |
1539 | |
1540 /* The X specific called different functions (XDraw*String | |
1541 vs. XDraw*String16), but apparently gdk_draw_text takes care | |
1542 of that for us. | |
1543 | |
1544 BUT, gdk_draw_text also does too much, by dividing the length | |
1545 by 2. So we fake them out my multiplying the length by the | |
1546 dimension of the text. This will do the right thing for | |
1547 single-dimension runs as well of course. | |
1548 */ | |
1549 (bgc ? gdk_draw_text : gdk_draw_text_image) | |
1550 (GDK_DRAWABLE (x_win), FONT_INSTANCE_GTK_FONT (fi), gc, xpos, | |
1551 dl->ypos, (char *) runs[i].ptr, runs[i].len * runs[i].dimension); | |
1552 #endif /* (not) THIS_IS_X */ | |
1553 } | |
1554 | |
1555 /* We draw underlines in the same color as the text. */ | |
1556 if (cachel->underline) | |
1557 { | |
1558 int upos, uthick; | |
1559 #ifdef THIS_IS_X | |
1560 unsigned long upos_ext, uthick_ext; | |
1561 XFontStruct *fs = | |
1562 use_x_font ? FONT_INSTANCE_X_FONT (XFONT_INSTANCE (font)) : 0; | |
1563 /* #### the logic of the next two may be suboptimal: we may want | |
1564 to use the POSITION and/or THICKNESS information with Xft */ | |
1565 if (fs && XGetFontProperty (fs, XA_UNDERLINE_POSITION, &upos_ext)) | |
1566 upos = (int) upos_ext; | |
1567 else | |
1568 #else /* THIS_IS_GTK */ | |
1569 /* Cannot get at font properties in Gtk, so we resort to | |
1570 guessing */ | |
1571 #endif /* THIS_IS_GTK */ | |
1572 upos = dl->descent / 2; | |
1573 #ifdef THIS_IS_X | |
1574 if (fs && XGetFontProperty (fs, XA_UNDERLINE_THICKNESS, &uthick_ext)) | |
1575 uthick = (int) uthick_ext; | |
1576 else | |
1577 #endif /* THIS_IS_X */ | |
1578 uthick = 1; | |
1579 if (dl->ypos + upos < dl->ypos + dl->descent - dl->clip) | |
1580 { | |
1581 if (dl->ypos + upos + uthick > dl->ypos + dl->descent - dl->clip) | |
1582 uthick = dl->descent - dl->clip - upos; | |
1583 | |
1584 if (uthick == 1) | |
1585 { | |
1586 XLIKE_DRAW_LINE (dpy, x_win, gc, xpos, dl->ypos + upos, | |
1587 xpos + this_width, dl->ypos + upos); | |
1588 } | |
1589 else if (uthick > 1) | |
1590 { | |
1591 XLIKE_FILL_RECTANGLE (dpy, x_win, gc, xpos, | |
1592 dl->ypos + upos, this_width, uthick); | |
1593 } | |
1594 } | |
1595 } | |
1596 | |
1597 if (cachel->strikethru) | |
1598 { | |
1599 #ifdef THIS_IS_X | |
1600 int ascent, descent, upos, uthick; | |
1601 unsigned long ascent_ext, descent_ext, uthick_ext; | |
1602 XFontStruct *fs = FONT_INSTANCE_X_FONT (fi); | |
1603 #else /* THIS_IS_GTK */ | |
1604 gint ascent, descent, upos, uthick; | |
1605 GdkFont *gfont = FONT_INSTANCE_GTK_FONT (fi); | |
1606 #endif /* THIS_IS_GTK */ | |
1607 | |
1608 #ifdef THIS_IS_X | |
1609 if (!use_x_font) | |
1610 { | |
1611 ascent = dl->ascent; | |
1612 descent = dl->descent; | |
1613 uthick = 1; | |
1614 } | |
1615 else | |
1616 { | |
1617 if (!XGetFontProperty (fs, XA_STRIKEOUT_ASCENT, &ascent_ext)) | |
1618 ascent = fs->ascent; | |
1619 else | |
1620 ascent = (int) ascent_ext; | |
1621 if (!XGetFontProperty (fs, XA_STRIKEOUT_DESCENT, &descent_ext)) | |
1622 descent = fs->descent; | |
1623 else | |
1624 descent = (int) descent_ext; | |
1625 if (!XGetFontProperty (fs, XA_UNDERLINE_THICKNESS, &uthick_ext)) | |
1626 uthick = 1; | |
1627 else | |
1628 uthick = (int) uthick_ext; | |
1629 } | |
1630 #else /* THIS_IS_GTK */ | |
1631 /* Cannot get at font properties in Gtk, so we resort to | |
1632 guessing */ | |
1633 | |
1634 ascent = gfont->ascent; | |
1635 descent = gfont->descent; | |
1636 uthick = 1; | |
1637 #endif /* THIS_IS_GTK */ | |
1638 | |
1639 upos = ascent - ((ascent + descent) / 2) + 1; | |
1640 | |
1641 /* Generally, upos will be positive (above the baseline),so | |
1642 subtract */ | |
1643 if (dl->ypos - upos < dl->ypos + dl->descent - dl->clip) | |
1644 { | |
1645 if (dl->ypos - upos + uthick > dl->ypos + dl->descent - dl->clip) | |
1646 uthick = dl->descent - dl->clip + upos; | |
1647 | |
1648 if (uthick == 1) | |
1649 XLIKE_DRAW_LINE (dpy, x_win, gc, xpos, dl->ypos - upos, | |
1650 xpos + this_width, dl->ypos - upos); | |
1651 else if (uthick > 1) | |
1652 XLIKE_FILL_RECTANGLE (dpy, x_win, gc, xpos, dl->ypos + upos, | |
1653 this_width, uthick); | |
1654 } | |
1655 } | |
1656 | |
1657 /* Restore the GC */ | |
1658 if (need_clipping) | |
1659 { | |
1660 #ifdef USE_XFT | |
1661 if (!use_x_font) | |
1662 { | |
1663 XftDrawSetClip (xftDraw, 0); | |
1664 } | |
1665 else | |
1666 #endif | |
1667 XLIKE_CLEAR_CLIP_MASK (dpy, gc); | |
1668 } | |
1669 | |
1670 /* If we are actually superimposing the cursor then redraw with just | |
1671 the appropriate section highlighted. */ | |
1672 if (cursor_clip && !cursor && focus && cursor_cachel) | |
1673 { | |
1674 #ifdef USE_XFT | |
1675 if (!use_x_font) /* Xft */ | |
1676 { | |
1677 XftFont *rf = FONT_INSTANCE_X_XFTFONT (fi); | |
1678 | |
1679 { /* set up clipping */ | |
1680 Region clip_reg = XCreateRegion(); | |
1681 XRectangle clip_box = { cursor_start, ypos, | |
1682 cursor_width, height }; | |
1683 | |
1684 XUnionRectWithRegion (&clip_box, clip_reg, clip_reg); | |
1685 XftDrawSetClip(xftDraw, clip_reg); | |
1686 XDestroyRegion(clip_reg); | |
1687 } | |
1688 { /* draw background rectangle & draw text */ | |
1689 int rect_height = FONT_INSTANCE_ASCENT(fi) | |
1690 + FONT_INSTANCE_DESCENT(fi); | |
1691 int rect_width = x_text_width_single_run(f, cachel, &runs[i]); | |
1692 XftColor xft_color; | |
1693 | |
1694 xft_color = XFT_FROB_LISP_COLOR (cursor_cachel->background, 0); | |
1695 XftDrawRect (xftDraw, &xft_color, | |
1696 xpos, ypos, rect_width, rect_height); | |
1697 | |
1698 xft_color = XFT_FROB_LISP_COLOR (cursor_cachel->foreground, 0); | |
1699 if (runs[i].dimension == 1) | |
1700 XftDrawString8 (xftDraw, &xft_color, rf, xpos, dl->ypos, | |
1701 runs[i].ptr, runs[i].len); | |
1702 else | |
1703 XftDrawString16 (xftDraw, &xft_color, rf, xpos, dl->ypos, | |
1704 (XftChar16 *) runs[i].ptr, runs[i].len); | |
1705 } | |
1706 | |
1707 XftDrawSetClip(xftDraw, 0); | |
1708 } | |
1709 else /* core font, not Xft */ | |
1710 #endif /* USE_XFT */ | |
1711 { | |
1712 XLIKE_RECTANGLE clip_box; | |
1713 XLIKE_GC cgc; | |
1714 cgc = XLIKE_get_gc (d, font, cursor_cachel->foreground, | |
1715 cursor_cachel->background, Qnil, Qnil); | |
1716 | |
1717 clip_box.x = 0; | |
1718 clip_box.y = 0; | |
1719 clip_box.width = cursor_width; | |
1720 clip_box.height = height; | |
1721 | |
1722 XLIKE_SET_CLIP_RECTANGLE (dpy, cgc, cursor_start, ypos, | |
1723 &clip_box); | |
1724 #ifdef THIS_IS_X | |
1725 if (runs[i].dimension == 1) | |
1726 XDrawImageString (dpy, x_win, cgc, xpos, dl->ypos, | |
1727 (char *) runs[i].ptr, runs[i].len); | |
1728 else | |
1729 XDrawImageString16 (dpy, x_win, cgc, xpos, dl->ypos, | |
1730 (XChar2b *) runs[i].ptr, runs[i].len); | |
1731 #else | |
1732 /* The X specific called different functions (XDraw*String | |
1733 vs. XDraw*String16), but apparently gdk_draw_text takes care | |
1734 of that for us. | |
1735 | |
1736 BUT, gdk_draw_text also does too much, by dividing the | |
1737 length by 2. So we fake them out my multiplying the | |
1738 length by the dimension of the text. This will do the | |
1739 right thing for single-dimension runs as well of course. | |
1740 */ | |
1741 gdk_draw_text_image (GDK_DRAWABLE (x_win), | |
1742 FONT_INSTANCE_GTK_FONT (fi), cgc, xpos, | |
1743 dl->ypos, (char *) runs[i].ptr, | |
1744 runs[i].len * runs[i].dimension); | |
1745 #endif /* (not) THIS_IS_X */ | |
1746 | |
1747 XLIKE_CLEAR_CLIP_MASK (dpy, cgc); | |
1748 } | |
1749 } | |
1750 | |
1751 xpos += this_width; | |
1752 } | |
1753 | |
1754 /* Draw the non-focus box or bar-cursor as needed. */ | |
1755 /* Can't this logic be simplified? */ | |
1756 if (cursor_cachel | |
1757 && ((cursor && !focus && NILP (bar_cursor_value)) | |
1758 || (cursor_width | |
1759 && (cursor_start + cursor_width >= clip_start) | |
1760 && !NILP (bar_cursor_value)))) | |
1761 { | |
1762 int tmp_height, tmp_y; | |
1763 int bar_width = EQ (bar_cursor_value, Qt) ? 1 : 2; | |
1764 int need_clipping = (cursor_start < clip_start | |
1765 || clip_end < cursor_start + cursor_width); | |
1766 | |
1767 /* #### This value is correct (as far as I know) because | |
1768 all of the times we need to draw this cursor, we will | |
1769 be called with exactly one character, so we know we | |
1770 can always use runs[0]. | |
1771 | |
1772 This is bogus as all hell, however. The cursor handling in | |
1773 this function is way bogus and desperately needs to be | |
1774 cleaned up. (In particular, the drawing of the cursor should | |
1775 really really be separated out of this function. This may be | |
1776 a bit tricky now because this function itself does way too | |
1777 much stuff, a lot of which needs to be moved into | |
1778 redisplay.c.) This is the only way to be able to easily add | |
1779 new cursor types or (e.g.) make the bar cursor be able to | |
1780 span two characters instead of overlaying just one. */ | |
1781 int bogusly_obtained_ascent_value = | |
1782 XFONT_INSTANCE (FACE_CACHEL_FONT (cachel, runs[0].charset))->ascent; | |
1783 | |
1784 if (!NILP (bar_cursor_value)) | |
1785 { | |
1786 gc = XLIKE_get_gc (d, Qnil, cursor_cachel->background, Qnil, Qnil, | |
1787 make_int (bar_width)); | |
1788 } | |
1789 else | |
1790 { | |
1791 gc = XLIKE_get_gc (d, Qnil, cursor_cachel->background, | |
1792 Qnil, Qnil, Qnil); | |
1793 } | |
1794 | |
1795 tmp_y = dl->ypos - bogusly_obtained_ascent_value; | |
1796 tmp_height = cursor_height; | |
1797 if (tmp_y + tmp_height > (int) (ypos + height)) | |
1798 { | |
1799 tmp_y = ypos + height - tmp_height; | |
1800 if (tmp_y < (int) ypos) | |
1801 tmp_y = ypos; | |
1802 tmp_height = ypos + height - tmp_y; | |
1803 } | |
1804 | |
1805 if (need_clipping) | |
1806 { | |
1807 XLIKE_RECTANGLE clip_box; | |
1808 clip_box.x = 0; | |
1809 clip_box.y = 0; | |
1810 clip_box.width = clip_end - clip_start; | |
1811 clip_box.height = tmp_height; | |
1812 XLIKE_SET_CLIP_RECTANGLE (dpy, gc, clip_start, tmp_y, &clip_box); | |
1813 } | |
1814 | |
1815 if (!focus && NILP (bar_cursor_value)) | |
1816 { | |
1817 XLIKE_DRAW_RECTANGLE (dpy, x_win, gc, cursor_start, tmp_y, | |
1818 cursor_width - 1, tmp_height - 1); | |
1819 } | |
1820 else if (focus && !NILP (bar_cursor_value)) | |
1821 { | |
1822 XLIKE_DRAW_LINE (dpy, x_win, gc, cursor_start + bar_width - 1, tmp_y, | |
1823 cursor_start + bar_width - 1, | |
1824 tmp_y + tmp_height - 1); | |
1825 } | |
1826 | |
1827 /* Restore the GC */ | |
1828 if (need_clipping) | |
1829 { | |
1830 XLIKE_CLEAR_CLIP_MASK (dpy, gc); | |
1831 } | |
1832 } | |
1833 | |
1834 #ifdef USE_XFT | |
1835 #undef XFT_FROB_LISP_COLOR | |
1836 #endif | |
1837 } | |
1838 | |
1839 #ifdef THIS_IS_GTK | |
1840 static void | |
1841 our_draw_bitmap (GdkDrawable *drawable, | |
1842 GdkGC *gc, | |
1843 GdkPixmap *src, | |
1844 gint xsrc, | |
1845 gint ysrc, | |
1846 gint xdest, | |
1847 gint ydest, | |
1848 gint width, | |
1849 gint height); | |
1850 #endif /* THIS_IS_GTK */ | |
1851 | |
1852 | |
1853 void | |
1854 XLIKE_OUTPUT_XLIKE_PIXMAP (struct frame *f, Lisp_Image_Instance *p, int x, | |
1855 int y, int xoffset, int yoffset, | |
1856 int width, int height, | |
1857 XLIKE_PIXCOLOR fg, XLIKE_PIXCOLOR bg, | |
1858 XLIKE_GC override_gc) | |
1859 { | |
1860 struct device *d = XDEVICE (f->device); | |
1861 XLIKE_DISPLAY dpy = GET_XLIKE_DISPLAY (d); | |
1862 XLIKE_WINDOW x_win = GET_XLIKE_WINDOW (f); | |
1863 XLIKE_GC gc; | |
1864 XLIKE_GCVALUES gcv; | |
1865 unsigned long pixmap_mask; | |
1866 | |
1867 if (!override_gc) | |
1868 { | |
1869 memset (&gcv, ~0, sizeof (gcv)); | |
1870 gcv.graphics_exposures = XLIKE_FALSE; | |
1871 XLIKE_SET_PIXCOLOR_COPY (gcv.foreground, fg); | |
1872 XLIKE_SET_PIXCOLOR_COPY (gcv.background, bg); | |
1873 pixmap_mask = XLIKE_GC_FOREGROUND | XLIKE_GC_BACKGROUND | XLIKE_GC_EXPOSURES; | |
1874 | |
1875 if (IMAGE_INSTANCE_XLIKE_MASK (p)) | |
1876 { | |
1877 gcv.function = XLIKE_GX_COPY; | |
1878 gcv.clip_mask = IMAGE_INSTANCE_XLIKE_MASK (p); | |
1879 gcv.clip_x_origin = x - xoffset; | |
1880 gcv.clip_y_origin = y - yoffset; | |
1881 pixmap_mask |= (XLIKE_GC_FUNCTION | XLIKE_GC_CLIP_MASK | | |
1882 XLIKE_GC_CLIP_X_ORIGIN | | |
1883 XLIKE_GC_CLIP_Y_ORIGIN); | |
1884 /* Can't set a clip rectangle below because we already have a mask. | |
1885 We could conceivably create a new clipmask by zeroing out | |
1886 everything outside the clip region. Is it worth it? | |
1887 Is it possible to get an equivalent effect by changing the | |
1888 args to XCopyArea below rather than messing with a clip box? | |
1889 - dkindred@cs.cmu.edu | |
1890 Yes. We don't clip at all now - andy@xemacs.org | |
1891 */ | |
1892 } | |
1893 | |
1894 gc = gc_cache_lookup (DEVICE_XLIKE_GC_CACHE (d), &gcv, pixmap_mask); | |
1895 } | |
1896 else | |
1897 { | |
1898 gc = override_gc; | |
1899 /* override_gc might have a mask already--we don't want to nuke it. | |
1900 Maybe we can insist that override_gc have no mask, or use | |
1901 one of the suggestions above. */ | |
1902 } | |
1903 | |
1904 #ifdef THIS_IS_X | |
1905 /* depth of 0 means it's a bitmap, not a pixmap, and we should use | |
1906 XCopyPlane (1 = current foreground color, 0 = background) instead | |
1907 of XCopyArea, which means that the bits in the pixmap are actual | |
1908 pixel values, instead of symbolic of fg/bg. */ | |
1909 #endif /* THIS_IS_X */ | |
1910 if (IMAGE_INSTANCE_PIXMAP_DEPTH (p) > 0) | |
1911 { | |
1912 #ifdef THIS_IS_X | |
1913 XCopyArea (dpy, | |
1914 IMAGE_INSTANCE_X_PIXMAP_SLICE | |
1915 (p, IMAGE_INSTANCE_PIXMAP_SLICE (p)), x_win, gc, xoffset, | |
1916 yoffset, width, | |
1917 height, x, y); | |
1918 #else /* THIS_IS_GTK */ | |
1919 gdk_draw_pixmap (GDK_DRAWABLE (x_win), gc, | |
1920 IMAGE_INSTANCE_GTK_PIXMAP (p), | |
1921 xoffset, yoffset, x, y, width, height); | |
1922 #endif /* THIS_IS_GTK */ | |
1923 } | |
1924 else | |
1925 { | |
1926 #ifdef THIS_IS_X | |
1927 XCopyPlane (dpy, IMAGE_INSTANCE_X_PIXMAP_SLICE | |
1928 (p, IMAGE_INSTANCE_PIXMAP_SLICE (p)), x_win, gc, | |
1929 xoffset, yoffset, width, height, x, y, 1L); | |
1930 #else /* THIS_IS_GTK */ | |
1931 our_draw_bitmap (GDK_DRAWABLE (x_win), gc, | |
1932 IMAGE_INSTANCE_GTK_PIXMAP (p), | |
1933 xoffset, yoffset, x, y, width, height); | |
1934 #endif /* THIS_IS_GTK */ | |
1935 } | |
1936 } | |
1937 | |
1938 static void | |
1939 XLIKE_output_pixmap (struct window *w, Lisp_Object image_instance, | |
1940 struct display_box *db, struct display_glyph_area *dga, | |
1941 face_index findex, int cursor_start, int cursor_width, | |
1942 int cursor_height, int UNUSED (bg_pixmap)) | |
1943 { | |
1944 struct frame *f = XFRAME (w->frame); | |
1945 struct device *d = XDEVICE (f->device); | |
1946 Lisp_Image_Instance *p = XIMAGE_INSTANCE (image_instance); | |
1947 XLIKE_DISPLAY dpy = GET_XLIKE_DISPLAY (d); | |
1948 XLIKE_WINDOW x_win = GET_XLIKE_WINDOW (f); | |
1949 | |
1950 /* Output the pixmap. */ | |
1951 { | |
1952 Lisp_Object tmp_pixel; | |
1953 XLIKE_COLOR tmp_bcolor, tmp_fcolor; | |
1954 | |
1955 tmp_pixel = WINDOW_FACE_CACHEL_FOREGROUND (w, findex); | |
1956 tmp_fcolor = XCOLOR_INSTANCE_XLIKE_COLOR (tmp_pixel); | |
1957 tmp_pixel = WINDOW_FACE_CACHEL_BACKGROUND (w, findex); | |
1958 tmp_bcolor = XCOLOR_INSTANCE_XLIKE_COLOR (tmp_pixel); | |
1959 | |
1960 XLIKE_OUTPUT_XLIKE_PIXMAP (f, p, db->xpos, db->ypos, | |
1961 dga->xoffset, dga->yoffset, | |
1962 dga->width, dga->height, | |
1963 XLIKE_COLOR_TO_PIXCOLOR (tmp_fcolor), | |
1964 XLIKE_COLOR_TO_PIXCOLOR (tmp_bcolor), 0); | |
1965 } | |
1966 | |
1967 /* Draw a cursor over top of the pixmap. */ | |
1968 if (cursor_width && cursor_height && (cursor_start >= db->xpos) | |
1969 && !NILP (w->text_cursor_visible_p) | |
1970 && (cursor_start < db->xpos + dga->width)) | |
1971 { | |
1972 XLIKE_GC gc; | |
1973 int focus = EQ (w->frame, DEVICE_FRAME_WITH_FOCUS_REAL (d)); | |
1974 struct face_cachel *cursor_cachel = | |
1975 WINDOW_FACE_CACHEL (w, | |
1976 get_builtin_face_cache_index | |
1977 (w, Vtext_cursor_face)); | |
1978 | |
1979 gc = XLIKE_get_gc (d, Qnil, cursor_cachel->background, Qnil, Qnil, Qnil); | |
1980 | |
1981 if (cursor_width > db->xpos + dga->width - cursor_start) | |
1982 cursor_width = db->xpos + dga->width - cursor_start; | |
1983 | |
1984 if (focus) | |
1985 XLIKE_FILL_RECTANGLE (dpy, x_win, gc, cursor_start, db->ypos, | |
1986 cursor_width, cursor_height); | |
1987 else | |
1988 { | |
1989 XLIKE_DRAW_RECTANGLE (dpy, x_win, gc, cursor_start, db->ypos, | |
1990 cursor_width, cursor_height); | |
1991 } | |
1992 } | |
1993 } | |
1994 | |
1995 /***************************************************************************** | |
1996 XLIKE_output_vertical_divider | |
1997 | |
1998 Draw a vertical divider down the right side of the given window. | |
1999 ****************************************************************************/ | |
2000 static void | |
2001 XLIKE_output_vertical_divider (struct window *w, int USED_IF_X(clear)) | |
2002 { | |
2003 struct frame *f = XFRAME (w->frame); | |
2004 struct device *d = XDEVICE (f->device); | |
2005 | |
2006 XLIKE_DISPLAY dpy = GET_XLIKE_DISPLAY (d); | |
2007 XLIKE_WINDOW x_win = GET_XLIKE_WINDOW (f); | |
2008 Lisp_Object tmp_pixel; | |
2009 XLIKE_GCVALUES gcv; | |
2010 XLIKE_GC background_gc; | |
2011 #ifdef THIS_IS_X | |
2012 enum edge_style style; | |
2013 #endif /* THIS_IS_X */ | |
2014 unsigned long mask; | |
2015 int x, y1, y2, width, shadow_thickness, spacing, line_width; | |
2016 face_index div_face = | |
2017 get_builtin_face_cache_index (w, Vvertical_divider_face); | |
2018 | |
2019 width = window_divider_width (w); | |
2020 shadow_thickness = XINT (w->vertical_divider_shadow_thickness); | |
2021 spacing = XINT (w->vertical_divider_spacing); | |
2022 line_width = XINT (w->vertical_divider_line_width); | |
2023 x = WINDOW_RIGHT (w) - width; | |
2024 y1 = WINDOW_TOP (w); | |
2025 y2 = WINDOW_BOTTOM (w); | |
2026 | |
2027 memset (&gcv, ~0, sizeof (gcv)); | |
2028 | |
2029 tmp_pixel = WINDOW_FACE_CACHEL_BACKGROUND (w, div_face); | |
2030 | |
2031 /* First, get the GC's. */ | |
2032 XLIKE_SET_PIXCOLOR_COPY | |
2033 (gcv.background, | |
2034 XLIKE_COLOR_TO_PIXCOLOR (XCOLOR_INSTANCE_XLIKE_COLOR (tmp_pixel))); | |
2035 gcv.foreground = gcv.background; | |
2036 gcv.graphics_exposures = XLIKE_FALSE; | |
2037 mask = XLIKE_GC_FOREGROUND | XLIKE_GC_BACKGROUND | XLIKE_GC_EXPOSURES; | |
2038 | |
2039 background_gc = gc_cache_lookup (DEVICE_XLIKE_GC_CACHE (d), &gcv, mask); | |
2040 | |
2041 /* Clear the divider area first. This needs to be done when a | |
2042 window split occurs. */ | |
2043 #ifdef THIS_IS_X | |
2044 if (clear) | |
2045 XClearArea (dpy, x_win, x, y1, width, y2 - y1, False); | |
2046 #else /* THIS_IS_GTK */ | |
2047 /* if (clear) */ | |
2048 gdk_draw_rectangle (GDK_DRAWABLE (x_win), background_gc, TRUE, | |
2049 x, y1, width, y2 - y1); | |
2050 #endif /* THIS_IS_GTK */ | |
2051 | |
2052 #ifndef THIS_IS_GTK | |
2053 /* #### FIXME Why not? Formerly '#if 0' in the GDK code */ | |
2054 /* Draw the divider line. */ | |
2055 XLIKE_FILL_RECTANGLE (dpy, x_win, background_gc, | |
2056 x + spacing + shadow_thickness, y1, | |
2057 line_width, y2 - y1); | |
2058 | |
2059 /* This code not formerly present in GTK version, maybe the omittal | |
2060 is intentional? */ | |
2061 if (shadow_thickness < 0) | |
2062 { | |
2063 shadow_thickness = -shadow_thickness; | |
2064 style = EDGE_BEVEL_IN; | |
2065 } | |
2066 else | |
2067 { | |
2068 style = EDGE_BEVEL_OUT; | |
2069 } | |
2070 #endif /* not THIS_IS_GTK */ | |
2071 | |
2072 /* Draw the shadows around the divider line */ | |
2073 #ifdef THIS_IS_X | |
2074 x_bevel_area (w, div_face, x + spacing, y1, | |
2075 width - 2 * spacing, y2 - y1, | |
2076 shadow_thickness, EDGE_ALL, style); | |
2077 #else /* THIS_IS_GTK */ | |
2078 gtk_output_shadows (f, x + spacing, y1, | |
2079 width - 2 * spacing, y2 - y1, | |
2080 shadow_thickness); | |
2081 #endif /* THIS_IS_GTK */ | |
2082 } | |
2083 | |
2084 /***************************************************************************** | |
2085 XLIKE_output_blank | |
2086 | |
2087 Output a blank by clearing the area it covers in the foreground color | |
2088 of its face. | |
2089 ****************************************************************************/ | |
2090 static void | |
2091 XLIKE_output_blank (struct window *w, struct display_line *dl, struct rune *rb, | |
2092 int start_pixpos, int cursor_start, int cursor_width) | |
2093 { | |
2094 struct frame *f = XFRAME (w->frame); | |
2095 struct device *d = XDEVICE (f->device); | |
2096 | |
2097 XLIKE_DISPLAY dpy = GET_XLIKE_DISPLAY (d); | |
2098 XLIKE_WINDOW x_win = GET_XLIKE_WINDOW (f); | |
2099 XLIKE_GC gc; | |
2100 struct face_cachel *cursor_cachel = | |
2101 WINDOW_FACE_CACHEL (w, | |
2102 get_builtin_face_cache_index | |
2103 (w, Vtext_cursor_face)); | |
2104 Lisp_Object bg_pmap; | |
2105 Lisp_Object buffer = WINDOW_BUFFER (w); | |
2106 Lisp_Object bar_cursor_value = symbol_value_in_buffer (Qbar_cursor, | |
2107 buffer); | |
2108 | |
2109 int x = rb->xpos; | |
2110 int y = XLIKE_DISPLAY_LINE_YPOS (dl); | |
2111 int height = XLIKE_DISPLAY_LINE_HEIGHT (dl); | |
2112 int width = rb->width; | |
2113 | |
2114 /* Unmap all subwindows in the area we are going to blank. */ | |
2115 redisplay_unmap_subwindows_maybe (f, x, y, width, height); | |
2116 | |
2117 if (start_pixpos > x) | |
2118 { | |
2119 if (start_pixpos >= (x + width)) | |
2120 return; | |
2121 else | |
2122 { | |
2123 width -= (start_pixpos - x); | |
2124 x = start_pixpos; | |
2125 } | |
2126 } | |
2127 | |
2128 bg_pmap = WINDOW_FACE_CACHEL_BACKGROUND_PIXMAP (w, rb->findex); | |
2129 if (!IMAGE_INSTANCEP (bg_pmap) | |
2130 || !IMAGE_INSTANCE_PIXMAP_TYPE_P (XIMAGE_INSTANCE (bg_pmap))) | |
2131 bg_pmap = Qnil; | |
2132 | |
2133 if (NILP (bg_pmap)) | |
2134 gc = XLIKE_get_gc (d, Qnil, WINDOW_FACE_CACHEL_BACKGROUND (w, rb->findex), | |
2135 Qnil, Qnil, Qnil); | |
2136 else | |
2137 gc = XLIKE_get_gc (d, Qnil, WINDOW_FACE_CACHEL_FOREGROUND (w, rb->findex), | |
2138 WINDOW_FACE_CACHEL_BACKGROUND (w, rb->findex), bg_pmap, | |
2139 Qnil); | |
2140 | |
2141 XLIKE_FILL_RECTANGLE (dpy, x_win, gc, x, y, width, height); | |
2142 | |
2143 /* If this rune is marked as having the cursor, then it is actually | |
2144 representing a tab. */ | |
2145 if (!NILP (w->text_cursor_visible_p) | |
2146 && (rb->cursor_type == CURSOR_ON | |
2147 || (cursor_width | |
2148 && (cursor_start + cursor_width > x) | |
2149 && cursor_start < (x + width)))) | |
2150 { | |
2151 int cursor_height, cursor_y; | |
2152 int focus = EQ (w->frame, DEVICE_FRAME_WITH_FOCUS_REAL (d)); | |
2153 Lisp_Font_Instance *fi; | |
2154 | |
2155 fi = XFONT_INSTANCE (FACE_CACHEL_FONT | |
2156 (WINDOW_FACE_CACHEL (w, rb->findex), | |
2157 Vcharset_ascii)); | |
2158 | |
2159 gc = XLIKE_get_gc (d, Qnil, cursor_cachel->background, Qnil, Qnil, Qnil); | |
2160 | |
2161 cursor_y = dl->ypos - fi->ascent; | |
2162 cursor_height = fi->height; | |
2163 if (cursor_y + cursor_height > y + height) | |
2164 cursor_height = y + height - cursor_y; | |
2165 | |
2166 if (focus) | |
2167 { | |
2168 if (NILP (bar_cursor_value)) | |
2169 { | |
2170 XLIKE_FILL_RECTANGLE (dpy, x_win, gc, cursor_start, cursor_y, | |
2171 fi->width, cursor_height); | |
2172 } | |
2173 else | |
2174 { | |
2175 int bar_width = EQ (bar_cursor_value, Qt) ? 1 : 2; | |
2176 | |
2177 gc = XLIKE_get_gc (d, Qnil, cursor_cachel->background, | |
2178 Qnil, Qnil, make_int (bar_width)); | |
2179 XLIKE_DRAW_LINE (dpy, x_win, gc, cursor_start + bar_width - 1, | |
2180 cursor_y, cursor_start + bar_width - 1, | |
2181 cursor_y + cursor_height - 1); | |
2182 } | |
2183 } | |
2184 else if (NILP (bar_cursor_value)) | |
2185 { | |
2186 XLIKE_DRAW_RECTANGLE (dpy, x_win, gc, cursor_start, cursor_y, | |
2187 fi->width - 1, cursor_height - 1); | |
2188 } | |
2189 } | |
2190 } | |
2191 | |
2192 /***************************************************************************** | |
2193 XLIKE_output_horizontal_line | |
2194 | |
2195 Output a horizontal line in the foreground of its face. | |
2196 ****************************************************************************/ | |
2197 static void | |
2198 XLIKE_output_horizontal_line (struct window *w, struct display_line *dl, | |
2199 struct rune *rb) | |
2200 { | |
2201 struct frame *f = XFRAME (w->frame); | |
2202 struct device *d = XDEVICE (f->device); | |
2203 | |
2204 XLIKE_DISPLAY dpy = GET_XLIKE_DISPLAY (d); | |
2205 XLIKE_WINDOW x_win = GET_XLIKE_WINDOW (f); | |
2206 XLIKE_GC gc; | |
2207 | |
2208 int x = rb->xpos; | |
2209 int width = rb->width; | |
2210 int height = XLIKE_DISPLAY_LINE_HEIGHT (dl); | |
2211 int ypos1, ypos2, ypos3, ypos4; | |
2212 | |
2213 ypos1 = XLIKE_DISPLAY_LINE_YPOS (dl); | |
2214 ypos2 = ypos1 + rb->object.hline.yoffset; | |
2215 ypos3 = ypos2 + rb->object.hline.thickness; | |
2216 ypos4 = dl->ypos + dl->descent - dl->clip; | |
2217 | |
2218 /* First clear the area not covered by the line. */ | |
2219 if (height - rb->object.hline.thickness > 0) | |
2220 { | |
2221 gc = XLIKE_get_gc (d, Qnil, | |
2222 WINDOW_FACE_CACHEL_FOREGROUND (w, rb->findex), | |
2223 Qnil, Qnil, Qnil); | |
2224 | |
2225 if (ypos2 - ypos1 > 0) | |
2226 XLIKE_FILL_RECTANGLE (dpy, x_win, gc, x, ypos1, width, ypos2 - ypos1); | |
2227 if (ypos4 - ypos3 > 0) | |
2228 XLIKE_FILL_RECTANGLE (dpy, x_win, gc, x, ypos1, width, ypos2 - ypos1); | |
2229 } | |
2230 | |
2231 #ifdef THIS_IS_GTK | |
2232 { | |
2233 GtkStyle *style = FRAME_GTK_TEXT_WIDGET (f)->style; | |
2234 gtk_paint_hline (style, x_win, GTK_STATE_NORMAL, NULL, | |
2235 FRAME_GTK_TEXT_WIDGET (f), "hline", x, x + width, ypos2); | |
2236 } | |
2237 #else /* THIS_IS_X */ | |
2238 /* Now draw the line. */ | |
2239 gc = XLIKE_get_gc (d, Qnil, WINDOW_FACE_CACHEL_BACKGROUND (w, rb->findex), | |
2240 Qnil, Qnil, Qnil); | |
2241 | |
2242 if (ypos2 < ypos1) | |
2243 ypos2 = ypos1; | |
2244 if (ypos3 > ypos4) | |
2245 ypos3 = ypos4; | |
2246 | |
2247 if (ypos3 - ypos2 > 0) | |
2248 XLIKE_FILL_RECTANGLE (dpy, x_win, gc, x, ypos2, width, ypos3 - ypos2); | |
2249 #endif /* THIS_IS_X */ | |
2250 } | |
2251 | |
2252 /**************************************************************************** | |
2253 XLIKE_clear_region | |
2254 | |
2255 Clear the area in the box defined by the given parameters using the | |
2256 given face. | |
2257 ****************************************************************************/ | |
2258 static void | |
2259 XLIKE_clear_region (Lisp_Object UNUSED (locale), struct device* d, | |
2260 struct frame* f, face_index UNUSED (findex), int x, int y, | |
2261 int width, int height, Lisp_Object fcolor, | |
2262 Lisp_Object bcolor, Lisp_Object background_pixmap) | |
2263 { | |
2264 XLIKE_DISPLAY dpy = GET_XLIKE_DISPLAY (d); | |
2265 XLIKE_WINDOW x_win = GET_XLIKE_WINDOW (f); | |
2266 XLIKE_GC gc = NULL; | |
2267 | |
2268 if (!UNBOUNDP (background_pixmap)) | |
2269 { | |
2270 gc = XLIKE_get_gc (d, Qnil, fcolor, bcolor, background_pixmap, Qnil); | |
2271 } | |
2272 | |
2273 if (gc) | |
2274 XLIKE_FILL_RECTANGLE (dpy, x_win, gc, x, y, width, height); | |
2275 else | |
2276 XLIKE_CLEAR_AREA (dpy, x_win, x, y, width, height); | |
2277 } | |
2278 | |
2279 /***************************************************************************** | |
2280 xlike_output_eol_cursor | |
2281 | |
2282 Draw a cursor at the end of a line. The end-of-line cursor is | |
2283 narrower than the normal cursor. | |
2284 ****************************************************************************/ | |
2285 static void | |
2286 XLIKE_output_eol_cursor (struct window *w, struct display_line *dl, int xpos, | |
2287 face_index findex) | |
2288 { | |
2289 struct frame *f = XFRAME (w->frame); | |
2290 struct device *d = XDEVICE (f->device); | |
2291 Lisp_Object window; | |
2292 | |
2293 XLIKE_DISPLAY dpy = GET_XLIKE_DISPLAY (d); | |
2294 XLIKE_WINDOW x_win = GET_XLIKE_WINDOW (f); | |
2295 XLIKE_GC gc = NULL; | |
2296 face_index elt = get_builtin_face_cache_index (w, Vtext_cursor_face); | |
2297 struct face_cachel *cursor_cachel = WINDOW_FACE_CACHEL (w, elt); | |
2298 | |
2299 int focus = EQ (w->frame, DEVICE_FRAME_WITH_FOCUS_REAL (d)); | |
2300 Lisp_Object bar_cursor_value = symbol_value_in_buffer (Qbar_cursor, | |
2301 WINDOW_BUFFER (w)); | |
2302 | |
2303 int x = xpos; | |
2304 int y = XLIKE_DISPLAY_LINE_YPOS (dl); | |
2305 int width = EOL_CURSOR_WIDTH; | |
2306 int height = XLIKE_DISPLAY_LINE_HEIGHT (dl); | |
2307 int cursor_height, cursor_y; | |
2308 int defheight, defascent; | |
2309 | |
2310 window = wrap_window (w); | |
2311 redisplay_clear_region (window, findex, x, y, width, height); | |
2312 | |
2313 if (NILP (w->text_cursor_visible_p)) | |
2314 return; | |
2315 | |
2316 gc = XLIKE_get_gc (d, Qnil, cursor_cachel->background, Qnil, Qnil, Qnil); | |
2317 | |
2318 default_face_font_info (window, &defascent, 0, &defheight, 0, 0); | |
2319 | |
2320 /* make sure the cursor is entirely contained between y and y+height */ | |
2321 cursor_height = min (defheight, height); | |
2322 cursor_y = max (y, min (y + height - cursor_height, | |
2323 dl->ypos - defascent)); | |
2324 | |
2325 if (focus) | |
2326 { | |
2327 #ifdef HAVE_XIM | |
2328 XIM_SetSpotLocation (f, x - 2 , cursor_y + cursor_height - 2); | |
2329 #endif /* HAVE_XIM */ | |
2330 | |
2331 if (NILP (bar_cursor_value)) | |
2332 { | |
2333 XLIKE_FILL_RECTANGLE (dpy, x_win, gc, x, cursor_y, width, | |
2334 cursor_height); | |
2335 } | |
2336 else | |
2337 { | |
2338 int bar_width = EQ (bar_cursor_value, Qt) ? 1 : 2; | |
2339 | |
2340 gc = XLIKE_get_gc (d, Qnil, cursor_cachel->background, Qnil, Qnil, | |
2341 make_int (bar_width)); | |
2342 XLIKE_DRAW_LINE (dpy, x_win, gc, x + bar_width - 1, cursor_y, | |
2343 x + bar_width - 1, cursor_y + cursor_height - 1); | |
2344 } | |
2345 } | |
2346 else if (NILP (bar_cursor_value)) | |
2347 { | |
2348 XLIKE_DRAW_RECTANGLE (dpy, x_win, gc, x, cursor_y, width - 1, | |
2349 cursor_height - 1); | |
2350 } | |
2351 } | |
2352 | |
2353 static void | |
2354 XLIKE_clear_frame_window (Lisp_Object window) | |
2355 { | |
2356 struct window *w = XWINDOW (window); | |
2357 | |
2358 if (!NILP (w->vchild)) | |
2359 { | |
2360 XLIKE_clear_frame_windows (w->vchild); | |
2361 return; | |
2362 } | |
2363 | |
2364 if (!NILP (w->hchild)) | |
2365 { | |
2366 XLIKE_clear_frame_windows (w->hchild); | |
2367 return; | |
2368 } | |
2369 | |
2370 redisplay_clear_to_window_end (w, WINDOW_TEXT_TOP (w), | |
2371 WINDOW_TEXT_BOTTOM (w)); | |
2372 } | |
2373 | |
2374 static void | |
2375 XLIKE_clear_frame_windows (Lisp_Object window) | |
2376 { | |
2377 for (; !NILP (window); window = XWINDOW (window)->next) | |
2378 XLIKE_clear_frame_window (window); | |
2379 } | |
2380 | |
2381 static void | |
2382 XLIKE_clear_frame (struct frame *f) | |
2383 { | |
2384 XLIKE_DISPLAY dpy = GET_XLIKE_DISPLAY (XDEVICE (f->device)); | |
2385 XLIKE_WINDOW x_win = GET_XLIKE_WINDOW (f); | |
2386 int x, y, width, height; | |
2387 Lisp_Object frame; | |
2388 | |
2389 x = FRAME_LEFT_BORDER_START (f); | |
2390 width = (FRAME_PIXWIDTH (f) - FRAME_REAL_LEFT_TOOLBAR_WIDTH (f) - | |
2391 FRAME_REAL_RIGHT_TOOLBAR_WIDTH (f) - | |
2392 2 * FRAME_REAL_LEFT_TOOLBAR_BORDER_WIDTH (f) - | |
2393 2 * FRAME_REAL_RIGHT_TOOLBAR_BORDER_WIDTH (f)); | |
2394 /* #### This adjustment by 1 should be being done in the macros. | |
2395 There is some small differences between when the menubar is on | |
2396 and off that we still need to deal with. */ | |
2397 y = FRAME_TOP_BORDER_START (f) - 1; | |
2398 height = (FRAME_PIXHEIGHT (f) - FRAME_REAL_TOP_TOOLBAR_HEIGHT (f) - | |
2399 FRAME_REAL_BOTTOM_TOOLBAR_HEIGHT (f) - | |
2400 2 * FRAME_REAL_TOP_TOOLBAR_BORDER_WIDTH (f) - | |
2401 2 * FRAME_REAL_BOTTOM_TOOLBAR_BORDER_WIDTH (f)) + 1; | |
2402 | |
2403 XLIKE_CLEAR_AREA (dpy, x_win, x, y, width, height); | |
2404 | |
2405 frame = wrap_frame (f); | |
2406 | |
2407 if (!UNBOUNDP (FACE_BACKGROUND_PIXMAP (Vdefault_face, frame)) | |
2408 || !UNBOUNDP (FACE_BACKGROUND_PIXMAP (Vleft_margin_face, frame)) | |
2409 || !UNBOUNDP (FACE_BACKGROUND_PIXMAP (Vright_margin_face, frame))) | |
2410 { | |
2411 XLIKE_clear_frame_windows (f->root_window); | |
2412 } | |
2413 #ifdef THIS_IS_X | |
2414 { | |
2415 struct device *d = XDEVICE (f->device); | |
2416 if (!(check_if_pending_expose_event (d))) | |
2417 XFlush (DEVICE_X_DISPLAY (d)); | |
2418 } | |
2419 #endif /* THIS_IS_X */ | |
2420 } | |
2421 | |
2422 /* briefly swap the foreground and background colors. | |
2423 */ | |
2424 | |
2425 static int | |
2426 XLIKE_flash (struct device *d) | |
2427 { | |
2428 struct frame *f = device_selected_frame (d); | |
2429 XLIKE_DISPLAY dpy = GET_XLIKE_DISPLAY (d); | |
2430 XLIKE_WINDOW win = GET_XLIKE_WINDOW (f); | |
2431 XLIKE_GC gc = NULL; | |
2432 XLIKE_GCVALUES gcv; | |
2433 XLIKE_COLOR tmp_fcolor, tmp_bcolor; | |
2434 Lisp_Object tmp_pixel, frame; | |
2435 struct window *w = XWINDOW (FRAME_ROOT_WINDOW (f)); | |
2436 int flash_height; | |
2437 | |
2438 frame = wrap_frame (f); | |
2439 | |
2440 tmp_pixel = FACE_FOREGROUND (Vdefault_face, frame); | |
2441 XLIKE_SET_PIXCOLOR_COPY (tmp_fcolor, | |
2442 XCOLOR_INSTANCE_XLIKE_COLOR (tmp_pixel)); | |
2443 tmp_pixel = FACE_BACKGROUND (Vdefault_face, frame); | |
2444 XLIKE_SET_PIXCOLOR_COPY (tmp_bcolor, | |
2445 XCOLOR_INSTANCE_XLIKE_COLOR (tmp_pixel)); | |
2446 memset (&gcv, ~0, sizeof (gcv)); /* initialize all slots to ~0 */ | |
2447 XLIKE_SET_PIXCOLOR_NUM (gcv.foreground, | |
2448 (tmp_fcolor.pixel ^ tmp_bcolor.pixel)); | |
2449 gcv.function = XLIKE_GX_XOR; | |
2450 gcv.graphics_exposures = XLIKE_FALSE; | |
2451 gc = gc_cache_lookup (DEVICE_XLIKE_GC_CACHE (XDEVICE (f->device)), &gcv, | |
2452 XLIKE_GC_FOREGROUND | XLIKE_GC_FUNCTION | XLIKE_GC_EXPOSURES); | |
2453 default_face_height_and_width (frame, &flash_height, 0); | |
2454 | |
2455 /* If window is tall, flash top and bottom line. */ | |
2456 if (EQ (Vvisible_bell, Qtop_bottom) && w->pixel_height > 3 * flash_height) | |
2457 { | |
2458 XLIKE_FILL_RECTANGLE (dpy, win, gc, w->pixel_left, w->pixel_top, | |
2459 w->pixel_width, flash_height); | |
2460 XLIKE_FILL_RECTANGLE (dpy, win, gc, w->pixel_left, | |
2461 w->pixel_top + w->pixel_height - flash_height, | |
2462 w->pixel_width, flash_height); | |
2463 } | |
2464 else | |
2465 /* If it is short, flash it all. */ | |
2466 XLIKE_FILL_RECTANGLE (dpy, win, gc, w->pixel_left, w->pixel_top, | |
2467 w->pixel_width, w->pixel_height); | |
2468 | |
2469 XLIKE_FLUSH (dpy); | |
2470 | |
2471 #ifdef HAVE_SELECT | |
2472 { | |
2473 int usecs = 100000; | |
2474 struct timeval tv; | |
2475 tv.tv_sec = usecs / 1000000L; | |
2476 tv.tv_usec = usecs % 1000000L; | |
2477 /* I'm sure someone is going to complain about this... */ | |
2478 select (0, 0, 0, 0, &tv); | |
2479 } | |
2480 #else | |
2481 #ifdef HAVE_POLL | |
2482 poll (0, 0, 100); | |
2483 #else /* !HAVE_POLL */ | |
2484 #error bite me | |
2485 #endif /* HAVE_POLL */ | |
2486 #endif /* HAVE_SELECT */ | |
2487 | |
2488 /* If window is tall, flash top and bottom line. */ | |
2489 if (EQ (Vvisible_bell, Qtop_bottom) && w->pixel_height > 3 * flash_height) | |
2490 { | |
2491 XLIKE_FILL_RECTANGLE (dpy, win, gc, w->pixel_left, w->pixel_top, | |
2492 w->pixel_width, flash_height); | |
2493 XLIKE_FILL_RECTANGLE (dpy, win, gc, w->pixel_left, | |
2494 w->pixel_top + w->pixel_height - flash_height, | |
2495 w->pixel_width, flash_height); | |
2496 } | |
2497 else | |
2498 /* If it is short, flash it all. */ | |
2499 XLIKE_FILL_RECTANGLE (dpy, win, gc, w->pixel_left, w->pixel_top, | |
2500 w->pixel_width, w->pixel_height); | |
2501 | |
2502 XLIKE_FLUSH (dpy); | |
2503 | |
2504 return 1; | |
2505 } | |
2506 | |
2507 | |
2508 /************************************************************************/ | |
2509 /* initialization */ | |
2510 /************************************************************************/ | |
2511 | |
2512 void | |
2513 console_type_create_redisplay_XLIKE (void) | |
2514 { | |
2515 /* redisplay methods */ | |
2516 XLIKE_CONSOLE_HAS_METHOD (text_width); | |
2517 XLIKE_CONSOLE_HAS_METHOD (output_display_block); | |
2518 XLIKE_CONSOLE_HAS_METHOD (divider_height); | |
2519 XLIKE_CONSOLE_HAS_METHOD (eol_cursor_width); | |
2520 XLIKE_CONSOLE_HAS_METHOD (output_vertical_divider); | |
2521 XLIKE_CONSOLE_HAS_METHOD (clear_region); | |
2522 XLIKE_CONSOLE_HAS_METHOD (clear_frame); | |
2523 XLIKE_CONSOLE_HAS_METHOD (flash); | |
2524 XLIKE_CONSOLE_HAS_METHOD (ring_bell); | |
2525 XLIKE_CONSOLE_HAS_METHOD (bevel_area); | |
2526 XLIKE_CONSOLE_HAS_METHOD (output_string); | |
2527 XLIKE_CONSOLE_HAS_METHOD (output_pixmap); | |
2528 | |
2529 #ifdef THIS_IS_X | |
2530 XLIKE_CONSOLE_HAS_METHOD (window_output_begin); | |
2531 XLIKE_CONSOLE_HAS_METHOD (window_output_end); | |
2532 #endif | |
2533 } |