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.
6 This file is part of XEmacs.
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
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
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. */
23 /* Synched up with: Not in FSF. */
25 /* Author: Chuck Thompson */
26 /* Gtk flavor by William Perry */
28 /* Lots of work done by Ben Wing for Mule */
33 #include "console-gtk.h"
34 #include "gccache-gtk.h"
35 #include "glyphs-gtk.h"
36 #include "objects-gtk.h"
43 #include "redisplay.h"
47 #include "sysproc.h" /* for select() */
51 #include "file-coding.h" /* for CCL conversion */
60 #define EOL_CURSOR_WIDTH 5
62 static void gtk_output_pixmap (struct window *w, struct display_line *dl,
63 Lisp_Object image_instance, int xpos,
65 int start_pixpos, int width, face_index findex,
66 int cursor_start, int cursor_width,
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,
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);
89 static void __describe_gc (GdkGC *);
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.
110 Returns the number of runs actually used. */
113 separate_textual_runs (unsigned char *text_storage,
114 struct textual_run *run_storage,
115 CONST Emchar *str, Charcount len)
117 Lisp_Object prev_charset = Qunbound; /* not Qnil because that is a
118 possible valid charset when
119 MULE is not defined */
123 struct ccl_program char_converter;
124 int need_ccl_conversion = 0;
127 for (i = 0; i < len; i++)
135 BREAKUP_CHAR (ch, charset, byte1, byte2);
136 dimension = XCHARSET_DIMENSION (charset);
137 graphic = XCHARSET_GRAPHIC (charset);
139 if (!EQ (charset, prev_charset))
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;
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;
153 prev_charset = charset;
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);
169 else if (graphic == 1)
175 if (need_ccl_conversion)
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];
185 *text_storage++ = (unsigned char) byte1;
187 *text_storage++ = (unsigned char) byte2;
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;
201 /****************************************************************************/
203 /* Gtk output routines */
205 /****************************************************************************/
208 gtk_text_width_single_run (struct face_cachel *cachel, struct textual_run *run)
210 Lisp_Object font_inst = FACE_CACHEL_FONT (cachel, run->charset);
211 struct Lisp_Font_Instance *fi = XFONT_INSTANCE (font_inst);
213 if (!fi->proportional_p)
215 return fi->width * run->len;
219 if (run->dimension == 2)
221 stderr_out ("Measuring wide characters\n");
222 return gdk_text_width_wc (FONT_INSTANCE_GTK_FONT (fi),
223 (GdkWChar *) run->ptr, run->len);
227 return gdk_text_width (FONT_INSTANCE_GTK_FONT (fi),
228 (char *) run->ptr, run->len);
236 Given a string and a face, return the string's length in pixels when
237 displayed in the font associated with the face.
241 gtk_text_width (struct frame *f, struct face_cachel *cachel, CONST Emchar *str,
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);
250 nruns = separate_textual_runs (text_storage, runs, str, len);
252 for (i = 0; i < nruns; i++)
253 width_so_far += gtk_text_width_single_run (cachel, runs + i);
258 /*****************************************************************************
261 Return the height of the horizontal divider. This is a function because
262 divider_height is a device method.
264 #### If we add etched horizontal divider lines this will have to get
266 ****************************************************************************/
268 gtk_divider_height (void)
273 /*****************************************************************************
276 Return the width of the end-of-line cursor. This is a function
277 because eol_cursor_width is a device method.
278 ****************************************************************************/
280 gtk_eol_cursor_width (void)
282 return EOL_CURSOR_WIDTH;
285 /*****************************************************************************
286 gtk_output_display_block
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 ****************************************************************************/
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)
296 struct frame *f = XFRAME (w->frame);
300 struct display_block *db = Dynarr_atp (dl->display_blocks, block);
301 rune_dynarr *rba = db->runes;
307 Lisp_Object charset = Qunbound; /* Qnil is a valid charset when
308 MULE is not defined */
310 XSETWINDOW (window, w);
311 rb = Dynarr_atp (rba, start);
315 /* Nothing to do so don't do anything. */
323 if (rb->type == RUNE_CHAR)
324 charset = CHAR_CHARSET (rb->object.chr.ch);
328 end = Dynarr_length (rba);
329 buf = Dynarr_new (Emchar);
333 rb = Dynarr_atp (rba, elt);
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)))
339 Dynarr_add (buf, rb->object.chr.ch);
345 if (Dynarr_length (buf))
347 gtk_output_string (w, dl, buf, xpos, 0, start_pixpos, width,
348 findex, 0, cursor_start, cursor_width,
356 if (rb->type == RUNE_CHAR)
360 charset = CHAR_CHARSET (rb->object.chr.ch);
362 if (rb->cursor_type == CURSOR_ON)
364 if (rb->object.chr.ch == '\n')
366 gtk_output_eol_cursor (w, dl, xpos, findex);
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,
381 else if (rb->object.chr.ch == '\n')
383 /* Clear in case a cursor was formerly here. */
384 int height = dl->ascent + dl->descent - dl->clip;
386 redisplay_clear_region (window, findex, xpos, dl->ypos - dl->ascent,
391 else if (rb->type == RUNE_BLANK || rb->type == RUNE_HLINE)
393 if (rb->type == RUNE_BLANK)
394 gtk_output_blank (w, dl, rb, start_pixpos, cursor_start,
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
405 w->shadow_thickness_changed = 1;
406 gtk_output_hline (w, dl, rb);
412 rb = Dynarr_atp (rba, elt);
418 else if (rb->type == RUNE_DGLYPH)
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);
427 XSETWINDOW (window, w);
428 instance = glyph_image_instance (rb->object.dglyph.glyph,
429 window, ERROR_ME_NOT, 1);
432 if (IMAGE_INSTANCEP (instance))
433 switch (XIMAGE_INSTANCE_TYPE (instance))
437 /* #### This is way losing. See the comment in
440 XIMAGE_INSTANCE_TEXT_STRING (instance);
441 convert_bufbyte_string_into_emchar_dynarr
442 (XSTRING_DATA (string), XSTRING_LENGTH (string), buf);
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,
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);
466 if (EQ (XIMAGE_INSTANCE_WIDGET_TYPE (instance),
469 redisplay_output_layout (window, instance, &dbox,
471 cursor_start, cursor_width,
476 case IMAGE_SUBWINDOW:
477 redisplay_output_subwindow (w, instance, &dbox, &dga,
478 findex, cursor_start,
479 cursor_width, cursor_height);
483 /* nothing is as nothing does */
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);
502 /* #### This is really conditionalized well for optimized
505 && !EQ (Qzero, w->modeline_shadow_thickness)
507 || f->windows_structure_changed
508 || w->shadow_thickness_changed))
509 gtk_bevel_modeline (w, dl);
514 /*****************************************************************************
517 Draw a 3d border around the modeline on window W.
518 ****************************************************************************/
520 gtk_bevel_modeline (struct window *w, struct display_line *dl)
522 struct frame *f = XFRAME (w->frame);
523 int shadow_thickness = MODELINE_SHADOW_THICKNESS (w);
524 int x,y, width, height;
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;
531 gtk_output_shadows (f, x, y, width, height, shadow_thickness);
534 /*****************************************************************************
537 Given a number of parameters return a GC with those properties.
538 ****************************************************************************/
540 gtk_get_gc (struct device *d, Lisp_Object font, Lisp_Object fg, Lisp_Object bg,
541 Lisp_Object bg_pmap, Lisp_Object lwidth)
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. */
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;
559 gcv.font = FONT_INSTANCE_GTK_FONT (XFONT_INSTANCE (font));
564 if (!NILP (fg) && !COLOR_INSTANCEP (fg) && !INTP (fg))
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 = ");
575 if (COLOR_INSTANCEP (fg))
576 gcv.foreground = * COLOR_INSTANCE_GTK_COLOR (XCOLOR_INSTANCE (fg));
578 gcv.foreground.pixel = XINT (fg);
579 mask |= GDK_GC_FOREGROUND;
584 if (COLOR_INSTANCEP (bg))
585 gcv.background = * COLOR_INSTANCE_GTK_COLOR (XCOLOR_INSTANCE (bg));
587 gcv.background.pixel = XINT (fg);
588 mask |= GDK_GC_BACKGROUND;
591 if (IMAGE_INSTANCEP (bg_pmap)
592 && IMAGE_INSTANCE_PIXMAP_TYPE_P (XIMAGE_INSTANCE (bg_pmap)))
594 if (XIMAGE_INSTANCE_PIXMAP_DEPTH (bg_pmap) == 0)
596 gcv.fill = GDK_OPAQUE_STIPPLED;
597 gcv.stipple = XIMAGE_INSTANCE_GTK_PIXMAP (bg_pmap);
598 mask |= (GDK_GC_STIPPLE | GDK_GC_FILL);
602 gcv.fill = GDK_TILED;
603 gcv.tile = XIMAGE_INSTANCE_GTK_PIXMAP (bg_pmap);
604 mask |= (GDK_GC_TILE | GDK_GC_FILL);
610 gcv.line_width = XINT (lwidth);
611 mask |= GDK_GC_LINE_WIDTH;
614 return gc_cache_lookup (DEVICE_GTK_GC_CACHE (d), &gcv, mask);
617 /*****************************************************************************
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.
624 The meaning of the parameters is something like this:
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
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
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.
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 ****************************************************************************/
651 gdk_draw_text_image (GdkDrawable *drawable,
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)
665 /* General variables */
666 struct frame *f = XFRAME (w->frame);
667 struct device *d = XDEVICE (f->device);
670 GdkWindow *x_win = GET_GTK_WIDGET_WINDOW (FRAME_GTK_TEXT_WIDGET (f));
674 /* Cursor-related variables */
675 int focus = EQ (w->frame, DEVICE_FRAME_WITH_FOCUS_REAL (d));
677 Lisp_Object bar_cursor_value = symbol_value_in_buffer (Qbar_cursor,
679 struct face_cachel *cursor_cachel = 0;
681 /* Text-related variables */
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);
690 struct face_cachel *cachel = WINDOW_FACE_CACHEL (w, findex);
692 XSETDEVICE (device, d);
693 XSETWINDOW (window, w);
696 width = gtk_text_width (f, cachel, Dynarr_atp (buf, 0), Dynarr_length (buf));
697 height = dl->ascent + dl->descent - dl->clip;
699 /* Regularize the variables passed in. */
701 if (clip_start < xpos)
703 clip_end = xpos + width;
704 if (clip_start >= clip_end)
705 /* It's all clipped out. */
710 nruns = separate_textual_runs (text_storage, runs, Dynarr_atp (buf, 0),
711 Dynarr_length (buf));
713 cursor_clip = (cursor_start >= clip_start &&
714 cursor_start < clip_end);
716 /* This cursor code is really a mess. */
717 if (!NILP (w->text_cursor_visible_p)
721 && (cursor_start + cursor_width >= clip_start)
722 && !NILP (bar_cursor_value))))
724 /* These have to be in separate statements in order to avoid a
726 face_index sucks = get_builtin_face_cache_index (w, Vtext_cursor_face);
727 cursor_cachel = WINDOW_FACE_CACHEL (w, sucks);
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
732 cachel = WINDOW_FACE_CACHEL (w, findex);
735 bg_pmap = cachel->background_pixmap;
736 if (!IMAGE_INSTANCEP (bg_pmap)
737 || !IMAGE_INSTANCE_PIXMAP_TYPE_P (XIMAGE_INSTANCE (bg_pmap)))
740 if ((cursor && focus && NILP (bar_cursor_value)
741 && !NILP (w->text_cursor_visible_p)) || NILP (bg_pmap))
744 bgc = gtk_get_gc (d, Qnil, cachel->foreground, cachel->background,
748 gdk_draw_rectangle (GDK_DRAWABLE (x_win), bgc, TRUE, clip_start,
749 dl->ypos - dl->ascent, clip_end - clip_start,
752 for (i = 0; i < nruns; i++)
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);
760 if (EQ (font, Vthe_null_font_instance))
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);
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
771 if ((int) fi->height < (int) (height + dl->clip))
773 int clear_start = max (xpos, clip_start);
774 int clear_end = min (xpos + this_width, clip_end);
778 int ypos1_line, ypos1_string, ypos2_line, ypos2_string;
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;
785 /* Make sure we don't clear below the real bottom of the
787 if (ypos1_string > ypos2_line)
788 ypos1_string = ypos2_line;
789 if (ypos2_string > ypos2_line)
790 ypos2_string = ypos2_line;
792 if (ypos1_line < ypos1_string)
794 redisplay_clear_region (window, findex, clear_start, ypos1_line,
795 clear_end - clear_start,
796 ypos1_string - ypos1_line);
799 if (ypos2_line > ypos2_string)
801 redisplay_clear_region (window, findex, clear_start, ypos2_string,
802 clear_end - clear_start,
803 ypos2_line - ypos2_string);
808 redisplay_clear_region (window, findex, clear_start,
809 dl->ypos - dl->ascent, clear_end - clear_start,
814 if (cursor && cursor_cachel && focus && NILP (bar_cursor_value))
816 gc = gtk_get_gc (d, font, cursor_cachel->foreground,
817 cursor_cachel->background, Qnil, Qnil);
821 gc = gtk_get_gc (d, font, cachel->foreground, cachel->background,
827 GdkRectangle clip_box;
831 clip_box.width = clip_end - clip_start;
832 clip_box.height = height;
834 gdk_gc_set_clip_rectangle (gc, &clip_box);
835 gdk_gc_set_clip_origin (gc, clip_start, dl->ypos - dl->ascent);
838 /* The X specific called different functions (XDraw*String
839 vs. XDraw*String16), but apparently gdk_draw_text takes care
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.
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);
851 /* We draw underlines in the same color as the text. */
852 if (cachel->underline)
854 unsigned long upos, uthick;
856 /* Cannot get at font properties in Gtk, so we resort to
858 upos = dl->descent / 2;
861 if (dl->ypos + upos < dl->ypos + dl->descent - dl->clip)
863 if (dl->ypos + upos + uthick > dl->ypos + dl->descent - dl->clip)
864 uthick = dl->descent - dl->clip - upos;
868 gdk_draw_line (GDK_DRAWABLE (x_win), gc, xpos, dl->ypos + upos,
869 xpos + this_width, dl->ypos + upos);
873 gdk_draw_rectangle (GDK_DRAWABLE (x_win), gc, TRUE, xpos,
874 dl->ypos + upos, this_width, uthick);
879 if (cachel->strikethru) {
880 unsigned long ascent,descent,upos, uthick;
881 GdkFont *gfont = FONT_INSTANCE_GTK_FONT (XFONT_INSTANCE (font));
883 /* Cannot get at font properties in Gtk, so we resort to
886 ascent = gfont->ascent;
887 descent = gfont->descent;
890 upos = ascent - ((ascent + descent) / 2) + 1;
892 /* Generally, upos will be positive (above the baseline),so subtract */
893 if (dl->ypos - upos < dl->ypos + dl->descent - dl->clip)
895 if (dl->ypos - upos + uthick > dl->ypos + dl->descent - dl->clip)
896 uthick = dl->descent - dl->clip + upos;
900 gdk_draw_line (GDK_DRAWABLE (x_win), gc, xpos, dl->ypos - upos,
901 xpos + this_width, dl->ypos - upos);
905 gdk_draw_rectangle (GDK_DRAWABLE (x_win), gc, TRUE, xpos, dl->ypos + upos,
914 gdk_gc_set_clip_rectangle (gc, NULL);
915 gdk_gc_set_clip_origin (gc, 0, 0);
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)
923 GdkRectangle clip_box;
925 cgc = gtk_get_gc (d, font, cursor_cachel->foreground,
926 cursor_cachel->background, Qnil, Qnil);
930 clip_box.width = cursor_width;
931 clip_box.height = height;
933 gdk_gc_set_clip_rectangle (cgc, &clip_box);
934 gdk_gc_set_clip_origin (cgc, cursor_start, dl->ypos - dl->ascent);
936 /* The X specific called different functions (XDraw*String
937 vs. XDraw*String16), but apparently gdk_draw_text takes care
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.
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);
949 gdk_gc_set_clip_rectangle (cgc, NULL);
950 gdk_gc_set_clip_origin (cgc, 0, 0);
956 /* Draw the non-focus box or bar-cursor as needed. */
957 /* Can't this logic be simplified? */
959 && ((cursor && !focus && NILP (bar_cursor_value))
961 && (cursor_start + cursor_width >= clip_start)
962 && !NILP (bar_cursor_value))))
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);
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].
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;
986 if (!NILP (bar_cursor_value))
988 gc = gtk_get_gc (d, Qnil, cursor_cachel->background, Qnil, Qnil,
989 make_int (bar_width));
993 gc = gtk_get_gc (d, Qnil, cursor_cachel->background,
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))
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;
1009 GdkRectangle clip_box;
1012 clip_box.width = clip_end - clip_start;
1013 clip_box.height = tmp_height;
1015 gdk_gc_set_clip_rectangle (gc, &clip_box);
1016 gdk_gc_set_clip_origin (gc, clip_start, tmp_y);
1019 if (!focus && NILP (bar_cursor_value))
1021 gdk_draw_rectangle (GDK_DRAWABLE (x_win), gc, FALSE,
1022 cursor_start, tmp_y,
1023 cursor_width - 1, tmp_height - 1);
1025 else if (focus && !NILP (bar_cursor_value))
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);
1032 /* Restore the GC */
1035 gdk_gc_set_clip_rectangle (gc, NULL);
1036 gdk_gc_set_clip_origin (gc, 0, 0);
1042 our_draw_bitmap (GdkDrawable *drawable,
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)
1058 struct device *d = XDEVICE (f->device);
1059 GdkWindow *x_win = GET_GTK_WIDGET_WINDOW (FRAME_GTK_TEXT_WIDGET (f));
1063 unsigned long pixmap_mask;
1064 int need_clipping = (clip_x || clip_y);
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;
1074 if (IMAGE_INSTANCE_GTK_MASK (p))
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 */
1091 gc = gc_cache_lookup (DEVICE_GTK_GC_CACHE (d), &gcv, pixmap_mask);
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. */
1104 GdkRectangle clip_box;
1106 clip_box.x = clip_x;
1107 clip_box.y = clip_y;
1108 clip_box.width = clip_width;
1109 clip_box.height = clip_height;
1111 gdk_gc_set_clip_rectangle (gc, &clip_box);
1112 gdk_gc_set_clip_origin (gc, x, y);
1115 if (IMAGE_INSTANCE_PIXMAP_DEPTH (p) > 0)
1117 gdk_draw_pixmap (GDK_DRAWABLE (x_win), gc,
1118 IMAGE_INSTANCE_GTK_PIXMAP (p),
1119 0, pixmap_offset, x, y, width, height);
1123 our_draw_bitmap (GDK_DRAWABLE (x_win), gc,
1124 IMAGE_INSTANCE_GTK_PIXMAP (p),
1125 0, pixmap_offset, x, y, width, height);
1130 gdk_gc_set_clip_rectangle (gc, NULL);
1131 gdk_gc_set_clip_origin (gc, 0, 0);
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)
1141 struct frame *f = XFRAME (w->frame);
1142 struct device *d = XDEVICE (f->device);
1143 struct Lisp_Image_Instance *p = XIMAGE_INSTANCE (image_instance);
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;
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. */
1157 int pixmap_offset = (int) (IMAGE_INSTANCE_PIXMAP_HEIGHT (p) - lheight) / 2;
1159 int pixmap_offset = 0;
1162 XSETWINDOW (window, w);
1164 if ((start_pixpos >= 0 && start_pixpos > xpos) || xoffset)
1166 if (start_pixpos > xpos && start_pixpos > xpos + width)
1171 if (start_pixpos > xpos)
1173 clip_x += (start_pixpos - xpos);
1174 clip_width -= (start_pixpos - xpos);
1183 /* Place markers for possible future functionality (clipping the top
1184 half instead of the bottom half; think pixel scrolling). */
1186 clip_height = pheight;
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))
1202 int clear_x, clear_y, clear_width, clear_height;
1204 if (IMAGE_INSTANCE_GTK_MASK (p))
1206 clear_y = dl->ypos - dl->ascent;
1207 clear_height = lheight;
1211 clear_y = dl->ypos - dl->ascent + pheight;
1212 clear_height = lheight - pheight;
1215 if (start_pixpos >= 0 && start_pixpos > xpos)
1217 clear_x = start_pixpos;
1218 clear_width = xpos + width - start_pixpos;
1223 clear_width = width;
1226 redisplay_clear_region (window, findex, clear_x, clear_y,
1227 clear_width, clear_height);
1230 /* Output the pixmap. */
1232 Lisp_Object tmp_pixel;
1233 GdkColor *tmp_bcolor, *tmp_fcolor;
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));
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);
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))
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));
1259 gc = gtk_get_gc (d, Qnil, cursor_cachel->background, Qnil, Qnil, Qnil);
1261 if (cursor_width > xpos + pwidth - cursor_start)
1262 cursor_width = xpos + pwidth - cursor_start;
1264 gdk_draw_rectangle (GDK_DRAWABLE (x_win), gc, focus ? TRUE : FALSE,
1265 cursor_start, y, cursor_width,
1270 /*****************************************************************************
1271 gtk_output_vertical_divider
1273 Draw a vertical divider down the right side of the given window.
1274 ****************************************************************************/
1276 gtk_output_vertical_divider (struct window *w, int clear)
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;
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);
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);
1296 memset (&gcv, ~0, sizeof (gcv));
1298 tmp_pixel = WINDOW_FACE_CACHEL_BACKGROUND (w, div_face);
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;
1305 background_gc = gc_cache_lookup (DEVICE_GTK_GC_CACHE (d), &gcv, mask);
1307 /* Clear the divider area first. This needs to be done when a
1308 window split occurs. */
1310 gdk_draw_rectangle (GDK_DRAWABLE (x_win), background_gc, TRUE,
1311 x, y1, width, y2 - y1);
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);
1320 /* Draw the shadows around the divider line */
1321 gtk_output_shadows (f, x + spacing, y1,
1322 width - 2 * spacing, y2 - y1,
1326 /*****************************************************************************
1329 Output a blank by clearing the area it covers in the foreground color
1331 ****************************************************************************/
1333 gtk_output_blank (struct window *w, struct display_line *dl, struct rune *rb,
1334 int start_pixpos, int cursor_start, int cursor_width)
1336 struct frame *f = XFRAME (w->frame);
1337 struct device *d = XDEVICE (f->device);
1339 GdkWindow *x_win = GET_GTK_WIDGET_WINDOW (FRAME_GTK_TEXT_WIDGET (f));
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,
1351 int y = dl->ypos - dl->ascent;
1352 int width = rb->width;
1353 int height = dl->ascent + dl->descent - dl->clip;
1355 if (start_pixpos > x)
1357 if (start_pixpos >= (x + width))
1361 width -= (start_pixpos - x);
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)))
1372 gc = gtk_get_gc (d, Qnil, WINDOW_FACE_CACHEL_BACKGROUND (w, rb->findex),
1375 gc = gtk_get_gc (d, Qnil, WINDOW_FACE_CACHEL_FOREGROUND (w, rb->findex),
1376 WINDOW_FACE_CACHEL_BACKGROUND (w, rb->findex), bg_pmap,
1379 gdk_draw_rectangle (GDK_DRAWABLE (x_win), gc, TRUE, x, y, width, height);
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
1386 && (cursor_start + cursor_width > x)
1387 && cursor_start < (x + width))))
1389 int cursor_height, cursor_y;
1390 int focus = EQ (w->frame, DEVICE_FRAME_WITH_FOCUS_REAL (d));
1391 struct Lisp_Font_Instance *fi;
1393 fi = XFONT_INSTANCE (FACE_CACHEL_FONT
1394 (WINDOW_FACE_CACHEL (w, rb->findex),
1397 gc = gtk_get_gc (d, Qnil, cursor_cachel->background, Qnil, Qnil, Qnil);
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;
1406 if (NILP (bar_cursor_value))
1408 gdk_draw_rectangle (GDK_DRAWABLE (x_win), gc, TRUE,
1409 cursor_start, cursor_y,
1410 fi->width, cursor_height);
1414 int bar_width = EQ (bar_cursor_value, Qt) ? 1 : 2;
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);
1423 else if (NILP (bar_cursor_value))
1425 gdk_draw_rectangle (GDK_DRAWABLE (x_win), gc, FALSE,
1426 cursor_start, cursor_y,
1427 fi->width - 1, cursor_height - 1);
1432 /*****************************************************************************
1435 Output a horizontal line in the foreground of its face.
1436 ****************************************************************************/
1438 gtk_output_hline (struct window *w, struct display_line *dl, struct rune *rb)
1440 struct frame *f = XFRAME (w->frame);
1441 struct device *d = XDEVICE (f->device);
1442 GtkStyle *style = FRAME_GTK_TEXT_WIDGET (f)->style;
1444 GdkWindow *x_win = GET_GTK_WIDGET_WINDOW (FRAME_GTK_TEXT_WIDGET (f));
1448 int width = rb->width;
1449 int height = dl->ascent + dl->descent - dl->clip;
1451 int ypos1, ypos2, ypos3, ypos4;
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;
1458 /* First clear the area not covered by the line. */
1459 if (height - rb->object.hline.thickness > 0)
1461 gc = gtk_get_gc (d, Qnil, WINDOW_FACE_CACHEL_FOREGROUND (w, rb->findex),
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);
1470 gtk_paint_hline (style, x_win, GTK_STATE_NORMAL, NULL, FRAME_GTK_TEXT_WIDGET (f),
1471 "hline", x, x + width, ypos2);
1473 /* Now draw the line. */
1474 gc = gtk_get_gc (d, Qnil, WINDOW_FACE_CACHEL_BACKGROUND (w, rb->findex),
1482 if (ypos3 - ypos2 > 0)
1483 gdk_draw_rectangle (GDK_DRAWABLE (x_win), gc, TRUE, x, ypos2, width, ypos3 - ypos2);
1487 /*****************************************************************************
1490 Draw a shadow around the given area using the standard theme engine routines.
1491 ****************************************************************************/
1493 gtk_output_shadows (struct frame *f, int x, int y, int width, int height,
1494 int shadow_thickness)
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;
1500 if (shadow_thickness < 0)
1502 stype = GTK_SHADOW_IN;
1504 else if (shadow_thickness == 0)
1506 stype = GTK_SHADOW_NONE;
1509 /* Do we want to have some magic constants to set
1510 GTK_SHADOW_ETCHED_IN or GTK_SHADOW_ETCHED_OUT? */
1512 gtk_paint_shadow (style, x_win, GTK_STATE_NORMAL, stype, NULL,
1513 FRAME_GTK_TEXT_WIDGET (f), "modeline",
1514 x, y, width, height);
1517 /*****************************************************************************
1518 gtk_clear_to_window_end
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
1523 ****************************************************************************/
1525 gtk_clear_to_window_end (struct window *w, int ypos1, int ypos2)
1527 int height = ypos2 - ypos1;
1531 struct frame *f = XFRAME (w->frame);
1533 int bflag = (window_needs_vertical_divider (w) ? 0 : 1);
1534 layout_bounds bounds;
1536 bounds = calculate_display_line_boundaries (w, bflag);
1537 XSETWINDOW (window, w);
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);
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);
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);
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);
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);
1565 /*****************************************************************************
1566 gtk_redraw_exposed_window
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
1571 ****************************************************************************/
1573 gtk_redraw_exposed_window (struct window *w, int x, int y, int width, int height)
1575 struct frame *f = XFRAME (w->frame);
1577 int start_x, start_y, end_x, end_y;
1578 int orig_windows_structure_changed;
1580 display_line_dynarr *cdla = window_display_lines (w, CURRENT_DISP);
1582 if (!NILP (w->vchild))
1584 gtk_redraw_exposed_windows (w->vchild, x, y, width, height);
1587 else if (!NILP (w->hchild))
1589 gtk_redraw_exposed_windows (w->hchild, x, y, width, height);
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))
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);
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;
1612 if (window_needs_vertical_divider (w))
1614 gtk_output_vertical_divider (w, 0);
1617 for (line = 0; line < Dynarr_length (cdla); line++)
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;
1623 if (bottom_y >= start_y)
1634 output_display_line (w, 0, cdla, line, start_x, end_x);
1639 f->windows_structure_changed = orig_windows_structure_changed;
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);
1647 /*****************************************************************************
1648 gtk_redraw_exposed_windows
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 ****************************************************************************/
1654 gtk_redraw_exposed_windows (Lisp_Object window, int x, int y, int width,
1657 for (; !NILP (window); window = XWINDOW (window)->next)
1658 gtk_redraw_exposed_window (XWINDOW (window), x, y, width, height);
1661 /*****************************************************************************
1662 gtk_redraw_exposed_area
1664 For each window on the given frame, ensure that any area in the
1665 Exposed area is redrawn.
1666 ****************************************************************************/
1668 gtk_redraw_exposed_area (struct frame *f, int x, int y, int width, int height)
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. */
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
1680 MAYBE_FRAMEMETH (f, redraw_exposed_toolbars, (f, x, y, width, height));
1682 redraw_exposed_gutters (f, x, y, width, height);
1684 if (!f->window_face_cache_reset)
1686 gtk_redraw_exposed_windows (f->root_window, x, y, width, height);
1689 MARK_FRAME_CHANGED (f);
1692 /****************************************************************************
1695 Clear the area in the box defined by the given parameters using the
1697 ****************************************************************************/
1699 gtk_clear_region (Lisp_Object locale, struct device* d, struct frame* f, face_index findex,
1701 int width, int height, Lisp_Object fcolor, Lisp_Object bcolor,
1702 Lisp_Object background_pixmap)
1707 x_win = GET_GTK_WIDGET_WINDOW (FRAME_GTK_TEXT_WIDGET (f));
1709 if (!UNBOUNDP (background_pixmap))
1711 gc = gtk_get_gc (d, Qnil, fcolor, bcolor, background_pixmap, Qnil);
1716 gdk_draw_rectangle (GDK_DRAWABLE (x_win), gc,TRUE,
1717 x, y, width, height);
1721 gdk_window_clear_area (x_win, x, y, width, height);
1725 /*****************************************************************************
1726 gtk_output_eol_cursor
1728 Draw a cursor at the end of a line. The end-of-line cursor is
1729 narrower than the normal cursor.
1730 ****************************************************************************/
1732 gtk_output_eol_cursor (struct window *w, struct display_line *dl, int xpos,
1735 struct frame *f = XFRAME (w->frame);
1736 struct device *d = XDEVICE (f->device);
1739 GdkWindow *x_win = GET_GTK_WIDGET_WINDOW (FRAME_GTK_TEXT_WIDGET (f));
1741 face_index elt = get_builtin_face_cache_index (w, Vtext_cursor_face);
1742 struct face_cachel *cursor_cachel = WINDOW_FACE_CACHEL (w, elt);
1744 int focus = EQ (w->frame, DEVICE_FRAME_WITH_FOCUS_REAL (d));
1745 Lisp_Object bar_cursor_value = symbol_value_in_buffer (Qbar_cursor,
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;
1755 XSETWINDOW (window, w);
1756 redisplay_clear_region (window, findex, x, y, width, height);
1758 if (NILP (w->text_cursor_visible_p))
1761 gc = gtk_get_gc (d, Qnil, cursor_cachel->background, Qnil, Qnil, Qnil);
1763 default_face_font_info (window, &defascent, 0, &defheight, 0, 0);
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));
1772 if (NILP (bar_cursor_value))
1774 gdk_draw_rectangle (GDK_DRAWABLE (x_win), gc, TRUE, x, cursor_y, width, cursor_height);
1778 int bar_width = EQ (bar_cursor_value, Qt) ? 1 : 2;
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);
1786 else if (NILP (bar_cursor_value))
1788 gdk_draw_rectangle (GDK_DRAWABLE (x_win), gc, FALSE, x, cursor_y, width - 1,
1794 gtk_clear_frame_window (Lisp_Object window)
1796 struct window *w = XWINDOW (window);
1798 if (!NILP (w->vchild))
1800 gtk_clear_frame_windows (w->vchild);
1804 if (!NILP (w->hchild))
1806 gtk_clear_frame_windows (w->hchild);
1810 gtk_clear_to_window_end (w, WINDOW_TEXT_TOP (w), WINDOW_TEXT_BOTTOM (w));
1814 gtk_clear_frame_windows (Lisp_Object window)
1816 for (; !NILP (window); window = XWINDOW (window)->next)
1817 gtk_clear_frame_window (window);
1821 gtk_clear_frame (struct frame *f)
1823 GdkWindow *x_win = GET_GTK_WIDGET_WINDOW (FRAME_GTK_TEXT_WIDGET (f));
1824 int x, y, width, height;
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;
1841 gdk_window_clear_area (x_win, x, y, width, height);
1843 XSETFRAME (frame, f);
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)))
1849 gtk_clear_frame_windows (f->root_window);
1854 gtk_flash (struct device *d)
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));
1863 XSETFRAME (frame, f);
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)));
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);
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);
1885 #else /* !HAVE_POLL */
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);
1897 #endif /* HAVE_POLL */
1898 #endif /* HAVE_SELECT */
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);
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)
1914 struct frame *f = XFRAME (w->frame);
1915 struct device *d = XDEVICE (f->device);
1917 gtk_output_shadows (f, x, y, width, height, shadow_thickness);
1922 /* Make audible bell. */
1924 gtk_ring_bell (struct device *d, int volume, int pitch, int duration)
1926 /* Gdk does not allow us to control the duration / pitch / volume */
1931 /************************************************************************/
1932 /* initialization */
1933 /************************************************************************/
1936 console_type_create_redisplay_gtk (void)
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); */
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
1959 #include <gdk/gdkx.h>
1962 gdk_draw_text_image (GdkDrawable *drawable,
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);
1974 gdk_draw_rectangle (drawable, gc, TRUE, x, y, width, height);
1975 gdk_draw_text (drawable, font, gc, x, y, text, text_length);
1977 GdkWindowPrivate *drawable_private;
1978 GdkFontPrivate *font_private;
1979 GdkGCPrivate *gc_private;
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);
1986 drawable_private = (GdkWindowPrivate*) drawable;
1987 if (drawable_private->destroyed)
1989 gc_private = (GdkGCPrivate*) gc;
1990 font_private = (GdkFontPrivate*) font;
1992 if (font->type == GDK_FONT_FONT)
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))
1998 XDrawImageString (drawable_private->xdisplay, drawable_private->xwindow,
1999 gc_private->xgc, x, y, text, text_length);
2003 XDrawImageString16 (drawable_private->xdisplay, drawable_private->xwindow,
2004 gc_private->xgc, x, y, (XChar2b *) text, text_length / 2);
2007 else if (font->type == GDK_FONT_FONTSET)
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);
2014 g_error("undefined font type\n");
2019 our_draw_bitmap (GdkDrawable *drawable,
2029 GdkWindowPrivate *drawable_private;
2030 GdkWindowPrivate *src_private;
2031 GdkGCPrivate *gc_private;
2033 g_return_if_fail (drawable != NULL);
2034 g_return_if_fail (src != NULL);
2035 g_return_if_fail (gc != NULL);
2037 drawable_private = (GdkWindowPrivate*) drawable;
2038 src_private = (GdkWindowPrivate*) src;
2039 if (drawable_private->destroyed || src_private->destroyed)
2041 gc_private = (GdkGCPrivate*) gc;
2044 width = src_private->width;
2046 height = src_private->height;
2048 XCopyPlane (drawable_private->xdisplay,
2049 src_private->xwindow,
2050 drawable_private->xwindow,