comparison src/redisplay-gtk.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
comparison
equal deleted inserted replaced
4881:a4322ac49e37 4882:eab9498ecc0e
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 25
26 /* Author: Chuck Thompson */
27 /* Gtk flavor by William Perry */
28
29 /* Lots of work done by Ben Wing for Mule */
30
31 #include <config.h>
32 #include "lisp.h"
33
34 #include "buffer.h"
35 #include "debug.h"
36 #include "device-impl.h"
37 #include "faces.h"
38 #include "file-coding.h"
39 #include "frame-impl.h"
40 #include "gutter.h"
41 #include "redisplay.h"
42 #include "sysdep.h"
43 #include "window.h"
44
45 #include "console-gtk-impl.h"
46 #include "gccache-gtk.h"
47 #include "glyphs-gtk.h"
48 #include "objects-gtk-impl.h"
49
50 #include "sysproc.h" /* for select() */
51
52 #ifdef MULE
53 #include "mule-ccl.h"
54 #endif
55
56 #define CONST const
57
58 #define EOL_CURSOR_WIDTH 5
59
60 static void gtk_output_pixmap (struct window *w,
61 Lisp_Object image_instance,
62 struct display_box *db,
63 struct display_glyph_area *dga,
64 face_index findex,
65 int cursor_start,
66 int cursor_width,
67 int cursor_height,
68 int bgpixmap);
69 static void gtk_output_vertical_divider (struct window *w, int clear);
70 static void gtk_output_blank (struct window *w, struct display_line *dl,
71 struct rune *rb, int start_pixpos,
72 int cursor_start, int cursor_width);
73 static void gtk_output_horizontal_line (struct window *w,
74 struct display_line *dl,
75 struct rune *rb);
76 static void gtk_clear_region (Lisp_Object locale, struct device* d, struct frame* f,
77 face_index findex, int x, int y,
78 int width, int height, Lisp_Object fcolor, Lisp_Object bcolor,
79 Lisp_Object background_pixmap);
80 static void gtk_output_eol_cursor (struct window *w, struct display_line *dl,
81 int xpos, face_index findex);
82 static void gtk_clear_frame (struct frame *f);
83 static void gtk_clear_frame_windows (Lisp_Object window);
84 static void gtk_bevel_modeline (struct window *w, struct display_line *dl);
85
86 #if 0
87 static void __describe_gc (GdkGC *);
88 #endif
89
90 #include "redisplay-xlike-inc.c" 26 #include "redisplay-xlike-inc.c"
91
92 /****************************************************************************/
93 /* */
94 /* Gtk output routines */
95 /* */
96 /****************************************************************************/
97
98 static int
99 gtk_text_width_single_run (struct face_cachel *cachel, struct textual_run *run)
100 {
101 Lisp_Object font_inst = FACE_CACHEL_FONT (cachel, run->charset);
102 struct Lisp_Font_Instance *fi = XFONT_INSTANCE (font_inst);
103
104 if (!fi->proportional_p)
105 {
106 return fi->width * run->len;
107 }
108 else
109 {
110 if (run->dimension == 2)
111 {
112 stderr_out ("Measuring wide characters\n");
113 return gdk_text_width_wc (FONT_INSTANCE_GTK_FONT (fi),
114 (GdkWChar *) run->ptr, run->len);
115 }
116 else
117 {
118 return gdk_text_width (FONT_INSTANCE_GTK_FONT (fi),
119 (char *) run->ptr, run->len);
120 }
121 }
122 }
123
124 /*
125 gtk_text_width
126
127 Given a string and a face, return the string's length in pixels when
128 displayed in the font associated with the face.
129 */
130
131 static int
132 gtk_text_width (struct frame *UNUSED (f), struct face_cachel *cachel,
133 CONST Ichar *str, Charcount len)
134 {
135 /* !!#### */
136 int width_so_far = 0;
137 unsigned char *text_storage = (unsigned char *) ALLOCA (2 * len);
138 struct textual_run *runs = alloca_array (struct textual_run, len);
139 int nruns;
140 int i;
141
142 nruns = separate_textual_runs (text_storage, runs, str, len);
143
144 for (i = 0; i < nruns; i++)
145 width_so_far += gtk_text_width_single_run (cachel, runs + i);
146
147 return width_so_far;
148 }
149
150 /*****************************************************************************
151 gtk_divider_height
152
153 Return the height of the horizontal divider. This is a function because
154 divider_height is a device method.
155
156 #### If we add etched horizontal divider lines this will have to get
157 smarter.
158 ****************************************************************************/
159 static int
160 gtk_divider_height (void)
161 {
162 return 2;
163 }
164
165 /*****************************************************************************
166 gtk_eol_cursor_width
167
168 Return the width of the end-of-line cursor. This is a function
169 because eol_cursor_width is a device method.
170 ****************************************************************************/
171 static int
172 gtk_eol_cursor_width (void)
173 {
174 return EOL_CURSOR_WIDTH;
175 }
176
177 /*****************************************************************************
178 gtk_output_display_block
179
180 Given a display line, a block number for that start line, output all
181 runes between start and end in the specified display block.
182 ****************************************************************************/
183 static void
184 gtk_output_display_block (struct window *w, struct display_line *dl, int block,
185 int start, int end, int start_pixpos, int cursor_start,
186 int cursor_width, int cursor_height)
187 {
188 struct frame *f = XFRAME (w->frame);
189 Ichar_dynarr *buf;
190 Lisp_Object window;
191
192 struct display_block *db = Dynarr_atp (dl->display_blocks, block);
193 rune_dynarr *rba = db->runes;
194 struct rune *rb;
195
196 int elt = start;
197 face_index findex;
198 int xpos, width;
199 Lisp_Object charset = Qunbound; /* Qnil is a valid charset when
200 MULE is not defined */
201
202 window = wrap_window (w);
203 rb = Dynarr_atp (rba, start);
204
205 if (!rb)
206 {
207 /* Nothing to do so don't do anything. */
208 return;
209 }
210 else
211 {
212 findex = rb->findex;
213 xpos = rb->xpos;
214 width = 0;
215 if (rb->type == RUNE_CHAR)
216 charset = ichar_charset (rb->object.chr.ch);
217 }
218
219 if (end < 0)
220 end = Dynarr_length (rba);
221 buf = Dynarr_new (Ichar);
222
223 while (elt < end)
224 {
225 rb = Dynarr_atp (rba, elt);
226
227 if (rb->findex == findex && rb->type == RUNE_CHAR
228 && rb->object.chr.ch != '\n' && rb->cursor_type != CURSOR_ON
229 && EQ (charset, ichar_charset (rb->object.chr.ch)))
230 {
231 Dynarr_add (buf, rb->object.chr.ch);
232 width += rb->width;
233 elt++;
234 }
235 else
236 {
237 if (Dynarr_length (buf))
238 {
239 gtk_output_string (w, dl, buf, xpos, 0, start_pixpos, width,
240 findex, 0, cursor_start, cursor_width,
241 cursor_height);
242 xpos = rb->xpos;
243 width = 0;
244 }
245 Dynarr_reset (buf);
246 width = 0;
247
248 if (rb->type == RUNE_CHAR)
249 {
250 findex = rb->findex;
251 xpos = rb->xpos;
252 charset = ichar_charset (rb->object.chr.ch);
253
254 if (rb->cursor_type == CURSOR_ON)
255 {
256 if (rb->object.chr.ch == '\n')
257 {
258 gtk_output_eol_cursor (w, dl, xpos, findex);
259 }
260 else
261 {
262 Dynarr_add (buf, rb->object.chr.ch);
263 gtk_output_string (w, dl, buf, xpos, 0, start_pixpos,
264 rb->width, findex, 1,
265 cursor_start, cursor_width,
266 cursor_height);
267 Dynarr_reset (buf);
268 }
269
270 xpos += rb->width;
271 elt++;
272 }
273 else if (rb->object.chr.ch == '\n')
274 {
275 /* Clear in case a cursor was formerly here. */
276 int height = dl->ascent + dl->descent - dl->clip;
277
278 redisplay_clear_region (window, findex, xpos, dl->ypos - dl->ascent,
279 rb->width, height);
280 elt++;
281 }
282 }
283 else if (rb->type == RUNE_BLANK || rb->type == RUNE_HLINE)
284 {
285 if (rb->type == RUNE_BLANK)
286 gtk_output_blank (w, dl, rb, start_pixpos, cursor_start,
287 cursor_width);
288 else
289 {
290 /* #### Our flagging of when we need to redraw the
291 modeline shadows sucks. Since RUNE_HLINE is only used
292 by the modeline at the moment it is a good bet
293 that if it gets redrawn then we should also
294 redraw the shadows. This won't be true forever.
295 We borrow the shadow_thickness_changed flag for
296 now. */
297 w->shadow_thickness_changed = 1;
298 gtk_output_horizontal_line (w, dl, rb);
299 }
300
301 elt++;
302 if (elt < end)
303 {
304 rb = Dynarr_atp (rba, elt);
305
306 findex = rb->findex;
307 xpos = rb->xpos;
308 }
309 }
310 else if (rb->type == RUNE_DGLYPH)
311 {
312 Lisp_Object instance;
313 struct display_box dbox;
314 struct display_glyph_area dga;
315 redisplay_calculate_display_boxes (dl, rb->xpos, rb->object.dglyph.xoffset,
316 rb->object.dglyph.yoffset ,start_pixpos,
317 rb->width, &dbox, &dga);
318
319 window = wrap_window (w);
320 instance = glyph_image_instance (rb->object.dglyph.glyph,
321 window, ERROR_ME_DEBUG_WARN, 1);
322 findex = rb->findex;
323
324 if (IMAGE_INSTANCEP (instance))
325 switch (XIMAGE_INSTANCE_TYPE (instance))
326 {
327 case IMAGE_TEXT:
328 {
329 /* #### This is way losing. See the comment in
330 add_glyph_rune(). */
331 Lisp_Object string =
332 XIMAGE_INSTANCE_TEXT_STRING (instance);
333 convert_ibyte_string_into_ichar_dynarr
334 (XSTRING_DATA (string), XSTRING_LENGTH (string), buf);
335
336 gtk_output_string (w, dl, buf, xpos,
337 rb->object.dglyph.xoffset,
338 start_pixpos, -1, findex,
339 (rb->cursor_type == CURSOR_ON),
340 cursor_start, cursor_width,
341 cursor_height);
342 Dynarr_reset (buf);
343 }
344 break;
345
346 case IMAGE_MONO_PIXMAP:
347 case IMAGE_COLOR_PIXMAP:
348 redisplay_output_pixmap (w, instance, &dbox, &dga,
349 findex,cursor_start,
350 cursor_width, cursor_height, 0);
351 break;
352
353 case IMAGE_POINTER:
354 ABORT ();
355
356 case IMAGE_WIDGET:
357 if (EQ (XIMAGE_INSTANCE_WIDGET_TYPE (instance),
358 Qlayout))
359 {
360 redisplay_output_layout (window, instance, &dbox,
361 &dga, findex,
362 cursor_start, cursor_width,
363 cursor_height);
364 break;
365 }
366
367 case IMAGE_SUBWINDOW:
368 redisplay_output_subwindow (w, instance, &dbox, &dga,
369 findex, cursor_start,
370 cursor_width, cursor_height);
371 break;
372
373 case IMAGE_NOTHING:
374 /* nothing is as nothing does */
375 break;
376
377 default:
378 ABORT ();
379 }
380
381 xpos += rb->width;
382 elt++;
383 }
384 else
385 ABORT ();
386 }
387 }
388
389 if (Dynarr_length (buf))
390 gtk_output_string (w, dl, buf, xpos, 0, start_pixpos, width, findex,
391 0, cursor_start, cursor_width, cursor_height);
392
393 /* #### This is really conditionalized well for optimized
394 performance. */
395 if (dl->modeline
396 && !EQ (Qzero, w->modeline_shadow_thickness)
397 && (f->clear
398 || f->windows_structure_changed
399 || w->shadow_thickness_changed))
400 gtk_bevel_modeline (w, dl);
401
402 Dynarr_free (buf);
403 }
404 27
405 /***************************************************************************** 28 /*****************************************************************************
406 gtk_bevel_modeline 29 gtk_bevel_modeline
407 30
408 Draw a 3d border around the modeline on window W. 31 Draw a 3d border around the modeline on window W.
418 width = WINDOW_MODELINE_RIGHT (w) - x; 41 width = WINDOW_MODELINE_RIGHT (w) - x;
419 y = dl->ypos - dl->ascent - shadow_thickness; 42 y = dl->ypos - dl->ascent - shadow_thickness;
420 height = dl->ascent + dl->descent + 2 * shadow_thickness; 43 height = dl->ascent + dl->descent + 2 * shadow_thickness;
421 44
422 gtk_output_shadows (f, x, y, width, height, shadow_thickness); 45 gtk_output_shadows (f, x, y, width, height, shadow_thickness);
423 }
424
425 /*****************************************************************************
426 gtk_get_gc
427
428 Given a number of parameters return a GC with those properties.
429 ****************************************************************************/
430 GdkGC *
431 gtk_get_gc (struct device *d, Lisp_Object font, Lisp_Object fg, Lisp_Object bg,
432 Lisp_Object bg_pmap, Lisp_Object lwidth)
433 {
434 GdkGCValues gcv;
435 unsigned long mask;
436
437 memset (&gcv, ~0, sizeof (gcv));
438 gcv.graphics_exposures = FALSE;
439 /* Make absolutely sure that we don't pick up a clipping region in
440 the GC returned by this function. */
441 gcv.clip_mask = 0;
442 gcv.clip_x_origin = 0;
443 gcv.clip_y_origin = 0;
444 gcv.fill = GDK_SOLID;
445 mask = GDK_GC_EXPOSURES | GDK_GC_CLIP_MASK | GDK_GC_CLIP_X_ORIGIN | GDK_GC_CLIP_Y_ORIGIN;
446 mask |= GDK_GC_FILL;
447
448 if (!NILP (font))
449 {
450 gcv.font = FONT_INSTANCE_GTK_FONT (XFONT_INSTANCE (font));
451 mask |= GDK_GC_FONT;
452 }
453
454 /* evil kludge! */
455 if (!NILP (fg) && !COLOR_INSTANCEP (fg) && !INTP (fg))
456 {
457 /* #### I fixed once case where this was getting it. It was a
458 bad macro expansion (compiler bug). */
459 fprintf (stderr, "Help! gtk_get_gc got a bogus fg value! fg = ");
460 debug_print (fg);
461 fg = Qnil;
462 }
463
464 if (!NILP (fg))
465 {
466 if (COLOR_INSTANCEP (fg))
467 gcv.foreground = * COLOR_INSTANCE_GTK_COLOR (XCOLOR_INSTANCE (fg));
468 else
469 gcv.foreground.pixel = XINT (fg);
470 mask |= GDK_GC_FOREGROUND;
471 }
472
473 if (!NILP (bg))
474 {
475 if (COLOR_INSTANCEP (bg))
476 gcv.background = * COLOR_INSTANCE_GTK_COLOR (XCOLOR_INSTANCE (bg));
477 else
478 gcv.background.pixel = XINT (fg);
479 mask |= GDK_GC_BACKGROUND;
480 }
481
482 if (IMAGE_INSTANCEP (bg_pmap)
483 && IMAGE_INSTANCE_PIXMAP_TYPE_P (XIMAGE_INSTANCE (bg_pmap)))
484 {
485 if (XIMAGE_INSTANCE_PIXMAP_DEPTH (bg_pmap) == 0)
486 {
487 gcv.fill = GDK_OPAQUE_STIPPLED;
488 gcv.stipple = XIMAGE_INSTANCE_GTK_PIXMAP (bg_pmap);
489 mask |= (GDK_GC_STIPPLE | GDK_GC_FILL);
490 }
491 else
492 {
493 gcv.fill = GDK_TILED;
494 gcv.tile = XIMAGE_INSTANCE_GTK_PIXMAP (bg_pmap);
495 mask |= (GDK_GC_TILE | GDK_GC_FILL);
496 }
497 }
498
499 if (!NILP (lwidth))
500 {
501 gcv.line_width = XINT (lwidth);
502 mask |= GDK_GC_LINE_WIDTH;
503 }
504
505 return gc_cache_lookup (DEVICE_GTK_GC_CACHE (d), &gcv, (GdkGCValuesMask) mask);
506 }
507
508 /*****************************************************************************
509 gtk_output_string
510
511 Given a string and a starting position, output that string in the
512 given face. If cursor is true, draw a cursor around the string.
513 Correctly handles multiple charsets in the string.
514
515 The meaning of the parameters is something like this:
516
517 W Window that the text is to be displayed in.
518 DL Display line that this text is on. The values in the
519 structure are used to determine the vertical position and
520 clipping range of the text.
521 BUF Dynamic array of Ichars specifying what is actually to be
522 drawn.
523 XPOS X position in pixels where the text should start being drawn.
524 XOFFSET Number of pixels to be chopped off the left side of the
525 text. The effect is as if the text were shifted to the
526 left this many pixels and clipped at XPOS.
527 CLIP_START Clip everything left of this X position.
528 WIDTH Clip everything right of XPOS + WIDTH.
529 FINDEX Index for the face cache element describing how to display
530 the text.
531 CURSOR #### I don't understand this. There's something
532 strange and overcomplexified with this variable.
533 Chuck, explain please?
534 CURSOR_START Starting X position of cursor.
535 CURSOR_WIDTH Width of cursor in pixels.
536 CURSOR_HEIGHT Height of cursor in pixels.
537
538 Starting Y position of cursor is the top of the text line.
539 The cursor is drawn sometimes whether or not CURSOR is set. ???
540 ****************************************************************************/
541 static
542 void gdk_draw_text_image (GdkDrawable *drawable,
543 GdkFont *font,
544 GdkGC *gc,
545 gint x,
546 gint y,
547 const gchar *text,
548 gint text_length);
549
550 void
551 gtk_output_string (struct window *w, struct display_line *dl,
552 Ichar_dynarr *buf, int xpos, int xoffset, int clip_start,
553 int width, face_index findex, int cursor,
554 int cursor_start, int cursor_width, int cursor_height)
555 {
556 /* !!#### Needs review */
557 /* General variables */
558 struct frame *f = XFRAME (w->frame);
559 struct device *d = XDEVICE (f->device);
560 Lisp_Object device;
561 Lisp_Object window;
562 GdkWindow *x_win = GET_GTK_WIDGET_WINDOW (FRAME_GTK_TEXT_WIDGET (f));
563
564 int clip_end;
565
566 /* Cursor-related variables */
567 int focus = EQ (w->frame, DEVICE_FRAME_WITH_FOCUS_REAL (d));
568 int cursor_clip;
569 Lisp_Object bar_cursor_value = symbol_value_in_buffer (Qbar_cursor,
570 WINDOW_BUFFER (w));
571 struct face_cachel *cursor_cachel = 0;
572
573 /* Text-related variables */
574 Lisp_Object bg_pmap;
575 GdkGC *bgc, *gc;
576 int height;
577 int len = Dynarr_length (buf);
578 unsigned char *text_storage = (unsigned char *) ALLOCA (2 * len);
579 struct textual_run *runs = alloca_array (struct textual_run, len);
580 int nruns;
581 int i;
582 struct face_cachel *cachel = WINDOW_FACE_CACHEL (w, findex);
583
584 device = wrap_device (d);
585 window = wrap_window (w);
586
587 if (width < 0)
588 width = gtk_text_width (f, cachel, Dynarr_atp (buf, 0), Dynarr_length (buf));
589 height = dl->ascent + dl->descent - dl->clip;
590
591 /* Regularize the variables passed in. */
592
593 if (clip_start < xpos)
594 clip_start = xpos;
595 clip_end = xpos + width;
596 if (clip_start >= clip_end)
597 /* It's all clipped out. */
598 return;
599
600 xpos -= xoffset;
601
602 nruns = separate_textual_runs (text_storage, runs, Dynarr_atp (buf, 0),
603 Dynarr_length (buf));
604
605 cursor_clip = (cursor_start >= clip_start &&
606 cursor_start < clip_end);
607
608 /* This cursor code is really a mess. */
609 if (!NILP (w->text_cursor_visible_p)
610 && (cursor
611 || cursor_clip
612 || (cursor_width
613 && (cursor_start + cursor_width >= clip_start)
614 && !NILP (bar_cursor_value))))
615 {
616 /* These have to be in separate statements in order to avoid a
617 compiler bug. */
618 face_index sucks = get_builtin_face_cache_index (w, Vtext_cursor_face);
619 cursor_cachel = WINDOW_FACE_CACHEL (w, sucks);
620
621 /* We have to reset this since any call to WINDOW_FACE_CACHEL
622 may cause the cache to resize and any pointers to it to
623 become invalid. */
624 cachel = WINDOW_FACE_CACHEL (w, findex);
625 }
626
627 bg_pmap = cachel->background_pixmap;
628 if (!IMAGE_INSTANCEP (bg_pmap)
629 || !IMAGE_INSTANCE_PIXMAP_TYPE_P (XIMAGE_INSTANCE (bg_pmap)))
630 bg_pmap = Qnil;
631
632 if ((cursor && focus && NILP (bar_cursor_value)
633 && !NILP (w->text_cursor_visible_p)) || NILP (bg_pmap))
634 bgc = 0;
635 else
636 bgc = gtk_get_gc (d, Qnil, cachel->foreground, cachel->background,
637 bg_pmap, Qnil);
638
639 if (bgc)
640 gdk_draw_rectangle (GDK_DRAWABLE (x_win), bgc, TRUE, clip_start,
641 dl->ypos - dl->ascent, clip_end - clip_start,
642 height);
643
644 for (i = 0; i < nruns; i++)
645 {
646 Lisp_Object font = FACE_CACHEL_FONT (cachel, runs[i].charset);
647 struct Lisp_Font_Instance *fi = XFONT_INSTANCE (font);
648 GdkFont *gdk_font = FONT_INSTANCE_GTK_FONT (fi);
649 int this_width;
650 int need_clipping;
651
652 if (EQ (font, Vthe_null_font_instance))
653 continue;
654
655 this_width = gtk_text_width_single_run (cachel, runs + i);
656 need_clipping = (dl->clip || clip_start > xpos ||
657 clip_end < xpos + this_width);
658
659 /* XDrawImageString only clears the area equal to the height of
660 the given font. It is possible that a font is being displayed
661 on a line taller than it is, so this would cause us to fail to
662 clear some areas. */
663 if ((int) fi->height < (int) (height + dl->clip))
664 {
665 int clear_start = max (xpos, clip_start);
666 int clear_end = min (xpos + this_width, clip_end);
667
668 if (cursor)
669 {
670 int ypos1_line, ypos1_string, ypos2_line, ypos2_string;
671
672 ypos1_string = dl->ypos - fi->ascent;
673 ypos2_string = dl->ypos + fi->descent;
674 ypos1_line = dl->ypos - dl->ascent;
675 ypos2_line = dl->ypos + dl->descent - dl->clip;
676
677 /* Make sure we don't clear below the real bottom of the
678 line. */
679 if (ypos1_string > ypos2_line)
680 ypos1_string = ypos2_line;
681 if (ypos2_string > ypos2_line)
682 ypos2_string = ypos2_line;
683
684 if (ypos1_line < ypos1_string)
685 {
686 redisplay_clear_region (window, findex, clear_start, ypos1_line,
687 clear_end - clear_start,
688 ypos1_string - ypos1_line);
689 }
690
691 if (ypos2_line > ypos2_string)
692 {
693 redisplay_clear_region (window, findex, clear_start, ypos2_string,
694 clear_end - clear_start,
695 ypos2_line - ypos2_string);
696 }
697 }
698 else
699 {
700 redisplay_clear_region (window, findex, clear_start,
701 dl->ypos - dl->ascent, clear_end - clear_start,
702 height);
703 }
704 }
705
706 if (cursor && cursor_cachel && focus && NILP (bar_cursor_value))
707 {
708 gc = gtk_get_gc (d, font, cursor_cachel->foreground,
709 cursor_cachel->background, Qnil, Qnil);
710 }
711 else
712 {
713 gc = gtk_get_gc (d, font, cachel->foreground, cachel->background,
714 Qnil, Qnil);
715 }
716
717 if (need_clipping)
718 {
719 GdkRectangle clip_box;
720
721 clip_box.x = 0;
722 clip_box.y = 0;
723 clip_box.width = clip_end - clip_start;
724 clip_box.height = height;
725
726 gdk_gc_set_clip_rectangle (gc, &clip_box);
727 gdk_gc_set_clip_origin (gc, clip_start, dl->ypos - dl->ascent);
728 }
729
730 /* The X specific called different functions (XDraw*String
731 vs. XDraw*String16), but apparently gdk_draw_text takes care
732 of that for us.
733
734 BUT, gdk_draw_text also does too much, by dividing the length
735 by 2. So we fake them out my multiplying the length by the
736 dimension of the text. This will do the right thing for
737 single-dimension runs as well of course.
738 */
739 (bgc ? gdk_draw_text : gdk_draw_text_image) (GDK_DRAWABLE (x_win), gdk_font, gc, xpos,
740 dl->ypos, (char *) runs[i].ptr,
741 runs[i].len * runs[i].dimension);
742
743 /* We draw underlines in the same color as the text. */
744 if (cachel->underline)
745 {
746 int upos, uthick;
747
748 /* Cannot get at font properties in Gtk, so we resort to
749 guessing */
750 upos = dl->descent / 2;
751 uthick = 1;
752
753 if ((dl->ypos + upos) < (dl->ypos + dl->descent - dl->clip))
754 {
755 if (dl->ypos + upos + uthick > dl->ypos + dl->descent - dl->clip)
756 uthick = dl->descent - dl->clip - upos;
757
758 if (uthick == 1)
759 {
760 gdk_draw_line (GDK_DRAWABLE (x_win), gc, xpos, dl->ypos + upos,
761 xpos + this_width, dl->ypos + upos);
762 }
763 else if (uthick > 1)
764 {
765 gdk_draw_rectangle (GDK_DRAWABLE (x_win), gc, TRUE, xpos,
766 dl->ypos + upos, this_width, uthick);
767 }
768 }
769 }
770
771 if (cachel->strikethru) {
772 gint ascent,descent,upos, uthick;
773 GdkFont *gfont = FONT_INSTANCE_GTK_FONT (XFONT_INSTANCE (font));
774
775 /* Cannot get at font properties in Gtk, so we resort to
776 guessing */
777
778 ascent = gfont->ascent;
779 descent = gfont->descent;
780 uthick = 1;
781
782 upos = ascent - ((ascent + descent) / 2) + 1;
783
784 /* Generally, upos will be positive (above the baseline),so subtract */
785 if (dl->ypos - upos < dl->ypos + dl->descent - dl->clip)
786 {
787 if (dl->ypos - upos + uthick > dl->ypos + dl->descent - dl->clip)
788 uthick = dl->descent - dl->clip + upos;
789
790 if (uthick == 1)
791 {
792 gdk_draw_line (GDK_DRAWABLE (x_win), gc, xpos, dl->ypos - upos,
793 xpos + this_width, dl->ypos - upos);
794 }
795 else if (uthick > 1)
796 {
797 gdk_draw_rectangle (GDK_DRAWABLE (x_win), gc, TRUE, xpos, dl->ypos + upos,
798 this_width, uthick);
799 }
800 }
801 }
802
803 /* Restore the GC */
804 if (need_clipping)
805 {
806 gdk_gc_set_clip_rectangle (gc, NULL);
807 gdk_gc_set_clip_origin (gc, 0, 0);
808 }
809
810 /* If we are actually superimposing the cursor then redraw with just
811 the appropriate section highlighted. */
812 if (cursor_clip && !cursor && focus && cursor_cachel)
813 {
814 GdkGC *cgc;
815 GdkRectangle clip_box;
816
817 cgc = gtk_get_gc (d, font, cursor_cachel->foreground,
818 cursor_cachel->background, Qnil, Qnil);
819
820 clip_box.x = 0;
821 clip_box.y = 0;
822 clip_box.width = cursor_width;
823 clip_box.height = height;
824
825 gdk_gc_set_clip_rectangle (cgc, &clip_box);
826 gdk_gc_set_clip_origin (cgc, cursor_start, dl->ypos - dl->ascent);
827
828 /* The X specific called different functions (XDraw*String
829 vs. XDraw*String16), but apparently gdk_draw_text takes care
830 of that for us.
831
832 BUT, gdk_draw_text also does too much, by dividing the
833 length by 2. So we fake them out my multiplying the
834 length by the dimension of the text. This will do the
835 right thing for single-dimension runs as well of course.
836 */
837 gdk_draw_text_image (GDK_DRAWABLE (x_win), gdk_font, cgc, xpos,
838 dl->ypos, (char *) runs[i].ptr,
839 runs[i].len * runs[i].dimension);
840
841 gdk_gc_set_clip_rectangle (cgc, NULL);
842 gdk_gc_set_clip_origin (cgc, 0, 0);
843 }
844
845 xpos += this_width;
846 }
847
848 /* Draw the non-focus box or bar-cursor as needed. */
849 /* Can't this logic be simplified? */
850 if (cursor_cachel
851 && ((cursor && !focus && NILP (bar_cursor_value))
852 || (cursor_width
853 && (cursor_start + cursor_width >= clip_start)
854 && !NILP (bar_cursor_value))))
855 {
856 int tmp_height, tmp_y;
857 int bar_width = EQ (bar_cursor_value, Qt) ? 1 : 2;
858 int need_clipping = (cursor_start < clip_start
859 || clip_end < cursor_start + cursor_width);
860
861 /* #### This value is correct (as far as I know) because
862 all of the times we need to draw this cursor, we will
863 be called with exactly one character, so we know we
864 can always use runs[0].
865
866 This is bogus as all hell, however. The cursor handling in
867 this function is way bogus and desperately needs to be
868 cleaned up. (In particular, the drawing of the cursor should
869 really really be separated out of this function. This may be
870 a bit tricky now because this function itself does way too
871 much stuff, a lot of which needs to be moved into
872 redisplay.c) This is the only way to be able to easily add
873 new cursor types or (e.g.) make the bar cursor be able to
874 span two characters instead of overlaying just one. */
875 int bogusly_obtained_ascent_value =
876 XFONT_INSTANCE (FACE_CACHEL_FONT (cachel, runs[0].charset))->ascent;
877
878 if (!NILP (bar_cursor_value))
879 {
880 gc = gtk_get_gc (d, Qnil, cursor_cachel->background, Qnil, Qnil,
881 make_int (bar_width));
882 }
883 else
884 {
885 gc = gtk_get_gc (d, Qnil, cursor_cachel->background,
886 Qnil, Qnil, Qnil);
887 }
888
889 tmp_y = dl->ypos - bogusly_obtained_ascent_value;
890 tmp_height = cursor_height;
891 if (tmp_y + tmp_height > (int) (dl->ypos - dl->ascent + height))
892 {
893 tmp_y = dl->ypos - dl->ascent + height - tmp_height;
894 if (tmp_y < (int) (dl->ypos - dl->ascent))
895 tmp_y = dl->ypos - dl->ascent;
896 tmp_height = dl->ypos - dl->ascent + height - tmp_y;
897 }
898
899 if (need_clipping)
900 {
901 GdkRectangle clip_box;
902 clip_box.x = 0;
903 clip_box.y = 0;
904 clip_box.width = clip_end - clip_start;
905 clip_box.height = tmp_height;
906
907 gdk_gc_set_clip_rectangle (gc, &clip_box);
908 gdk_gc_set_clip_origin (gc, clip_start, tmp_y);
909 }
910
911 if (!focus && NILP (bar_cursor_value))
912 {
913 gdk_draw_rectangle (GDK_DRAWABLE (x_win), gc, FALSE,
914 cursor_start, tmp_y,
915 cursor_width - 1, tmp_height - 1);
916 }
917 else if (focus && !NILP (bar_cursor_value))
918 {
919 gdk_draw_line (GDK_DRAWABLE (x_win), gc,
920 cursor_start + bar_width - 1, tmp_y,
921 cursor_start + bar_width - 1, tmp_y + tmp_height - 1);
922 }
923
924 /* Restore the GC */
925 if (need_clipping)
926 {
927 gdk_gc_set_clip_rectangle (gc, NULL);
928 gdk_gc_set_clip_origin (gc, 0, 0);
929 }
930 }
931 }
932
933 static void
934 our_draw_bitmap (GdkDrawable *drawable,
935 GdkGC *gc,
936 GdkPixmap *src,
937 gint xsrc,
938 gint ysrc,
939 gint xdest,
940 gint ydest,
941 gint width,
942 gint height);
943
944 static void
945 gtk_output_gdk_pixmap (struct frame *f, struct Lisp_Image_Instance *p, int x,
946 int y, int xoffset, int yoffset,
947 int width, int height,
948 GdkColor *fg, GdkColor *bg, GdkGC *override_gc)
949 {
950 struct device *d = XDEVICE (f->device);
951 GdkWindow *x_win = GET_GTK_WIDGET_WINDOW (FRAME_GTK_TEXT_WIDGET (f));
952
953 GdkGC *gc;
954 GdkGCValues gcv;
955 unsigned long pixmap_mask;
956
957 if (!override_gc)
958 {
959 memset (&gcv, ~0, sizeof (gcv));
960 gcv.graphics_exposures = FALSE;
961 gcv.foreground = *fg;
962 gcv.background = *bg;
963 pixmap_mask = GDK_GC_FOREGROUND | GDK_GC_BACKGROUND | GDK_GC_EXPOSURES;
964
965 if (IMAGE_INSTANCE_GTK_MASK (p))
966 {
967 gcv.function = GDK_COPY;
968 gcv.clip_mask = IMAGE_INSTANCE_GTK_MASK (p);
969 gcv.clip_x_origin = x - xoffset;
970 gcv.clip_y_origin = y - yoffset;
971 pixmap_mask |= (GDK_GC_FUNCTION | GDK_GC_CLIP_MASK | GDK_GC_CLIP_X_ORIGIN |
972 GDK_GC_CLIP_Y_ORIGIN);
973 /* Can't set a clip rectangle below because we already have a mask.
974 We could conceivably create a new clipmask by zeroing out
975 everything outside the clip region. Is it worth it?
976 Is it possible to get an equivalent effect by changing the
977 args to XCopyArea below rather than messing with a clip box?
978 - dkindred@cs.cmu.edu
979 Yes. We don't clip at all now - andy@xemacs.org
980 */
981 }
982
983 gc = gc_cache_lookup (DEVICE_GTK_GC_CACHE (d), &gcv, pixmap_mask);
984 }
985 else
986 {
987 gc = override_gc;
988 /* override_gc might have a mask already--we don't want to nuke it.
989 Maybe we can insist that override_gc have no mask, or use
990 one of the suggestions above. */
991 }
992
993 if (IMAGE_INSTANCE_PIXMAP_DEPTH (p) > 0)
994 {
995 gdk_draw_pixmap (GDK_DRAWABLE (x_win), gc,
996 IMAGE_INSTANCE_GTK_PIXMAP (p),
997 xoffset, yoffset, x, y, width, height);
998 }
999 else
1000 {
1001 our_draw_bitmap (GDK_DRAWABLE (x_win), gc,
1002 IMAGE_INSTANCE_GTK_PIXMAP (p),
1003 xoffset, yoffset, x, y, width, height);
1004 }
1005 }
1006
1007 static void
1008 gtk_output_pixmap (struct window *w,
1009 Lisp_Object image_instance,
1010 struct display_box *db,
1011 struct display_glyph_area *dga,
1012 face_index findex,
1013 int cursor_start,
1014 int cursor_width,
1015 int cursor_height,
1016 int UNUSED (bg_pixmap))
1017 {
1018 struct frame *f = XFRAME (w->frame);
1019 struct device *d = XDEVICE (f->device);
1020 struct Lisp_Image_Instance *p = XIMAGE_INSTANCE (image_instance);
1021 Lisp_Object window;
1022
1023 GdkWindow *x_win = GET_GTK_WIDGET_WINDOW (FRAME_GTK_TEXT_WIDGET (f));
1024
1025 window = wrap_window (w);
1026
1027 /* Output the pixmap. */
1028 {
1029 Lisp_Object tmp_pixel;
1030 GdkColor *tmp_bcolor, *tmp_fcolor;
1031
1032 tmp_pixel = WINDOW_FACE_CACHEL_FOREGROUND (w, findex);
1033 tmp_fcolor = COLOR_INSTANCE_GTK_COLOR (XCOLOR_INSTANCE (tmp_pixel));
1034 tmp_pixel = WINDOW_FACE_CACHEL_BACKGROUND (w, findex);
1035 tmp_bcolor = COLOR_INSTANCE_GTK_COLOR (XCOLOR_INSTANCE (tmp_pixel));
1036
1037 gtk_output_gdk_pixmap (f, p, db->xpos, db->ypos,
1038 dga->xoffset, dga->yoffset,
1039 dga->width, dga->height,
1040 tmp_fcolor, tmp_bcolor, NULL);
1041 }
1042
1043 /* Draw a cursor over top of the pixmap. */
1044 if (cursor_width && cursor_height && (cursor_start >= db->xpos)
1045 && !NILP (w->text_cursor_visible_p)
1046 && (cursor_start < (db->xpos + dga->width)))
1047 {
1048 GdkGC *gc;
1049 int focus = EQ (w->frame, DEVICE_FRAME_WITH_FOCUS_REAL (d));
1050 struct face_cachel *cursor_cachel =
1051 WINDOW_FACE_CACHEL (w,
1052 get_builtin_face_cache_index
1053 (w, Vtext_cursor_face));
1054
1055 gc = gtk_get_gc (d, Qnil, cursor_cachel->background, Qnil, Qnil, Qnil);
1056
1057 if (cursor_width > db->xpos + dga->width - cursor_start)
1058 cursor_width = db->xpos + dga->width - cursor_start;
1059
1060 gdk_draw_rectangle (GDK_DRAWABLE (x_win), gc, focus ? TRUE : FALSE,
1061 cursor_start, db->ypos, cursor_width,
1062 cursor_height);
1063 }
1064 }
1065
1066 /*****************************************************************************
1067 gtk_output_vertical_divider
1068
1069 Draw a vertical divider down the right side of the given window.
1070 ****************************************************************************/
1071 static void
1072 gtk_output_vertical_divider (struct window *w, int UNUSED(clear))
1073 {
1074 struct frame *f = XFRAME (w->frame);
1075 struct device *d = XDEVICE (f->device);
1076 GdkWindow *x_win = GET_GTK_WIDGET_WINDOW (FRAME_GTK_TEXT_WIDGET (f));
1077 GdkGC *background_gc;
1078 Lisp_Object tmp_pixel;
1079 GdkGCValues gcv;
1080 unsigned long mask;
1081 int x, y1, y2, width, shadow_thickness, spacing, line_width;
1082 face_index div_face = get_builtin_face_cache_index (w, Vvertical_divider_face);
1083
1084 width = window_divider_width (w);
1085 shadow_thickness = XINT (w->vertical_divider_shadow_thickness);
1086 spacing = XINT (w->vertical_divider_spacing);
1087 line_width = XINT (w->vertical_divider_line_width);
1088 x = WINDOW_RIGHT (w) - width;
1089 y1 = WINDOW_TOP (w);
1090 y2 = WINDOW_BOTTOM (w);
1091
1092 memset (&gcv, ~0, sizeof (gcv));
1093
1094 tmp_pixel = WINDOW_FACE_CACHEL_BACKGROUND (w, div_face);
1095
1096 gcv.background = * COLOR_INSTANCE_GTK_COLOR (XCOLOR_INSTANCE (tmp_pixel));
1097 gcv.foreground = gcv.background;
1098 gcv.graphics_exposures = FALSE;
1099 mask = GDK_GC_FOREGROUND | GDK_GC_BACKGROUND | GDK_GC_EXPOSURES;
1100
1101 background_gc = gc_cache_lookup (DEVICE_GTK_GC_CACHE (d), &gcv, mask);
1102
1103 /* Clear the divider area first. This needs to be done when a
1104 window split occurs. */
1105 /* if (clear) */
1106 gdk_draw_rectangle (GDK_DRAWABLE (x_win), background_gc, TRUE,
1107 x, y1, width, y2 - y1);
1108
1109 #if 0
1110 /* Draw the divider line. */
1111 gdk_draw_rectangle (GDK_DRAWABLE (x_win), background_gc, TRUE,
1112 x + spacing + shadow_thickness, y1,
1113 line_width, y2 - y1);
1114 #endif
1115
1116 /* Draw the shadows around the divider line */
1117 gtk_output_shadows (f, x + spacing, y1,
1118 width - 2 * spacing, y2 - y1,
1119 shadow_thickness);
1120 }
1121
1122 /*****************************************************************************
1123 gtk_output_blank
1124
1125 Output a blank by clearing the area it covers in the foreground color
1126 of its face.
1127 ****************************************************************************/
1128 static void
1129 gtk_output_blank (struct window *w, struct display_line *dl, struct rune *rb,
1130 int start_pixpos, int cursor_start, int cursor_width)
1131 {
1132 struct frame *f = XFRAME (w->frame);
1133 struct device *d = XDEVICE (f->device);
1134
1135 GdkWindow *x_win = GET_GTK_WIDGET_WINDOW (FRAME_GTK_TEXT_WIDGET (f));
1136 GdkGC *gc;
1137 struct face_cachel *cursor_cachel =
1138 WINDOW_FACE_CACHEL (w,
1139 get_builtin_face_cache_index
1140 (w, Vtext_cursor_face));
1141 Lisp_Object bg_pmap;
1142 Lisp_Object buffer = WINDOW_BUFFER (w);
1143 Lisp_Object bar_cursor_value = symbol_value_in_buffer (Qbar_cursor,
1144 buffer);
1145
1146 int x = rb->xpos;
1147 int y = dl->ypos - dl->ascent;
1148 int width = rb->width;
1149 int height = dl->ascent + dl->descent - dl->clip;
1150
1151 if (start_pixpos > x)
1152 {
1153 if (start_pixpos >= (x + width))
1154 return;
1155 else
1156 {
1157 width -= (start_pixpos - x);
1158 x = start_pixpos;
1159 }
1160 }
1161
1162 bg_pmap = WINDOW_FACE_CACHEL_BACKGROUND_PIXMAP (w, rb->findex);
1163 if (!IMAGE_INSTANCEP (bg_pmap)
1164 || !IMAGE_INSTANCE_PIXMAP_TYPE_P (XIMAGE_INSTANCE (bg_pmap)))
1165 bg_pmap = Qnil;
1166
1167 if (NILP (bg_pmap))
1168 gc = gtk_get_gc (d, Qnil, WINDOW_FACE_CACHEL_BACKGROUND (w, rb->findex),
1169 Qnil, Qnil, Qnil);
1170 else
1171 gc = gtk_get_gc (d, Qnil, WINDOW_FACE_CACHEL_FOREGROUND (w, rb->findex),
1172 WINDOW_FACE_CACHEL_BACKGROUND (w, rb->findex), bg_pmap,
1173 Qnil);
1174
1175 gdk_draw_rectangle (GDK_DRAWABLE (x_win), gc, TRUE, x, y, width, height);
1176
1177 /* If this rune is marked as having the cursor, then it is actually
1178 representing a tab. */
1179 if (!NILP (w->text_cursor_visible_p)
1180 && (rb->cursor_type == CURSOR_ON
1181 || (cursor_width
1182 && (cursor_start + cursor_width > x)
1183 && cursor_start < (x + width))))
1184 {
1185 int cursor_height, cursor_y;
1186 int focus = EQ (w->frame, DEVICE_FRAME_WITH_FOCUS_REAL (d));
1187 struct Lisp_Font_Instance *fi;
1188
1189 fi = XFONT_INSTANCE (FACE_CACHEL_FONT
1190 (WINDOW_FACE_CACHEL (w, rb->findex),
1191 Vcharset_ascii));
1192
1193 gc = gtk_get_gc (d, Qnil, cursor_cachel->background, Qnil, Qnil, Qnil);
1194
1195 cursor_y = dl->ypos - fi->ascent;
1196 cursor_height = fi->height;
1197 if (cursor_y + cursor_height > y + height)
1198 cursor_height = y + height - cursor_y;
1199
1200 if (focus)
1201 {
1202 if (NILP (bar_cursor_value))
1203 {
1204 gdk_draw_rectangle (GDK_DRAWABLE (x_win), gc, TRUE,
1205 cursor_start, cursor_y,
1206 fi->width, cursor_height);
1207 }
1208 else
1209 {
1210 int bar_width = EQ (bar_cursor_value, Qt) ? 1 : 2;
1211
1212 gc = gtk_get_gc (d, Qnil, cursor_cachel->background, Qnil, Qnil,
1213 make_int (bar_width));
1214 gdk_draw_line (GDK_DRAWABLE (x_win), gc, cursor_start + bar_width - 1,
1215 cursor_y, cursor_start + bar_width - 1,
1216 cursor_y + cursor_height - 1);
1217 }
1218 }
1219 else if (NILP (bar_cursor_value))
1220 {
1221 gdk_draw_rectangle (GDK_DRAWABLE (x_win), gc, FALSE,
1222 cursor_start, cursor_y,
1223 fi->width - 1, cursor_height - 1);
1224 }
1225 }
1226 }
1227
1228 /*****************************************************************************
1229 gtk_output_horizontal_line
1230
1231 Output a horizontal line in the foreground of its face.
1232 ****************************************************************************/
1233 static void
1234 gtk_output_horizontal_line (struct window *w,
1235 struct display_line *dl,
1236 struct rune *rb)
1237 {
1238 struct frame *f = XFRAME (w->frame);
1239 struct device *d = XDEVICE (f->device);
1240 GtkStyle *style = FRAME_GTK_TEXT_WIDGET (f)->style;
1241
1242 GdkWindow *x_win = GET_GTK_WIDGET_WINDOW (FRAME_GTK_TEXT_WIDGET (f));
1243 GdkGC *gc;
1244
1245 int x = rb->xpos;
1246 int width = rb->width;
1247 int height = dl->ascent + dl->descent - dl->clip;
1248
1249 int ypos1, ypos2, ypos3, ypos4;
1250
1251 ypos1 = dl->ypos - dl->ascent;
1252 ypos2 = ypos1 + rb->object.hline.yoffset;
1253 ypos3 = ypos2 + rb->object.hline.thickness;
1254 ypos4 = dl->ypos + dl->descent - dl->clip;
1255
1256 /* First clear the area not covered by the line. */
1257 if (height - rb->object.hline.thickness > 0)
1258 {
1259 gc = gtk_get_gc (d, Qnil, WINDOW_FACE_CACHEL_FOREGROUND (w, rb->findex),
1260 Qnil, Qnil, Qnil);
1261
1262 if (ypos2 - ypos1 > 0)
1263 gdk_draw_rectangle (GDK_DRAWABLE (x_win), gc, TRUE, x, ypos1, width, ypos2 - ypos1);
1264 if (ypos4 - ypos3 > 0)
1265 gdk_draw_rectangle (GDK_DRAWABLE (x_win), gc, TRUE, x, ypos1, width, ypos2 - ypos1);
1266 }
1267
1268 gtk_paint_hline (style, x_win, GTK_STATE_NORMAL, NULL, FRAME_GTK_TEXT_WIDGET (f),
1269 "hline", x, x + width, ypos2);
1270 #if 0
1271 /* Now draw the line. */
1272 gc = gtk_get_gc (d, Qnil, WINDOW_FACE_CACHEL_BACKGROUND (w, rb->findex),
1273 Qnil, Qnil, Qnil);
1274
1275 if (ypos2 < ypos1)
1276 ypos2 = ypos1;
1277 if (ypos3 > ypos4)
1278 ypos3 = ypos4;
1279
1280 if (ypos3 - ypos2 > 0)
1281 gdk_draw_rectangle (GDK_DRAWABLE (x_win), gc, TRUE, x, ypos2, width, ypos3 - ypos2);
1282 #endif
1283 } 46 }
1284 47
1285 /***************************************************************************** 48 /*****************************************************************************
1286 gtk_output_shadows 49 gtk_output_shadows
1287 50
1310 gtk_paint_shadow (style, x_win, GTK_STATE_NORMAL, stype, NULL, 73 gtk_paint_shadow (style, x_win, GTK_STATE_NORMAL, stype, NULL,
1311 FRAME_GTK_TEXT_WIDGET (f), "modeline", 74 FRAME_GTK_TEXT_WIDGET (f), "modeline",
1312 x, y, width, height); 75 x, y, width, height);
1313 } 76 }
1314 77
1315 /*****************************************************************************
1316 gtk_clear_to_window_end
1317
1318 Clear the area between ypos1 and ypos2. Each margin area and the
1319 text area is handled separately since they may each have their own
1320 background color.
1321 ****************************************************************************/
1322 static void
1323 gtk_clear_to_window_end (struct window *w, int ypos1, int ypos2)
1324 {
1325 int height = ypos2 - ypos1;
1326
1327 if (height)
1328 {
1329 struct frame *f = XFRAME (w->frame);
1330 Lisp_Object window;
1331 int bflag = (window_needs_vertical_divider (w) ? 0 : 1);
1332 layout_bounds bounds;
1333
1334 bounds = calculate_display_line_boundaries (w, bflag);
1335 window = wrap_window (w);
1336
1337 if (window_is_leftmost (w))
1338 redisplay_clear_region (window, DEFAULT_INDEX, FRAME_LEFT_BORDER_START (f),
1339 ypos1, FRAME_BORDER_WIDTH (f), height);
1340
1341 if (bounds.left_in - bounds.left_out > 0)
1342 redisplay_clear_region (window,
1343 get_builtin_face_cache_index (w, Vleft_margin_face),
1344 bounds.left_out, ypos1,
1345 bounds.left_in - bounds.left_out, height);
1346
1347 if (bounds.right_in - bounds.left_in > 0)
1348 redisplay_clear_region (window, DEFAULT_INDEX, bounds.left_in, ypos1,
1349 bounds.right_in - bounds.left_in, height);
1350
1351 if (bounds.right_out - bounds.right_in > 0)
1352 redisplay_clear_region (window,
1353 get_builtin_face_cache_index (w, Vright_margin_face),
1354 bounds.right_in, ypos1,
1355 bounds.right_out - bounds.right_in, height);
1356
1357 if (window_is_rightmost (w))
1358 redisplay_clear_region (window, DEFAULT_INDEX, FRAME_RIGHT_BORDER_START (f),
1359 ypos1, FRAME_BORDER_WIDTH (f), height);
1360 }
1361 }
1362
1363 /****************************************************************************
1364 gtk_clear_region
1365
1366 Clear the area in the box defined by the given parameters using the
1367 given face.
1368 ****************************************************************************/
1369 static void
1370 gtk_clear_region (Lisp_Object UNUSED (locale), struct device* d,
1371 struct frame* f, face_index UNUSED (findex), int x, int y,
1372 int width, int height, Lisp_Object fcolor, Lisp_Object bcolor,
1373 Lisp_Object background_pixmap)
1374 {
1375 GdkWindow *x_win;
1376 GdkGC *gc = NULL;
1377
1378 x_win = GET_GTK_WIDGET_WINDOW (FRAME_GTK_TEXT_WIDGET (f));
1379
1380 if (!UNBOUNDP (background_pixmap))
1381 {
1382 gc = gtk_get_gc (d, Qnil, fcolor, bcolor, background_pixmap, Qnil);
1383 }
1384
1385 if (gc)
1386 {
1387 gdk_draw_rectangle (GDK_DRAWABLE (x_win), gc,TRUE,
1388 x, y, width, height);
1389 }
1390 else
1391 {
1392 gdk_window_clear_area (x_win, x, y, width, height);
1393 }
1394 }
1395
1396 /*****************************************************************************
1397 gtk_output_eol_cursor
1398
1399 Draw a cursor at the end of a line. The end-of-line cursor is
1400 narrower than the normal cursor.
1401 ****************************************************************************/
1402 static void
1403 gtk_output_eol_cursor (struct window *w, struct display_line *dl, int xpos,
1404 face_index findex)
1405 {
1406 struct frame *f = XFRAME (w->frame);
1407 struct device *d = XDEVICE (f->device);
1408 Lisp_Object window;
1409
1410 GdkWindow *x_win = GET_GTK_WIDGET_WINDOW (FRAME_GTK_TEXT_WIDGET (f));
1411 GdkGC *gc;
1412 face_index elt = get_builtin_face_cache_index (w, Vtext_cursor_face);
1413 struct face_cachel *cursor_cachel = WINDOW_FACE_CACHEL (w, elt);
1414
1415 int focus = EQ (w->frame, DEVICE_FRAME_WITH_FOCUS_REAL (d));
1416 Lisp_Object bar_cursor_value = symbol_value_in_buffer (Qbar_cursor,
1417 WINDOW_BUFFER (w));
1418
1419 int x = xpos;
1420 int y = dl->ypos - dl->ascent;
1421 int width = EOL_CURSOR_WIDTH;
1422 int height = dl->ascent + dl->descent - dl->clip;
1423 int cursor_height, cursor_y;
1424 int defheight, defascent;
1425
1426 window = wrap_window (w);
1427 redisplay_clear_region (window, findex, x, y, width, height);
1428
1429 if (NILP (w->text_cursor_visible_p))
1430 return;
1431
1432 gc = gtk_get_gc (d, Qnil, cursor_cachel->background, Qnil, Qnil, Qnil);
1433
1434 default_face_font_info (window, &defascent, 0, &defheight, 0, 0);
1435
1436 /* make sure the cursor is entirely contained between y and y+height */
1437 cursor_height = min (defheight, height);
1438 cursor_y = max (y, min (y + height - cursor_height,
1439 dl->ypos - defascent));
1440
1441 if (focus)
1442 {
1443 if (NILP (bar_cursor_value))
1444 {
1445 gdk_draw_rectangle (GDK_DRAWABLE (x_win), gc, TRUE, x, cursor_y, width, cursor_height);
1446 }
1447 else
1448 {
1449 int bar_width = EQ (bar_cursor_value, Qt) ? 1 : 2;
1450
1451 gc = gtk_get_gc (d, Qnil, cursor_cachel->background, Qnil, Qnil,
1452 make_int (bar_width));
1453 gdk_draw_line (GDK_DRAWABLE (x_win), gc, x + bar_width - 1, cursor_y,
1454 x + bar_width - 1, cursor_y + cursor_height - 1);
1455 }
1456 }
1457 else if (NILP (bar_cursor_value))
1458 {
1459 gdk_draw_rectangle (GDK_DRAWABLE (x_win), gc, FALSE, x, cursor_y, width - 1,
1460 cursor_height - 1);
1461 }
1462 }
1463
1464 static void
1465 gtk_clear_frame_window (Lisp_Object window)
1466 {
1467 struct window *w = XWINDOW (window);
1468
1469 if (!NILP (w->vchild))
1470 {
1471 gtk_clear_frame_windows (w->vchild);
1472 return;
1473 }
1474
1475 if (!NILP (w->hchild))
1476 {
1477 gtk_clear_frame_windows (w->hchild);
1478 return;
1479 }
1480
1481 gtk_clear_to_window_end (w, WINDOW_TEXT_TOP (w), WINDOW_TEXT_BOTTOM (w));
1482 }
1483
1484 static void
1485 gtk_clear_frame_windows (Lisp_Object window)
1486 {
1487 for (; !NILP (window); window = XWINDOW (window)->next)
1488 gtk_clear_frame_window (window);
1489 }
1490
1491 static void
1492 gtk_clear_frame (struct frame *f)
1493 {
1494 GdkWindow *x_win = GET_GTK_WIDGET_WINDOW (FRAME_GTK_TEXT_WIDGET (f));
1495 int x, y, width, height;
1496 Lisp_Object frame;
1497
1498 x = FRAME_LEFT_BORDER_START (f);
1499 width = (FRAME_PIXWIDTH (f) - FRAME_REAL_LEFT_TOOLBAR_WIDTH (f) -
1500 FRAME_REAL_RIGHT_TOOLBAR_WIDTH (f) -
1501 2 * FRAME_REAL_LEFT_TOOLBAR_BORDER_WIDTH (f) -
1502 2 * FRAME_REAL_RIGHT_TOOLBAR_BORDER_WIDTH (f));
1503 /* #### This adjustment by 1 should be being done in the macros.
1504 There is some small differences between when the menubar is on
1505 and off that we still need to deal with. */
1506 y = FRAME_TOP_BORDER_START (f) - 1;
1507 height = (FRAME_PIXHEIGHT (f) - FRAME_REAL_TOP_TOOLBAR_HEIGHT (f) -
1508 FRAME_REAL_BOTTOM_TOOLBAR_HEIGHT (f) -
1509 2 * FRAME_REAL_TOP_TOOLBAR_BORDER_WIDTH (f) -
1510 2 * FRAME_REAL_BOTTOM_TOOLBAR_BORDER_WIDTH (f)) + 1;
1511
1512 gdk_window_clear_area (x_win, x, y, width, height);
1513
1514 frame = wrap_frame (f);
1515
1516 if (!UNBOUNDP (FACE_BACKGROUND_PIXMAP (Vdefault_face, frame))
1517 || !UNBOUNDP (FACE_BACKGROUND_PIXMAP (Vleft_margin_face, frame))
1518 || !UNBOUNDP (FACE_BACKGROUND_PIXMAP (Vright_margin_face, frame)))
1519 {
1520 gtk_clear_frame_windows (f->root_window);
1521 }
1522 }
1523
1524 static int
1525 gtk_flash (struct device *d)
1526 {
1527 GdkGCValues gcv;
1528 GdkGC *gc;
1529 GdkColor tmp_fcolor, tmp_bcolor;
1530 Lisp_Object tmp_pixel, frame;
1531 struct frame *f = device_selected_frame (d);
1532 struct window *w = XWINDOW (FRAME_ROOT_WINDOW (f));
1533
1534 frame = wrap_frame (f);
1535
1536 tmp_pixel = FACE_FOREGROUND (Vdefault_face, frame);
1537 tmp_fcolor = * (COLOR_INSTANCE_GTK_COLOR (XCOLOR_INSTANCE (tmp_pixel)));
1538 tmp_pixel = FACE_BACKGROUND (Vdefault_face, frame);
1539 tmp_bcolor = * (COLOR_INSTANCE_GTK_COLOR (XCOLOR_INSTANCE (tmp_pixel)));
1540
1541 memset (&gcv, ~0, sizeof (gcv)); /* initialize all slots to ~0 */
1542 gcv.foreground.pixel = (tmp_fcolor.pixel ^ tmp_bcolor.pixel);
1543 gcv.function = GDK_XOR;
1544 gcv.graphics_exposures = FALSE;
1545 gc = gc_cache_lookup (DEVICE_GTK_GC_CACHE (XDEVICE (f->device)), &gcv,
1546 GDK_GC_FOREGROUND | GDK_GC_FUNCTION | GDK_GC_EXPOSURES);
1547
1548 gdk_draw_rectangle (GDK_DRAWABLE (GET_GTK_WIDGET_WINDOW (FRAME_GTK_SHELL_WIDGET (f))),
1549 gc, TRUE, w->pixel_left, w->pixel_top,
1550 w->pixel_width, w->pixel_height);
1551
1552 gdk_flush ();
1553
1554 #ifdef HAVE_SELECT
1555 {
1556 int usecs = 100000;
1557 struct timeval tv;
1558 tv.tv_sec = usecs / 1000000L;
1559 tv.tv_usec = usecs % 1000000L;
1560 /* I'm sure someone is going to complain about this... */
1561 select (0, 0, 0, 0, &tv);
1562 }
1563 #else
1564 #ifdef HAVE_POLL
1565 poll (0, 0, 100);
1566 #else
1567 bite me
1568 #endif
1569 #endif
1570
1571 gdk_draw_rectangle (GDK_DRAWABLE (GET_GTK_WIDGET_WINDOW (FRAME_GTK_SHELL_WIDGET (f))),
1572 gc, TRUE, w->pixel_left, w->pixel_top,
1573 w->pixel_width, w->pixel_height);
1574
1575 gdk_flush ();
1576
1577 return 1;
1578 }
1579
1580 static void 78 static void
1581 gtk_bevel_area (struct window *w, face_index UNUSED (findex), 79 gtk_bevel_area (struct window *w, face_index UNUSED (findex),
1582 int x, int y, int width, int height, 80 int x, int y, int width, int height,
1583 int shadow_thickness, int UNUSED (edges), 81 int shadow_thickness, int UNUSED (edges),
1584 enum edge_style UNUSED (style)) 82 enum edge_style UNUSED (style))
1601 gdk_beep (); 99 gdk_beep ();
1602 } 100 }
1603 } 101 }
1604 102
1605 103
1606 /************************************************************************/
1607 /* initialization */
1608 /************************************************************************/
1609
1610 void
1611 console_type_create_redisplay_gtk (void)
1612 {
1613 /* redisplay methods */
1614 CONSOLE_HAS_METHOD (gtk, text_width);
1615 CONSOLE_HAS_METHOD (gtk, output_display_block);
1616 CONSOLE_HAS_METHOD (gtk, divider_height);
1617 CONSOLE_HAS_METHOD (gtk, eol_cursor_width);
1618 CONSOLE_HAS_METHOD (gtk, output_vertical_divider);
1619 CONSOLE_HAS_METHOD (gtk, clear_to_window_end);
1620 CONSOLE_HAS_METHOD (gtk, clear_region);
1621 CONSOLE_HAS_METHOD (gtk, clear_frame);
1622 CONSOLE_HAS_METHOD (gtk, flash);
1623 CONSOLE_HAS_METHOD (gtk, ring_bell);
1624 CONSOLE_HAS_METHOD (gtk, bevel_area);
1625 CONSOLE_HAS_METHOD (gtk, output_string);
1626 CONSOLE_HAS_METHOD (gtk, output_pixmap);
1627 }
1628
1629 /* This makes me feel incredibly dirty... but there is no other way to 104 /* This makes me feel incredibly dirty... but there is no other way to
1630 get this done right other than calling clear_area before every 105 get this done right other than calling clear_area before every
1631 single $#!%@ing piece of text, which I do NOT want to do. */ 106 single $#!%@ing piece of text, which I do NOT want to do. */
1632 #define USE_X_SPECIFIC_DRAW_ROUTINES 1 107 #define USE_X_SPECIFIC_DRAW_ROUTINES 1
1633 108