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 }