comparison src/redisplay-xlike-inc.c @ 4933:77e3b19bd245

merge
author Ben Wing <ben@xemacs.org>
date Sun, 24 Jan 2010 22:06:20 -0600
parents ea701c23ed84
children e813cf16c015
comparison
equal deleted inserted replaced
4883:f730384b8ddf 4933:77e3b19bd245
1 /* Common code between X and GTK.
2 Copyright (C) 1994, 1995 Board of Trustees, University of Illinois.
3 Copyright (C) 1994 Lucid, Inc.
4 Copyright (C) 1995 Sun Microsystems, Inc.
5 Copyright (C) 2002, 2003, 2005, 2009, 2010 Ben Wing.
6
7 This file is part of XEmacs.
8
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
11 Free Software Foundation; either version 2, or (at your option) any
12 later version.
13
14 XEmacs is distributed in the hope that it will be useful, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with XEmacs; see the file COPYING. If not, write to
21 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22 Boston, MA 02111-1307, USA. */
23
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
363
364 /* Note: We do not use the Xmb*() functions and XFontSets, nor the
365 Motif XFontLists and CompoundStrings.
366 Those functions are generally losing for a number of reasons.
367 Most important, they only support one locale (e.g. you could
368 display Japanese and ASCII text, but not mixed Japanese/Chinese
369 text). You could maybe call setlocale() frequently to try to deal
370 with this, but that would generally fail because an XFontSet is
371 tied to one locale and won't have the other character sets in it.
372
373 fontconfig (the font database for Xft) has some specifier-like
374 properties, but it's not sufficient (witness the existence of
375 Pango). Pango might do the trick, but it's not a cross-platform
376 solution; it would need significant advantages to be worth the
377 effort.
378 */
379
380 struct textual_run
381 {
382 Lisp_Object charset;
383 unsigned char *ptr;
384 int len;
385 int dimension;
386 };
387
388 /* Separate out the text in STR (an array of Ichars, not a string
389 representation) of length LEN into a series of runs, stored in
390 RUN_STORAGE. RUN_STORAGE is guaranteed to hold enough space for all
391 runs that could be generated from this text. Each run points to the a
392 stretch of text given simply by the position codes TEXT_STORAGE into a
393 series of textual runs of a particular charset. Also convert the
394 characters as necessary into the format needed by XDrawImageString(),
395 XDrawImageString16(), et al. This means converting to one or two byte
396 format, possibly tweaking the high bits, and possibly running a CCL
397 program. You must pre-allocate the space used and pass it in. (This is
398 done so you can ALLOCA () the space.) (2 * len) bytes must be allocated
399 for TEXT_STORAGE and (len * sizeof (struct textual_run)) bytes of
400 RUN_STORAGE, where LEN is the length of the dynarr.
401
402 bufchar might not be fixed width (in the case of UTF-8).
403
404 Returns the number of runs actually used. */
405
406 /* Notes on Xft implementation
407
408 - With Unicode, we're no longer going to have repertoires reified as
409 charsets. (Not that we ever really did, what with corporate variants,
410 and so on.) So we really should be querying the face for the desired
411 font, rather than the character for the charset, and that's what would
412 determine the separation into runs.
413 - The widechar versions of fontconfig (and therefore Xft) functions
414 seem to be just bigendian Unicode. So there's actually no need to use
415 the 8-bit versions in computing runs and runes, it would seem.
416 */
417
418 #if !defined(USE_XFT) && !defined(MULE)
419 static int
420 separate_textual_runs_nomule (unsigned char *text_storage,
421 struct textual_run *run_storage,
422 const Ichar *str, Charcount len,
423 struct face_cachel *UNUSED(cachel))
424 {
425 if (!len)
426 return 0;
427
428 run_storage[0].ptr = text_storage;
429 run_storage[0].len = len;
430 run_storage[0].dimension = 1;
431 run_storage[0].charset = Qnil;
432
433 while (len--)
434 *text_storage++ = *str++;
435 return 1;
436 }
437 #endif
438
439 #if defined(USE_XFT) && !defined(MULE)
440 /*
441 Note that in this configuration the "Croatian hack" of using an 8-bit,
442 non-Latin-1 font to get localized display without Mule simply isn't
443 available. That's by design -- Unicode does not aid or abet that kind
444 of punning.
445 This means that the cast to XftChar16 gives the correct "conversion" to
446 UCS-2.
447 #### Is there an alignment issue with text_storage?
448 */
449 static int
450 separate_textual_runs_xft_nomule (unsigned char *text_storage,
451 struct textual_run *run_storage,
452 const Ichar *str, Charcount len,
453 struct face_cachel *UNUSED(cachel))
454 {
455 int i;
456 if (!len)
457 return 0;
458
459 run_storage[0].ptr = text_storage;
460 run_storage[0].len = len;
461 run_storage[0].dimension = 2;
462 run_storage[0].charset = Qnil;
463
464 for (i = 0; i < len; i++)
465 {
466 *(XftChar16 *)text_storage = str[i];
467 text_storage += sizeof(XftChar16);
468 }
469 return 1;
470 }
471 #endif
472
473 #if defined(USE_XFT) && defined(MULE)
474 static int
475 separate_textual_runs_xft_mule (unsigned char *text_storage,
476 struct textual_run *run_storage,
477 const Ichar *str, Charcount len,
478 struct face_cachel *UNUSED(cachel))
479 {
480 Lisp_Object prev_charset = Qunbound;
481 int runs_so_far = 0, i;
482
483 run_storage[0].ptr = text_storage;
484 run_storage[0].len = len;
485 run_storage[0].dimension = 2;
486 run_storage[0].charset = Qnil;
487
488 for (i = 0; i < len; i++)
489 {
490 Ichar ch = str[i];
491 Lisp_Object charset = ichar_charset(ch);
492 int ucs = ichar_to_unicode(ch);
493
494 /* If UCS is less than zero or greater than 0xFFFF, set ucs2 to
495 REPLACMENT CHARACTER. */
496 /* That means we can't handle characters outside of the BMP for now */
497 ucs = (ucs & ~0xFFFF) ? 0xFFFD : ucs;
498
499 if (!EQ (charset, prev_charset))
500 {
501 if (runs_so_far)
502 run_storage[runs_so_far-1].len = (text_storage - run_storage[runs_so_far-1].ptr) >> 1;
503 run_storage[runs_so_far].ptr = text_storage;
504 run_storage[runs_so_far].dimension = 2;
505 run_storage[runs_so_far].charset = charset;
506 prev_charset = charset;
507 runs_so_far++;
508 }
509
510 *(XftChar16 *)text_storage = ucs;
511 text_storage += sizeof(XftChar16);
512 }
513
514 if (runs_so_far)
515 run_storage[runs_so_far-1].len = (text_storage - run_storage[runs_so_far-1].ptr) >> 1;
516 return runs_so_far;
517 }
518 #endif
519
520 #if !defined(USE_XFT) && defined(MULE)
521 /*
522 This is the most complex function of this group, due to the various
523 indexing schemes used by different fonts. For our purposes, they
524 fall into three classes. Some fonts are indexed compatibly with ISO
525 2022; those fonts just use the Mule internal representation directly
526 (typically the high bit must be reset; this is determined by the `graphic'
527 flag). Some fonts are indexed by Unicode, specifically by UCS-2. These
528 are all translated using `ichar_to_unicode'. Finally some fonts have
529 irregular indexes, and must be translated ad hoc. In XEmacs ad hoc
530 translations are accomplished with CCL programs. */
531 static int
532 separate_textual_runs_mule (unsigned char *text_storage,
533 struct textual_run *run_storage,
534 const Ichar *str, Charcount len,
535 struct face_cachel *cachel)
536 {
537 Lisp_Object prev_charset = Qunbound;
538 int runs_so_far = 0, i;
539 Ibyte charset_leading_byte = LEADING_BYTE_ASCII;
540 int dimension = 1, graphic = 0, need_ccl_conversion = 0;
541 Lisp_Object ccl_prog;
542 struct ccl_program char_converter;
543
544 int translate_to_ucs_2 = 0;
545
546 for (i = 0; i < len; i++)
547 {
548 Ichar ch = str[i];
549 Lisp_Object charset;
550 int byte1, byte2; /* BREAKUP_ICHAR dereferences the addresses
551 of its arguments as pointer to int. */
552 BREAKUP_ICHAR (ch, charset, byte1, byte2);
553
554 if (!EQ (charset, prev_charset))
555 {
556 /* At this point, dimension' and `prev_charset' refer to just-
557 completed run. `runs_so_far' and `text_storage' refer to the
558 run about to start. */
559 if (runs_so_far)
560 {
561 /* Update metadata for previous run. */
562 run_storage[runs_so_far - 1].len =
563 text_storage - run_storage[runs_so_far - 1].ptr;
564 if (2 == dimension) run_storage[runs_so_far - 1].len >>= 1;
565 }
566
567 /* Compute metadata for current run.
568 First, classify font.
569 If the font is indexed by UCS-2, set `translate_to_ucs_2'.
570 Else if the charset has a CCL program, set `need_ccl_conversion'.
571 Else if the font is indexed by an ISO 2022 "graphic register",
572 set `graphic'.
573 These flags are almost mutually exclusive, but we're sloppy
574 about resetting "shadowed" flags. So the flags must be checked
575 in the proper order in computing byte1 and byte2, below. */
576 charset_leading_byte = XCHARSET_LEADING_BYTE(charset);
577 translate_to_ucs_2 =
578 bit_vector_bit (FACE_CACHEL_FONT_FINAL_STAGE (cachel),
579 charset_leading_byte - MIN_LEADING_BYTE);
580 if (translate_to_ucs_2)
581 {
582 dimension = 2;
583 }
584 else
585 {
586 dimension = XCHARSET_DIMENSION (charset);
587
588 /* Check for CCL charset.
589 If setup_ccl_program fails, we'll get a garbaged display.
590 This should never happen, and even if it does, it should
591 be harmless (unless the X server has buggy handling of
592 characters undefined in the font). It may be marginally
593 more useful to users and debuggers than substituting a
594 fixed replacement character. */
595 ccl_prog = XCHARSET_CCL_PROGRAM (charset);
596 if ((!NILP (ccl_prog))
597 && (setup_ccl_program (&char_converter, ccl_prog) >= 0))
598 {
599 need_ccl_conversion = 1;
600 }
601 else
602 {
603 /* The charset must have an ISO 2022-compatible font index.
604 There are 2 "registers" (what such fonts use as index).
605 GL (graphic == 0) has the high bit of each octet reset,
606 GR (graphic == 1) has it set. */
607 graphic = XCHARSET_GRAPHIC (charset);
608 need_ccl_conversion = 0;
609 }
610 }
611
612 /* Initialize metadata for current run. */
613 run_storage[runs_so_far].ptr = text_storage;
614 run_storage[runs_so_far].charset = charset;
615 run_storage[runs_so_far].dimension = dimension;
616
617 /* Update loop variables. */
618 prev_charset = charset;
619 runs_so_far++;
620 }
621
622 /* Must check flags in this order. See comment above. */
623 if (translate_to_ucs_2)
624 {
625 int ucs = ichar_to_unicode(ch);
626 /* If UCS is less than zero or greater than 0xFFFF, set ucs2 to
627 REPLACMENT CHARACTER. */
628 ucs = (ucs & ~0xFFFF) ? 0xFFFD : ucs;
629
630 byte1 = ucs >> 8;
631 byte2 = ucs;
632 }
633 else if (need_ccl_conversion)
634 {
635 char_converter.reg[0] = charset_leading_byte;
636 char_converter.reg[1] = byte1;
637 char_converter.reg[2] = byte2;
638 ccl_driver (&char_converter, 0, 0, 0, 0, CCL_MODE_ENCODING);
639 byte1 = char_converter.reg[1];
640 byte2 = char_converter.reg[2];
641 }
642 else if (graphic == 0)
643 {
644 byte1 &= 0x7F;
645 byte2 &= 0x7F;
646 }
647 else
648 {
649 byte1 |= 0x80;
650 byte2 |= 0x80;
651 }
652
653 *text_storage++ = (unsigned char)byte1;
654
655 if (2 == dimension) *text_storage++ = (unsigned char)byte2;
656 }
657
658 if (runs_so_far)
659 {
660 run_storage[runs_so_far - 1].len =
661 text_storage - run_storage[runs_so_far - 1].ptr;
662 /* Dimension retains the relevant value for the run before it. */
663 if (2 == dimension)
664 run_storage[runs_so_far - 1].len >>= 1;
665 }
666
667 return runs_so_far;
668 }
669 #endif
670
671 static int
672 separate_textual_runs (unsigned char *text_storage,
673 struct textual_run *run_storage,
674 const Ichar *str, Charcount len,
675 struct face_cachel *cachel)
676 {
677 #if defined(USE_XFT) && defined(MULE)
678 return separate_textual_runs_xft_mule (text_storage, run_storage,
679 str, len, cachel);
680 #endif
681 #if defined(USE_XFT) && !defined(MULE)
682 return separate_textual_runs_xft_nomule (text_storage, run_storage,
683 str, len, cachel);
684 #endif
685 #if !defined(USE_XFT) && defined(MULE)
686 return separate_textual_runs_mule (text_storage, run_storage,
687 str, len, cachel);
688 #endif
689 #if !defined(USE_XFT) && !defined(MULE)
690 return separate_textual_runs_nomule (text_storage, run_storage,
691 str, len, cachel);
692 #endif
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 static int
771 XLIKE_text_width (struct window *w, struct face_cachel *cachel,
772 const Ichar *str, Charcount len)
773 {
774 /* !!#### Needs review */
775 int width_so_far = 0;
776 unsigned char *text_storage = (unsigned char *) ALLOCA (2 * len);
777 struct textual_run *runs = alloca_array (struct textual_run, len);
778 struct frame *f = WINDOW_XFRAME (w);
779 int nruns;
780 int i;
781
782 nruns = separate_textual_runs (text_storage, runs, str, len,
783 cachel);
784
785 for (i = 0; i < nruns; i++)
786 width_so_far += XLIKE_text_width_single_run (f, cachel, runs + i);
787
788 return width_so_far;
789 }
790
791 /*****************************************************************************
792 XLIKE_divider_height
793
794 Return the height of the horizontal divider. This is a function because
795 divider_height is a device method.
796
797 #### If we add etched horizontal divider lines this will have to get
798 smarter.
799 ****************************************************************************/
800 static int
801 XLIKE_divider_height (void)
802 {
803 #ifdef THIS_IS_X
804 return 1;
805 #else /* THIS_IS_GTK */
806 return 2;
807 #endif /* THIS_IS_GTK */
808 }
809
810 /*****************************************************************************
811 XLIKE_eol_cursor_width
812
813 Return the width of the end-of-line cursor. This is a function
814 because eol_cursor_width is a device method.
815 ****************************************************************************/
816 static int
817 XLIKE_eol_cursor_width (void)
818 {
819 return EOL_CURSOR_WIDTH;
820 }
821
822 /*****************************************************************************
823 XLIKE_output_display_block
824
825 Given a display line, a block number for that start line, output all
826 runes between start and end in the specified display block.
827 ****************************************************************************/
828 static void
829 XLIKE_output_display_block (struct window *w, struct display_line *dl,
830 int block, int start, int end, int start_pixpos,
831 int cursor_start, int cursor_width,
832 int cursor_height)
833 {
834 #ifndef USE_XFT
835 struct frame *f = XFRAME (w->frame);
836 #endif
837 Ichar_dynarr *buf;
838 Lisp_Object window;
839
840 struct display_block *db = Dynarr_atp (dl->display_blocks, block);
841 rune_dynarr *rba = db->runes;
842 struct rune *rb;
843
844 int elt = start;
845 face_index findex;
846 int xpos, width = 0;
847 Lisp_Object charset = Qunbound; /* Qnil is a valid charset when
848 MULE is not defined */
849
850 window = wrap_window (w);
851 rb = Dynarr_atp (rba, start);
852
853 if (!rb)
854 /* Nothing to do so don't do anything. */
855 return;
856
857 findex = rb->findex;
858 xpos = rb->xpos;
859 if (rb->type == RUNE_CHAR)
860 charset = ichar_charset (rb->object.chr.ch);
861
862 if (end < 0)
863 end = Dynarr_length (rba);
864 buf = Dynarr_new (Ichar);
865
866 while (elt < end)
867 {
868 rb = Dynarr_atp (rba, elt);
869
870 if (rb->findex == findex && rb->type == RUNE_CHAR
871 && rb->object.chr.ch != '\n' && rb->cursor_type != CURSOR_ON
872 && EQ (charset, ichar_charset (rb->object.chr.ch)))
873 {
874 Dynarr_add (buf, rb->object.chr.ch);
875 width += rb->width;
876 elt++;
877 }
878 else
879 {
880 if (Dynarr_length (buf))
881 {
882 XLIKE_output_string (w, dl, buf, xpos, 0, start_pixpos, width,
883 findex, 0, cursor_start, cursor_width,
884 cursor_height);
885 xpos = rb->xpos;
886 width = 0;
887 }
888 Dynarr_reset (buf);
889 width = 0;
890
891 if (rb->type == RUNE_CHAR)
892 {
893 findex = rb->findex;
894 xpos = rb->xpos;
895 charset = ichar_charset (rb->object.chr.ch);
896
897 if (rb->cursor_type == CURSOR_ON)
898 {
899 if (rb->object.chr.ch == '\n')
900 {
901 XLIKE_output_eol_cursor (w, dl, xpos, findex);
902 }
903 else
904 {
905 Dynarr_add (buf, rb->object.chr.ch);
906 XLIKE_output_string (w, dl, buf, xpos, 0, start_pixpos,
907 rb->width, findex, 1,
908 cursor_start, cursor_width,
909 cursor_height);
910 Dynarr_reset (buf);
911 }
912
913 xpos += rb->width;
914 elt++;
915 }
916 else if (rb->object.chr.ch == '\n')
917 {
918 /* Clear in case a cursor was formerly here. */
919 redisplay_clear_region (window, findex, xpos,
920 XLIKE_DISPLAY_LINE_YPOS (dl),
921 rb->width,
922 XLIKE_DISPLAY_LINE_HEIGHT (dl));
923 elt++;
924 }
925 }
926 else if (rb->type == RUNE_BLANK || rb->type == RUNE_HLINE)
927 {
928 if (rb->type == RUNE_BLANK)
929 XLIKE_output_blank (w, dl, rb, start_pixpos, cursor_start,
930 cursor_width);
931 else
932 {
933 /* #### Our flagging of when we need to redraw the
934 modeline shadows sucks. Since RUNE_HLINE is only used
935 by the modeline at the moment it is a good bet
936 that if it gets redrawn then we should also
937 redraw the shadows. This won't be true forever.
938 We borrow the shadow_thickness_changed flag for
939 now. */
940 w->shadow_thickness_changed = 1;
941 XLIKE_output_horizontal_line (w, dl, rb);
942 }
943
944 elt++;
945 if (elt < end)
946 {
947 rb = Dynarr_atp (rba, elt);
948
949 findex = rb->findex;
950 xpos = rb->xpos;
951 }
952 }
953 else if (rb->type == RUNE_DGLYPH)
954 {
955 Lisp_Object instance;
956 struct display_box dbox;
957 struct display_glyph_area dga;
958
959 redisplay_calculate_display_boxes (dl, rb->xpos, rb->object.dglyph.xoffset,
960 rb->object.dglyph.yoffset, start_pixpos,
961 rb->width, &dbox, &dga);
962
963 window = wrap_window (w);
964 instance = glyph_image_instance (rb->object.dglyph.glyph,
965 window, ERROR_ME_DEBUG_WARN, 1);
966 findex = rb->findex;
967
968 if (IMAGE_INSTANCEP (instance))
969 {
970 switch (XIMAGE_INSTANCE_TYPE (instance))
971 {
972 case IMAGE_TEXT:
973 #ifdef THIS_IS_GTK
974 {
975 /* !!#### Examine for Mule-izing */
976 /* #### This is way losing. See the comment in
977 add_glyph_rune(). */
978 Lisp_Object string =
979 XIMAGE_INSTANCE_TEXT_STRING (instance);
980 convert_ibyte_string_into_ichar_dynarr
981 (XSTRING_DATA (string), XSTRING_LENGTH (string),
982 buf);
983
984 gtk_output_string (w, dl, buf, xpos,
985 rb->object.dglyph.xoffset,
986 start_pixpos, -1, findex,
987 (rb->cursor_type == CURSOR_ON),
988 cursor_start, cursor_width,
989 cursor_height);
990 Dynarr_reset (buf);
991 }
992 break;
993 #else
994 ABORT ();
995 #endif /* THIS_IS_GTK */
996 case IMAGE_MONO_PIXMAP:
997 case IMAGE_COLOR_PIXMAP:
998 redisplay_output_pixmap (w, instance, &dbox, &dga,
999 findex, cursor_start,
1000 cursor_width,
1001 cursor_height, 0);
1002 break;
1003
1004 case IMAGE_WIDGET:
1005 if (EQ (XIMAGE_INSTANCE_WIDGET_TYPE (instance),
1006 Qlayout))
1007 {
1008 redisplay_output_layout (window, instance, &dbox,
1009 &dga, findex,
1010 cursor_start, cursor_width,
1011 cursor_height);
1012 break;
1013 }
1014
1015 case IMAGE_SUBWINDOW:
1016 redisplay_output_subwindow (w, instance, &dbox, &dga,
1017 findex, cursor_start,
1018 cursor_width, cursor_height);
1019 break;
1020
1021 case IMAGE_NOTHING:
1022 /* nothing is as nothing does */
1023 break;
1024
1025 case IMAGE_POINTER:
1026 default:
1027 ABORT ();
1028 }
1029 IMAGE_INSTANCE_OPTIMIZE_OUTPUT
1030 (XIMAGE_INSTANCE (instance)) = 0;
1031 }
1032
1033 xpos += rb->width;
1034 elt++;
1035 }
1036 else
1037 ABORT ();
1038 }
1039 }
1040
1041 if (Dynarr_length (buf))
1042 XLIKE_output_string (w, dl, buf, xpos, 0, start_pixpos, width, findex,
1043 0, cursor_start, cursor_width, cursor_height);
1044
1045 if (dl->modeline
1046 && !EQ (Qzero, w->modeline_shadow_thickness)
1047 #ifndef USE_XFT
1048 /* This optimization doesn't work right with some Xft fonts, which
1049 leave antialiasing turds at the boundary. I don't know if this
1050 is an Xft bug or not, but I think it is. See x_output_string. */
1051 && (f->clear
1052 || f->windows_structure_changed
1053 || w->shadow_thickness_changed)
1054 #endif
1055 )
1056 bevel_modeline (w, dl);
1057
1058 Dynarr_free (buf);
1059 }
1060
1061 /*****************************************************************************
1062 XLIKE_get_gc
1063
1064 Given a number of parameters return a GC with those properties.
1065 ****************************************************************************/
1066 static XLIKE_GC
1067 XLIKE_get_gc (struct device *d, Lisp_Object font, Lisp_Object fg,
1068 Lisp_Object bg, Lisp_Object bg_pmap, Lisp_Object lwidth)
1069 {
1070 XLIKE_GCVALUES gcv;
1071 unsigned long mask;
1072
1073 memset (&gcv, ~0, sizeof (gcv));
1074 gcv.graphics_exposures = XLIKE_FALSE;
1075 /* Make absolutely sure that we don't pick up a clipping region in
1076 the GC returned by this function. */
1077 gcv.clip_mask = XLIKE_NONE;
1078 gcv.clip_x_origin = 0;
1079 gcv.clip_y_origin = 0;
1080 gcv.XLIKE_FILL_MEMBER = XLIKE_FILL_SOLID;
1081 mask = XLIKE_GC_EXPOSURES | XLIKE_GC_CLIP_MASK | XLIKE_GC_CLIP_X_ORIGIN | XLIKE_GC_CLIP_Y_ORIGIN;
1082 mask |= XLIKE_GC_FILL;
1083
1084 if (!NILP (font)
1085 #ifdef USE_XFT
1086 /* Only set the font if it's a core font */
1087 /* the renderfont will be set elsewhere (not part of gc) */
1088 && !FONT_INSTANCE_X_XFTFONT (XFONT_INSTANCE (font))
1089 #endif
1090 )
1091 {
1092 gcv.font =
1093 XLIKE_FONT_NUM (FONT_INSTANCE_XLIKE_FONT (XFONT_INSTANCE (font)));
1094 mask |= XLIKE_GC_FONT;
1095 }
1096
1097 /* evil kludge! */
1098 if (!NILP (fg) && !COLOR_INSTANCEP (fg) && !INTP (fg))
1099 {
1100 /* #### I fixed one case where this was getting hit. It was a
1101 bad macro expansion (compiler bug). */
1102 stderr_out ("Help! x_get_gc got a bogus fg value! fg = ");
1103 debug_print (fg);
1104 fg = Qnil;
1105 }
1106
1107 if (!NILP (fg))
1108 {
1109 if (COLOR_INSTANCEP (fg))
1110 XLIKE_SET_PIXCOLOR_COPY
1111 (gcv.foreground,
1112 XLIKE_COLOR_TO_PIXCOLOR (XCOLOR_INSTANCE_XLIKE_COLOR (fg)));
1113 else
1114 XLIKE_SET_PIXCOLOR_NUM (gcv.foreground, XINT (fg));
1115 mask |= XLIKE_GC_FOREGROUND;
1116 }
1117
1118 if (!NILP (bg))
1119 {
1120 if (COLOR_INSTANCEP (bg))
1121 XLIKE_SET_PIXCOLOR_COPY
1122 (gcv.background,
1123 XLIKE_COLOR_TO_PIXCOLOR (XCOLOR_INSTANCE_XLIKE_COLOR (bg)));
1124 else
1125 XLIKE_SET_PIXCOLOR_NUM (gcv.background, XINT (bg));
1126 mask |= XLIKE_GC_BACKGROUND;
1127 }
1128
1129 /* This special case comes from a request to draw text with a face which has
1130 the dim property. We'll use a stippled foreground GC. */
1131 if (EQ (bg_pmap, Qdim))
1132 {
1133 assert (DEVICE_XLIKE_GRAY_PIXMAP (d) != XLIKE_NONE);
1134
1135 gcv.XLIKE_FILL_MEMBER = XLIKE_FILL_STIPPLED;
1136 gcv.stipple = DEVICE_XLIKE_GRAY_PIXMAP (d);
1137 mask |= (XLIKE_GC_FILL | XLIKE_GC_STIPPLE);
1138 }
1139 else if (IMAGE_INSTANCEP (bg_pmap)
1140 && IMAGE_INSTANCE_PIXMAP_TYPE_P (XIMAGE_INSTANCE (bg_pmap)))
1141 {
1142 if (XIMAGE_INSTANCE_PIXMAP_DEPTH (bg_pmap) == 0)
1143 {
1144 gcv.XLIKE_FILL_MEMBER = XLIKE_FILL_OPAQUE_STIPPLED;
1145 gcv.stipple = XIMAGE_INSTANCE_XLIKE_PIXMAP (bg_pmap);
1146 mask |= (XLIKE_GC_STIPPLE | XLIKE_GC_FILL);
1147 }
1148 else
1149 {
1150 gcv.XLIKE_FILL_MEMBER = XLIKE_FILL_TILED;
1151 gcv.tile = XIMAGE_INSTANCE_XLIKE_PIXMAP (bg_pmap);
1152 mask |= (XLIKE_GC_TILE | XLIKE_GC_FILL);
1153 }
1154 }
1155
1156 if (!NILP (lwidth))
1157 {
1158 gcv.line_width = XINT (lwidth);
1159 mask |= XLIKE_GC_LINE_WIDTH;
1160 }
1161
1162 #if 0
1163 debug_out ("\nx_get_gc: calling gc_cache_lookup\n");
1164 #endif
1165 return gc_cache_lookup (DEVICE_XLIKE_GC_CACHE (d), &gcv, mask);
1166 }
1167
1168 /*****************************************************************************
1169 XLIKE_output_string
1170
1171 Given a string and a starting position, output that string in the
1172 given face. If cursor is true, draw a cursor around the string.
1173 Correctly handles multiple charsets in the string.
1174
1175 The meaning of the parameters is something like this:
1176
1177 W Window that the text is to be displayed in.
1178 DL Display line that this text is on. The values in the
1179 structure are used to determine the vertical position and
1180 clipping range of the text.
1181 BUF Dynamic array of Ichars specifying what is actually to be
1182 drawn.
1183 XPOS X position in pixels where the text should start being drawn.
1184 XOFFSET Number of pixels to be chopped off the left side of the
1185 text. The effect is as if the text were shifted to the
1186 left this many pixels and clipped at XPOS.
1187 CLIP_START Clip everything left of this X position.
1188 WIDTH Clip everything right of XPOS + WIDTH.
1189 FINDEX Index for the face cache element describing how to display
1190 the text.
1191 CURSOR #### I don't understand this. There's something
1192 strange and overcomplexified with this variable.
1193 Chuck, explain please?
1194 CURSOR_START Starting X position of cursor.
1195 CURSOR_WIDTH Width of cursor in pixels.
1196 CURSOR_HEIGHT Height of cursor in pixels.
1197
1198 Starting Y position of cursor is the top of the text line.
1199 The cursor is drawn sometimes whether or not CURSOR is set. ???
1200 ****************************************************************************/
1201 #ifdef THIS_IS_GTK
1202 static
1203 void gdk_draw_text_image (GdkDrawable *drawable,
1204 GdkFont *font,
1205 GdkGC *gc,
1206 gint x,
1207 gint y,
1208 const gchar *text,
1209 gint text_length);
1210
1211 #endif /* THIS_IS_GTK */
1212 void
1213 XLIKE_output_string (struct window *w, struct display_line *dl,
1214 Ichar_dynarr *buf, int xpos, int xoffset, int clip_start,
1215 int width, face_index findex, int cursor,
1216 int cursor_start, int cursor_width, int cursor_height)
1217 {
1218 /* General variables */
1219 struct frame *f = XFRAME (w->frame);
1220 struct device *d = XDEVICE (f->device);
1221 XLIKE_DISPLAY dpy = GET_XLIKE_DISPLAY (d);
1222 XLIKE_WINDOW x_win = GET_XLIKE_WINDOW (f);
1223 Lisp_Object window = wrap_window (w);
1224
1225 int clip_end;
1226
1227 /* Cursor-related variables */
1228 int focus = EQ (w->frame, DEVICE_FRAME_WITH_FOCUS_REAL (d));
1229 int cursor_clip;
1230 Lisp_Object bar_cursor_value = symbol_value_in_buffer (Qbar_cursor,
1231 WINDOW_BUFFER (w));
1232 struct face_cachel *cursor_cachel = 0;
1233
1234 /* Text-related variables */
1235 Lisp_Object bg_pmap;
1236 XLIKE_GC bgc, gc;
1237 int height = XLIKE_DISPLAY_LINE_HEIGHT (dl);
1238 int ypos = XLIKE_DISPLAY_LINE_YPOS (dl);
1239 int len = Dynarr_length (buf);
1240 unsigned char *text_storage = (unsigned char *) ALLOCA (2 * len);
1241 struct textual_run *runs = alloca_array (struct textual_run, len);
1242 int nruns;
1243 int i;
1244 struct face_cachel *cachel = WINDOW_FACE_CACHEL (w, findex);
1245
1246 #ifdef THIS_IS_X
1247 int use_x_font = 1; /* #### bogus!!
1248 The logic of this function needs review! */
1249 #endif
1250 #ifdef USE_XFT
1251 Colormap cmap = DEVICE_X_COLORMAP (d);
1252 Visual *visual = DEVICE_X_VISUAL (d);
1253 static XftColor fg, bg;
1254 XftDraw *xftDraw;
1255
1256 /* Lazily initialize frame's xftDraw member. */
1257 if (!FRAME_X_XFTDRAW (f)) {
1258 FRAME_X_XFTDRAW (f) = XftDrawCreate (dpy, x_win, visual, cmap);
1259 }
1260 xftDraw = FRAME_X_XFTDRAW (f);
1261
1262 /* #### This will probably cause asserts when passed a Lisp integer for a
1263 color. See ca. line 759 this file.
1264 #### Maybe xft_convert_color should take an XColor, not a pixel. */
1265 #define XFT_FROB_LISP_COLOR(color, dim) \
1266 xft_convert_color (dpy, cmap, visual, \
1267 COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (color)).pixel, \
1268 (dim))
1269 #endif /* USE_XFT */
1270
1271 if (width < 0)
1272 width = XLIKE_text_width (w, cachel, Dynarr_atp (buf, 0),
1273 Dynarr_length (buf));
1274
1275 /* Regularize the variables passed in. */
1276
1277 if (clip_start < xpos)
1278 clip_start = xpos;
1279 clip_end = xpos + width;
1280 if (clip_start >= clip_end)
1281 /* It's all clipped out. */
1282 return;
1283
1284 xpos -= xoffset;
1285
1286 /* make sure the area we are about to display is subwindow free. */
1287 redisplay_unmap_subwindows_maybe (f, clip_start, ypos,
1288 clip_end - clip_start, height);
1289
1290 cursor_clip = (cursor_start >= clip_start &&
1291 cursor_start < clip_end);
1292
1293 /* This cursor code is really a mess. */
1294 if (!NILP (w->text_cursor_visible_p)
1295 && (cursor
1296 || cursor_clip
1297 || (cursor_width
1298 && (cursor_start + cursor_width >= clip_start)
1299 && !NILP (bar_cursor_value))))
1300 {
1301 /* These have to be in separate statements in order to avoid a
1302 compiler bug. */
1303 face_index sucks = get_builtin_face_cache_index (w, Vtext_cursor_face);
1304 cursor_cachel = WINDOW_FACE_CACHEL (w, sucks);
1305
1306 /* We have to reset this since any call to WINDOW_FACE_CACHEL
1307 may cause the cache to resize and any pointers to it to
1308 become invalid. */
1309 cachel = WINDOW_FACE_CACHEL (w, findex);
1310 }
1311
1312 #ifdef HAVE_XIM
1313 if (cursor && focus && (cursor_start == clip_start) && cursor_height)
1314 XIM_SetSpotLocation (f, xpos - 2, dl->ypos + dl->descent - 2);
1315 #endif /* HAVE_XIM */
1316
1317 bg_pmap = cachel->background_pixmap;
1318 if (!IMAGE_INSTANCEP (bg_pmap)
1319 || !IMAGE_INSTANCE_PIXMAP_TYPE_P (XIMAGE_INSTANCE (bg_pmap)))
1320 bg_pmap = Qnil;
1321
1322 if ((cursor && focus && NILP (bar_cursor_value)
1323 && !NILP (w->text_cursor_visible_p)) || NILP (bg_pmap))
1324 bgc = 0;
1325 else
1326 bgc = XLIKE_get_gc (d, Qnil, cachel->foreground, cachel->background,
1327 bg_pmap, Qnil);
1328
1329 if (bgc)
1330 {
1331 XLIKE_FILL_RECTANGLE (dpy, x_win, bgc, clip_start,
1332 ypos, clip_end - clip_start,
1333 height);
1334 }
1335
1336 nruns = separate_textual_runs (text_storage, runs, Dynarr_atp (buf, 0),
1337 Dynarr_length (buf), cachel);
1338
1339 for (i = 0; i < nruns; i++)
1340 {
1341 Lisp_Object font = FACE_CACHEL_FONT (cachel, runs[i].charset);
1342 Lisp_Font_Instance *fi = XFONT_INSTANCE (font);
1343 int this_width;
1344 int need_clipping;
1345
1346 if (EQ (font, Vthe_null_font_instance))
1347 continue;
1348
1349 this_width = XLIKE_text_width_single_run (f, cachel, runs + i);
1350 need_clipping = (dl->clip || clip_start > xpos ||
1351 clip_end < xpos + this_width);
1352
1353 /* XDrawImageString only clears the area equal to the height of
1354 the given font. It is possible that a font is being displayed
1355 on a line taller than it is, so this would cause us to fail to
1356 clear some areas. */
1357 if ((int) fi->height < (int) (height + dl->clip +
1358 XLIKE_DISPLAY_LINE_TOP_CLIP (dl)))
1359 {
1360 int clear_start = max (xpos, clip_start);
1361 int clear_end = min (xpos + this_width, clip_end);
1362
1363 if (cursor)
1364 {
1365 int ypos1_line, ypos1_string, ypos2_line, ypos2_string;
1366
1367 ypos1_string = dl->ypos - fi->ascent;
1368 ypos2_string = dl->ypos + fi->descent;
1369 ypos1_line = ypos;
1370 ypos2_line = ypos1_line + height;
1371
1372 /* Make sure we don't clear below the real bottom of the
1373 line. */
1374 if (ypos1_string > ypos2_line)
1375 ypos1_string = ypos2_line;
1376 if (ypos2_string > ypos2_line)
1377 ypos2_string = ypos2_line;
1378
1379 if (ypos1_line < ypos1_string)
1380 {
1381 redisplay_clear_region (window, findex, clear_start, ypos1_line,
1382 clear_end - clear_start,
1383 ypos1_string - ypos1_line);
1384 }
1385
1386 if (ypos2_line > ypos2_string)
1387 {
1388 redisplay_clear_region (window, findex, clear_start, ypos2_string,
1389 clear_end - clear_start,
1390 ypos2_line - ypos2_string);
1391 }
1392 }
1393 else
1394 {
1395 redisplay_clear_region (window, findex, clear_start,
1396 ypos, clear_end - clear_start,
1397 height);
1398 }
1399 }
1400
1401 if (cursor && cursor_cachel && focus && NILP (bar_cursor_value))
1402 {
1403 #ifdef USE_XFT
1404 fg = XFT_FROB_LISP_COLOR (cursor_cachel->foreground, 0);
1405 bg = XFT_FROB_LISP_COLOR (cursor_cachel->background, 0);
1406 #endif
1407 gc = XLIKE_get_gc (d, font, cursor_cachel->foreground,
1408 cursor_cachel->background, Qnil, Qnil);
1409 }
1410 else if (cachel->dim)
1411 {
1412 /* Ensure the gray bitmap exists */
1413 if (DEVICE_XLIKE_GRAY_PIXMAP (d) == XLIKE_NONE)
1414 DEVICE_XLIKE_GRAY_PIXMAP (d) =
1415 #ifdef THIS_IS_X
1416 XCreateBitmapFromData (dpy, x_win, (char *)gray_bits,
1417 gray_width, gray_height)
1418 #else
1419 /* #### FIXME! Implement me! */
1420 XLIKE_NONE
1421 #endif
1422 ;
1423
1424 /* Request a GC with the gray stipple pixmap to draw dimmed text */
1425 #ifdef USE_XFT
1426 fg = XFT_FROB_LISP_COLOR (cachel->foreground, 1);
1427 bg = XFT_FROB_LISP_COLOR (cachel->background, 0);
1428 #endif
1429 gc = XLIKE_get_gc (d, font, cachel->foreground, cachel->background,
1430 Qdim, Qnil);
1431 }
1432 else
1433 {
1434 #ifdef USE_XFT
1435 fg = XFT_FROB_LISP_COLOR (cachel->foreground, 0);
1436 bg = XFT_FROB_LISP_COLOR (cachel->background, 0);
1437 #endif
1438 gc = XLIKE_get_gc (d, font, cachel->foreground, cachel->background,
1439 Qnil, Qnil);
1440 }
1441 #ifdef USE_XFT
1442 {
1443 XftFont *rf = FONT_INSTANCE_X_XFTFONT (fi);
1444
1445 if (rf)
1446 {
1447 use_x_font = 0;
1448 if (need_clipping)
1449 {
1450 Region clip_reg = XCreateRegion();
1451 XRectangle clip_box = { clip_start, ypos,
1452 clip_end - clip_start, height };
1453
1454 XUnionRectWithRegion (&clip_box, clip_reg, clip_reg);
1455 XftDrawSetClip(xftDraw, clip_reg);
1456 XDestroyRegion(clip_reg);
1457 }
1458
1459 if (!bgc)
1460 {
1461 /* #### Neither rect_height nor XftTextExtents as computed
1462 below handles the vertical space taken up by antialiasing,
1463 which for some fonts (eg, Bitstream Vera Sans Mono-16 on
1464 my Mac PowerBook G4) leaves behind orphaned dots on
1465 insertion or deletion earlier in the line, especially in
1466 the case of the underscore character.
1467 Interestingly, insertion or deletion of a single character
1468 immediately after a refresh does not leave any droppings,
1469 but any further insertions or deletions do.
1470 While adding a pixel to rect_height (mostly) takes care of
1471 this, it trashes aggressively laid-out elements like the
1472 modeline (overwriting part of the bevel).
1473 OK, unconditionally redraw the bevel, and increment
1474 rect_height by 1. See x_output_display_block. -- sjt */
1475 struct textual_run *run = &runs[i];
1476 int rect_width = x_text_width_single_run (f, cachel, run);
1477 #ifndef USE_XFTTEXTENTS_TO_AVOID_FONT_DROPPINGS
1478 int rect_height = FONT_INSTANCE_ASCENT(fi)
1479 + FONT_INSTANCE_DESCENT(fi) + 1;
1480 #else
1481 int rect_height = FONT_INSTANCE_ASCENT(fi)
1482 + FONT_INSTANCE_DESCENT(fi);
1483 XGlyphInfo gi;
1484 if (run->dimension == 2) {
1485 XftTextExtents16 (dpy,
1486 FONT_INSTANCE_X_XFTFONT(fi),
1487 (XftChar16 *) run->ptr, run->len, &gi);
1488 } else {
1489 XftTextExtents8 (dpy,
1490 FONT_INSTANCE_X_XFTFONT(fi),
1491 run->ptr, run->len, &gi);
1492 }
1493 rect_height = rect_height > gi.height
1494 ? rect_height : gi.height;
1495 #endif
1496
1497 XftDrawRect (xftDraw, &bg,
1498 xpos, ypos, rect_width, rect_height);
1499 }
1500
1501 if (runs[i].dimension == 1)
1502 XftDrawString8 (xftDraw, &fg, rf, xpos, dl->ypos,
1503 runs[i].ptr, runs[i].len);
1504 else
1505 XftDrawString16 (xftDraw, &fg, rf, xpos, dl->ypos,
1506 (XftChar16 *) runs[i].ptr, runs[i].len);
1507 }
1508 }
1509 #endif /* USE_XFT */
1510
1511 #ifdef THIS_IS_X
1512 if (use_x_font)
1513 #endif
1514 {
1515 if (need_clipping)
1516 {
1517 XLIKE_RECTANGLE clip_box;
1518
1519 clip_box.x = 0;
1520 clip_box.y = 0;
1521 clip_box.width = clip_end - clip_start;
1522 clip_box.height = height;
1523
1524 XLIKE_SET_CLIP_RECTANGLE (dpy, gc, clip_start, ypos, &clip_box);
1525 }
1526
1527 #ifdef THIS_IS_X
1528 if (runs[i].dimension == 1)
1529 (bgc ? XDrawString : XDrawImageString)
1530 (dpy, x_win, gc, xpos, dl->ypos,
1531 (char *) runs[i].ptr, runs[i].len);
1532 else
1533 (bgc ? XDrawString16 : XDrawImageString16)
1534 (dpy, x_win, gc, xpos, dl->ypos,
1535 (XChar2b *) runs[i].ptr, runs[i].len);
1536 #else /* THIS_IS_GTK */
1537
1538 /* The X specific called different functions (XDraw*String
1539 vs. XDraw*String16), but apparently gdk_draw_text takes care
1540 of that for us.
1541
1542 BUT, gdk_draw_text also does too much, by dividing the length
1543 by 2. So we fake them out my multiplying the length by the
1544 dimension of the text. This will do the right thing for
1545 single-dimension runs as well of course.
1546 */
1547 (bgc ? gdk_draw_text : gdk_draw_text_image)
1548 (GDK_DRAWABLE (x_win), FONT_INSTANCE_GTK_FONT (fi), gc, xpos,
1549 dl->ypos, (char *) runs[i].ptr, runs[i].len * runs[i].dimension);
1550 #endif /* (not) THIS_IS_X */
1551 }
1552
1553 /* We draw underlines in the same color as the text. */
1554 if (cachel->underline)
1555 {
1556 int upos, uthick;
1557 #ifdef THIS_IS_X
1558 unsigned long upos_ext, uthick_ext;
1559 XFontStruct *fs =
1560 use_x_font ? FONT_INSTANCE_X_FONT (XFONT_INSTANCE (font)) : 0;
1561 /* #### the logic of the next two may be suboptimal: we may want
1562 to use the POSITION and/or THICKNESS information with Xft */
1563 if (fs && XGetFontProperty (fs, XA_UNDERLINE_POSITION, &upos_ext))
1564 upos = (int) upos_ext;
1565 else
1566 #else /* THIS_IS_GTK */
1567 /* Cannot get at font properties in Gtk, so we resort to
1568 guessing */
1569 #endif /* THIS_IS_GTK */
1570 upos = dl->descent / 2;
1571 #ifdef THIS_IS_X
1572 if (fs && XGetFontProperty (fs, XA_UNDERLINE_THICKNESS, &uthick_ext))
1573 uthick = (int) uthick_ext;
1574 else
1575 #endif /* THIS_IS_X */
1576 uthick = 1;
1577 if (dl->ypos + upos < dl->ypos + dl->descent - dl->clip)
1578 {
1579 if (dl->ypos + upos + uthick > dl->ypos + dl->descent - dl->clip)
1580 uthick = dl->descent - dl->clip - upos;
1581
1582 if (uthick == 1)
1583 {
1584 XLIKE_DRAW_LINE (dpy, x_win, gc, xpos, dl->ypos + upos,
1585 xpos + this_width, dl->ypos + upos);
1586 }
1587 else if (uthick > 1)
1588 {
1589 XLIKE_FILL_RECTANGLE (dpy, x_win, gc, xpos,
1590 dl->ypos + upos, this_width, uthick);
1591 }
1592 }
1593 }
1594
1595 if (cachel->strikethru)
1596 {
1597 #ifdef THIS_IS_X
1598 int ascent, descent, upos, uthick;
1599 unsigned long ascent_ext, descent_ext, uthick_ext;
1600 XFontStruct *fs = FONT_INSTANCE_X_FONT (fi);
1601 #else /* THIS_IS_GTK */
1602 gint ascent, descent, upos, uthick;
1603 GdkFont *gfont = FONT_INSTANCE_GTK_FONT (fi);
1604 #endif /* THIS_IS_GTK */
1605
1606 #ifdef THIS_IS_X
1607 if (!use_x_font)
1608 {
1609 ascent = dl->ascent;
1610 descent = dl->descent;
1611 uthick = 1;
1612 }
1613 else
1614 {
1615 if (!XGetFontProperty (fs, XA_STRIKEOUT_ASCENT, &ascent_ext))
1616 ascent = fs->ascent;
1617 else
1618 ascent = (int) ascent_ext;
1619 if (!XGetFontProperty (fs, XA_STRIKEOUT_DESCENT, &descent_ext))
1620 descent = fs->descent;
1621 else
1622 descent = (int) descent_ext;
1623 if (!XGetFontProperty (fs, XA_UNDERLINE_THICKNESS, &uthick_ext))
1624 uthick = 1;
1625 else
1626 uthick = (int) uthick_ext;
1627 }
1628 #else /* THIS_IS_GTK */
1629 /* Cannot get at font properties in Gtk, so we resort to
1630 guessing */
1631
1632 ascent = gfont->ascent;
1633 descent = gfont->descent;
1634 uthick = 1;
1635 #endif /* THIS_IS_GTK */
1636
1637 upos = ascent - ((ascent + descent) / 2) + 1;
1638
1639 /* Generally, upos will be positive (above the baseline),so
1640 subtract */
1641 if (dl->ypos - upos < dl->ypos + dl->descent - dl->clip)
1642 {
1643 if (dl->ypos - upos + uthick > dl->ypos + dl->descent - dl->clip)
1644 uthick = dl->descent - dl->clip + upos;
1645
1646 if (uthick == 1)
1647 XLIKE_DRAW_LINE (dpy, x_win, gc, xpos, dl->ypos - upos,
1648 xpos + this_width, dl->ypos - upos);
1649 else if (uthick > 1)
1650 XLIKE_FILL_RECTANGLE (dpy, x_win, gc, xpos, dl->ypos + upos,
1651 this_width, uthick);
1652 }
1653 }
1654
1655 /* Restore the GC */
1656 if (need_clipping)
1657 {
1658 #ifdef USE_XFT
1659 if (!use_x_font)
1660 {
1661 XftDrawSetClip (xftDraw, 0);
1662 }
1663 else
1664 #endif
1665 XLIKE_CLEAR_CLIP_MASK (dpy, gc);
1666 }
1667
1668 /* If we are actually superimposing the cursor then redraw with just
1669 the appropriate section highlighted. */
1670 if (cursor_clip && !cursor && focus && cursor_cachel)
1671 {
1672 #ifdef USE_XFT
1673 if (!use_x_font) /* Xft */
1674 {
1675 XftFont *rf = FONT_INSTANCE_X_XFTFONT (fi);
1676
1677 { /* set up clipping */
1678 Region clip_reg = XCreateRegion();
1679 XRectangle clip_box = { cursor_start, ypos,
1680 cursor_width, height };
1681
1682 XUnionRectWithRegion (&clip_box, clip_reg, clip_reg);
1683 XftDrawSetClip(xftDraw, clip_reg);
1684 XDestroyRegion(clip_reg);
1685 }
1686 { /* draw background rectangle & draw text */
1687 int rect_height = FONT_INSTANCE_ASCENT(fi)
1688 + FONT_INSTANCE_DESCENT(fi);
1689 int rect_width = x_text_width_single_run(f, cachel, &runs[i]);
1690 XftColor xft_color;
1691
1692 xft_color = XFT_FROB_LISP_COLOR (cursor_cachel->background, 0);
1693 XftDrawRect (xftDraw, &xft_color,
1694 xpos, ypos, rect_width, rect_height);
1695
1696 xft_color = XFT_FROB_LISP_COLOR (cursor_cachel->foreground, 0);
1697 if (runs[i].dimension == 1)
1698 XftDrawString8 (xftDraw, &xft_color, rf, xpos, dl->ypos,
1699 runs[i].ptr, runs[i].len);
1700 else
1701 XftDrawString16 (xftDraw, &xft_color, rf, xpos, dl->ypos,
1702 (XftChar16 *) runs[i].ptr, runs[i].len);
1703 }
1704
1705 XftDrawSetClip(xftDraw, 0);
1706 }
1707 else /* core font, not Xft */
1708 #endif /* USE_XFT */
1709 {
1710 XLIKE_RECTANGLE clip_box;
1711 XLIKE_GC cgc;
1712 cgc = XLIKE_get_gc (d, font, cursor_cachel->foreground,
1713 cursor_cachel->background, Qnil, Qnil);
1714
1715 clip_box.x = 0;
1716 clip_box.y = 0;
1717 clip_box.width = cursor_width;
1718 clip_box.height = height;
1719
1720 XLIKE_SET_CLIP_RECTANGLE (dpy, cgc, cursor_start, ypos,
1721 &clip_box);
1722 #ifdef THIS_IS_X
1723 if (runs[i].dimension == 1)
1724 XDrawImageString (dpy, x_win, cgc, xpos, dl->ypos,
1725 (char *) runs[i].ptr, runs[i].len);
1726 else
1727 XDrawImageString16 (dpy, x_win, cgc, xpos, dl->ypos,
1728 (XChar2b *) runs[i].ptr, runs[i].len);
1729 #else
1730 /* The X specific called different functions (XDraw*String
1731 vs. XDraw*String16), but apparently gdk_draw_text takes care
1732 of that for us.
1733
1734 BUT, gdk_draw_text also does too much, by dividing the
1735 length by 2. So we fake them out my multiplying the
1736 length by the dimension of the text. This will do the
1737 right thing for single-dimension runs as well of course.
1738 */
1739 gdk_draw_text_image (GDK_DRAWABLE (x_win),
1740 FONT_INSTANCE_GTK_FONT (fi), cgc, xpos,
1741 dl->ypos, (char *) runs[i].ptr,
1742 runs[i].len * runs[i].dimension);
1743 #endif /* (not) THIS_IS_X */
1744
1745 XLIKE_CLEAR_CLIP_MASK (dpy, cgc);
1746 }
1747 }
1748
1749 xpos += this_width;
1750 }
1751
1752 /* Draw the non-focus box or bar-cursor as needed. */
1753 /* Can't this logic be simplified? */
1754 if (cursor_cachel
1755 && ((cursor && !focus && NILP (bar_cursor_value))
1756 || (cursor_width
1757 && (cursor_start + cursor_width >= clip_start)
1758 && !NILP (bar_cursor_value))))
1759 {
1760 int tmp_height, tmp_y;
1761 int bar_width = EQ (bar_cursor_value, Qt) ? 1 : 2;
1762 int need_clipping = (cursor_start < clip_start
1763 || clip_end < cursor_start + cursor_width);
1764
1765 /* #### This value is correct (as far as I know) because
1766 all of the times we need to draw this cursor, we will
1767 be called with exactly one character, so we know we
1768 can always use runs[0].
1769
1770 This is bogus as all hell, however. The cursor handling in
1771 this function is way bogus and desperately needs to be
1772 cleaned up. (In particular, the drawing of the cursor should
1773 really really be separated out of this function. This may be
1774 a bit tricky now because this function itself does way too
1775 much stuff, a lot of which needs to be moved into
1776 redisplay.c.) This is the only way to be able to easily add
1777 new cursor types or (e.g.) make the bar cursor be able to
1778 span two characters instead of overlaying just one. */
1779 int bogusly_obtained_ascent_value =
1780 XFONT_INSTANCE (FACE_CACHEL_FONT (cachel, runs[0].charset))->ascent;
1781
1782 if (!NILP (bar_cursor_value))
1783 {
1784 gc = XLIKE_get_gc (d, Qnil, cursor_cachel->background, Qnil, Qnil,
1785 make_int (bar_width));
1786 }
1787 else
1788 {
1789 gc = XLIKE_get_gc (d, Qnil, cursor_cachel->background,
1790 Qnil, Qnil, Qnil);
1791 }
1792
1793 tmp_y = dl->ypos - bogusly_obtained_ascent_value;
1794 tmp_height = cursor_height;
1795 if (tmp_y + tmp_height > (int) (ypos + height))
1796 {
1797 tmp_y = ypos + height - tmp_height;
1798 if (tmp_y < (int) ypos)
1799 tmp_y = ypos;
1800 tmp_height = ypos + height - tmp_y;
1801 }
1802
1803 if (need_clipping)
1804 {
1805 XLIKE_RECTANGLE clip_box;
1806 clip_box.x = 0;
1807 clip_box.y = 0;
1808 clip_box.width = clip_end - clip_start;
1809 clip_box.height = tmp_height;
1810 XLIKE_SET_CLIP_RECTANGLE (dpy, gc, clip_start, tmp_y, &clip_box);
1811 }
1812
1813 if (!focus && NILP (bar_cursor_value))
1814 {
1815 XLIKE_DRAW_RECTANGLE (dpy, x_win, gc, cursor_start, tmp_y,
1816 cursor_width - 1, tmp_height - 1);
1817 }
1818 else if (focus && !NILP (bar_cursor_value))
1819 {
1820 XLIKE_DRAW_LINE (dpy, x_win, gc, cursor_start + bar_width - 1, tmp_y,
1821 cursor_start + bar_width - 1,
1822 tmp_y + tmp_height - 1);
1823 }
1824
1825 /* Restore the GC */
1826 if (need_clipping)
1827 {
1828 XLIKE_CLEAR_CLIP_MASK (dpy, gc);
1829 }
1830 }
1831
1832 #ifdef USE_XFT
1833 #undef XFT_FROB_LISP_COLOR
1834 #endif
1835 }
1836
1837 #ifdef THIS_IS_GTK
1838 static void
1839 our_draw_bitmap (GdkDrawable *drawable,
1840 GdkGC *gc,
1841 GdkPixmap *src,
1842 gint xsrc,
1843 gint ysrc,
1844 gint xdest,
1845 gint ydest,
1846 gint width,
1847 gint height);
1848 #endif /* THIS_IS_GTK */
1849
1850
1851 void
1852 XLIKE_OUTPUT_XLIKE_PIXMAP (struct frame *f, Lisp_Image_Instance *p, int x,
1853 int y, int xoffset, int yoffset,
1854 int width, int height,
1855 XLIKE_PIXCOLOR fg, XLIKE_PIXCOLOR bg,
1856 XLIKE_GC override_gc)
1857 {
1858 struct device *d = XDEVICE (f->device);
1859 XLIKE_DISPLAY dpy = GET_XLIKE_DISPLAY (d);
1860 XLIKE_WINDOW x_win = GET_XLIKE_WINDOW (f);
1861 XLIKE_GC gc;
1862 XLIKE_GCVALUES gcv;
1863 unsigned long pixmap_mask;
1864
1865 if (!override_gc)
1866 {
1867 memset (&gcv, ~0, sizeof (gcv));
1868 gcv.graphics_exposures = XLIKE_FALSE;
1869 XLIKE_SET_PIXCOLOR_COPY (gcv.foreground, fg);
1870 XLIKE_SET_PIXCOLOR_COPY (gcv.background, bg);
1871 pixmap_mask = XLIKE_GC_FOREGROUND | XLIKE_GC_BACKGROUND | XLIKE_GC_EXPOSURES;
1872
1873 if (IMAGE_INSTANCE_XLIKE_MASK (p))
1874 {
1875 gcv.function = XLIKE_GX_COPY;
1876 gcv.clip_mask = IMAGE_INSTANCE_XLIKE_MASK (p);
1877 gcv.clip_x_origin = x - xoffset;
1878 gcv.clip_y_origin = y - yoffset;
1879 pixmap_mask |= (XLIKE_GC_FUNCTION | XLIKE_GC_CLIP_MASK |
1880 XLIKE_GC_CLIP_X_ORIGIN |
1881 XLIKE_GC_CLIP_Y_ORIGIN);
1882 /* Can't set a clip rectangle below because we already have a mask.
1883 We could conceivably create a new clipmask by zeroing out
1884 everything outside the clip region. Is it worth it?
1885 Is it possible to get an equivalent effect by changing the
1886 args to XCopyArea below rather than messing with a clip box?
1887 - dkindred@cs.cmu.edu
1888 Yes. We don't clip at all now - andy@xemacs.org
1889 */
1890 }
1891
1892 gc = gc_cache_lookup (DEVICE_XLIKE_GC_CACHE (d), &gcv, pixmap_mask);
1893 }
1894 else
1895 {
1896 gc = override_gc;
1897 /* override_gc might have a mask already--we don't want to nuke it.
1898 Maybe we can insist that override_gc have no mask, or use
1899 one of the suggestions above. */
1900 }
1901
1902 #ifdef THIS_IS_X
1903 /* depth of 0 means it's a bitmap, not a pixmap, and we should use
1904 XCopyPlane (1 = current foreground color, 0 = background) instead
1905 of XCopyArea, which means that the bits in the pixmap are actual
1906 pixel values, instead of symbolic of fg/bg. */
1907 #endif /* THIS_IS_X */
1908 if (IMAGE_INSTANCE_PIXMAP_DEPTH (p) > 0)
1909 {
1910 #ifdef THIS_IS_X
1911 XCopyArea (dpy,
1912 IMAGE_INSTANCE_X_PIXMAP_SLICE
1913 (p, IMAGE_INSTANCE_PIXMAP_SLICE (p)), x_win, gc, xoffset,
1914 yoffset, width,
1915 height, x, y);
1916 #else /* THIS_IS_GTK */
1917 gdk_draw_pixmap (GDK_DRAWABLE (x_win), gc,
1918 IMAGE_INSTANCE_GTK_PIXMAP (p),
1919 xoffset, yoffset, x, y, width, height);
1920 #endif /* THIS_IS_GTK */
1921 }
1922 else
1923 {
1924 #ifdef THIS_IS_X
1925 XCopyPlane (dpy, IMAGE_INSTANCE_X_PIXMAP_SLICE
1926 (p, IMAGE_INSTANCE_PIXMAP_SLICE (p)), x_win, gc,
1927 xoffset, yoffset, width, height, x, y, 1L);
1928 #else /* THIS_IS_GTK */
1929 our_draw_bitmap (GDK_DRAWABLE (x_win), gc,
1930 IMAGE_INSTANCE_GTK_PIXMAP (p),
1931 xoffset, yoffset, x, y, width, height);
1932 #endif /* THIS_IS_GTK */
1933 }
1934 }
1935
1936 static void
1937 XLIKE_output_pixmap (struct window *w, Lisp_Object image_instance,
1938 struct display_box *db, struct display_glyph_area *dga,
1939 face_index findex, int cursor_start, int cursor_width,
1940 int cursor_height, int UNUSED (bg_pixmap))
1941 {
1942 struct frame *f = XFRAME (w->frame);
1943 struct device *d = XDEVICE (f->device);
1944 Lisp_Image_Instance *p = XIMAGE_INSTANCE (image_instance);
1945 XLIKE_DISPLAY dpy = GET_XLIKE_DISPLAY (d);
1946 XLIKE_WINDOW x_win = GET_XLIKE_WINDOW (f);
1947
1948 /* Output the pixmap. */
1949 {
1950 Lisp_Object tmp_pixel;
1951 XLIKE_COLOR tmp_bcolor, tmp_fcolor;
1952
1953 tmp_pixel = WINDOW_FACE_CACHEL_FOREGROUND (w, findex);
1954 tmp_fcolor = XCOLOR_INSTANCE_XLIKE_COLOR (tmp_pixel);
1955 tmp_pixel = WINDOW_FACE_CACHEL_BACKGROUND (w, findex);
1956 tmp_bcolor = XCOLOR_INSTANCE_XLIKE_COLOR (tmp_pixel);
1957
1958 XLIKE_OUTPUT_XLIKE_PIXMAP (f, p, db->xpos, db->ypos,
1959 dga->xoffset, dga->yoffset,
1960 dga->width, dga->height,
1961 XLIKE_COLOR_TO_PIXCOLOR (tmp_fcolor),
1962 XLIKE_COLOR_TO_PIXCOLOR (tmp_bcolor), 0);
1963 }
1964
1965 /* Draw a cursor over top of the pixmap. */
1966 if (cursor_width && cursor_height && (cursor_start >= db->xpos)
1967 && !NILP (w->text_cursor_visible_p)
1968 && (cursor_start < db->xpos + dga->width))
1969 {
1970 XLIKE_GC gc;
1971 int focus = EQ (w->frame, DEVICE_FRAME_WITH_FOCUS_REAL (d));
1972 struct face_cachel *cursor_cachel =
1973 WINDOW_FACE_CACHEL (w,
1974 get_builtin_face_cache_index
1975 (w, Vtext_cursor_face));
1976
1977 gc = XLIKE_get_gc (d, Qnil, cursor_cachel->background, Qnil, Qnil, Qnil);
1978
1979 if (cursor_width > db->xpos + dga->width - cursor_start)
1980 cursor_width = db->xpos + dga->width - cursor_start;
1981
1982 if (focus)
1983 XLIKE_FILL_RECTANGLE (dpy, x_win, gc, cursor_start, db->ypos,
1984 cursor_width, cursor_height);
1985 else
1986 {
1987 XLIKE_DRAW_RECTANGLE (dpy, x_win, gc, cursor_start, db->ypos,
1988 cursor_width, cursor_height);
1989 }
1990 }
1991 }
1992
1993 /*****************************************************************************
1994 XLIKE_output_vertical_divider
1995
1996 Draw a vertical divider down the right side of the given window.
1997 ****************************************************************************/
1998 static void
1999 XLIKE_output_vertical_divider (struct window *w, int USED_IF_X(clear))
2000 {
2001 struct frame *f = XFRAME (w->frame);
2002 struct device *d = XDEVICE (f->device);
2003
2004 XLIKE_DISPLAY dpy = GET_XLIKE_DISPLAY (d);
2005 XLIKE_WINDOW x_win = GET_XLIKE_WINDOW (f);
2006 Lisp_Object tmp_pixel;
2007 XLIKE_GCVALUES gcv;
2008 XLIKE_GC background_gc;
2009 #ifdef THIS_IS_X
2010 enum edge_style style;
2011 #endif /* THIS_IS_X */
2012 unsigned long mask;
2013 int x, y1, y2, width, shadow_thickness, spacing, line_width;
2014 face_index div_face =
2015 get_builtin_face_cache_index (w, Vvertical_divider_face);
2016
2017 width = window_divider_width (w);
2018 shadow_thickness = XINT (w->vertical_divider_shadow_thickness);
2019 spacing = XINT (w->vertical_divider_spacing);
2020 line_width = XINT (w->vertical_divider_line_width);
2021 x = WINDOW_RIGHT (w) - width;
2022 y1 = WINDOW_TOP (w);
2023 y2 = WINDOW_BOTTOM (w);
2024
2025 memset (&gcv, ~0, sizeof (gcv));
2026
2027 tmp_pixel = WINDOW_FACE_CACHEL_BACKGROUND (w, div_face);
2028
2029 /* First, get the GC's. */
2030 XLIKE_SET_PIXCOLOR_COPY
2031 (gcv.background,
2032 XLIKE_COLOR_TO_PIXCOLOR (XCOLOR_INSTANCE_XLIKE_COLOR (tmp_pixel)));
2033 gcv.foreground = gcv.background;
2034 gcv.graphics_exposures = XLIKE_FALSE;
2035 mask = XLIKE_GC_FOREGROUND | XLIKE_GC_BACKGROUND | XLIKE_GC_EXPOSURES;
2036
2037 background_gc = gc_cache_lookup (DEVICE_XLIKE_GC_CACHE (d), &gcv, mask);
2038
2039 /* Clear the divider area first. This needs to be done when a
2040 window split occurs. */
2041 #ifdef THIS_IS_X
2042 if (clear)
2043 XClearArea (dpy, x_win, x, y1, width, y2 - y1, False);
2044 #else /* THIS_IS_GTK */
2045 /* if (clear) */
2046 gdk_draw_rectangle (GDK_DRAWABLE (x_win), background_gc, TRUE,
2047 x, y1, width, y2 - y1);
2048 #endif /* THIS_IS_GTK */
2049
2050 #ifndef THIS_IS_GTK
2051 /* #### FIXME Why not? Formerly '#if 0' in the GDK code */
2052 /* Draw the divider line. */
2053 XLIKE_FILL_RECTANGLE (dpy, x_win, background_gc,
2054 x + spacing + shadow_thickness, y1,
2055 line_width, y2 - y1);
2056
2057 /* This code not formerly present in GTK version, maybe the omittal
2058 is intentional? */
2059 if (shadow_thickness < 0)
2060 {
2061 shadow_thickness = -shadow_thickness;
2062 style = EDGE_BEVEL_IN;
2063 }
2064 else
2065 {
2066 style = EDGE_BEVEL_OUT;
2067 }
2068 #endif /* not THIS_IS_GTK */
2069
2070 /* Draw the shadows around the divider line */
2071 #ifdef THIS_IS_X
2072 x_bevel_area (w, div_face, x + spacing, y1,
2073 width - 2 * spacing, y2 - y1,
2074 shadow_thickness, EDGE_ALL, style);
2075 #else /* THIS_IS_GTK */
2076 gtk_output_shadows (f, x + spacing, y1,
2077 width - 2 * spacing, y2 - y1,
2078 shadow_thickness);
2079 #endif /* THIS_IS_GTK */
2080 }
2081
2082 /*****************************************************************************
2083 XLIKE_output_blank
2084
2085 Output a blank by clearing the area it covers in the foreground color
2086 of its face.
2087 ****************************************************************************/
2088 static void
2089 XLIKE_output_blank (struct window *w, struct display_line *dl, struct rune *rb,
2090 int start_pixpos, int cursor_start, int cursor_width)
2091 {
2092 struct frame *f = XFRAME (w->frame);
2093 struct device *d = XDEVICE (f->device);
2094
2095 XLIKE_DISPLAY dpy = GET_XLIKE_DISPLAY (d);
2096 XLIKE_WINDOW x_win = GET_XLIKE_WINDOW (f);
2097 XLIKE_GC gc;
2098 struct face_cachel *cursor_cachel =
2099 WINDOW_FACE_CACHEL (w,
2100 get_builtin_face_cache_index
2101 (w, Vtext_cursor_face));
2102 Lisp_Object bg_pmap;
2103 Lisp_Object buffer = WINDOW_BUFFER (w);
2104 Lisp_Object bar_cursor_value = symbol_value_in_buffer (Qbar_cursor,
2105 buffer);
2106
2107 int x = rb->xpos;
2108 int y = XLIKE_DISPLAY_LINE_YPOS (dl);
2109 int height = XLIKE_DISPLAY_LINE_HEIGHT (dl);
2110 int width = rb->width;
2111
2112 /* Unmap all subwindows in the area we are going to blank. */
2113 redisplay_unmap_subwindows_maybe (f, x, y, width, height);
2114
2115 if (start_pixpos > x)
2116 {
2117 if (start_pixpos >= (x + width))
2118 return;
2119 else
2120 {
2121 width -= (start_pixpos - x);
2122 x = start_pixpos;
2123 }
2124 }
2125
2126 bg_pmap = WINDOW_FACE_CACHEL_BACKGROUND_PIXMAP (w, rb->findex);
2127 if (!IMAGE_INSTANCEP (bg_pmap)
2128 || !IMAGE_INSTANCE_PIXMAP_TYPE_P (XIMAGE_INSTANCE (bg_pmap)))
2129 bg_pmap = Qnil;
2130
2131 if (NILP (bg_pmap))
2132 gc = XLIKE_get_gc (d, Qnil, WINDOW_FACE_CACHEL_BACKGROUND (w, rb->findex),
2133 Qnil, Qnil, Qnil);
2134 else
2135 gc = XLIKE_get_gc (d, Qnil, WINDOW_FACE_CACHEL_FOREGROUND (w, rb->findex),
2136 WINDOW_FACE_CACHEL_BACKGROUND (w, rb->findex), bg_pmap,
2137 Qnil);
2138
2139 XLIKE_FILL_RECTANGLE (dpy, x_win, gc, x, y, width, height);
2140
2141 /* If this rune is marked as having the cursor, then it is actually
2142 representing a tab. */
2143 if (!NILP (w->text_cursor_visible_p)
2144 && (rb->cursor_type == CURSOR_ON
2145 || (cursor_width
2146 && (cursor_start + cursor_width > x)
2147 && cursor_start < (x + width))))
2148 {
2149 int cursor_height, cursor_y;
2150 int focus = EQ (w->frame, DEVICE_FRAME_WITH_FOCUS_REAL (d));
2151 Lisp_Font_Instance *fi;
2152
2153 fi = XFONT_INSTANCE (FACE_CACHEL_FONT
2154 (WINDOW_FACE_CACHEL (w, rb->findex),
2155 Vcharset_ascii));
2156
2157 gc = XLIKE_get_gc (d, Qnil, cursor_cachel->background, Qnil, Qnil, Qnil);
2158
2159 cursor_y = dl->ypos - fi->ascent;
2160 cursor_height = fi->height;
2161 if (cursor_y + cursor_height > y + height)
2162 cursor_height = y + height - cursor_y;
2163
2164 if (focus)
2165 {
2166 if (NILP (bar_cursor_value))
2167 {
2168 XLIKE_FILL_RECTANGLE (dpy, x_win, gc, cursor_start, cursor_y,
2169 fi->width, cursor_height);
2170 }
2171 else
2172 {
2173 int bar_width = EQ (bar_cursor_value, Qt) ? 1 : 2;
2174
2175 gc = XLIKE_get_gc (d, Qnil, cursor_cachel->background,
2176 Qnil, Qnil, make_int (bar_width));
2177 XLIKE_DRAW_LINE (dpy, x_win, gc, cursor_start + bar_width - 1,
2178 cursor_y, cursor_start + bar_width - 1,
2179 cursor_y + cursor_height - 1);
2180 }
2181 }
2182 else if (NILP (bar_cursor_value))
2183 {
2184 XLIKE_DRAW_RECTANGLE (dpy, x_win, gc, cursor_start, cursor_y,
2185 fi->width - 1, cursor_height - 1);
2186 }
2187 }
2188 }
2189
2190 /*****************************************************************************
2191 XLIKE_output_horizontal_line
2192
2193 Output a horizontal line in the foreground of its face.
2194 ****************************************************************************/
2195 static void
2196 XLIKE_output_horizontal_line (struct window *w, struct display_line *dl,
2197 struct rune *rb)
2198 {
2199 struct frame *f = XFRAME (w->frame);
2200 struct device *d = XDEVICE (f->device);
2201
2202 XLIKE_DISPLAY dpy = GET_XLIKE_DISPLAY (d);
2203 XLIKE_WINDOW x_win = GET_XLIKE_WINDOW (f);
2204 XLIKE_GC gc;
2205
2206 int x = rb->xpos;
2207 int width = rb->width;
2208 int height = XLIKE_DISPLAY_LINE_HEIGHT (dl);
2209 int ypos1, ypos2, ypos3, ypos4;
2210
2211 ypos1 = XLIKE_DISPLAY_LINE_YPOS (dl);
2212 ypos2 = ypos1 + rb->object.hline.yoffset;
2213 ypos3 = ypos2 + rb->object.hline.thickness;
2214 ypos4 = dl->ypos + dl->descent - dl->clip;
2215
2216 /* First clear the area not covered by the line. */
2217 if (height - rb->object.hline.thickness > 0)
2218 {
2219 gc = XLIKE_get_gc (d, Qnil,
2220 WINDOW_FACE_CACHEL_FOREGROUND (w, rb->findex),
2221 Qnil, Qnil, Qnil);
2222
2223 if (ypos2 - ypos1 > 0)
2224 XLIKE_FILL_RECTANGLE (dpy, x_win, gc, x, ypos1, width, ypos2 - ypos1);
2225 if (ypos4 - ypos3 > 0)
2226 XLIKE_FILL_RECTANGLE (dpy, x_win, gc, x, ypos1, width, ypos2 - ypos1);
2227 }
2228
2229 #ifdef THIS_IS_GTK
2230 {
2231 GtkStyle *style = FRAME_GTK_TEXT_WIDGET (f)->style;
2232 gtk_paint_hline (style, x_win, GTK_STATE_NORMAL, NULL,
2233 FRAME_GTK_TEXT_WIDGET (f), "hline", x, x + width, ypos2);
2234 }
2235 #else /* THIS_IS_X */
2236 /* Now draw the line. */
2237 gc = XLIKE_get_gc (d, Qnil, WINDOW_FACE_CACHEL_BACKGROUND (w, rb->findex),
2238 Qnil, Qnil, Qnil);
2239
2240 if (ypos2 < ypos1)
2241 ypos2 = ypos1;
2242 if (ypos3 > ypos4)
2243 ypos3 = ypos4;
2244
2245 if (ypos3 - ypos2 > 0)
2246 XLIKE_FILL_RECTANGLE (dpy, x_win, gc, x, ypos2, width, ypos3 - ypos2);
2247 #endif /* THIS_IS_X */
2248 }
2249
2250 /****************************************************************************
2251 XLIKE_clear_region
2252
2253 Clear the area in the box defined by the given parameters using the
2254 given face.
2255 ****************************************************************************/
2256 static void
2257 XLIKE_clear_region (Lisp_Object UNUSED (locale), struct device* d,
2258 struct frame* f, face_index UNUSED (findex), int x, int y,
2259 int width, int height, Lisp_Object fcolor,
2260 Lisp_Object bcolor, Lisp_Object background_pixmap)
2261 {
2262 XLIKE_DISPLAY dpy = GET_XLIKE_DISPLAY (d);
2263 XLIKE_WINDOW x_win = GET_XLIKE_WINDOW (f);
2264 XLIKE_GC gc = NULL;
2265
2266 if (!UNBOUNDP (background_pixmap))
2267 {
2268 gc = XLIKE_get_gc (d, Qnil, fcolor, bcolor, background_pixmap, Qnil);
2269 }
2270
2271 if (gc)
2272 XLIKE_FILL_RECTANGLE (dpy, x_win, gc, x, y, width, height);
2273 else
2274 XLIKE_CLEAR_AREA (dpy, x_win, x, y, width, height);
2275 }
2276
2277 /*****************************************************************************
2278 xlike_output_eol_cursor
2279
2280 Draw a cursor at the end of a line. The end-of-line cursor is
2281 narrower than the normal cursor.
2282 ****************************************************************************/
2283 static void
2284 XLIKE_output_eol_cursor (struct window *w, struct display_line *dl, int xpos,
2285 face_index findex)
2286 {
2287 struct frame *f = XFRAME (w->frame);
2288 struct device *d = XDEVICE (f->device);
2289 Lisp_Object window;
2290
2291 XLIKE_DISPLAY dpy = GET_XLIKE_DISPLAY (d);
2292 XLIKE_WINDOW x_win = GET_XLIKE_WINDOW (f);
2293 XLIKE_GC gc = NULL;
2294 face_index elt = get_builtin_face_cache_index (w, Vtext_cursor_face);
2295 struct face_cachel *cursor_cachel = WINDOW_FACE_CACHEL (w, elt);
2296
2297 int focus = EQ (w->frame, DEVICE_FRAME_WITH_FOCUS_REAL (d));
2298 Lisp_Object bar_cursor_value = symbol_value_in_buffer (Qbar_cursor,
2299 WINDOW_BUFFER (w));
2300
2301 int x = xpos;
2302 int y = XLIKE_DISPLAY_LINE_YPOS (dl);
2303 int width = EOL_CURSOR_WIDTH;
2304 int height = XLIKE_DISPLAY_LINE_HEIGHT (dl);
2305 int cursor_height, cursor_y;
2306 int defheight, defascent;
2307
2308 window = wrap_window (w);
2309 redisplay_clear_region (window, findex, x, y, width, height);
2310
2311 if (NILP (w->text_cursor_visible_p))
2312 return;
2313
2314 gc = XLIKE_get_gc (d, Qnil, cursor_cachel->background, Qnil, Qnil, Qnil);
2315
2316 default_face_font_info (window, &defascent, 0, &defheight, 0, 0);
2317
2318 /* make sure the cursor is entirely contained between y and y+height */
2319 cursor_height = min (defheight, height);
2320 cursor_y = max (y, min (y + height - cursor_height,
2321 dl->ypos - defascent));
2322
2323 if (focus)
2324 {
2325 #ifdef HAVE_XIM
2326 XIM_SetSpotLocation (f, x - 2 , cursor_y + cursor_height - 2);
2327 #endif /* HAVE_XIM */
2328
2329 if (NILP (bar_cursor_value))
2330 {
2331 XLIKE_FILL_RECTANGLE (dpy, x_win, gc, x, cursor_y, width,
2332 cursor_height);
2333 }
2334 else
2335 {
2336 int bar_width = EQ (bar_cursor_value, Qt) ? 1 : 2;
2337
2338 gc = XLIKE_get_gc (d, Qnil, cursor_cachel->background, Qnil, Qnil,
2339 make_int (bar_width));
2340 XLIKE_DRAW_LINE (dpy, x_win, gc, x + bar_width - 1, cursor_y,
2341 x + bar_width - 1, cursor_y + cursor_height - 1);
2342 }
2343 }
2344 else if (NILP (bar_cursor_value))
2345 {
2346 XLIKE_DRAW_RECTANGLE (dpy, x_win, gc, x, cursor_y, width - 1,
2347 cursor_height - 1);
2348 }
2349 }
2350
2351 static void
2352 XLIKE_clear_frame_window (Lisp_Object window)
2353 {
2354 struct window *w = XWINDOW (window);
2355
2356 if (!NILP (w->vchild))
2357 {
2358 XLIKE_clear_frame_windows (w->vchild);
2359 return;
2360 }
2361
2362 if (!NILP (w->hchild))
2363 {
2364 XLIKE_clear_frame_windows (w->hchild);
2365 return;
2366 }
2367
2368 redisplay_clear_to_window_end (w, WINDOW_TEXT_TOP (w),
2369 WINDOW_TEXT_BOTTOM (w));
2370 }
2371
2372 static void
2373 XLIKE_clear_frame_windows (Lisp_Object window)
2374 {
2375 for (; !NILP (window); window = XWINDOW (window)->next)
2376 XLIKE_clear_frame_window (window);
2377 }
2378
2379 static void
2380 XLIKE_clear_frame (struct frame *f)
2381 {
2382 XLIKE_DISPLAY dpy = GET_XLIKE_DISPLAY (XDEVICE (f->device));
2383 XLIKE_WINDOW x_win = GET_XLIKE_WINDOW (f);
2384 int x, y, width, height;
2385 Lisp_Object frame;
2386
2387 x = FRAME_LEFT_BORDER_START (f);
2388 width = (FRAME_PIXWIDTH (f) - FRAME_REAL_LEFT_TOOLBAR_WIDTH (f) -
2389 FRAME_REAL_RIGHT_TOOLBAR_WIDTH (f) -
2390 2 * FRAME_REAL_LEFT_TOOLBAR_BORDER_WIDTH (f) -
2391 2 * FRAME_REAL_RIGHT_TOOLBAR_BORDER_WIDTH (f));
2392 /* #### This adjustment by 1 should be being done in the macros.
2393 There is some small differences between when the menubar is on
2394 and off that we still need to deal with. */
2395 y = FRAME_TOP_BORDER_START (f) - 1;
2396 height = (FRAME_PIXHEIGHT (f) - FRAME_REAL_TOP_TOOLBAR_HEIGHT (f) -
2397 FRAME_REAL_BOTTOM_TOOLBAR_HEIGHT (f) -
2398 2 * FRAME_REAL_TOP_TOOLBAR_BORDER_WIDTH (f) -
2399 2 * FRAME_REAL_BOTTOM_TOOLBAR_BORDER_WIDTH (f)) + 1;
2400
2401 XLIKE_CLEAR_AREA (dpy, x_win, x, y, width, height);
2402
2403 frame = wrap_frame (f);
2404
2405 if (!UNBOUNDP (FACE_BACKGROUND_PIXMAP (Vdefault_face, frame))
2406 || !UNBOUNDP (FACE_BACKGROUND_PIXMAP (Vleft_margin_face, frame))
2407 || !UNBOUNDP (FACE_BACKGROUND_PIXMAP (Vright_margin_face, frame)))
2408 {
2409 XLIKE_clear_frame_windows (f->root_window);
2410 }
2411 #ifdef THIS_IS_X
2412 {
2413 struct device *d = XDEVICE (f->device);
2414 if (!(check_if_pending_expose_event (d)))
2415 XFlush (DEVICE_X_DISPLAY (d));
2416 }
2417 #endif /* THIS_IS_X */
2418 }
2419
2420 /* briefly swap the foreground and background colors.
2421 */
2422
2423 static int
2424 XLIKE_flash (struct device *d)
2425 {
2426 struct frame *f = device_selected_frame (d);
2427 XLIKE_DISPLAY dpy = GET_XLIKE_DISPLAY (d);
2428 XLIKE_WINDOW win = GET_XLIKE_WINDOW (f);
2429 XLIKE_GC gc = NULL;
2430 XLIKE_GCVALUES gcv;
2431 XLIKE_COLOR tmp_fcolor, tmp_bcolor;
2432 Lisp_Object tmp_pixel, frame;
2433 struct window *w = XWINDOW (FRAME_ROOT_WINDOW (f));
2434 int flash_height;
2435
2436 frame = wrap_frame (f);
2437
2438 tmp_pixel = FACE_FOREGROUND (Vdefault_face, frame);
2439 XLIKE_SET_PIXCOLOR_COPY (tmp_fcolor,
2440 XCOLOR_INSTANCE_XLIKE_COLOR (tmp_pixel));
2441 tmp_pixel = FACE_BACKGROUND (Vdefault_face, frame);
2442 XLIKE_SET_PIXCOLOR_COPY (tmp_bcolor,
2443 XCOLOR_INSTANCE_XLIKE_COLOR (tmp_pixel));
2444 memset (&gcv, ~0, sizeof (gcv)); /* initialize all slots to ~0 */
2445 XLIKE_SET_PIXCOLOR_NUM (gcv.foreground,
2446 (tmp_fcolor.pixel ^ tmp_bcolor.pixel));
2447 gcv.function = XLIKE_GX_XOR;
2448 gcv.graphics_exposures = XLIKE_FALSE;
2449 gc = gc_cache_lookup (DEVICE_XLIKE_GC_CACHE (XDEVICE (f->device)), &gcv,
2450 XLIKE_GC_FOREGROUND | XLIKE_GC_FUNCTION | XLIKE_GC_EXPOSURES);
2451 default_face_height_and_width (frame, &flash_height, 0);
2452
2453 /* If window is tall, flash top and bottom line. */
2454 if (EQ (Vvisible_bell, Qtop_bottom) && w->pixel_height > 3 * flash_height)
2455 {
2456 XLIKE_FILL_RECTANGLE (dpy, win, gc, w->pixel_left, w->pixel_top,
2457 w->pixel_width, flash_height);
2458 XLIKE_FILL_RECTANGLE (dpy, win, gc, w->pixel_left,
2459 w->pixel_top + w->pixel_height - flash_height,
2460 w->pixel_width, flash_height);
2461 }
2462 else
2463 /* If it is short, flash it all. */
2464 XLIKE_FILL_RECTANGLE (dpy, win, gc, w->pixel_left, w->pixel_top,
2465 w->pixel_width, w->pixel_height);
2466
2467 XLIKE_FLUSH (dpy);
2468
2469 #ifdef HAVE_SELECT
2470 {
2471 int usecs = 100000;
2472 struct timeval tv;
2473 tv.tv_sec = usecs / 1000000L;
2474 tv.tv_usec = usecs % 1000000L;
2475 /* I'm sure someone is going to complain about this... */
2476 select (0, 0, 0, 0, &tv);
2477 }
2478 #else
2479 #ifdef HAVE_POLL
2480 poll (0, 0, 100);
2481 #else /* !HAVE_POLL */
2482 #error bite me
2483 #endif /* HAVE_POLL */
2484 #endif /* HAVE_SELECT */
2485
2486 /* If window is tall, flash top and bottom line. */
2487 if (EQ (Vvisible_bell, Qtop_bottom) && w->pixel_height > 3 * flash_height)
2488 {
2489 XLIKE_FILL_RECTANGLE (dpy, win, gc, w->pixel_left, w->pixel_top,
2490 w->pixel_width, flash_height);
2491 XLIKE_FILL_RECTANGLE (dpy, win, gc, w->pixel_left,
2492 w->pixel_top + w->pixel_height - flash_height,
2493 w->pixel_width, flash_height);
2494 }
2495 else
2496 /* If it is short, flash it all. */
2497 XLIKE_FILL_RECTANGLE (dpy, win, gc, w->pixel_left, w->pixel_top,
2498 w->pixel_width, w->pixel_height);
2499
2500 XLIKE_FLUSH (dpy);
2501
2502 return 1;
2503 }
2504
2505
2506 /************************************************************************/
2507 /* initialization */
2508 /************************************************************************/
2509
2510 void
2511 console_type_create_redisplay_XLIKE (void)
2512 {
2513 /* redisplay methods */
2514 XLIKE_CONSOLE_HAS_METHOD (text_width);
2515 XLIKE_CONSOLE_HAS_METHOD (output_display_block);
2516 XLIKE_CONSOLE_HAS_METHOD (divider_height);
2517 XLIKE_CONSOLE_HAS_METHOD (eol_cursor_width);
2518 XLIKE_CONSOLE_HAS_METHOD (output_vertical_divider);
2519 XLIKE_CONSOLE_HAS_METHOD (clear_region);
2520 XLIKE_CONSOLE_HAS_METHOD (clear_frame);
2521 XLIKE_CONSOLE_HAS_METHOD (flash);
2522 XLIKE_CONSOLE_HAS_METHOD (ring_bell);
2523 XLIKE_CONSOLE_HAS_METHOD (bevel_area);
2524 XLIKE_CONSOLE_HAS_METHOD (output_string);
2525 XLIKE_CONSOLE_HAS_METHOD (output_pixmap);
2526
2527 #ifdef THIS_IS_X
2528 XLIKE_CONSOLE_HAS_METHOD (window_output_begin);
2529 XLIKE_CONSOLE_HAS_METHOD (window_output_end);
2530 #endif
2531 }