update.
[chise/xemacs-chise.git-] / src / redisplay-gtk.c
1 /* X output and frame manipulation routines.
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
6 This file is part of XEmacs.
7
8 XEmacs is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2, or (at your option) any
11 later version.
12
13 XEmacs is distributed in the hope that it will be useful, but WITHOUT
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16 for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with XEmacs; see the file COPYING.  If not, write to
20 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA.  */
22
23 /* Synched up with:  Not in FSF. */
24
25 /* Author: Chuck Thompson */
26 /* Gtk flavor by William Perry */
27
28 /* Lots of work done by Ben Wing for Mule */
29
30 #include <config.h>
31 #include "lisp.h"
32
33 #include "console-gtk.h"
34 #include "gccache-gtk.h"
35 #include "glyphs-gtk.h"
36 #include "objects-gtk.h"
37
38 #include "buffer.h"
39 #include "debug.h"
40 #include "faces.h"
41 #include "frame.h"
42 #include "gutter.h"
43 #include "redisplay.h"
44 #include "sysdep.h"
45 #include "window.h"
46
47 #include "sysproc.h" /* for select() */
48
49 #ifdef MULE
50 #include "mule-ccl.h"
51 #include "file-coding.h" /* for CCL conversion */
52 #endif
53
54 #ifdef HAVE_POLL
55 #include <sys/poll.h>
56 #endif
57
58 #define CONST const
59
60 #define EOL_CURSOR_WIDTH        5
61
62 static void gtk_output_pixmap (struct window *w, struct display_line *dl,
63                                Lisp_Object image_instance, int xpos,
64                                int xoffset,
65                                int start_pixpos, int width, face_index findex,
66                                int cursor_start, int cursor_width,
67                                int cursor_height);
68 static void gtk_output_vertical_divider (struct window *w, int clear);
69 static void gtk_output_blank (struct window *w, struct display_line *dl,
70                               struct rune *rb, int start_pixpos,
71                               int cursor_start, int cursor_width);
72 static void gtk_output_hline (struct window *w, struct display_line *dl,
73                               struct rune *rb);
74 static void gtk_redraw_exposed_window (struct window *w, int x, int y,
75                                        int width, int height);
76 static void gtk_redraw_exposed_windows (Lisp_Object window, int x, int y,
77                                         int width, int height);
78 static void gtk_clear_region (Lisp_Object locale, struct device* d, struct frame* f,
79                               face_index findex, int x, int y,
80                               int width, int height, Lisp_Object fcolor, Lisp_Object bcolor,
81                               Lisp_Object background_pixmap);
82 static void gtk_output_eol_cursor (struct window *w, struct display_line *dl,
83                                    int xpos, face_index findex);
84 static void gtk_clear_frame (struct frame *f);
85 static void gtk_clear_frame_windows (Lisp_Object window);
86 static void gtk_bevel_modeline (struct window *w, struct display_line *dl);
87
88 #if 0
89 static void __describe_gc (GdkGC *);
90 #endif
91
92 struct textual_run
93 {
94   Lisp_Object charset;
95   unsigned char *ptr;
96   int len;
97   int dimension;
98 };
99
100 /* Separate out the text in DYN into a series of textual runs of a
101    particular charset.  Also convert the characters as necessary into
102    the format needed by XDrawImageString(), XDrawImageString16(), et
103    al.  (This means converting to one or two byte format, possibly
104    tweaking the high bits, and possibly running a CCL program.) You
105    must pre-allocate the space used and pass it in. (This is done so
106    you can alloca() the space.)  You need to allocate (2 * len) bytes
107    of TEXT_STORAGE and (len * sizeof (struct textual_run)) bytes of
108    RUN_STORAGE, where LEN is the length of the dynarr.
109
110    Returns the number of runs actually used. */
111
112 static int
113 separate_textual_runs (unsigned char *text_storage,
114                        struct textual_run *run_storage,
115                        CONST Emchar *str, Charcount len)
116 {
117   Lisp_Object prev_charset = Qunbound; /* not Qnil because that is a
118                                           possible valid charset when
119                                           MULE is not defined */
120   int runs_so_far = 0;
121   int i;
122 #ifdef MULE
123   struct ccl_program char_converter;
124   int need_ccl_conversion = 0;
125 #endif
126
127   for (i = 0; i < len; i++)
128     {
129       Emchar ch = str[i];
130       Lisp_Object charset;
131       int byte1, byte2;
132       int dimension;
133       int graphic;
134
135       BREAKUP_CHAR (ch, charset, byte1, byte2);
136       dimension = XCHARSET_DIMENSION (charset);
137       graphic   = XCHARSET_GRAPHIC   (charset);
138
139       if (!EQ (charset, prev_charset))
140         {
141           run_storage[runs_so_far].ptr       = text_storage;
142           run_storage[runs_so_far].charset   = charset;
143           run_storage[runs_so_far].dimension = dimension;
144
145           if (runs_so_far)
146             {
147               run_storage[runs_so_far - 1].len =
148                 text_storage - run_storage[runs_so_far - 1].ptr;
149               if (run_storage[runs_so_far - 1].dimension == 2)
150                 run_storage[runs_so_far - 1].len >>= 1;
151             }
152           runs_so_far++;
153           prev_charset = charset;
154 #ifdef MULE
155           {
156             Lisp_Object ccl_prog = XCHARSET_CCL_PROGRAM (charset);
157             need_ccl_conversion = !NILP (ccl_prog);
158             if (need_ccl_conversion)
159               setup_ccl_program (&char_converter, ccl_prog);
160           }
161 #endif
162         }
163
164       if (graphic == 0)
165         {
166           byte1 &= 0x7F;
167           byte2 &= 0x7F;
168         }
169       else if (graphic == 1)
170         {
171           byte1 |= 0x80;
172           byte2 |= 0x80;
173         }
174 #ifdef MULE
175       if (need_ccl_conversion)
176         {
177           char_converter.reg[0] = XCHARSET_ID (charset);
178           char_converter.reg[1] = byte1;
179           char_converter.reg[2] = byte2;
180           ccl_driver (&char_converter, 0, 0, 0, 0, CCL_MODE_ENCODING);
181           byte1 = char_converter.reg[1];
182           byte2 = char_converter.reg[2];
183         }
184 #endif
185       *text_storage++ = (unsigned char) byte1;
186       if (dimension == 2)
187         *text_storage++ = (unsigned char) byte2;
188     }
189
190   if (runs_so_far)
191     {
192       run_storage[runs_so_far - 1].len =
193         text_storage - run_storage[runs_so_far - 1].ptr;
194       if (run_storage[runs_so_far - 1].dimension == 2)
195         run_storage[runs_so_far - 1].len >>= 1;
196     }
197
198   return runs_so_far;
199 }
200
201 /****************************************************************************/
202 /*                                                                          */
203 /*                          Gtk output routines                             */
204 /*                                                                          */
205 /****************************************************************************/
206
207 static int
208 gtk_text_width_single_run (struct face_cachel *cachel, struct textual_run *run)
209 {
210   Lisp_Object font_inst = FACE_CACHEL_FONT (cachel, run->charset);
211   struct Lisp_Font_Instance *fi = XFONT_INSTANCE (font_inst);
212
213   if (!fi->proportional_p)
214   {
215     return fi->width * run->len;
216   }
217   else
218     {
219       if (run->dimension == 2)
220         {
221           stderr_out ("Measuring wide characters\n");
222           return gdk_text_width_wc (FONT_INSTANCE_GTK_FONT (fi),
223                                     (GdkWChar *) run->ptr, run->len);
224         }
225       else
226         {
227           return gdk_text_width (FONT_INSTANCE_GTK_FONT (fi),
228                                  (char *) run->ptr, run->len);
229         }
230     }
231 }
232
233 /*
234    gtk_text_width
235
236    Given a string and a face, return the string's length in pixels when
237    displayed in the font associated with the face.
238    */
239
240 static int
241 gtk_text_width (struct frame *f, struct face_cachel *cachel, CONST Emchar *str,
242                 Charcount len)
243 {
244   int width_so_far = 0;
245   unsigned char *text_storage = (unsigned char *) alloca (2 * len);
246   struct textual_run *runs = alloca_array (struct textual_run, len);
247   int nruns;
248   int i;
249
250   nruns = separate_textual_runs (text_storage, runs, str, len);
251
252   for (i = 0; i < nruns; i++)
253     width_so_far += gtk_text_width_single_run (cachel, runs + i);
254
255   return width_so_far;
256 }
257
258 /*****************************************************************************
259  gtk_divider_height
260
261  Return the height of the horizontal divider.  This is a function because
262  divider_height is a device method.
263
264  #### If we add etched horizontal divider lines this will have to get
265  smarter.
266  ****************************************************************************/
267 static int
268 gtk_divider_height (void)
269 {
270   return 2;
271 }
272
273 /*****************************************************************************
274  gtk_eol_cursor_width
275
276  Return the width of the end-of-line cursor.  This is a function
277  because eol_cursor_width is a device method.
278  ****************************************************************************/
279 static int
280 gtk_eol_cursor_width (void)
281 {
282   return EOL_CURSOR_WIDTH;
283 }
284
285 /*****************************************************************************
286  gtk_output_display_block
287
288  Given a display line, a block number for that start line, output all
289  runes between start and end in the specified display block.
290  ****************************************************************************/
291 static void
292 gtk_output_display_block (struct window *w, struct display_line *dl, int block,
293                           int start, int end, int start_pixpos, int cursor_start,
294                           int cursor_width, int cursor_height)
295 {
296   struct frame *f = XFRAME (w->frame);
297   Emchar_dynarr *buf = Dynarr_new (Emchar);
298   Lisp_Object window;
299
300   struct display_block *db = Dynarr_atp (dl->display_blocks, block);
301   rune_dynarr *rba = db->runes;
302   struct rune *rb;
303
304   int elt = start;
305   face_index findex;
306   int xpos, width;
307   Lisp_Object charset = Qunbound; /* Qnil is a valid charset when
308                                      MULE is not defined */
309
310   XSETWINDOW (window, w);
311   rb = Dynarr_atp (rba, start);
312
313   if (!rb)
314     {
315       /* Nothing to do so don't do anything. */
316       return;
317     }
318   else
319     {
320       findex = rb->findex;
321       xpos = rb->xpos;
322       width = 0;
323       if (rb->type == RUNE_CHAR)
324         charset = CHAR_CHARSET (rb->object.chr.ch);
325     }
326
327   if (end < 0)
328     end = Dynarr_length (rba);
329   Dynarr_reset (buf);
330
331   while (elt < end)
332     {
333       rb = Dynarr_atp (rba, elt);
334
335       if (rb->findex == findex && rb->type == RUNE_CHAR
336           && rb->object.chr.ch != '\n' && rb->cursor_type != CURSOR_ON
337           && EQ (charset, CHAR_CHARSET (rb->object.chr.ch)))
338         {
339           Dynarr_add (buf, rb->object.chr.ch);
340           width += rb->width;
341           elt++;
342         }
343       else
344         {
345           if (Dynarr_length (buf))
346             {
347               gtk_output_string (w, dl, buf, xpos, 0, start_pixpos, width,
348                                  findex, 0, cursor_start, cursor_width,
349                                  cursor_height);
350               xpos = rb->xpos;
351               width = 0;
352             }
353           Dynarr_reset (buf);
354           width = 0;
355
356           if (rb->type == RUNE_CHAR)
357             {
358               findex = rb->findex;
359               xpos = rb->xpos;
360               charset = CHAR_CHARSET (rb->object.chr.ch);
361
362               if (rb->cursor_type == CURSOR_ON)
363                 {
364                   if (rb->object.chr.ch == '\n')
365                     {
366                       gtk_output_eol_cursor (w, dl, xpos, findex);
367                     }
368                   else
369                     {
370                       Dynarr_add (buf, rb->object.chr.ch);
371                       gtk_output_string (w, dl, buf, xpos, 0, start_pixpos,
372                                          rb->width, findex, 1,
373                                          cursor_start, cursor_width,
374                                          cursor_height);
375                       Dynarr_reset (buf);
376                     }
377
378                   xpos += rb->width;
379                   elt++;
380                 }
381               else if (rb->object.chr.ch == '\n')
382                 {
383                   /* Clear in case a cursor was formerly here. */
384                   int height = dl->ascent + dl->descent - dl->clip;
385
386                   redisplay_clear_region (window, findex, xpos, dl->ypos - dl->ascent,
387                                           rb->width, height);
388                   elt++;
389                 }
390             }
391           else if (rb->type == RUNE_BLANK || rb->type == RUNE_HLINE)
392             {
393               if (rb->type == RUNE_BLANK)
394                 gtk_output_blank (w, dl, rb, start_pixpos, cursor_start,
395                                   cursor_width);
396               else
397                 {
398                   /* #### Our flagging of when we need to redraw the
399                      modeline shadows sucks.  Since RUNE_HLINE is only used
400                      by the modeline at the moment it is a good bet
401                      that if it gets redrawn then we should also
402                      redraw the shadows.  This won't be true forever.
403                      We borrow the shadow_thickness_changed flag for
404                      now. */
405                   w->shadow_thickness_changed = 1;
406                   gtk_output_hline (w, dl, rb);
407                 }
408
409               elt++;
410               if (elt < end)
411                 {
412                   rb = Dynarr_atp (rba, elt);
413
414                   findex = rb->findex;
415                   xpos = rb->xpos;
416                 }
417             }
418           else if (rb->type == RUNE_DGLYPH)
419             {
420               Lisp_Object instance;
421               struct display_box dbox;
422               struct display_glyph_area dga;
423               redisplay_calculate_display_boxes (dl, rb->xpos, rb->object.dglyph.xoffset,
424                                                  rb->object.dglyph.yoffset ,start_pixpos,
425                                                  rb->width, &dbox, &dga);
426
427               XSETWINDOW (window, w);
428               instance = glyph_image_instance (rb->object.dglyph.glyph,
429                                                window, ERROR_ME_NOT, 1);
430               findex = rb->findex;
431
432               if (IMAGE_INSTANCEP (instance))
433                 switch (XIMAGE_INSTANCE_TYPE (instance))
434                   {
435                   case IMAGE_TEXT:
436                     {
437                       /* #### This is way losing.  See the comment in
438                          add_glyph_rune(). */
439                       Lisp_Object string =
440                         XIMAGE_INSTANCE_TEXT_STRING (instance);
441                       convert_bufbyte_string_into_emchar_dynarr
442                         (XSTRING_DATA (string), XSTRING_LENGTH (string), buf);
443
444                       gtk_output_string (w, dl, buf, xpos,
445                                          rb->object.dglyph.xoffset,
446                                          start_pixpos, -1, findex,
447                                          (rb->cursor_type == CURSOR_ON),
448                                          cursor_start, cursor_width,
449                                          cursor_height);
450                       Dynarr_reset (buf);
451                     }
452                     break;
453
454                   case IMAGE_MONO_PIXMAP:
455                   case IMAGE_COLOR_PIXMAP:
456                     gtk_output_pixmap (w, dl, instance, xpos,
457                                        rb->object.dglyph.xoffset, start_pixpos,
458                                        rb->width, findex, cursor_start,
459                                        cursor_width, cursor_height);
460                     break;
461
462                   case IMAGE_POINTER:
463                     abort ();
464
465                   case IMAGE_WIDGET:
466                       if (EQ (XIMAGE_INSTANCE_WIDGET_TYPE (instance),
467                               Qlayout))
468                         {
469                           redisplay_output_layout (window, instance, &dbox,
470                                                    &dga, findex,
471                                                    cursor_start, cursor_width,
472                                                    cursor_height);
473                           break;
474                         }
475
476                   case IMAGE_SUBWINDOW:
477                     redisplay_output_subwindow (w, instance, &dbox, &dga,
478                                                 findex, cursor_start,
479                                                 cursor_width, cursor_height);
480                     break;
481
482                   case IMAGE_NOTHING:
483                     /* nothing is as nothing does */
484                     break;
485
486                   default:
487                     abort ();
488                   }
489
490               xpos += rb->width;
491               elt++;
492             }
493           else
494             abort ();
495         }
496     }
497
498   if (Dynarr_length (buf))
499     gtk_output_string (w, dl, buf, xpos, 0, start_pixpos, width, findex,
500                        0, cursor_start, cursor_width, cursor_height);
501
502   /* #### This is really conditionalized well for optimized
503      performance. */
504   if (dl->modeline
505       && !EQ (Qzero, w->modeline_shadow_thickness)
506       && (f->clear
507           || f->windows_structure_changed
508           || w->shadow_thickness_changed))
509     gtk_bevel_modeline (w, dl);
510
511   Dynarr_free (buf);
512 }
513
514 /*****************************************************************************
515  gtk_bevel_modeline
516
517  Draw a 3d border around the modeline on window W.
518  ****************************************************************************/
519 static void
520 gtk_bevel_modeline (struct window *w, struct display_line *dl)
521 {
522   struct frame *f = XFRAME (w->frame);
523   int shadow_thickness = MODELINE_SHADOW_THICKNESS (w);
524   int x,y, width, height;
525
526   x = WINDOW_MODELINE_LEFT (w);
527   width = WINDOW_MODELINE_RIGHT (w) - x;
528   y = dl->ypos - dl->ascent - shadow_thickness;
529   height = dl->ascent + dl->descent + 2 * shadow_thickness;
530
531   gtk_output_shadows (f, x, y, width, height, shadow_thickness);
532 }
533
534 /*****************************************************************************
535  gtk_get_gc
536
537  Given a number of parameters return a GC with those properties.
538  ****************************************************************************/
539 GdkGC *
540 gtk_get_gc (struct device *d, Lisp_Object font, Lisp_Object fg, Lisp_Object bg,
541             Lisp_Object bg_pmap, Lisp_Object lwidth)
542 {
543   GdkGCValues gcv;
544   unsigned long mask;
545
546   memset (&gcv, ~0, sizeof (gcv));
547   gcv.graphics_exposures = FALSE;
548   /* Make absolutely sure that we don't pick up a clipping region in
549      the GC returned by this function. */
550   gcv.clip_mask = 0;
551   gcv.clip_x_origin = 0;
552   gcv.clip_y_origin = 0;
553   gcv.fill = GDK_SOLID;
554   mask = GDK_GC_EXPOSURES | GDK_GC_CLIP_MASK | GDK_GC_CLIP_X_ORIGIN | GDK_GC_CLIP_Y_ORIGIN;
555   mask |= GDK_GC_FILL;
556
557   if (!NILP (font))
558     {
559       gcv.font = FONT_INSTANCE_GTK_FONT (XFONT_INSTANCE (font));
560       mask |= GDK_GC_FONT;
561     }
562
563   /* evil kludge! */
564   if (!NILP (fg) && !COLOR_INSTANCEP (fg) && !INTP (fg))
565     {
566       /* #### I fixed once case where this was getting it.  It was a
567          bad macro expansion (compiler bug). */
568       fprintf (stderr, "Help! gtk_get_gc got a bogus fg value! fg = ");
569       debug_print (fg);
570       fg = Qnil;
571     }
572
573   if (!NILP (fg))
574     {
575       if (COLOR_INSTANCEP (fg))
576         gcv.foreground = * COLOR_INSTANCE_GTK_COLOR (XCOLOR_INSTANCE (fg));
577       else
578         gcv.foreground.pixel = XINT (fg);
579       mask |= GDK_GC_FOREGROUND;
580     }
581
582   if (!NILP (bg))
583     {
584       if (COLOR_INSTANCEP (bg))
585         gcv.background = * COLOR_INSTANCE_GTK_COLOR (XCOLOR_INSTANCE (bg));
586       else
587         gcv.background.pixel = XINT (fg);
588       mask |= GDK_GC_BACKGROUND;
589     }
590
591   if (IMAGE_INSTANCEP (bg_pmap)
592       && IMAGE_INSTANCE_PIXMAP_TYPE_P (XIMAGE_INSTANCE (bg_pmap)))
593     {
594       if (XIMAGE_INSTANCE_PIXMAP_DEPTH (bg_pmap) == 0)
595         {
596           gcv.fill = GDK_OPAQUE_STIPPLED;
597           gcv.stipple = XIMAGE_INSTANCE_GTK_PIXMAP (bg_pmap);
598           mask |= (GDK_GC_STIPPLE | GDK_GC_FILL);
599         }
600       else
601         {
602           gcv.fill = GDK_TILED;
603           gcv.tile = XIMAGE_INSTANCE_GTK_PIXMAP (bg_pmap);
604           mask |= (GDK_GC_TILE | GDK_GC_FILL);
605         }
606     }
607
608   if (!NILP (lwidth))
609     {
610       gcv.line_width = XINT (lwidth);
611       mask |= GDK_GC_LINE_WIDTH;
612     }
613
614   return gc_cache_lookup (DEVICE_GTK_GC_CACHE (d), &gcv, mask);
615 }
616
617 /*****************************************************************************
618  gtk_output_string
619
620  Given a string and a starting position, output that string in the
621  given face.  If cursor is true, draw a cursor around the string.
622  Correctly handles multiple charsets in the string.
623
624  The meaning of the parameters is something like this:
625
626  W              Window that the text is to be displayed in.
627  DL             Display line that this text is on.  The values in the
628                 structure are used to determine the vertical position and
629                 clipping range of the text.
630  BUF            Dynamic array of Emchars specifying what is actually to be
631                 drawn.
632  XPOS           X position in pixels where the text should start being drawn.
633  XOFFSET        Number of pixels to be chopped off the left side of the
634                 text.  The effect is as if the text were shifted to the
635                 left this many pixels and clipped at XPOS.
636  CLIP_START     Clip everything left of this X position.
637  WIDTH          Clip everything right of XPOS + WIDTH.
638  FINDEX         Index for the face cache element describing how to display
639                 the text.
640  CURSOR         #### I don't understand this.  There's something
641                 strange and overcomplexified with this variable.
642                 Chuck, explain please?
643  CURSOR_START   Starting X position of cursor.
644  CURSOR_WIDTH   Width of cursor in pixels.
645  CURSOR_HEIGHT  Height of cursor in pixels.
646
647  Starting Y position of cursor is the top of the text line.
648  The cursor is drawn sometimes whether or not CURSOR is set. ???
649  ****************************************************************************/
650 void
651 gdk_draw_text_image (GdkDrawable *drawable,
652                      GdkFont     *font,
653                      GdkGC       *gc,
654                      gint         x,
655                      gint         y,
656                      const gchar *text,
657                      gint         text_length);
658
659 void
660 gtk_output_string (struct window *w, struct display_line *dl,
661                    Emchar_dynarr *buf, int xpos, int xoffset, int clip_start,
662                    int width, face_index findex, int cursor,
663                    int cursor_start, int cursor_width, int cursor_height)
664 {
665   /* General variables */
666   struct frame *f = XFRAME (w->frame);
667   struct device *d = XDEVICE (f->device);
668   Lisp_Object device;
669   Lisp_Object window;
670   GdkWindow *x_win = GET_GTK_WIDGET_WINDOW (FRAME_GTK_TEXT_WIDGET (f));
671
672   int clip_end;
673
674   /* Cursor-related variables */
675   int focus = EQ (w->frame, DEVICE_FRAME_WITH_FOCUS_REAL (d));
676   int cursor_clip;
677   Lisp_Object bar_cursor_value = symbol_value_in_buffer (Qbar_cursor,
678                                                          WINDOW_BUFFER (w));
679   struct face_cachel *cursor_cachel = 0;
680
681   /* Text-related variables */
682   Lisp_Object bg_pmap;
683   GdkGC *bgc, *gc;
684   int height;
685   int len = Dynarr_length (buf);
686   unsigned char *text_storage = (unsigned char *) alloca (2 * len);
687   struct textual_run *runs = alloca_array (struct textual_run, len);
688   int nruns;
689   int i;
690   struct face_cachel *cachel = WINDOW_FACE_CACHEL (w, findex);
691
692   XSETDEVICE (device, d);
693   XSETWINDOW (window, w);
694
695   if (width < 0)
696     width = gtk_text_width (f, cachel, Dynarr_atp (buf, 0), Dynarr_length (buf));
697   height = dl->ascent + dl->descent - dl->clip;
698
699   /* Regularize the variables passed in. */
700
701   if (clip_start < xpos)
702     clip_start = xpos;
703   clip_end = xpos + width;
704   if (clip_start >= clip_end)
705     /* It's all clipped out. */
706     return;
707
708   xpos -= xoffset;
709
710   nruns = separate_textual_runs (text_storage, runs, Dynarr_atp (buf, 0),
711                                  Dynarr_length (buf));
712
713   cursor_clip = (cursor_start >= clip_start &&
714                  cursor_start < clip_end);
715
716   /* This cursor code is really a mess. */
717   if (!NILP (w->text_cursor_visible_p)
718       && (cursor
719           || cursor_clip
720           || (cursor_width
721               && (cursor_start + cursor_width >= clip_start)
722               && !NILP (bar_cursor_value))))
723     {
724       /* These have to be in separate statements in order to avoid a
725          compiler bug. */
726       face_index sucks = get_builtin_face_cache_index (w, Vtext_cursor_face);
727       cursor_cachel = WINDOW_FACE_CACHEL (w, sucks);
728
729       /* We have to reset this since any call to WINDOW_FACE_CACHEL
730          may cause the cache to resize and any pointers to it to
731          become invalid. */
732       cachel = WINDOW_FACE_CACHEL (w, findex);
733     }
734
735   bg_pmap = cachel->background_pixmap;
736   if (!IMAGE_INSTANCEP (bg_pmap)
737       || !IMAGE_INSTANCE_PIXMAP_TYPE_P (XIMAGE_INSTANCE (bg_pmap)))
738     bg_pmap = Qnil;
739
740   if ((cursor && focus && NILP (bar_cursor_value)
741        && !NILP (w->text_cursor_visible_p)) || NILP (bg_pmap))
742     bgc = 0;
743   else
744     bgc = gtk_get_gc (d, Qnil, cachel->foreground, cachel->background,
745                       bg_pmap, Qnil);
746
747   if (bgc)
748     gdk_draw_rectangle (GDK_DRAWABLE (x_win), bgc, TRUE, clip_start,
749                         dl->ypos - dl->ascent, clip_end - clip_start,
750                         height);
751
752   for (i = 0; i < nruns; i++)
753     {
754       Lisp_Object font = FACE_CACHEL_FONT (cachel, runs[i].charset);
755       struct Lisp_Font_Instance *fi = XFONT_INSTANCE (font);
756       GdkFont *gdk_font = FONT_INSTANCE_GTK_FONT (fi);
757       int this_width;
758       int need_clipping;
759
760       if (EQ (font, Vthe_null_font_instance))
761         continue;
762
763       this_width = gtk_text_width_single_run (cachel, runs + i);
764       need_clipping = (dl->clip || clip_start > xpos ||
765                        clip_end < xpos + this_width);
766
767       /* XDrawImageString only clears the area equal to the height of
768          the given font.  It is possible that a font is being displayed
769          on a line taller than it is, so this would cause us to fail to
770          clear some areas. */
771       if ((int) fi->height < (int) (height + dl->clip))
772         {
773           int clear_start = max (xpos, clip_start);
774           int clear_end = min (xpos + this_width, clip_end);
775
776           if (cursor)
777             {
778               int ypos1_line, ypos1_string, ypos2_line, ypos2_string;
779
780               ypos1_string = dl->ypos - fi->ascent;
781               ypos2_string = dl->ypos + fi->descent;
782               ypos1_line = dl->ypos - dl->ascent;
783               ypos2_line = dl->ypos + dl->descent - dl->clip;
784
785               /* Make sure we don't clear below the real bottom of the
786                  line. */
787               if (ypos1_string > ypos2_line)
788                 ypos1_string = ypos2_line;
789               if (ypos2_string > ypos2_line)
790                 ypos2_string = ypos2_line;
791
792               if (ypos1_line < ypos1_string)
793                 {
794                   redisplay_clear_region (window, findex, clear_start, ypos1_line,
795                                     clear_end - clear_start,
796                                     ypos1_string - ypos1_line);
797                 }
798
799               if (ypos2_line > ypos2_string)
800                 {
801                   redisplay_clear_region (window, findex, clear_start, ypos2_string,
802                                           clear_end - clear_start,
803                                           ypos2_line - ypos2_string);
804                 }
805             }
806           else
807             {
808               redisplay_clear_region (window, findex, clear_start,
809                                       dl->ypos - dl->ascent, clear_end - clear_start,
810                                       height);
811             }
812         }
813
814       if (cursor && cursor_cachel && focus && NILP (bar_cursor_value))
815       {
816         gc = gtk_get_gc (d, font, cursor_cachel->foreground,
817                          cursor_cachel->background, Qnil, Qnil);
818       }
819       else
820       {
821         gc = gtk_get_gc (d, font, cachel->foreground, cachel->background,
822                          Qnil, Qnil);
823       }
824
825       if (need_clipping)
826         {
827           GdkRectangle clip_box;
828
829           clip_box.x = 0;
830           clip_box.y = 0;
831           clip_box.width = clip_end - clip_start;
832           clip_box.height = height;
833
834           gdk_gc_set_clip_rectangle (gc, &clip_box);
835           gdk_gc_set_clip_origin (gc, clip_start, dl->ypos - dl->ascent);
836         }
837
838       /* The X specific called different functions (XDraw*String
839          vs. XDraw*String16), but apparently gdk_draw_text takes care
840          of that for us.
841
842          BUT, gdk_draw_text also does too much, by dividing the length
843          by 2.  So we fake them out my multiplying the length by the
844          dimension of the text.  This will do the right thing for
845          single-dimension runs as well of course.
846       */
847       (bgc ? gdk_draw_text : gdk_draw_text_image) (GDK_DRAWABLE (x_win), gdk_font, gc, xpos,
848                                                    dl->ypos, (char *) runs[i].ptr,
849                                                    runs[i].len * runs[i].dimension);
850
851       /* We draw underlines in the same color as the text. */
852       if (cachel->underline)
853         {
854           unsigned long upos, uthick;
855
856           /* Cannot get at font properties in Gtk, so we resort to
857              guessing */
858           upos = dl->descent / 2;
859           uthick = 1;
860
861           if (dl->ypos + upos < dl->ypos + dl->descent - dl->clip)
862             {
863               if (dl->ypos + upos + uthick > dl->ypos + dl->descent - dl->clip)
864                 uthick = dl->descent - dl->clip - upos;
865
866               if (uthick == 1)
867                 {
868                   gdk_draw_line (GDK_DRAWABLE (x_win), gc, xpos, dl->ypos + upos,
869                              xpos + this_width, dl->ypos + upos);
870                 }
871               else if (uthick > 1)
872                 {
873                     gdk_draw_rectangle (GDK_DRAWABLE (x_win), gc, TRUE, xpos,
874                                         dl->ypos + upos, this_width, uthick);
875                 }
876             }
877         }
878
879       if (cachel->strikethru) {
880         unsigned long ascent,descent,upos, uthick;
881         GdkFont *gfont = FONT_INSTANCE_GTK_FONT (XFONT_INSTANCE (font));
882
883         /* Cannot get at font properties in Gtk, so we resort to
884            guessing */
885
886         ascent = gfont->ascent;
887         descent = gfont->descent;
888         uthick = 1;
889
890         upos = ascent - ((ascent + descent) / 2) + 1;
891
892         /* Generally, upos will be positive (above the baseline),so subtract */
893         if (dl->ypos - upos < dl->ypos + dl->descent - dl->clip)
894           {
895             if (dl->ypos - upos + uthick > dl->ypos + dl->descent - dl->clip)
896               uthick = dl->descent - dl->clip + upos;
897
898             if (uthick == 1)
899               {
900                   gdk_draw_line (GDK_DRAWABLE (x_win), gc, xpos, dl->ypos - upos,
901                                  xpos + this_width, dl->ypos - upos);
902               }
903             else if (uthick > 1)
904               {
905                   gdk_draw_rectangle (GDK_DRAWABLE (x_win), gc, TRUE, xpos, dl->ypos + upos,
906                                       this_width, uthick);
907               }
908           }
909       }
910
911       /* Restore the GC */
912       if (need_clipping)
913         {
914             gdk_gc_set_clip_rectangle (gc, NULL);
915             gdk_gc_set_clip_origin (gc, 0, 0);
916         }
917
918       /* If we are actually superimposing the cursor then redraw with just
919          the appropriate section highlighted. */
920       if (cursor_clip && !cursor && focus && cursor_cachel)
921         {
922           GdkGC *cgc;
923           GdkRectangle clip_box;
924
925           cgc = gtk_get_gc (d, font, cursor_cachel->foreground,
926                             cursor_cachel->background, Qnil, Qnil);
927
928           clip_box.x = 0;
929           clip_box.y = 0;
930           clip_box.width = cursor_width;
931           clip_box.height = height;
932
933           gdk_gc_set_clip_rectangle (cgc, &clip_box);
934           gdk_gc_set_clip_origin (cgc, cursor_start, dl->ypos - dl->ascent);
935
936           /* The X specific called different functions (XDraw*String
937              vs. XDraw*String16), but apparently gdk_draw_text takes care
938              of that for us.
939
940              BUT, gdk_draw_text also does too much, by dividing the
941              length by 2.  So we fake them out my multiplying the
942              length by the dimension of the text.  This will do the
943              right thing for single-dimension runs as well of course.
944           */
945           gdk_draw_text_image (GDK_DRAWABLE (x_win), gdk_font, cgc, xpos,
946                                dl->ypos, (char *) runs[i].ptr,
947                                runs[i].len * runs[i].dimension);
948
949           gdk_gc_set_clip_rectangle (cgc, NULL);
950           gdk_gc_set_clip_origin (cgc, 0, 0);
951         }
952
953       xpos += this_width;
954     }
955
956   /* Draw the non-focus box or bar-cursor as needed. */
957   /* Can't this logic be simplified? */
958   if (cursor_cachel
959       && ((cursor && !focus && NILP (bar_cursor_value))
960           || (cursor_width
961               && (cursor_start + cursor_width >= clip_start)
962               && !NILP (bar_cursor_value))))
963     {
964       int tmp_height, tmp_y;
965       int bar_width = EQ (bar_cursor_value, Qt) ? 1 : 2;
966       int need_clipping = (cursor_start < clip_start
967                            || clip_end < cursor_start + cursor_width);
968
969       /* #### This value is correct (as far as I know) because
970          all of the times we need to draw this cursor, we will
971          be called with exactly one character, so we know we
972          can always use runs[0].
973
974          This is bogus as all hell, however.  The cursor handling in
975          this function is way bogus and desperately needs to be
976          cleaned up. (In particular, the drawing of the cursor should
977          really really be separated out of this function.  This may be
978          a bit tricky now because this function itself does way too
979          much stuff, a lot of which needs to be moved into
980          redisplay.c) This is the only way to be able to easily add
981          new cursor types or (e.g.) make the bar cursor be able to
982          span two characters instead of overlaying just one. */
983       int bogusly_obtained_ascent_value =
984         XFONT_INSTANCE (FACE_CACHEL_FONT (cachel, runs[0].charset))->ascent;
985
986       if (!NILP (bar_cursor_value))
987         {
988           gc = gtk_get_gc (d, Qnil, cursor_cachel->background, Qnil, Qnil,
989                            make_int (bar_width));
990         }
991       else
992         {
993           gc = gtk_get_gc (d, Qnil, cursor_cachel->background,
994                            Qnil, Qnil, Qnil);
995         }
996
997       tmp_y = dl->ypos - bogusly_obtained_ascent_value;
998       tmp_height = cursor_height;
999       if (tmp_y + tmp_height > (int) (dl->ypos - dl->ascent + height))
1000         {
1001           tmp_y = dl->ypos - dl->ascent + height - tmp_height;
1002           if (tmp_y < (int) (dl->ypos - dl->ascent))
1003             tmp_y = dl->ypos - dl->ascent;
1004           tmp_height = dl->ypos - dl->ascent + height - tmp_y;
1005         }
1006
1007       if (need_clipping)
1008         {
1009           GdkRectangle clip_box;
1010           clip_box.x = 0;
1011           clip_box.y = 0;
1012           clip_box.width = clip_end - clip_start;
1013           clip_box.height = tmp_height;
1014
1015           gdk_gc_set_clip_rectangle (gc, &clip_box);
1016           gdk_gc_set_clip_origin (gc, clip_start, tmp_y);
1017         }
1018
1019       if (!focus && NILP (bar_cursor_value))
1020         {
1021             gdk_draw_rectangle (GDK_DRAWABLE (x_win), gc, FALSE,
1022                                 cursor_start, tmp_y,
1023                                 cursor_width - 1, tmp_height - 1);
1024         }
1025       else if (focus && !NILP (bar_cursor_value))
1026         {
1027             gdk_draw_line (GDK_DRAWABLE (x_win), gc,
1028                            cursor_start + bar_width - 1, tmp_y,
1029                            cursor_start + bar_width - 1, tmp_y + tmp_height - 1);
1030         }
1031
1032       /* Restore the GC */
1033       if (need_clipping)
1034         {
1035             gdk_gc_set_clip_rectangle (gc, NULL);
1036             gdk_gc_set_clip_origin (gc, 0, 0);
1037         }
1038     }
1039 }
1040
1041 static void
1042 our_draw_bitmap (GdkDrawable *drawable,
1043                  GdkGC       *gc,
1044                  GdkPixmap   *src,
1045                  gint         xsrc,
1046                  gint         ysrc,
1047                  gint         xdest,
1048                  gint         ydest,
1049                  gint         width,
1050                  gint         height);
1051
1052 void
1053 gtk_output_gdk_pixmap (struct frame *f, struct Lisp_Image_Instance *p, int x,
1054                        int y, int clip_x, int clip_y, int clip_width,
1055                        int clip_height, int width, int height, int pixmap_offset,
1056                        GdkColor *fg, GdkColor *bg, GdkGC *override_gc)
1057 {
1058   struct device *d = XDEVICE (f->device);
1059   GdkWindow *x_win = GET_GTK_WIDGET_WINDOW (FRAME_GTK_TEXT_WIDGET (f));
1060
1061   GdkGC *gc;
1062   GdkGCValues gcv;
1063   unsigned long pixmap_mask;
1064   int need_clipping = (clip_x || clip_y);
1065
1066   if (!override_gc)
1067     {
1068       memset (&gcv, ~0, sizeof (gcv));
1069       gcv.graphics_exposures = FALSE;
1070       gcv.foreground = *fg;
1071       gcv.background = *bg;
1072       pixmap_mask = GDK_GC_FOREGROUND | GDK_GC_BACKGROUND | GDK_GC_EXPOSURES;
1073
1074       if (IMAGE_INSTANCE_GTK_MASK (p))
1075         {
1076           gcv.function = GDK_COPY;
1077           gcv.clip_mask = IMAGE_INSTANCE_GTK_MASK (p);
1078           gcv.clip_x_origin = x;
1079           gcv.clip_y_origin = y - pixmap_offset;
1080           pixmap_mask |= (GDK_GC_FUNCTION | GDK_GC_CLIP_MASK | GDK_GC_CLIP_X_ORIGIN |
1081                           GDK_GC_CLIP_Y_ORIGIN);
1082           /* Can't set a clip rectangle below because we already have a mask.
1083              We could conceivably create a new clipmask by zeroing out
1084              everything outside the clip region.  Is it worth it?
1085              Is it possible to get an equivalent effect by changing the
1086              args to XCopyArea below rather than messing with a clip box?
1087              - dkindred@cs.cmu.edu */
1088           need_clipping = 0;
1089         }
1090
1091       gc = gc_cache_lookup (DEVICE_GTK_GC_CACHE (d), &gcv, pixmap_mask);
1092     }
1093   else
1094     {
1095       gc = override_gc;
1096       /* override_gc might have a mask already--we don't want to nuke it.
1097          Maybe we can insist that override_gc have no mask, or use
1098          one of the suggestions above. */
1099       need_clipping = 0;
1100     }
1101
1102   if (need_clipping)
1103     {
1104       GdkRectangle clip_box;
1105
1106       clip_box.x = clip_x;
1107       clip_box.y = clip_y;
1108       clip_box.width = clip_width;
1109       clip_box.height = clip_height;
1110
1111       gdk_gc_set_clip_rectangle (gc, &clip_box);
1112       gdk_gc_set_clip_origin (gc, x, y);
1113     }
1114
1115   if (IMAGE_INSTANCE_PIXMAP_DEPTH (p) > 0)
1116     {
1117       gdk_draw_pixmap (GDK_DRAWABLE (x_win), gc,
1118                        IMAGE_INSTANCE_GTK_PIXMAP (p),
1119                        0, pixmap_offset, x, y, width, height);
1120     }
1121   else
1122     {
1123       our_draw_bitmap (GDK_DRAWABLE (x_win), gc,
1124                        IMAGE_INSTANCE_GTK_PIXMAP (p),
1125                        0, pixmap_offset, x, y, width, height);
1126     }
1127
1128   if (need_clipping)
1129   {
1130       gdk_gc_set_clip_rectangle (gc, NULL);
1131       gdk_gc_set_clip_origin (gc, 0, 0);
1132   }
1133 }
1134
1135 static void
1136 gtk_output_pixmap (struct window *w, struct display_line *dl,
1137                    Lisp_Object image_instance, int xpos, int xoffset,
1138                    int start_pixpos, int width, face_index findex,
1139                    int cursor_start, int cursor_width, int cursor_height)
1140 {
1141   struct frame *f = XFRAME (w->frame);
1142   struct device *d = XDEVICE (f->device);
1143   struct Lisp_Image_Instance *p = XIMAGE_INSTANCE (image_instance);
1144   Lisp_Object window;
1145
1146   GdkWindow *x_win = GET_GTK_WIDGET_WINDOW (FRAME_GTK_TEXT_WIDGET (f));
1147   int lheight = dl->ascent + dl->descent - dl->clip;
1148   int pheight = ((int) IMAGE_INSTANCE_PIXMAP_HEIGHT (p) > lheight ? lheight :
1149                  IMAGE_INSTANCE_PIXMAP_HEIGHT (p));
1150   int pwidth = min (width + xoffset, (int) IMAGE_INSTANCE_PIXMAP_WIDTH (p));
1151   int clip_x, clip_y, clip_width, clip_height;
1152
1153   /* The pixmap_offset is used to center the pixmap on lines which are
1154      shorter than it is.  This results in odd effects when scrolling
1155      pixmaps off of the bottom.  Let's try not using it. */
1156 #if 0
1157   int pixmap_offset = (int) (IMAGE_INSTANCE_PIXMAP_HEIGHT (p) - lheight) / 2;
1158 #else
1159   int pixmap_offset = 0;
1160 #endif
1161
1162   XSETWINDOW (window, w);
1163
1164   if ((start_pixpos >= 0 && start_pixpos > xpos) || xoffset)
1165     {
1166       if (start_pixpos > xpos && start_pixpos > xpos + width)
1167         return;
1168
1169       clip_x = xoffset;
1170       clip_width = width;
1171       if (start_pixpos > xpos)
1172         {
1173           clip_x += (start_pixpos - xpos);
1174           clip_width -= (start_pixpos - xpos);
1175         }
1176     }
1177   else
1178     {
1179       clip_x = 0;
1180       clip_width = 0;
1181     }
1182
1183   /* Place markers for possible future functionality (clipping the top
1184      half instead of the bottom half; think pixel scrolling). */
1185   clip_y = 0;
1186   clip_height = pheight;
1187
1188   /* Clear the area the pixmap is going into.  The pixmap itself will
1189      always take care of the full width.  We don't want to clear where
1190      it is going to go in order to avoid flicker.  So, all we have to
1191      take care of is any area above or below the pixmap. */
1192   /* #### We take a shortcut for now.  We know that since we have
1193      pixmap_offset hardwired to 0 that the pixmap is against the top
1194      edge so all we have to worry about is below it. */
1195   /* #### Unless the pixmap has a mask in which case we have to clear
1196      the whole damn thing since we can't yet clear just the area not
1197      included in the mask. */
1198   if (((int) (dl->ypos - dl->ascent + pheight) <
1199        (int) (dl->ypos + dl->descent - dl->clip))
1200       || IMAGE_INSTANCE_GTK_MASK (p))
1201     {
1202       int clear_x, clear_y, clear_width, clear_height;
1203
1204       if (IMAGE_INSTANCE_GTK_MASK (p))
1205         {
1206           clear_y = dl->ypos - dl->ascent;
1207           clear_height = lheight;
1208         }
1209       else
1210         {
1211           clear_y = dl->ypos - dl->ascent + pheight;
1212           clear_height = lheight - pheight;
1213         }
1214
1215       if (start_pixpos >= 0 && start_pixpos > xpos)
1216         {
1217           clear_x = start_pixpos;
1218           clear_width = xpos + width - start_pixpos;
1219         }
1220       else
1221         {
1222           clear_x = xpos;
1223           clear_width = width;
1224         }
1225
1226       redisplay_clear_region (window, findex, clear_x, clear_y,
1227                               clear_width, clear_height);
1228     }
1229
1230   /* Output the pixmap. */
1231   {
1232     Lisp_Object tmp_pixel;
1233     GdkColor *tmp_bcolor, *tmp_fcolor;
1234
1235     tmp_pixel = WINDOW_FACE_CACHEL_FOREGROUND (w, findex);
1236     tmp_fcolor = COLOR_INSTANCE_GTK_COLOR (XCOLOR_INSTANCE (tmp_pixel));
1237     tmp_pixel = WINDOW_FACE_CACHEL_BACKGROUND (w, findex);
1238     tmp_bcolor = COLOR_INSTANCE_GTK_COLOR (XCOLOR_INSTANCE (tmp_pixel));
1239
1240     gtk_output_gdk_pixmap (f, p, xpos - xoffset, dl->ypos - dl->ascent, clip_x,
1241                            clip_y, clip_width, clip_height,
1242                            pwidth, pheight, pixmap_offset,
1243                            tmp_fcolor, tmp_bcolor, 0);
1244   }
1245
1246   /* Draw a cursor over top of the pixmap. */
1247   if (cursor_width && cursor_height && (cursor_start >= xpos)
1248       && !NILP (w->text_cursor_visible_p)
1249       && (cursor_start < xpos + pwidth))
1250     {
1251       GdkGC *gc;
1252       int focus = EQ (w->frame, DEVICE_FRAME_WITH_FOCUS_REAL (d));
1253       int y = dl->ypos - dl->ascent;
1254       struct face_cachel *cursor_cachel =
1255         WINDOW_FACE_CACHEL (w,
1256                             get_builtin_face_cache_index
1257                             (w, Vtext_cursor_face));
1258
1259       gc = gtk_get_gc (d, Qnil, cursor_cachel->background, Qnil, Qnil, Qnil);
1260
1261       if (cursor_width > xpos + pwidth - cursor_start)
1262         cursor_width = xpos + pwidth - cursor_start;
1263
1264       gdk_draw_rectangle (GDK_DRAWABLE (x_win), gc, focus ? TRUE : FALSE,
1265                           cursor_start, y, cursor_width,
1266                           cursor_height);
1267     }
1268 }
1269
1270 /*****************************************************************************
1271  gtk_output_vertical_divider
1272
1273  Draw a vertical divider down the right side of the given window.
1274  ****************************************************************************/
1275 static void
1276 gtk_output_vertical_divider (struct window *w, int clear)
1277 {
1278   struct frame *f = XFRAME (w->frame);
1279   struct device *d = XDEVICE (f->device);
1280   GdkWindow *x_win = GET_GTK_WIDGET_WINDOW (FRAME_GTK_TEXT_WIDGET (f));
1281   GdkGC *background_gc;
1282   Lisp_Object tmp_pixel;
1283   GdkGCValues gcv;
1284   unsigned long mask;
1285   int x, y1, y2, width, shadow_thickness, spacing, line_width;
1286   face_index div_face = get_builtin_face_cache_index (w, Vvertical_divider_face);
1287   
1288   width = window_divider_width (w);
1289   shadow_thickness = XINT (w->vertical_divider_shadow_thickness);
1290   spacing = XINT (w->vertical_divider_spacing);
1291   line_width = XINT (w->vertical_divider_line_width);
1292   x = WINDOW_RIGHT (w) - width;
1293   y1 = WINDOW_TOP (w);
1294   y2 = WINDOW_BOTTOM (w);
1295   
1296   memset (&gcv, ~0, sizeof (gcv));
1297   
1298   tmp_pixel = WINDOW_FACE_CACHEL_BACKGROUND (w, div_face);
1299   
1300   gcv.background = * COLOR_INSTANCE_GTK_COLOR (XCOLOR_INSTANCE (tmp_pixel));
1301   gcv.foreground = gcv.background;
1302   gcv.graphics_exposures = FALSE;
1303   mask = GDK_GC_FOREGROUND | GDK_GC_BACKGROUND | GDK_GC_EXPOSURES;
1304
1305   background_gc = gc_cache_lookup (DEVICE_GTK_GC_CACHE (d), &gcv, mask);
1306
1307   /* Clear the divider area first.  This needs to be done when a
1308      window split occurs. */
1309   /* if (clear) */
1310   gdk_draw_rectangle (GDK_DRAWABLE (x_win), background_gc, TRUE,
1311                       x, y1, width, y2 - y1);
1312
1313 #if 0
1314   /* Draw the divider line. */
1315   gdk_draw_rectangle (GDK_DRAWABLE (x_win), background_gc, TRUE,
1316                       x + spacing + shadow_thickness, y1,
1317                       line_width, y2 - y1);
1318 #endif
1319   
1320   /* Draw the shadows around the divider line */
1321   gtk_output_shadows (f, x + spacing, y1, 
1322                       width - 2 * spacing, y2 - y1,
1323                       shadow_thickness);
1324 }
1325
1326 /*****************************************************************************
1327  gtk_output_blank
1328
1329  Output a blank by clearing the area it covers in the foreground color
1330  of its face.
1331  ****************************************************************************/
1332 static void
1333 gtk_output_blank (struct window *w, struct display_line *dl, struct rune *rb,
1334                   int start_pixpos, int cursor_start, int cursor_width)
1335 {
1336   struct frame *f = XFRAME (w->frame);
1337   struct device *d = XDEVICE (f->device);
1338
1339   GdkWindow *x_win = GET_GTK_WIDGET_WINDOW (FRAME_GTK_TEXT_WIDGET (f));
1340   GdkGC *gc;
1341   struct face_cachel *cursor_cachel =
1342     WINDOW_FACE_CACHEL (w,
1343                         get_builtin_face_cache_index
1344                         (w, Vtext_cursor_face));
1345   Lisp_Object bg_pmap;
1346   Lisp_Object buffer = WINDOW_BUFFER (w);
1347   Lisp_Object bar_cursor_value = symbol_value_in_buffer (Qbar_cursor,
1348                                                          buffer);
1349
1350   int x = rb->xpos;
1351   int y = dl->ypos - dl->ascent;
1352   int width = rb->width;
1353   int height = dl->ascent + dl->descent - dl->clip;
1354
1355   if (start_pixpos > x)
1356     {
1357       if (start_pixpos >= (x + width))
1358         return;
1359       else
1360         {
1361           width -= (start_pixpos - x);
1362           x = start_pixpos;
1363         }
1364     }
1365
1366   bg_pmap = WINDOW_FACE_CACHEL_BACKGROUND_PIXMAP (w, rb->findex);
1367   if (!IMAGE_INSTANCEP (bg_pmap)
1368       || !IMAGE_INSTANCE_PIXMAP_TYPE_P (XIMAGE_INSTANCE (bg_pmap)))
1369     bg_pmap = Qnil;
1370
1371   if (NILP (bg_pmap))
1372     gc = gtk_get_gc (d, Qnil, WINDOW_FACE_CACHEL_BACKGROUND (w, rb->findex),
1373                      Qnil, Qnil, Qnil);
1374   else
1375     gc = gtk_get_gc (d, Qnil, WINDOW_FACE_CACHEL_FOREGROUND (w, rb->findex),
1376                      WINDOW_FACE_CACHEL_BACKGROUND (w, rb->findex), bg_pmap,
1377                      Qnil);
1378
1379   gdk_draw_rectangle (GDK_DRAWABLE (x_win), gc, TRUE, x, y, width, height);
1380
1381   /* If this rune is marked as having the cursor, then it is actually
1382      representing a tab. */
1383   if (!NILP (w->text_cursor_visible_p)
1384       && (rb->cursor_type == CURSOR_ON
1385           || (cursor_width
1386               && (cursor_start + cursor_width > x)
1387               && cursor_start < (x + width))))
1388     {
1389       int cursor_height, cursor_y;
1390       int focus = EQ (w->frame, DEVICE_FRAME_WITH_FOCUS_REAL (d));
1391       struct Lisp_Font_Instance *fi;
1392
1393       fi = XFONT_INSTANCE (FACE_CACHEL_FONT
1394                            (WINDOW_FACE_CACHEL (w, rb->findex),
1395                             Vcharset_ascii));
1396
1397       gc = gtk_get_gc (d, Qnil, cursor_cachel->background, Qnil, Qnil, Qnil);
1398
1399       cursor_y = dl->ypos - fi->ascent;
1400       cursor_height = fi->height;
1401       if (cursor_y + cursor_height > y + height)
1402         cursor_height = y + height - cursor_y;
1403
1404       if (focus)
1405         {
1406           if (NILP (bar_cursor_value))
1407             {
1408                 gdk_draw_rectangle (GDK_DRAWABLE (x_win), gc, TRUE,
1409                                     cursor_start, cursor_y,
1410                                     fi->width, cursor_height);
1411             }
1412           else
1413             {
1414               int bar_width = EQ (bar_cursor_value, Qt) ? 1 : 2;
1415
1416               gc = gtk_get_gc (d, Qnil, cursor_cachel->background, Qnil, Qnil,
1417                                make_int (bar_width));
1418               gdk_draw_line (GDK_DRAWABLE (x_win), gc, cursor_start + bar_width - 1,
1419                              cursor_y, cursor_start + bar_width - 1,
1420                              cursor_y + cursor_height - 1);
1421             }
1422         }
1423       else if (NILP (bar_cursor_value))
1424         {
1425             gdk_draw_rectangle (GDK_DRAWABLE (x_win), gc, FALSE,
1426                                 cursor_start, cursor_y,
1427                                 fi->width - 1, cursor_height - 1);
1428         }
1429     }
1430 }
1431
1432 /*****************************************************************************
1433  gtk_output_hline
1434
1435  Output a horizontal line in the foreground of its face.
1436  ****************************************************************************/
1437 static void
1438 gtk_output_hline (struct window *w, struct display_line *dl, struct rune *rb)
1439 {
1440   struct frame *f = XFRAME (w->frame);
1441   struct device *d = XDEVICE (f->device);
1442   GtkStyle *style = FRAME_GTK_TEXT_WIDGET (f)->style;
1443
1444   GdkWindow *x_win = GET_GTK_WIDGET_WINDOW (FRAME_GTK_TEXT_WIDGET (f));
1445   GdkGC *gc;
1446
1447   int x = rb->xpos;
1448   int width = rb->width;
1449   int height = dl->ascent + dl->descent - dl->clip;
1450
1451   int ypos1, ypos2, ypos3, ypos4;
1452
1453   ypos1 = dl->ypos - dl->ascent;
1454   ypos2 = ypos1 + rb->object.hline.yoffset;
1455   ypos3 = ypos2 + rb->object.hline.thickness;
1456   ypos4 = dl->ypos + dl->descent - dl->clip;
1457
1458   /* First clear the area not covered by the line. */
1459   if (height - rb->object.hline.thickness > 0)
1460     {
1461       gc = gtk_get_gc (d, Qnil, WINDOW_FACE_CACHEL_FOREGROUND (w, rb->findex),
1462                      Qnil, Qnil, Qnil);
1463
1464       if (ypos2 - ypos1 > 0)
1465           gdk_draw_rectangle (GDK_DRAWABLE (x_win), gc, TRUE, x, ypos1, width, ypos2 - ypos1);
1466       if (ypos4 - ypos3 > 0)
1467           gdk_draw_rectangle (GDK_DRAWABLE (x_win), gc, TRUE, x, ypos1, width, ypos2 - ypos1);
1468     }
1469
1470   gtk_paint_hline (style, x_win, GTK_STATE_NORMAL, NULL, FRAME_GTK_TEXT_WIDGET (f),
1471                    "hline", x, x + width, ypos2);
1472 #if 0
1473   /* Now draw the line. */
1474   gc = gtk_get_gc (d, Qnil, WINDOW_FACE_CACHEL_BACKGROUND (w, rb->findex),
1475                    Qnil, Qnil, Qnil);
1476
1477   if (ypos2 < ypos1)
1478     ypos2 = ypos1;
1479   if (ypos3 > ypos4)
1480     ypos3 = ypos4;
1481
1482   if (ypos3 - ypos2 > 0)
1483       gdk_draw_rectangle (GDK_DRAWABLE (x_win), gc, TRUE, x, ypos2, width, ypos3 - ypos2);
1484 #endif
1485 }
1486
1487 /*****************************************************************************
1488  gtk_output_shadows
1489
1490  Draw a shadow around the given area using the standard theme engine routines.
1491  ****************************************************************************/
1492 void
1493 gtk_output_shadows (struct frame *f, int x, int y, int width, int height,
1494                     int shadow_thickness)
1495 {
1496   GdkWindow *x_win = GET_GTK_WIDGET_WINDOW (FRAME_GTK_TEXT_WIDGET (f));
1497   GtkStyle *style = FRAME_GTK_TEXT_WIDGET (f)->style;
1498   GtkShadowType stype = GTK_SHADOW_OUT;
1499
1500   if (shadow_thickness < 0)
1501   {
1502       stype = GTK_SHADOW_IN;
1503   }
1504   else if (shadow_thickness == 0)
1505   {
1506       stype = GTK_SHADOW_NONE;
1507   }
1508
1509   /* Do we want to have some magic constants to set
1510      GTK_SHADOW_ETCHED_IN or GTK_SHADOW_ETCHED_OUT? */
1511
1512   gtk_paint_shadow (style, x_win, GTK_STATE_NORMAL, stype, NULL,
1513                     FRAME_GTK_TEXT_WIDGET (f), "modeline",
1514                     x, y, width, height);
1515 }
1516
1517 /*****************************************************************************
1518  gtk_clear_to_window_end
1519
1520  Clear the area between ypos1 and ypos2.  Each margin area and the
1521  text area is handled separately since they may each have their own
1522  background color.
1523  ****************************************************************************/
1524 static void
1525 gtk_clear_to_window_end (struct window *w, int ypos1, int ypos2)
1526 {
1527   int height = ypos2 - ypos1;
1528
1529   if (height)
1530     {
1531       struct frame *f = XFRAME (w->frame);
1532       Lisp_Object window;
1533       int bflag = (window_needs_vertical_divider (w) ? 0 : 1);
1534       layout_bounds bounds;
1535
1536       bounds = calculate_display_line_boundaries (w, bflag);
1537       XSETWINDOW (window, w);
1538
1539       if (window_is_leftmost (w))
1540         redisplay_clear_region (window, DEFAULT_INDEX, FRAME_LEFT_BORDER_START (f),
1541                                 ypos1, FRAME_BORDER_WIDTH (f), height);
1542
1543       if (bounds.left_in - bounds.left_out > 0)
1544         redisplay_clear_region (window,
1545                                 get_builtin_face_cache_index (w, Vleft_margin_face),
1546                                 bounds.left_out, ypos1,
1547                                 bounds.left_in - bounds.left_out, height);
1548
1549       if (bounds.right_in - bounds.left_in > 0)
1550         redisplay_clear_region (window, DEFAULT_INDEX, bounds.left_in, ypos1,
1551                                 bounds.right_in - bounds.left_in, height);
1552
1553       if (bounds.right_out - bounds.right_in > 0)
1554         redisplay_clear_region (window,
1555                                 get_builtin_face_cache_index (w, Vright_margin_face),
1556                                 bounds.right_in, ypos1,
1557                                 bounds.right_out - bounds.right_in, height);
1558
1559       if (window_is_rightmost (w))
1560         redisplay_clear_region (window, DEFAULT_INDEX, FRAME_RIGHT_BORDER_START (f),
1561                                 ypos1, FRAME_BORDER_WIDTH (f), height);
1562     }
1563 }
1564
1565 /*****************************************************************************
1566  gtk_redraw_exposed_window
1567
1568  Given a bounding box for an area that needs to be redrawn, determine
1569  what parts of what lines are contained within and re-output their
1570  contents.
1571  ****************************************************************************/
1572 static void
1573 gtk_redraw_exposed_window (struct window *w, int x, int y, int width, int height)
1574 {
1575   struct frame *f = XFRAME (w->frame);
1576   int line;
1577   int start_x, start_y, end_x, end_y;
1578   int orig_windows_structure_changed;
1579
1580   display_line_dynarr *cdla = window_display_lines (w, CURRENT_DISP);
1581
1582   if (!NILP (w->vchild))
1583     {
1584       gtk_redraw_exposed_windows (w->vchild, x, y, width, height);
1585       return;
1586     }
1587   else if (!NILP (w->hchild))
1588     {
1589       gtk_redraw_exposed_windows (w->hchild, x, y, width, height);
1590       return;
1591     }
1592
1593   /* If the window doesn't intersect the exposed region, we're done here. */
1594   if (x >= WINDOW_RIGHT (w) || (x + width) <= WINDOW_LEFT (w)
1595       || y >= WINDOW_BOTTOM (w) || (y + height) <= WINDOW_TOP (w))
1596     {
1597       return;
1598     }
1599   else
1600     {
1601       start_x = max (WINDOW_LEFT (w), x);
1602       end_x = min (WINDOW_RIGHT (w), (x + width));
1603       start_y = max (WINDOW_TOP (w), y);
1604       end_y = min (WINDOW_BOTTOM (w), y + height);
1605
1606       /* We do this to make sure that the 3D modelines get redrawn if
1607          they are in the exposed region. */
1608       orig_windows_structure_changed = f->windows_structure_changed;
1609       f->windows_structure_changed = 1;
1610     }
1611
1612   if (window_needs_vertical_divider (w))
1613     {
1614       gtk_output_vertical_divider (w, 0);
1615     }
1616
1617   for (line = 0; line < Dynarr_length (cdla); line++)
1618     {
1619       struct display_line *cdl = Dynarr_atp (cdla, line);
1620       int top_y = cdl->ypos - cdl->ascent;
1621       int bottom_y = cdl->ypos + cdl->descent;
1622
1623       if (bottom_y >= start_y)
1624         {
1625           if (top_y > end_y)
1626             {
1627               if (line == 0)
1628                 continue;
1629               else
1630                 break;
1631             }
1632           else
1633             {
1634               output_display_line (w, 0, cdla, line, start_x, end_x);
1635             }
1636         }
1637     }
1638
1639   f->windows_structure_changed = orig_windows_structure_changed;
1640
1641   /* If there have never been any face cache_elements created, then this
1642      expose event doesn't actually have anything to do. */
1643   if (Dynarr_largest (w->face_cachels))
1644     redisplay_clear_bottom_of_window (w, cdla, start_y, end_y);
1645 }
1646
1647 /*****************************************************************************
1648  gtk_redraw_exposed_windows
1649
1650  For each window beneath the given window in the window hierarchy,
1651  ensure that it is redrawn if necessary after an Expose event.
1652  ****************************************************************************/
1653 static void
1654 gtk_redraw_exposed_windows (Lisp_Object window, int x, int y, int width,
1655                             int height)
1656 {
1657   for (; !NILP (window); window = XWINDOW (window)->next)
1658     gtk_redraw_exposed_window (XWINDOW (window), x, y, width, height);
1659 }
1660
1661 /*****************************************************************************
1662  gtk_redraw_exposed_area
1663
1664  For each window on the given frame, ensure that any area in the
1665  Exposed area is redrawn.
1666  ****************************************************************************/
1667 void
1668 gtk_redraw_exposed_area (struct frame *f, int x, int y, int width, int height)
1669 {
1670   /* If any window on the frame has had its face cache reset then the
1671      redisplay structures are effectively invalid.  If we attempt to
1672      use them we'll blow up.  We mark the frame as changed to ensure
1673      that redisplay will do a full update.  This probably isn't
1674      necessary but it can't hurt. */
1675
1676 #ifdef HAVE_TOOLBARS
1677   /* #### We would rather put these off as well but there is currently
1678      no combination of flags which will force an unchanged toolbar to
1679      redraw anyhow. */
1680   MAYBE_FRAMEMETH (f, redraw_exposed_toolbars, (f, x, y, width, height));
1681 #endif
1682   redraw_exposed_gutters (f, x, y, width, height);
1683
1684   if (!f->window_face_cache_reset)
1685     {
1686       gtk_redraw_exposed_windows (f->root_window, x, y, width, height);
1687     }
1688   else
1689     MARK_FRAME_CHANGED (f);
1690 }
1691
1692 /****************************************************************************
1693  gtk_clear_region
1694
1695  Clear the area in the box defined by the given parameters using the
1696  given face.
1697  ****************************************************************************/
1698 static void
1699 gtk_clear_region (Lisp_Object locale, struct device* d, struct frame* f, face_index findex,
1700                   int x, int y,
1701                   int width, int height, Lisp_Object fcolor, Lisp_Object bcolor,
1702                   Lisp_Object background_pixmap)
1703 {
1704   GdkWindow *x_win;
1705   GdkGC *gc = NULL;
1706
1707   x_win = GET_GTK_WIDGET_WINDOW (FRAME_GTK_TEXT_WIDGET (f));
1708
1709   if (!UNBOUNDP (background_pixmap))
1710     {
1711       gc = gtk_get_gc (d, Qnil, fcolor, bcolor, background_pixmap, Qnil);
1712     }
1713
1714   if (gc)
1715     {
1716       gdk_draw_rectangle (GDK_DRAWABLE (x_win), gc,TRUE,
1717                           x, y, width, height);
1718     }
1719   else
1720     {
1721       gdk_window_clear_area (x_win, x, y, width, height);
1722     }
1723 }
1724
1725 /*****************************************************************************
1726  gtk_output_eol_cursor
1727
1728  Draw a cursor at the end of a line.  The end-of-line cursor is
1729  narrower than the normal cursor.
1730  ****************************************************************************/
1731 static void
1732 gtk_output_eol_cursor (struct window *w, struct display_line *dl, int xpos,
1733                        face_index findex)
1734 {
1735   struct frame *f = XFRAME (w->frame);
1736   struct device *d = XDEVICE (f->device);
1737   Lisp_Object window;
1738
1739   GdkWindow *x_win = GET_GTK_WIDGET_WINDOW (FRAME_GTK_TEXT_WIDGET (f));
1740   GdkGC *gc;
1741   face_index elt = get_builtin_face_cache_index (w, Vtext_cursor_face);
1742   struct face_cachel *cursor_cachel = WINDOW_FACE_CACHEL (w, elt);
1743
1744   int focus = EQ (w->frame, DEVICE_FRAME_WITH_FOCUS_REAL (d));
1745   Lisp_Object bar_cursor_value = symbol_value_in_buffer (Qbar_cursor,
1746                                                          WINDOW_BUFFER (w));
1747
1748   int x = xpos;
1749   int y = dl->ypos - dl->ascent;
1750   int width = EOL_CURSOR_WIDTH;
1751   int height = dl->ascent + dl->descent - dl->clip;
1752   int cursor_height, cursor_y;
1753   int defheight, defascent;
1754
1755   XSETWINDOW (window, w);
1756   redisplay_clear_region (window, findex, x, y, width, height);
1757
1758   if (NILP (w->text_cursor_visible_p))
1759     return;
1760
1761   gc = gtk_get_gc (d, Qnil, cursor_cachel->background, Qnil, Qnil, Qnil);
1762
1763   default_face_font_info (window, &defascent, 0, &defheight, 0, 0);
1764
1765   /* make sure the cursor is entirely contained between y and y+height */
1766   cursor_height = min (defheight, height);
1767   cursor_y = max (y, min (y + height - cursor_height,
1768                           dl->ypos - defascent));
1769
1770   if (focus)
1771     {
1772       if (NILP (bar_cursor_value))
1773         {
1774             gdk_draw_rectangle (GDK_DRAWABLE (x_win), gc, TRUE, x, cursor_y, width, cursor_height);
1775         }
1776       else
1777         {
1778           int bar_width = EQ (bar_cursor_value, Qt) ? 1 : 2;
1779
1780           gc = gtk_get_gc (d, Qnil, cursor_cachel->background, Qnil, Qnil,
1781                            make_int (bar_width));
1782           gdk_draw_line (GDK_DRAWABLE (x_win), gc, x + bar_width - 1, cursor_y,
1783                          x + bar_width - 1, cursor_y + cursor_height - 1);
1784         }
1785     }
1786   else if (NILP (bar_cursor_value))
1787     {
1788         gdk_draw_rectangle (GDK_DRAWABLE (x_win), gc, FALSE, x, cursor_y, width - 1,
1789                             cursor_height - 1);
1790     }
1791 }
1792
1793 static void
1794 gtk_clear_frame_window (Lisp_Object window)
1795 {
1796   struct window *w = XWINDOW (window);
1797
1798   if (!NILP (w->vchild))
1799     {
1800       gtk_clear_frame_windows (w->vchild);
1801       return;
1802     }
1803
1804   if (!NILP (w->hchild))
1805     {
1806       gtk_clear_frame_windows (w->hchild);
1807       return;
1808     }
1809
1810   gtk_clear_to_window_end (w, WINDOW_TEXT_TOP (w), WINDOW_TEXT_BOTTOM (w));
1811 }
1812
1813 static void
1814 gtk_clear_frame_windows (Lisp_Object window)
1815 {
1816   for (; !NILP (window); window = XWINDOW (window)->next)
1817     gtk_clear_frame_window (window);
1818 }
1819
1820 static void
1821 gtk_clear_frame (struct frame *f)
1822 {
1823   GdkWindow *x_win = GET_GTK_WIDGET_WINDOW (FRAME_GTK_TEXT_WIDGET (f));
1824   int x, y, width, height;
1825   Lisp_Object frame;
1826
1827   x = FRAME_LEFT_BORDER_START (f);
1828   width = (FRAME_PIXWIDTH (f) - FRAME_REAL_LEFT_TOOLBAR_WIDTH (f) -
1829            FRAME_REAL_RIGHT_TOOLBAR_WIDTH (f) -
1830            2 * FRAME_REAL_LEFT_TOOLBAR_BORDER_WIDTH (f) -
1831            2 * FRAME_REAL_RIGHT_TOOLBAR_BORDER_WIDTH (f));
1832   /* #### This adjustment by 1 should be being done in the macros.
1833      There is some small differences between when the menubar is on
1834      and off that we still need to deal with. */
1835   y = FRAME_TOP_BORDER_START (f) - 1;
1836   height = (FRAME_PIXHEIGHT (f) - FRAME_REAL_TOP_TOOLBAR_HEIGHT (f) -
1837             FRAME_REAL_BOTTOM_TOOLBAR_HEIGHT (f) -
1838             2 * FRAME_REAL_TOP_TOOLBAR_BORDER_WIDTH (f) -
1839             2 * FRAME_REAL_BOTTOM_TOOLBAR_BORDER_WIDTH (f)) + 1;
1840
1841   gdk_window_clear_area (x_win, x, y, width, height);
1842
1843   XSETFRAME (frame, f);
1844
1845   if (!UNBOUNDP (FACE_BACKGROUND_PIXMAP (Vdefault_face, frame))
1846       || !UNBOUNDP (FACE_BACKGROUND_PIXMAP (Vleft_margin_face, frame))
1847       || !UNBOUNDP (FACE_BACKGROUND_PIXMAP (Vright_margin_face, frame)))
1848     {
1849       gtk_clear_frame_windows (f->root_window);
1850     }
1851 }
1852
1853 static int
1854 gtk_flash (struct device *d)
1855 {
1856   GdkGCValues gcv;
1857   GdkGC *gc;
1858   GdkColor tmp_fcolor, tmp_bcolor;
1859   Lisp_Object tmp_pixel, frame;
1860   struct frame *f = device_selected_frame (d);
1861   struct window *w = XWINDOW (FRAME_ROOT_WINDOW (f));
1862
1863   XSETFRAME (frame, f);
1864
1865   tmp_pixel = FACE_FOREGROUND (Vdefault_face, frame);
1866   tmp_fcolor = * (COLOR_INSTANCE_GTK_COLOR (XCOLOR_INSTANCE (tmp_pixel)));
1867   tmp_pixel = FACE_BACKGROUND (Vdefault_face, frame);
1868   tmp_bcolor = * (COLOR_INSTANCE_GTK_COLOR (XCOLOR_INSTANCE (tmp_pixel)));
1869
1870   memset (&gcv, ~0, sizeof (gcv)); /* initialize all slots to ~0 */
1871   gcv.foreground.pixel  = (tmp_fcolor.pixel ^ tmp_bcolor.pixel);
1872   gcv.function = GDK_XOR;
1873   gcv.graphics_exposures = FALSE;
1874   gc = gc_cache_lookup (DEVICE_GTK_GC_CACHE (XDEVICE (f->device)), &gcv,
1875                         GDK_GC_FOREGROUND | GDK_GC_FUNCTION | GDK_GC_EXPOSURES);
1876
1877   gdk_draw_rectangle (GDK_DRAWABLE (GET_GTK_WIDGET_WINDOW (FRAME_GTK_SHELL_WIDGET (f))),
1878                       gc, TRUE, w->pixel_left, w->pixel_top,
1879                       w->pixel_width, w->pixel_height);
1880
1881   gdk_flush ();
1882
1883 #ifdef HAVE_POLL
1884   poll (0, 0, 100);
1885 #else /* !HAVE_POLL */
1886 #ifdef HAVE_SELECT
1887   {
1888     int usecs = 100000;
1889     struct timeval tv;
1890     tv.tv_sec  = usecs / 1000000L;
1891     tv.tv_usec = usecs % 1000000L;
1892     /* I'm sure someone is going to complain about this... */
1893     select (0, 0, 0, 0, &tv);
1894   }
1895 #else
1896   bite me
1897 #endif /* HAVE_POLL */
1898 #endif /* HAVE_SELECT */
1899
1900   gdk_draw_rectangle (GDK_DRAWABLE (GET_GTK_WIDGET_WINDOW (FRAME_GTK_SHELL_WIDGET (f))),
1901                       gc, TRUE, w->pixel_left, w->pixel_top,
1902                       w->pixel_width, w->pixel_height);
1903
1904   gdk_flush ();
1905
1906   return 1;
1907 }
1908
1909 static void
1910 gtk_bevel_area (struct window *w, face_index findex,
1911                 int x, int y, int width, int height,
1912                 int shadow_thickness, int edges, enum edge_style style)
1913 {
1914   struct frame *f = XFRAME (w->frame);
1915   struct device *d = XDEVICE (f->device);
1916
1917   gtk_output_shadows (f, x, y, width, height, shadow_thickness);
1918 }
1919
1920
1921
1922 /* Make audible bell.  */
1923 static void
1924 gtk_ring_bell (struct device *d, int volume, int pitch, int duration)
1925 {
1926         /* Gdk does not allow us to control the duration / pitch / volume */
1927         gdk_beep ();
1928 }
1929
1930 \f
1931 /************************************************************************/
1932 /*                            initialization                            */
1933 /************************************************************************/
1934
1935 void
1936 console_type_create_redisplay_gtk (void)
1937 {
1938   /* redisplay methods */
1939   CONSOLE_HAS_METHOD (gtk, text_width);
1940   CONSOLE_HAS_METHOD (gtk, output_display_block);
1941   CONSOLE_HAS_METHOD (gtk, divider_height);
1942   CONSOLE_HAS_METHOD (gtk, eol_cursor_width);
1943   CONSOLE_HAS_METHOD (gtk, output_vertical_divider);
1944   CONSOLE_HAS_METHOD (gtk, clear_to_window_end);
1945   CONSOLE_HAS_METHOD (gtk, clear_region);
1946   CONSOLE_HAS_METHOD (gtk, clear_frame);
1947   CONSOLE_HAS_METHOD (gtk, flash);
1948   CONSOLE_HAS_METHOD (gtk, ring_bell);
1949   CONSOLE_HAS_METHOD (gtk, bevel_area);
1950   CONSOLE_HAS_METHOD (gtk, output_string);
1951   /*  CONSOLE_HAS_METHOD (gtk, output_pixmap); */
1952 }
1953
1954 /* This makes me feel incredibly dirty... but there is no other way to
1955    get this done right other than calling clear_area before every
1956    single $#!%@ing piece of text, which I do NOT want to do. */
1957 #define USE_X_SPECIFIC_DRAW_ROUTINES 1
1958
1959 #include <gdk/gdkx.h>
1960
1961 void
1962 gdk_draw_text_image (GdkDrawable *drawable,
1963                      GdkFont     *font,
1964                      GdkGC       *gc,
1965                      gint         x,
1966                      gint         y,
1967                      const gchar *text,
1968                      gint         text_length)
1969 {
1970 #if !USE_X_SPECIFIC_DRAW_ROUTINES
1971   int width = gdk_text_measure (font, text, text_length);
1972   int height = gdk_text_height (font, text, text_length);
1973
1974   gdk_draw_rectangle (drawable, gc, TRUE, x, y, width, height);
1975   gdk_draw_text (drawable, font, gc, x, y, text, text_length);
1976 #else
1977   GdkWindowPrivate *drawable_private;
1978   GdkFontPrivate *font_private;
1979   GdkGCPrivate *gc_private;
1980
1981   g_return_if_fail (drawable != NULL);
1982   g_return_if_fail (font != NULL);
1983   g_return_if_fail (gc != NULL);
1984   g_return_if_fail (text != NULL);
1985
1986   drawable_private = (GdkWindowPrivate*) drawable;
1987   if (drawable_private->destroyed)
1988     return;
1989   gc_private = (GdkGCPrivate*) gc;
1990   font_private = (GdkFontPrivate*) font;
1991
1992   if (font->type == GDK_FONT_FONT)
1993     {
1994       XFontStruct *xfont = (XFontStruct *) font_private->xfont;
1995       XSetFont(drawable_private->xdisplay, gc_private->xgc, xfont->fid);
1996       if ((xfont->min_byte1 == 0) && (xfont->max_byte1 == 0))
1997         {
1998           XDrawImageString (drawable_private->xdisplay, drawable_private->xwindow,
1999                             gc_private->xgc, x, y, text, text_length);
2000         }
2001       else
2002         {
2003           XDrawImageString16 (drawable_private->xdisplay, drawable_private->xwindow,
2004                               gc_private->xgc, x, y, (XChar2b *) text, text_length / 2);
2005         }
2006     }
2007   else if (font->type == GDK_FONT_FONTSET)
2008     {
2009       XFontSet fontset = (XFontSet) font_private->xfont;
2010       XmbDrawImageString (drawable_private->xdisplay, drawable_private->xwindow,
2011                           fontset, gc_private->xgc, x, y, text, text_length);
2012     }
2013   else
2014     g_error("undefined font type\n");
2015 #endif
2016 }
2017
2018 static void
2019 our_draw_bitmap (GdkDrawable *drawable,
2020                  GdkGC       *gc,
2021                  GdkPixmap   *src,
2022                  gint         xsrc,
2023                  gint         ysrc,
2024                  gint         xdest,
2025                  gint         ydest,
2026                  gint         width,
2027                  gint         height)
2028 {
2029   GdkWindowPrivate *drawable_private;
2030   GdkWindowPrivate *src_private;
2031   GdkGCPrivate *gc_private;
2032
2033   g_return_if_fail (drawable != NULL);
2034   g_return_if_fail (src != NULL);
2035   g_return_if_fail (gc != NULL);
2036
2037   drawable_private = (GdkWindowPrivate*) drawable;
2038   src_private = (GdkWindowPrivate*) src;
2039   if (drawable_private->destroyed || src_private->destroyed)
2040     return;
2041   gc_private = (GdkGCPrivate*) gc;
2042
2043   if (width == -1)
2044     width = src_private->width;
2045   if (height == -1)
2046     height = src_private->height;
2047
2048   XCopyPlane (drawable_private->xdisplay,
2049              src_private->xwindow,
2050              drawable_private->xwindow,
2051              gc_private->xgc,
2052              xsrc, ysrc,
2053              width, height,
2054              xdest, ydest, 1L);
2055 }