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 */
56 #define EOL_CURSOR_WIDTH 5
58 static void gtk_output_pixmap (struct window *w, struct display_line *dl,
59 Lisp_Object image_instance, int xpos,
61 int start_pixpos, int width, face_index findex,
62 int cursor_start, int cursor_width,
64 static void gtk_output_vertical_divider (struct window *w, int clear);
65 static void gtk_output_blank (struct window *w, struct display_line *dl,
66 struct rune *rb, int start_pixpos,
67 int cursor_start, int cursor_width);
68 static void gtk_output_hline (struct window *w, struct display_line *dl,
70 static void gtk_redraw_exposed_window (struct window *w, int x, int y,
71 int width, int height);
72 static void gtk_redraw_exposed_windows (Lisp_Object window, int x, int y,
73 int width, int height);
74 static void gtk_clear_region (Lisp_Object locale, struct device* d, struct frame* f,
75 face_index findex, int x, int y,
76 int width, int height, Lisp_Object fcolor, Lisp_Object bcolor,
77 Lisp_Object background_pixmap);
78 static void gtk_output_eol_cursor (struct window *w, struct display_line *dl,
79 int xpos, face_index findex);
80 static void gtk_clear_frame (struct frame *f);
81 static void gtk_clear_frame_windows (Lisp_Object window);
82 static void gtk_bevel_modeline (struct window *w, struct display_line *dl);
85 static void __describe_gc (GdkGC *);
96 /* Separate out the text in DYN into a series of textual runs of a
97 particular charset. Also convert the characters as necessary into
98 the format needed by XDrawImageString(), XDrawImageString16(), et
99 al. (This means converting to one or two byte format, possibly
100 tweaking the high bits, and possibly running a CCL program.) You
101 must pre-allocate the space used and pass it in. (This is done so
102 you can alloca() the space.) You need to allocate (2 * len) bytes
103 of TEXT_STORAGE and (len * sizeof (struct textual_run)) bytes of
104 RUN_STORAGE, where LEN is the length of the dynarr.
106 Returns the number of runs actually used. */
109 separate_textual_runs (unsigned char *text_storage,
110 struct textual_run *run_storage,
111 CONST Emchar *str, Charcount len)
113 Lisp_Object prev_charset = Qunbound; /* not Qnil because that is a
114 possible valid charset when
115 MULE is not defined */
119 struct ccl_program char_converter;
120 int need_ccl_conversion = 0;
123 for (i = 0; i < len; i++)
131 BREAKUP_CHAR (ch, charset, byte1, byte2);
132 dimension = XCHARSET_DIMENSION (charset);
133 graphic = XCHARSET_GRAPHIC (charset);
135 if (!EQ (charset, prev_charset))
137 run_storage[runs_so_far].ptr = text_storage;
138 run_storage[runs_so_far].charset = charset;
139 run_storage[runs_so_far].dimension = dimension;
143 run_storage[runs_so_far - 1].len =
144 text_storage - run_storage[runs_so_far - 1].ptr;
145 if (run_storage[runs_so_far - 1].dimension == 2)
146 run_storage[runs_so_far - 1].len >>= 1;
149 prev_charset = charset;
152 Lisp_Object ccl_prog = XCHARSET_CCL_PROGRAM (charset);
153 need_ccl_conversion = !NILP (ccl_prog);
154 if (need_ccl_conversion)
155 setup_ccl_program (&char_converter, ccl_prog);
165 else if (graphic == 1)
171 if (need_ccl_conversion)
173 char_converter.reg[0] = XCHARSET_ID (charset);
174 char_converter.reg[1] = byte1;
175 char_converter.reg[2] = byte2;
176 ccl_driver (&char_converter, 0, 0, 0, 0, CCL_MODE_ENCODING);
177 byte1 = char_converter.reg[1];
178 byte2 = char_converter.reg[2];
181 *text_storage++ = (unsigned char) byte1;
183 *text_storage++ = (unsigned char) byte2;
188 run_storage[runs_so_far - 1].len =
189 text_storage - run_storage[runs_so_far - 1].ptr;
190 if (run_storage[runs_so_far - 1].dimension == 2)
191 run_storage[runs_so_far - 1].len >>= 1;
197 /****************************************************************************/
199 /* Gtk output routines */
201 /****************************************************************************/
204 gtk_text_width_single_run (struct face_cachel *cachel, struct textual_run *run)
206 Lisp_Object font_inst = FACE_CACHEL_FONT (cachel, run->charset);
207 struct Lisp_Font_Instance *fi = XFONT_INSTANCE (font_inst);
209 if (!fi->proportional_p)
211 return fi->width * run->len;
215 if (run->dimension == 2)
217 stderr_out ("Measuring wide characters\n");
218 return gdk_text_width_wc (FONT_INSTANCE_GTK_FONT (fi),
219 (GdkWChar *) run->ptr, run->len);
223 return gdk_text_width (FONT_INSTANCE_GTK_FONT (fi),
224 (char *) run->ptr, run->len);
232 Given a string and a face, return the string's length in pixels when
233 displayed in the font associated with the face.
237 gtk_text_width (struct frame *f, struct face_cachel *cachel, CONST Emchar *str,
240 int width_so_far = 0;
241 unsigned char *text_storage = (unsigned char *) alloca (2 * len);
242 struct textual_run *runs = alloca_array (struct textual_run, len);
246 nruns = separate_textual_runs (text_storage, runs, str, len);
248 for (i = 0; i < nruns; i++)
249 width_so_far += gtk_text_width_single_run (cachel, runs + i);
254 /*****************************************************************************
257 Return the height of the horizontal divider. This is a function because
258 divider_height is a device method.
260 #### If we add etched horizontal divider lines this will have to get
262 ****************************************************************************/
264 gtk_divider_height (void)
269 /*****************************************************************************
272 Return the width of the end-of-line cursor. This is a function
273 because eol_cursor_width is a device method.
274 ****************************************************************************/
276 gtk_eol_cursor_width (void)
278 return EOL_CURSOR_WIDTH;
281 /*****************************************************************************
282 gtk_output_display_block
284 Given a display line, a block number for that start line, output all
285 runes between start and end in the specified display block.
286 ****************************************************************************/
288 gtk_output_display_block (struct window *w, struct display_line *dl, int block,
289 int start, int end, int start_pixpos, int cursor_start,
290 int cursor_width, int cursor_height)
292 struct frame *f = XFRAME (w->frame);
293 Emchar_dynarr *buf = Dynarr_new (Emchar);
296 struct display_block *db = Dynarr_atp (dl->display_blocks, block);
297 rune_dynarr *rba = db->runes;
303 Lisp_Object charset = Qunbound; /* Qnil is a valid charset when
304 MULE is not defined */
306 XSETWINDOW (window, w);
307 rb = Dynarr_atp (rba, start);
311 /* Nothing to do so don't do anything. */
319 if (rb->type == RUNE_CHAR)
320 charset = CHAR_CHARSET (rb->object.chr.ch);
324 end = Dynarr_length (rba);
329 rb = Dynarr_atp (rba, elt);
331 if (rb->findex == findex && rb->type == RUNE_CHAR
332 && rb->object.chr.ch != '\n' && rb->cursor_type != CURSOR_ON
333 && EQ (charset, CHAR_CHARSET (rb->object.chr.ch)))
335 Dynarr_add (buf, rb->object.chr.ch);
341 if (Dynarr_length (buf))
343 gtk_output_string (w, dl, buf, xpos, 0, start_pixpos, width,
344 findex, 0, cursor_start, cursor_width,
352 if (rb->type == RUNE_CHAR)
356 charset = CHAR_CHARSET (rb->object.chr.ch);
358 if (rb->cursor_type == CURSOR_ON)
360 if (rb->object.chr.ch == '\n')
362 gtk_output_eol_cursor (w, dl, xpos, findex);
366 Dynarr_add (buf, rb->object.chr.ch);
367 gtk_output_string (w, dl, buf, xpos, 0, start_pixpos,
368 rb->width, findex, 1,
369 cursor_start, cursor_width,
377 else if (rb->object.chr.ch == '\n')
379 /* Clear in case a cursor was formerly here. */
380 int height = dl->ascent + dl->descent - dl->clip;
382 redisplay_clear_region (window, findex, xpos, dl->ypos - dl->ascent,
387 else if (rb->type == RUNE_BLANK || rb->type == RUNE_HLINE)
389 if (rb->type == RUNE_BLANK)
390 gtk_output_blank (w, dl, rb, start_pixpos, cursor_start,
394 /* #### Our flagging of when we need to redraw the
395 modeline shadows sucks. Since RUNE_HLINE is only used
396 by the modeline at the moment it is a good bet
397 that if it gets redrawn then we should also
398 redraw the shadows. This won't be true forever.
399 We borrow the shadow_thickness_changed flag for
401 w->shadow_thickness_changed = 1;
402 gtk_output_hline (w, dl, rb);
408 rb = Dynarr_atp (rba, elt);
414 else if (rb->type == RUNE_DGLYPH)
416 Lisp_Object instance;
417 struct display_box dbox;
418 struct display_glyph_area dga;
419 redisplay_calculate_display_boxes (dl, rb->xpos, rb->object.dglyph.xoffset,
420 start_pixpos, rb->width,
423 XSETWINDOW (window, w);
424 instance = glyph_image_instance (rb->object.dglyph.glyph,
425 window, ERROR_ME_NOT, 1);
428 if (IMAGE_INSTANCEP (instance))
429 switch (XIMAGE_INSTANCE_TYPE (instance))
433 /* #### This is way losing. See the comment in
436 XIMAGE_INSTANCE_TEXT_STRING (instance);
437 convert_bufbyte_string_into_emchar_dynarr
438 (XSTRING_DATA (string), XSTRING_LENGTH (string), buf);
440 gtk_output_string (w, dl, buf, xpos,
441 rb->object.dglyph.xoffset,
442 start_pixpos, -1, findex,
443 (rb->cursor_type == CURSOR_ON),
444 cursor_start, cursor_width,
450 case IMAGE_MONO_PIXMAP:
451 case IMAGE_COLOR_PIXMAP:
452 gtk_output_pixmap (w, dl, instance, xpos,
453 rb->object.dglyph.xoffset, start_pixpos,
454 rb->width, findex, cursor_start,
455 cursor_width, cursor_height);
462 if (EQ (XIMAGE_INSTANCE_WIDGET_TYPE (instance),
465 redisplay_output_layout (window, instance, &dbox,
467 cursor_start, cursor_width,
472 case IMAGE_SUBWINDOW:
473 redisplay_output_subwindow (w, instance, &dbox, &dga,
474 findex, cursor_start,
475 cursor_width, cursor_height);
479 /* nothing is as nothing does */
494 if (Dynarr_length (buf))
495 gtk_output_string (w, dl, buf, xpos, 0, start_pixpos, width, findex,
496 0, cursor_start, cursor_width, cursor_height);
498 /* #### This is really conditionalized well for optimized
501 && !EQ (Qzero, w->modeline_shadow_thickness)
503 || f->windows_structure_changed
504 || w->shadow_thickness_changed))
505 gtk_bevel_modeline (w, dl);
510 /*****************************************************************************
513 Draw a 3d border around the modeline on window W.
514 ****************************************************************************/
516 gtk_bevel_modeline (struct window *w, struct display_line *dl)
518 struct frame *f = XFRAME (w->frame);
519 int shadow_thickness = MODELINE_SHADOW_THICKNESS (w);
520 int x,y, width, height;
522 x = WINDOW_MODELINE_LEFT (w);
523 width = WINDOW_MODELINE_RIGHT (w) - x;
524 y = dl->ypos - dl->ascent - shadow_thickness;
525 height = dl->ascent + dl->descent + 2 * shadow_thickness;
527 gtk_output_shadows (f, x, y, width, height, shadow_thickness);
530 /*****************************************************************************
533 Given a number of parameters return a GC with those properties.
534 ****************************************************************************/
536 gtk_get_gc (struct device *d, Lisp_Object font, Lisp_Object fg, Lisp_Object bg,
537 Lisp_Object bg_pmap, Lisp_Object lwidth)
542 memset (&gcv, ~0, sizeof (gcv));
543 gcv.graphics_exposures = FALSE;
544 /* Make absolutely sure that we don't pick up a clipping region in
545 the GC returned by this function. */
547 gcv.clip_x_origin = 0;
548 gcv.clip_y_origin = 0;
549 gcv.fill = GDK_SOLID;
550 mask = GDK_GC_EXPOSURES | GDK_GC_CLIP_MASK | GDK_GC_CLIP_X_ORIGIN | GDK_GC_CLIP_Y_ORIGIN;
555 gcv.font = FONT_INSTANCE_GTK_FONT (XFONT_INSTANCE (font));
560 if (!NILP (fg) && !COLOR_INSTANCEP (fg) && !INTP (fg))
562 /* #### I fixed once case where this was getting it. It was a
563 bad macro expansion (compiler bug). */
564 fprintf (stderr, "Help! gtk_get_gc got a bogus fg value! fg = ");
571 if (COLOR_INSTANCEP (fg))
572 gcv.foreground = * COLOR_INSTANCE_GTK_COLOR (XCOLOR_INSTANCE (fg));
574 gcv.foreground.pixel = XINT (fg);
575 mask |= GDK_GC_FOREGROUND;
580 if (COLOR_INSTANCEP (bg))
581 gcv.background = * COLOR_INSTANCE_GTK_COLOR (XCOLOR_INSTANCE (bg));
583 gcv.background.pixel = XINT (fg);
584 mask |= GDK_GC_BACKGROUND;
587 if (IMAGE_INSTANCEP (bg_pmap)
588 && IMAGE_INSTANCE_PIXMAP_TYPE_P (XIMAGE_INSTANCE (bg_pmap)))
590 if (XIMAGE_INSTANCE_PIXMAP_DEPTH (bg_pmap) == 0)
592 gcv.fill = GDK_OPAQUE_STIPPLED;
593 gcv.stipple = XIMAGE_INSTANCE_GTK_PIXMAP (bg_pmap);
594 mask |= (GDK_GC_STIPPLE | GDK_GC_FILL);
598 gcv.fill = GDK_TILED;
599 gcv.tile = XIMAGE_INSTANCE_GTK_PIXMAP (bg_pmap);
600 mask |= (GDK_GC_TILE | GDK_GC_FILL);
606 gcv.line_width = XINT (lwidth);
607 mask |= GDK_GC_LINE_WIDTH;
610 return gc_cache_lookup (DEVICE_GTK_GC_CACHE (d), &gcv, mask);
613 /*****************************************************************************
616 Given a string and a starting position, output that string in the
617 given face. If cursor is true, draw a cursor around the string.
618 Correctly handles multiple charsets in the string.
620 The meaning of the parameters is something like this:
622 W Window that the text is to be displayed in.
623 DL Display line that this text is on. The values in the
624 structure are used to determine the vertical position and
625 clipping range of the text.
626 BUF Dynamic array of Emchars specifying what is actually to be
628 XPOS X position in pixels where the text should start being drawn.
629 XOFFSET Number of pixels to be chopped off the left side of the
630 text. The effect is as if the text were shifted to the
631 left this many pixels and clipped at XPOS.
632 CLIP_START Clip everything left of this X position.
633 WIDTH Clip everything right of XPOS + WIDTH.
634 FINDEX Index for the face cache element describing how to display
636 CURSOR #### I don't understand this. There's something
637 strange and overcomplexified with this variable.
638 Chuck, explain please?
639 CURSOR_START Starting X position of cursor.
640 CURSOR_WIDTH Width of cursor in pixels.
641 CURSOR_HEIGHT Height of cursor in pixels.
643 Starting Y position of cursor is the top of the text line.
644 The cursor is drawn sometimes whether or not CURSOR is set. ???
645 ****************************************************************************/
647 gdk_draw_text_image (GdkDrawable *drawable,
656 gtk_output_string (struct window *w, struct display_line *dl,
657 Emchar_dynarr *buf, int xpos, int xoffset, int clip_start,
658 int width, face_index findex, int cursor,
659 int cursor_start, int cursor_width, int cursor_height)
661 /* General variables */
662 struct frame *f = XFRAME (w->frame);
663 struct device *d = XDEVICE (f->device);
666 GdkWindow *x_win = GET_GTK_WIDGET_WINDOW (FRAME_GTK_TEXT_WIDGET (f));
670 /* Cursor-related variables */
671 int focus = EQ (w->frame, DEVICE_FRAME_WITH_FOCUS_REAL (d));
673 Lisp_Object bar_cursor_value = symbol_value_in_buffer (Qbar_cursor,
675 struct face_cachel *cursor_cachel = 0;
677 /* Text-related variables */
681 int len = Dynarr_length (buf);
682 unsigned char *text_storage = (unsigned char *) alloca (2 * len);
683 struct textual_run *runs = alloca_array (struct textual_run, len);
686 struct face_cachel *cachel = WINDOW_FACE_CACHEL (w, findex);
688 XSETDEVICE (device, d);
689 XSETWINDOW (window, w);
692 width = gtk_text_width (f, cachel, Dynarr_atp (buf, 0), Dynarr_length (buf));
693 height = dl->ascent + dl->descent - dl->clip;
695 /* Regularize the variables passed in. */
697 if (clip_start < xpos)
699 clip_end = xpos + width;
700 if (clip_start >= clip_end)
701 /* It's all clipped out. */
706 nruns = separate_textual_runs (text_storage, runs, Dynarr_atp (buf, 0),
707 Dynarr_length (buf));
709 cursor_clip = (cursor_start >= clip_start &&
710 cursor_start < clip_end);
712 /* This cursor code is really a mess. */
713 if (!NILP (w->text_cursor_visible_p)
717 && (cursor_start + cursor_width >= clip_start)
718 && !NILP (bar_cursor_value))))
720 /* These have to be in separate statements in order to avoid a
722 face_index sucks = get_builtin_face_cache_index (w, Vtext_cursor_face);
723 cursor_cachel = WINDOW_FACE_CACHEL (w, sucks);
725 /* We have to reset this since any call to WINDOW_FACE_CACHEL
726 may cause the cache to resize and any pointers to it to
728 cachel = WINDOW_FACE_CACHEL (w, findex);
731 bg_pmap = cachel->background_pixmap;
732 if (!IMAGE_INSTANCEP (bg_pmap)
733 || !IMAGE_INSTANCE_PIXMAP_TYPE_P (XIMAGE_INSTANCE (bg_pmap)))
736 if ((cursor && focus && NILP (bar_cursor_value)
737 && !NILP (w->text_cursor_visible_p)) || NILP (bg_pmap))
740 bgc = gtk_get_gc (d, Qnil, cachel->foreground, cachel->background,
744 gdk_draw_rectangle (GDK_DRAWABLE (x_win), bgc, TRUE, clip_start,
745 dl->ypos - dl->ascent, clip_end - clip_start,
748 for (i = 0; i < nruns; i++)
750 Lisp_Object font = FACE_CACHEL_FONT (cachel, runs[i].charset);
751 struct Lisp_Font_Instance *fi = XFONT_INSTANCE (font);
752 GdkFont *gdk_font = FONT_INSTANCE_GTK_FONT (fi);
756 if (EQ (font, Vthe_null_font_instance))
759 this_width = gtk_text_width_single_run (cachel, runs + i);
760 need_clipping = (dl->clip || clip_start > xpos ||
761 clip_end < xpos + this_width);
763 /* XDrawImageString only clears the area equal to the height of
764 the given font. It is possible that a font is being displayed
765 on a line taller than it is, so this would cause us to fail to
767 if ((int) fi->height < (int) (height + dl->clip))
769 int clear_start = max (xpos, clip_start);
770 int clear_end = min (xpos + this_width, clip_end);
774 int ypos1_line, ypos1_string, ypos2_line, ypos2_string;
776 ypos1_string = dl->ypos - fi->ascent;
777 ypos2_string = dl->ypos + fi->descent;
778 ypos1_line = dl->ypos - dl->ascent;
779 ypos2_line = dl->ypos + dl->descent - dl->clip;
781 /* Make sure we don't clear below the real bottom of the
783 if (ypos1_string > ypos2_line)
784 ypos1_string = ypos2_line;
785 if (ypos2_string > ypos2_line)
786 ypos2_string = ypos2_line;
788 if (ypos1_line < ypos1_string)
790 redisplay_clear_region (window, findex, clear_start, ypos1_line,
791 clear_end - clear_start,
792 ypos1_string - ypos1_line);
795 if (ypos2_line > ypos2_string)
797 redisplay_clear_region (window, findex, clear_start, ypos2_string,
798 clear_end - clear_start,
799 ypos2_line - ypos2_string);
804 redisplay_clear_region (window, findex, clear_start,
805 dl->ypos - dl->ascent, clear_end - clear_start,
810 if (cursor && cursor_cachel && focus && NILP (bar_cursor_value))
812 gc = gtk_get_gc (d, font, cursor_cachel->foreground,
813 cursor_cachel->background, Qnil, Qnil);
817 gc = gtk_get_gc (d, font, cachel->foreground, cachel->background,
823 GdkRectangle clip_box;
827 clip_box.width = clip_end - clip_start;
828 clip_box.height = height;
830 gdk_gc_set_clip_rectangle (gc, &clip_box);
831 gdk_gc_set_clip_origin (gc, clip_start, dl->ypos - dl->ascent);
834 /* The X specific called different functions (XDraw*String
835 vs. XDraw*String16), but apparently gdk_draw_text takes care
838 BUT, gdk_draw_text also does too much, by dividing the length
839 by 2. So we fake them out my multiplying the length by the
840 dimension of the text. This will do the right thing for
841 single-dimension runs as well of course.
843 (bgc ? gdk_draw_text : gdk_draw_text_image) (GDK_DRAWABLE (x_win), gdk_font, gc, xpos,
844 dl->ypos, (char *) runs[i].ptr,
845 runs[i].len * runs[i].dimension);
847 /* We draw underlines in the same color as the text. */
848 if (cachel->underline)
850 unsigned long upos, uthick;
852 /* Cannot get at font properties in Gtk, so we resort to
854 upos = dl->descent / 2;
857 if (dl->ypos + upos < dl->ypos + dl->descent - dl->clip)
859 if (dl->ypos + upos + uthick > dl->ypos + dl->descent - dl->clip)
860 uthick = dl->descent - dl->clip - upos;
864 gdk_draw_line (GDK_DRAWABLE (x_win), gc, xpos, dl->ypos + upos,
865 xpos + this_width, dl->ypos + upos);
869 gdk_draw_rectangle (GDK_DRAWABLE (x_win), gc, TRUE, xpos,
870 dl->ypos + upos, this_width, uthick);
875 if (cachel->strikethru) {
876 unsigned long ascent,descent,upos, uthick;
877 GdkFont *gfont = FONT_INSTANCE_GTK_FONT (XFONT_INSTANCE (font));
879 /* Cannot get at font properties in Gtk, so we resort to
882 ascent = gfont->ascent;
883 descent = gfont->descent;
886 upos = ascent - ((ascent + descent) / 2) + 1;
888 /* Generally, upos will be positive (above the baseline),so subtract */
889 if (dl->ypos - upos < dl->ypos + dl->descent - dl->clip)
891 if (dl->ypos - upos + uthick > dl->ypos + dl->descent - dl->clip)
892 uthick = dl->descent - dl->clip + upos;
896 gdk_draw_line (GDK_DRAWABLE (x_win), gc, xpos, dl->ypos - upos,
897 xpos + this_width, dl->ypos - upos);
901 gdk_draw_rectangle (GDK_DRAWABLE (x_win), gc, TRUE, xpos, dl->ypos + upos,
910 gdk_gc_set_clip_rectangle (gc, NULL);
911 gdk_gc_set_clip_origin (gc, 0, 0);
914 /* If we are actually superimposing the cursor then redraw with just
915 the appropriate section highlighted. */
916 if (cursor_clip && !cursor && focus && cursor_cachel)
919 GdkRectangle clip_box;
921 cgc = gtk_get_gc (d, font, cursor_cachel->foreground,
922 cursor_cachel->background, Qnil, Qnil);
926 clip_box.width = cursor_width;
927 clip_box.height = height;
929 gdk_gc_set_clip_rectangle (cgc, &clip_box);
930 gdk_gc_set_clip_origin (cgc, cursor_start, dl->ypos - dl->ascent);
932 /* The X specific called different functions (XDraw*String
933 vs. XDraw*String16), but apparently gdk_draw_text takes care
936 BUT, gdk_draw_text also does too much, by dividing the
937 length by 2. So we fake them out my multiplying the
938 length by the dimension of the text. This will do the
939 right thing for single-dimension runs as well of course.
941 gdk_draw_text_image (GDK_DRAWABLE (x_win), gdk_font, cgc, xpos,
942 dl->ypos, (char *) runs[i].ptr,
943 runs[i].len * runs[i].dimension);
945 gdk_gc_set_clip_rectangle (cgc, NULL);
946 gdk_gc_set_clip_origin (cgc, 0, 0);
952 /* Draw the non-focus box or bar-cursor as needed. */
953 /* Can't this logic be simplified? */
955 && ((cursor && !focus && NILP (bar_cursor_value))
957 && (cursor_start + cursor_width >= clip_start)
958 && !NILP (bar_cursor_value))))
960 int tmp_height, tmp_y;
961 int bar_width = EQ (bar_cursor_value, Qt) ? 1 : 2;
962 int need_clipping = (cursor_start < clip_start
963 || clip_end < cursor_start + cursor_width);
965 /* #### This value is correct (as far as I know) because
966 all of the times we need to draw this cursor, we will
967 be called with exactly one character, so we know we
968 can always use runs[0].
970 This is bogus as all hell, however. The cursor handling in
971 this function is way bogus and desperately needs to be
972 cleaned up. (In particular, the drawing of the cursor should
973 really really be separated out of this function. This may be
974 a bit tricky now because this function itself does way too
975 much stuff, a lot of which needs to be moved into
976 redisplay.c) This is the only way to be able to easily add
977 new cursor types or (e.g.) make the bar cursor be able to
978 span two characters instead of overlaying just one. */
979 int bogusly_obtained_ascent_value =
980 XFONT_INSTANCE (FACE_CACHEL_FONT (cachel, runs[0].charset))->ascent;
982 if (!NILP (bar_cursor_value))
984 gc = gtk_get_gc (d, Qnil, cursor_cachel->background, Qnil, Qnil,
985 make_int (bar_width));
989 gc = gtk_get_gc (d, Qnil, cursor_cachel->background,
993 tmp_y = dl->ypos - bogusly_obtained_ascent_value;
994 tmp_height = cursor_height;
995 if (tmp_y + tmp_height > (int) (dl->ypos - dl->ascent + height))
997 tmp_y = dl->ypos - dl->ascent + height - tmp_height;
998 if (tmp_y < (int) (dl->ypos - dl->ascent))
999 tmp_y = dl->ypos - dl->ascent;
1000 tmp_height = dl->ypos - dl->ascent + height - tmp_y;
1005 GdkRectangle clip_box;
1008 clip_box.width = clip_end - clip_start;
1009 clip_box.height = tmp_height;
1011 gdk_gc_set_clip_rectangle (gc, &clip_box);
1012 gdk_gc_set_clip_origin (gc, clip_start, tmp_y);
1015 if (!focus && NILP (bar_cursor_value))
1017 gdk_draw_rectangle (GDK_DRAWABLE (x_win), gc, FALSE,
1018 cursor_start, tmp_y,
1019 cursor_width - 1, tmp_height - 1);
1021 else if (focus && !NILP (bar_cursor_value))
1023 gdk_draw_line (GDK_DRAWABLE (x_win), gc,
1024 cursor_start + bar_width - 1, tmp_y,
1025 cursor_start + bar_width - 1, tmp_y + tmp_height - 1);
1028 /* Restore the GC */
1031 gdk_gc_set_clip_rectangle (gc, NULL);
1032 gdk_gc_set_clip_origin (gc, 0, 0);
1038 our_draw_bitmap (GdkDrawable *drawable,
1049 gtk_output_gdk_pixmap (struct frame *f, struct Lisp_Image_Instance *p, int x,
1050 int y, int clip_x, int clip_y, int clip_width,
1051 int clip_height, int width, int height, int pixmap_offset,
1052 GdkColor *fg, GdkColor *bg, GdkGC *override_gc)
1054 struct device *d = XDEVICE (f->device);
1055 GdkWindow *x_win = GET_GTK_WIDGET_WINDOW (FRAME_GTK_TEXT_WIDGET (f));
1059 unsigned long pixmap_mask;
1060 int need_clipping = (clip_x || clip_y);
1064 memset (&gcv, ~0, sizeof (gcv));
1065 gcv.graphics_exposures = FALSE;
1066 gcv.foreground = *fg;
1067 gcv.background = *bg;
1068 pixmap_mask = GDK_GC_FOREGROUND | GDK_GC_BACKGROUND | GDK_GC_EXPOSURES;
1070 if (IMAGE_INSTANCE_GTK_MASK (p))
1072 gcv.function = GDK_COPY;
1073 gcv.clip_mask = IMAGE_INSTANCE_GTK_MASK (p);
1074 gcv.clip_x_origin = x;
1075 gcv.clip_y_origin = y - pixmap_offset;
1076 pixmap_mask |= (GDK_GC_FUNCTION | GDK_GC_CLIP_MASK | GDK_GC_CLIP_X_ORIGIN |
1077 GDK_GC_CLIP_Y_ORIGIN);
1078 /* Can't set a clip rectangle below because we already have a mask.
1079 We could conceivably create a new clipmask by zeroing out
1080 everything outside the clip region. Is it worth it?
1081 Is it possible to get an equivalent effect by changing the
1082 args to XCopyArea below rather than messing with a clip box?
1083 - dkindred@cs.cmu.edu */
1087 gc = gc_cache_lookup (DEVICE_GTK_GC_CACHE (d), &gcv, pixmap_mask);
1092 /* override_gc might have a mask already--we don't want to nuke it.
1093 Maybe we can insist that override_gc have no mask, or use
1094 one of the suggestions above. */
1100 GdkRectangle clip_box;
1102 clip_box.x = clip_x;
1103 clip_box.y = clip_y;
1104 clip_box.width = clip_width;
1105 clip_box.height = clip_height;
1107 gdk_gc_set_clip_rectangle (gc, &clip_box);
1108 gdk_gc_set_clip_origin (gc, x, y);
1111 if (IMAGE_INSTANCE_PIXMAP_DEPTH (p) > 0)
1113 gdk_draw_pixmap (GDK_DRAWABLE (x_win), gc,
1114 IMAGE_INSTANCE_GTK_PIXMAP (p),
1115 0, pixmap_offset, x, y, width, height);
1119 our_draw_bitmap (GDK_DRAWABLE (x_win), gc,
1120 IMAGE_INSTANCE_GTK_PIXMAP (p),
1121 0, pixmap_offset, x, y, width, height);
1126 gdk_gc_set_clip_rectangle (gc, NULL);
1127 gdk_gc_set_clip_origin (gc, 0, 0);
1132 gtk_output_pixmap (struct window *w, struct display_line *dl,
1133 Lisp_Object image_instance, int xpos, int xoffset,
1134 int start_pixpos, int width, face_index findex,
1135 int cursor_start, int cursor_width, int cursor_height)
1137 struct frame *f = XFRAME (w->frame);
1138 struct device *d = XDEVICE (f->device);
1139 struct Lisp_Image_Instance *p = XIMAGE_INSTANCE (image_instance);
1142 GdkWindow *x_win = GET_GTK_WIDGET_WINDOW (FRAME_GTK_TEXT_WIDGET (f));
1143 int lheight = dl->ascent + dl->descent - dl->clip;
1144 int pheight = ((int) IMAGE_INSTANCE_PIXMAP_HEIGHT (p) > lheight ? lheight :
1145 IMAGE_INSTANCE_PIXMAP_HEIGHT (p));
1146 int pwidth = min (width + xoffset, (int) IMAGE_INSTANCE_PIXMAP_WIDTH (p));
1147 int clip_x, clip_y, clip_width, clip_height;
1149 /* The pixmap_offset is used to center the pixmap on lines which are
1150 shorter than it is. This results in odd effects when scrolling
1151 pixmaps off of the bottom. Let's try not using it. */
1153 int pixmap_offset = (int) (IMAGE_INSTANCE_PIXMAP_HEIGHT (p) - lheight) / 2;
1155 int pixmap_offset = 0;
1158 XSETWINDOW (window, w);
1160 if ((start_pixpos >= 0 && start_pixpos > xpos) || xoffset)
1162 if (start_pixpos > xpos && start_pixpos > xpos + width)
1167 if (start_pixpos > xpos)
1169 clip_x += (start_pixpos - xpos);
1170 clip_width -= (start_pixpos - xpos);
1179 /* Place markers for possible future functionality (clipping the top
1180 half instead of the bottom half; think pixel scrolling). */
1182 clip_height = pheight;
1184 /* Clear the area the pixmap is going into. The pixmap itself will
1185 always take care of the full width. We don't want to clear where
1186 it is going to go in order to avoid flicker. So, all we have to
1187 take care of is any area above or below the pixmap. */
1188 /* #### We take a shortcut for now. We know that since we have
1189 pixmap_offset hardwired to 0 that the pixmap is against the top
1190 edge so all we have to worry about is below it. */
1191 /* #### Unless the pixmap has a mask in which case we have to clear
1192 the whole damn thing since we can't yet clear just the area not
1193 included in the mask. */
1194 if (((int) (dl->ypos - dl->ascent + pheight) <
1195 (int) (dl->ypos + dl->descent - dl->clip))
1196 || IMAGE_INSTANCE_GTK_MASK (p))
1198 int clear_x, clear_y, clear_width, clear_height;
1200 if (IMAGE_INSTANCE_GTK_MASK (p))
1202 clear_y = dl->ypos - dl->ascent;
1203 clear_height = lheight;
1207 clear_y = dl->ypos - dl->ascent + pheight;
1208 clear_height = lheight - pheight;
1211 if (start_pixpos >= 0 && start_pixpos > xpos)
1213 clear_x = start_pixpos;
1214 clear_width = xpos + width - start_pixpos;
1219 clear_width = width;
1222 redisplay_clear_region (window, findex, clear_x, clear_y,
1223 clear_width, clear_height);
1226 /* Output the pixmap. */
1228 Lisp_Object tmp_pixel;
1229 GdkColor *tmp_bcolor, *tmp_fcolor;
1231 tmp_pixel = WINDOW_FACE_CACHEL_FOREGROUND (w, findex);
1232 tmp_fcolor = COLOR_INSTANCE_GTK_COLOR (XCOLOR_INSTANCE (tmp_pixel));
1233 tmp_pixel = WINDOW_FACE_CACHEL_BACKGROUND (w, findex);
1234 tmp_bcolor = COLOR_INSTANCE_GTK_COLOR (XCOLOR_INSTANCE (tmp_pixel));
1236 gtk_output_gdk_pixmap (f, p, xpos - xoffset, dl->ypos - dl->ascent, clip_x,
1237 clip_y, clip_width, clip_height,
1238 pwidth, pheight, pixmap_offset,
1239 tmp_fcolor, tmp_bcolor, 0);
1242 /* Draw a cursor over top of the pixmap. */
1243 if (cursor_width && cursor_height && (cursor_start >= xpos)
1244 && !NILP (w->text_cursor_visible_p)
1245 && (cursor_start < xpos + pwidth))
1248 int focus = EQ (w->frame, DEVICE_FRAME_WITH_FOCUS_REAL (d));
1249 int y = dl->ypos - dl->ascent;
1250 struct face_cachel *cursor_cachel =
1251 WINDOW_FACE_CACHEL (w,
1252 get_builtin_face_cache_index
1253 (w, Vtext_cursor_face));
1255 gc = gtk_get_gc (d, Qnil, cursor_cachel->background, Qnil, Qnil, Qnil);
1257 if (cursor_width > xpos + pwidth - cursor_start)
1258 cursor_width = xpos + pwidth - cursor_start;
1260 gdk_draw_rectangle (GDK_DRAWABLE (x_win), gc, focus ? TRUE : FALSE,
1261 cursor_start, y, cursor_width,
1266 /*****************************************************************************
1267 gtk_output_vertical_divider
1269 Draw a vertical divider down the right side of the given window.
1270 ****************************************************************************/
1272 gtk_output_vertical_divider (struct window *w, int clear)
1274 struct frame *f = XFRAME (w->frame);
1275 struct device *d = XDEVICE (f->device);
1276 GdkWindow *x_win = GET_GTK_WIDGET_WINDOW (FRAME_GTK_TEXT_WIDGET (f));
1277 GdkGC *background_gc;
1278 Lisp_Object tmp_pixel;
1281 int x, y1, y2, width, shadow_thickness, spacing, line_width;
1282 face_index div_face = get_builtin_face_cache_index (w, Vvertical_divider_face);
1284 width = window_divider_width (w);
1285 shadow_thickness = XINT (w->vertical_divider_shadow_thickness);
1286 spacing = XINT (w->vertical_divider_spacing);
1287 line_width = XINT (w->vertical_divider_line_width);
1288 x = WINDOW_RIGHT (w) - width;
1289 y1 = WINDOW_TOP (w);
1290 y2 = WINDOW_BOTTOM (w);
1292 memset (&gcv, ~0, sizeof (gcv));
1294 tmp_pixel = WINDOW_FACE_CACHEL_BACKGROUND (w, div_face);
1296 gcv.background = * COLOR_INSTANCE_GTK_COLOR (XCOLOR_INSTANCE (tmp_pixel));
1297 gcv.foreground = gcv.background;
1298 gcv.graphics_exposures = FALSE;
1299 mask = GDK_GC_FOREGROUND | GDK_GC_BACKGROUND | GDK_GC_EXPOSURES;
1301 background_gc = gc_cache_lookup (DEVICE_GTK_GC_CACHE (d), &gcv, mask);
1303 /* Clear the divider area first. This needs to be done when a
1304 window split occurs. */
1306 gdk_draw_rectangle (GDK_DRAWABLE (x_win), background_gc, TRUE,
1307 x, y1, width, y2 - y1);
1310 /* Draw the divider line. */
1311 gdk_draw_rectangle (GDK_DRAWABLE (x_win), background_gc, TRUE,
1312 x + spacing + shadow_thickness, y1,
1313 line_width, y2 - y1);
1316 /* Draw the shadows around the divider line */
1317 gtk_output_shadows (f, x + spacing, y1,
1318 width - 2 * spacing, y2 - y1,
1322 /*****************************************************************************
1325 Output a blank by clearing the area it covers in the foreground color
1327 ****************************************************************************/
1329 gtk_output_blank (struct window *w, struct display_line *dl, struct rune *rb,
1330 int start_pixpos, int cursor_start, int cursor_width)
1332 struct frame *f = XFRAME (w->frame);
1333 struct device *d = XDEVICE (f->device);
1335 GdkWindow *x_win = GET_GTK_WIDGET_WINDOW (FRAME_GTK_TEXT_WIDGET (f));
1337 struct face_cachel *cursor_cachel =
1338 WINDOW_FACE_CACHEL (w,
1339 get_builtin_face_cache_index
1340 (w, Vtext_cursor_face));
1341 Lisp_Object bg_pmap;
1342 Lisp_Object buffer = WINDOW_BUFFER (w);
1343 Lisp_Object bar_cursor_value = symbol_value_in_buffer (Qbar_cursor,
1347 int y = dl->ypos - dl->ascent;
1348 int width = rb->width;
1349 int height = dl->ascent + dl->descent - dl->clip;
1351 if (start_pixpos > x)
1353 if (start_pixpos >= (x + width))
1357 width -= (start_pixpos - x);
1362 bg_pmap = WINDOW_FACE_CACHEL_BACKGROUND_PIXMAP (w, rb->findex);
1363 if (!IMAGE_INSTANCEP (bg_pmap)
1364 || !IMAGE_INSTANCE_PIXMAP_TYPE_P (XIMAGE_INSTANCE (bg_pmap)))
1368 gc = gtk_get_gc (d, Qnil, WINDOW_FACE_CACHEL_BACKGROUND (w, rb->findex),
1371 gc = gtk_get_gc (d, Qnil, WINDOW_FACE_CACHEL_FOREGROUND (w, rb->findex),
1372 WINDOW_FACE_CACHEL_BACKGROUND (w, rb->findex), bg_pmap,
1375 gdk_draw_rectangle (GDK_DRAWABLE (x_win), gc, TRUE, x, y, width, height);
1377 /* If this rune is marked as having the cursor, then it is actually
1378 representing a tab. */
1379 if (!NILP (w->text_cursor_visible_p)
1380 && (rb->cursor_type == CURSOR_ON
1382 && (cursor_start + cursor_width > x)
1383 && cursor_start < (x + width))))
1385 int cursor_height, cursor_y;
1386 int focus = EQ (w->frame, DEVICE_FRAME_WITH_FOCUS_REAL (d));
1387 struct Lisp_Font_Instance *fi;
1389 fi = XFONT_INSTANCE (FACE_CACHEL_FONT
1390 (WINDOW_FACE_CACHEL (w, rb->findex),
1393 gc = gtk_get_gc (d, Qnil, cursor_cachel->background, Qnil, Qnil, Qnil);
1395 cursor_y = dl->ypos - fi->ascent;
1396 cursor_height = fi->height;
1397 if (cursor_y + cursor_height > y + height)
1398 cursor_height = y + height - cursor_y;
1402 if (NILP (bar_cursor_value))
1404 gdk_draw_rectangle (GDK_DRAWABLE (x_win), gc, TRUE,
1405 cursor_start, cursor_y,
1406 fi->width, cursor_height);
1410 int bar_width = EQ (bar_cursor_value, Qt) ? 1 : 2;
1412 gc = gtk_get_gc (d, Qnil, cursor_cachel->background, Qnil, Qnil,
1413 make_int (bar_width));
1414 gdk_draw_line (GDK_DRAWABLE (x_win), gc, cursor_start + bar_width - 1,
1415 cursor_y, cursor_start + bar_width - 1,
1416 cursor_y + cursor_height - 1);
1419 else if (NILP (bar_cursor_value))
1421 gdk_draw_rectangle (GDK_DRAWABLE (x_win), gc, FALSE,
1422 cursor_start, cursor_y,
1423 fi->width - 1, cursor_height - 1);
1428 /*****************************************************************************
1431 Output a horizontal line in the foreground of its face.
1432 ****************************************************************************/
1434 gtk_output_hline (struct window *w, struct display_line *dl, struct rune *rb)
1436 struct frame *f = XFRAME (w->frame);
1437 struct device *d = XDEVICE (f->device);
1438 GtkStyle *style = FRAME_GTK_TEXT_WIDGET (f)->style;
1440 GdkWindow *x_win = GET_GTK_WIDGET_WINDOW (FRAME_GTK_TEXT_WIDGET (f));
1444 int width = rb->width;
1445 int height = dl->ascent + dl->descent - dl->clip;
1447 int ypos1, ypos2, ypos3, ypos4;
1449 ypos1 = dl->ypos - dl->ascent;
1450 ypos2 = ypos1 + rb->object.hline.yoffset;
1451 ypos3 = ypos2 + rb->object.hline.thickness;
1452 ypos4 = dl->ypos + dl->descent - dl->clip;
1454 /* First clear the area not covered by the line. */
1455 if (height - rb->object.hline.thickness > 0)
1457 gc = gtk_get_gc (d, Qnil, WINDOW_FACE_CACHEL_FOREGROUND (w, rb->findex),
1460 if (ypos2 - ypos1 > 0)
1461 gdk_draw_rectangle (GDK_DRAWABLE (x_win), gc, TRUE, x, ypos1, width, ypos2 - ypos1);
1462 if (ypos4 - ypos3 > 0)
1463 gdk_draw_rectangle (GDK_DRAWABLE (x_win), gc, TRUE, x, ypos1, width, ypos2 - ypos1);
1466 gtk_paint_hline (style, x_win, GTK_STATE_NORMAL, NULL, FRAME_GTK_TEXT_WIDGET (f),
1467 "hline", x, x + width, ypos2);
1469 /* Now draw the line. */
1470 gc = gtk_get_gc (d, Qnil, WINDOW_FACE_CACHEL_BACKGROUND (w, rb->findex),
1478 if (ypos3 - ypos2 > 0)
1479 gdk_draw_rectangle (GDK_DRAWABLE (x_win), gc, TRUE, x, ypos2, width, ypos3 - ypos2);
1483 /*****************************************************************************
1486 Draw a shadow around the given area using the standard theme engine routines.
1487 ****************************************************************************/
1489 gtk_output_shadows (struct frame *f, int x, int y, int width, int height,
1490 int shadow_thickness)
1492 GdkWindow *x_win = GET_GTK_WIDGET_WINDOW (FRAME_GTK_TEXT_WIDGET (f));
1493 GtkStyle *style = FRAME_GTK_TEXT_WIDGET (f)->style;
1494 GtkShadowType stype = GTK_SHADOW_OUT;
1496 if (shadow_thickness < 0)
1498 stype = GTK_SHADOW_IN;
1500 else if (shadow_thickness == 0)
1502 stype = GTK_SHADOW_NONE;
1505 /* Do we want to have some magic constants to set
1506 GTK_SHADOW_ETCHED_IN or GTK_SHADOW_ETCHED_OUT? */
1508 gtk_paint_shadow (style, x_win, GTK_STATE_NORMAL, stype, NULL,
1509 FRAME_GTK_TEXT_WIDGET (f), "modeline",
1510 x, y, width, height);
1513 /*****************************************************************************
1514 gtk_clear_to_window_end
1516 Clear the area between ypos1 and ypos2. Each margin area and the
1517 text area is handled separately since they may each have their own
1519 ****************************************************************************/
1521 gtk_clear_to_window_end (struct window *w, int ypos1, int ypos2)
1523 int height = ypos2 - ypos1;
1527 struct frame *f = XFRAME (w->frame);
1529 int bflag = (window_needs_vertical_divider (w) ? 0 : 1);
1530 layout_bounds bounds;
1532 bounds = calculate_display_line_boundaries (w, bflag);
1533 XSETWINDOW (window, w);
1535 if (window_is_leftmost (w))
1536 redisplay_clear_region (window, DEFAULT_INDEX, FRAME_LEFT_BORDER_START (f),
1537 ypos1, FRAME_BORDER_WIDTH (f), height);
1539 if (bounds.left_in - bounds.left_out > 0)
1540 redisplay_clear_region (window,
1541 get_builtin_face_cache_index (w, Vleft_margin_face),
1542 bounds.left_out, ypos1,
1543 bounds.left_in - bounds.left_out, height);
1545 if (bounds.right_in - bounds.left_in > 0)
1546 redisplay_clear_region (window, DEFAULT_INDEX, bounds.left_in, ypos1,
1547 bounds.right_in - bounds.left_in, height);
1549 if (bounds.right_out - bounds.right_in > 0)
1550 redisplay_clear_region (window,
1551 get_builtin_face_cache_index (w, Vright_margin_face),
1552 bounds.right_in, ypos1,
1553 bounds.right_out - bounds.right_in, height);
1555 if (window_is_rightmost (w))
1556 redisplay_clear_region (window, DEFAULT_INDEX, FRAME_RIGHT_BORDER_START (f),
1557 ypos1, FRAME_BORDER_WIDTH (f), height);
1561 /*****************************************************************************
1562 gtk_redraw_exposed_window
1564 Given a bounding box for an area that needs to be redrawn, determine
1565 what parts of what lines are contained within and re-output their
1567 ****************************************************************************/
1569 gtk_redraw_exposed_window (struct window *w, int x, int y, int width, int height)
1571 struct frame *f = XFRAME (w->frame);
1573 int start_x, start_y, end_x, end_y;
1574 int orig_windows_structure_changed;
1576 display_line_dynarr *cdla = window_display_lines (w, CURRENT_DISP);
1578 if (!NILP (w->vchild))
1580 gtk_redraw_exposed_windows (w->vchild, x, y, width, height);
1583 else if (!NILP (w->hchild))
1585 gtk_redraw_exposed_windows (w->hchild, x, y, width, height);
1589 /* If the window doesn't intersect the exposed region, we're done here. */
1590 if (x >= WINDOW_RIGHT (w) || (x + width) <= WINDOW_LEFT (w)
1591 || y >= WINDOW_BOTTOM (w) || (y + height) <= WINDOW_TOP (w))
1597 start_x = max (WINDOW_LEFT (w), x);
1598 end_x = min (WINDOW_RIGHT (w), (x + width));
1599 start_y = max (WINDOW_TOP (w), y);
1600 end_y = min (WINDOW_BOTTOM (w), y + height);
1602 /* We do this to make sure that the 3D modelines get redrawn if
1603 they are in the exposed region. */
1604 orig_windows_structure_changed = f->windows_structure_changed;
1605 f->windows_structure_changed = 1;
1608 if (window_needs_vertical_divider (w))
1610 gtk_output_vertical_divider (w, 0);
1613 for (line = 0; line < Dynarr_length (cdla); line++)
1615 struct display_line *cdl = Dynarr_atp (cdla, line);
1616 int top_y = cdl->ypos - cdl->ascent;
1617 int bottom_y = cdl->ypos + cdl->descent;
1619 if (bottom_y >= start_y)
1630 output_display_line (w, 0, cdla, line, start_x, end_x);
1635 f->windows_structure_changed = orig_windows_structure_changed;
1637 /* If there have never been any face cache_elements created, then this
1638 expose event doesn't actually have anything to do. */
1639 if (Dynarr_largest (w->face_cachels))
1640 redisplay_clear_bottom_of_window (w, cdla, start_y, end_y);
1643 /*****************************************************************************
1644 gtk_redraw_exposed_windows
1646 For each window beneath the given window in the window hierarchy,
1647 ensure that it is redrawn if necessary after an Expose event.
1648 ****************************************************************************/
1650 gtk_redraw_exposed_windows (Lisp_Object window, int x, int y, int width,
1653 for (; !NILP (window); window = XWINDOW (window)->next)
1654 gtk_redraw_exposed_window (XWINDOW (window), x, y, width, height);
1657 /*****************************************************************************
1658 gtk_redraw_exposed_area
1660 For each window on the given frame, ensure that any area in the
1661 Exposed area is redrawn.
1662 ****************************************************************************/
1664 gtk_redraw_exposed_area (struct frame *f, int x, int y, int width, int height)
1666 /* If any window on the frame has had its face cache reset then the
1667 redisplay structures are effectively invalid. If we attempt to
1668 use them we'll blow up. We mark the frame as changed to ensure
1669 that redisplay will do a full update. This probably isn't
1670 necessary but it can't hurt. */
1672 #ifdef HAVE_TOOLBARS
1673 /* #### We would rather put these off as well but there is currently
1674 no combination of flags which will force an unchanged toolbar to
1676 MAYBE_FRAMEMETH (f, redraw_exposed_toolbars, (f, x, y, width, height));
1678 redraw_exposed_gutters (f, x, y, width, height);
1680 if (!f->window_face_cache_reset)
1682 gtk_redraw_exposed_windows (f->root_window, x, y, width, height);
1685 MARK_FRAME_CHANGED (f);
1688 /****************************************************************************
1691 Clear the area in the box defined by the given parameters using the
1693 ****************************************************************************/
1695 gtk_clear_region (Lisp_Object locale, struct device* d, struct frame* f, face_index findex,
1697 int width, int height, Lisp_Object fcolor, Lisp_Object bcolor,
1698 Lisp_Object background_pixmap)
1703 x_win = GET_GTK_WIDGET_WINDOW (FRAME_GTK_TEXT_WIDGET (f));
1705 if (!UNBOUNDP (background_pixmap))
1707 gc = gtk_get_gc (d, Qnil, fcolor, bcolor, background_pixmap, Qnil);
1712 gdk_draw_rectangle (GDK_DRAWABLE (x_win), gc,TRUE,
1713 x, y, width, height);
1717 gdk_window_clear_area (x_win, x, y, width, height);
1721 /*****************************************************************************
1722 gtk_output_eol_cursor
1724 Draw a cursor at the end of a line. The end-of-line cursor is
1725 narrower than the normal cursor.
1726 ****************************************************************************/
1728 gtk_output_eol_cursor (struct window *w, struct display_line *dl, int xpos,
1731 struct frame *f = XFRAME (w->frame);
1732 struct device *d = XDEVICE (f->device);
1735 GdkWindow *x_win = GET_GTK_WIDGET_WINDOW (FRAME_GTK_TEXT_WIDGET (f));
1737 face_index elt = get_builtin_face_cache_index (w, Vtext_cursor_face);
1738 struct face_cachel *cursor_cachel = WINDOW_FACE_CACHEL (w, elt);
1740 int focus = EQ (w->frame, DEVICE_FRAME_WITH_FOCUS_REAL (d));
1741 Lisp_Object bar_cursor_value = symbol_value_in_buffer (Qbar_cursor,
1745 int y = dl->ypos - dl->ascent;
1746 int width = EOL_CURSOR_WIDTH;
1747 int height = dl->ascent + dl->descent - dl->clip;
1748 int cursor_height, cursor_y;
1749 int defheight, defascent;
1751 XSETWINDOW (window, w);
1752 redisplay_clear_region (window, findex, x, y, width, height);
1754 if (NILP (w->text_cursor_visible_p))
1757 gc = gtk_get_gc (d, Qnil, cursor_cachel->background, Qnil, Qnil, Qnil);
1759 default_face_font_info (window, &defascent, 0, &defheight, 0, 0);
1761 /* make sure the cursor is entirely contained between y and y+height */
1762 cursor_height = min (defheight, height);
1763 cursor_y = max (y, min (y + height - cursor_height,
1764 dl->ypos - defascent));
1768 if (NILP (bar_cursor_value))
1770 gdk_draw_rectangle (GDK_DRAWABLE (x_win), gc, TRUE, x, cursor_y, width, cursor_height);
1774 int bar_width = EQ (bar_cursor_value, Qt) ? 1 : 2;
1776 gc = gtk_get_gc (d, Qnil, cursor_cachel->background, Qnil, Qnil,
1777 make_int (bar_width));
1778 gdk_draw_line (GDK_DRAWABLE (x_win), gc, x + bar_width - 1, cursor_y,
1779 x + bar_width - 1, cursor_y + cursor_height - 1);
1782 else if (NILP (bar_cursor_value))
1784 gdk_draw_rectangle (GDK_DRAWABLE (x_win), gc, FALSE, x, cursor_y, width - 1,
1790 gtk_clear_frame_window (Lisp_Object window)
1792 struct window *w = XWINDOW (window);
1794 if (!NILP (w->vchild))
1796 gtk_clear_frame_windows (w->vchild);
1800 if (!NILP (w->hchild))
1802 gtk_clear_frame_windows (w->hchild);
1806 gtk_clear_to_window_end (w, WINDOW_TEXT_TOP (w), WINDOW_TEXT_BOTTOM (w));
1810 gtk_clear_frame_windows (Lisp_Object window)
1812 for (; !NILP (window); window = XWINDOW (window)->next)
1813 gtk_clear_frame_window (window);
1817 gtk_clear_frame (struct frame *f)
1819 GdkWindow *x_win = GET_GTK_WIDGET_WINDOW (FRAME_GTK_TEXT_WIDGET (f));
1820 int x, y, width, height;
1823 x = FRAME_LEFT_BORDER_START (f);
1824 width = (FRAME_PIXWIDTH (f) - FRAME_REAL_LEFT_TOOLBAR_WIDTH (f) -
1825 FRAME_REAL_RIGHT_TOOLBAR_WIDTH (f) -
1826 2 * FRAME_REAL_LEFT_TOOLBAR_BORDER_WIDTH (f) -
1827 2 * FRAME_REAL_RIGHT_TOOLBAR_BORDER_WIDTH (f));
1828 /* #### This adjustment by 1 should be being done in the macros.
1829 There is some small differences between when the menubar is on
1830 and off that we still need to deal with. */
1831 y = FRAME_TOP_BORDER_START (f) - 1;
1832 height = (FRAME_PIXHEIGHT (f) - FRAME_REAL_TOP_TOOLBAR_HEIGHT (f) -
1833 FRAME_REAL_BOTTOM_TOOLBAR_HEIGHT (f) -
1834 2 * FRAME_REAL_TOP_TOOLBAR_BORDER_WIDTH (f) -
1835 2 * FRAME_REAL_BOTTOM_TOOLBAR_BORDER_WIDTH (f)) + 1;
1837 gdk_window_clear_area (x_win, x, y, width, height);
1839 XSETFRAME (frame, f);
1841 if (!UNBOUNDP (FACE_BACKGROUND_PIXMAP (Vdefault_face, frame))
1842 || !UNBOUNDP (FACE_BACKGROUND_PIXMAP (Vleft_margin_face, frame))
1843 || !UNBOUNDP (FACE_BACKGROUND_PIXMAP (Vright_margin_face, frame)))
1845 gtk_clear_frame_windows (f->root_window);
1850 gtk_flash (struct device *d)
1854 GdkColor tmp_fcolor, tmp_bcolor;
1855 Lisp_Object tmp_pixel, frame;
1856 struct frame *f = device_selected_frame (d);
1857 struct window *w = XWINDOW (FRAME_ROOT_WINDOW (f));
1859 XSETFRAME (frame, f);
1861 tmp_pixel = FACE_FOREGROUND (Vdefault_face, frame);
1862 tmp_fcolor = * (COLOR_INSTANCE_GTK_COLOR (XCOLOR_INSTANCE (tmp_pixel)));
1863 tmp_pixel = FACE_BACKGROUND (Vdefault_face, frame);
1864 tmp_bcolor = * (COLOR_INSTANCE_GTK_COLOR (XCOLOR_INSTANCE (tmp_pixel)));
1866 memset (&gcv, ~0, sizeof (gcv)); /* initialize all slots to ~0 */
1867 gcv.foreground.pixel = (tmp_fcolor.pixel ^ tmp_bcolor.pixel);
1868 gcv.function = GDK_XOR;
1869 gcv.graphics_exposures = FALSE;
1870 gc = gc_cache_lookup (DEVICE_GTK_GC_CACHE (XDEVICE (f->device)), &gcv,
1871 GDK_GC_FOREGROUND | GDK_GC_FUNCTION | GDK_GC_EXPOSURES);
1873 gdk_draw_rectangle (GDK_DRAWABLE (GET_GTK_WIDGET_WINDOW (FRAME_GTK_SHELL_WIDGET (f))),
1874 gc, TRUE, w->pixel_left, w->pixel_top,
1875 w->pixel_width, w->pixel_height);
1881 #else /* !HAVE_POLL */
1886 tv.tv_sec = usecs / 1000000L;
1887 tv.tv_usec = usecs % 1000000L;
1888 /* I'm sure someone is going to complain about this... */
1889 select (0, 0, 0, 0, &tv);
1893 #endif /* HAVE_POLL */
1894 #endif /* HAVE_SELECT */
1896 gdk_draw_rectangle (GDK_DRAWABLE (GET_GTK_WIDGET_WINDOW (FRAME_GTK_SHELL_WIDGET (f))),
1897 gc, TRUE, w->pixel_left, w->pixel_top,
1898 w->pixel_width, w->pixel_height);
1906 gtk_bevel_area (struct window *w, face_index findex,
1907 int x, int y, int width, int height,
1908 int shadow_thickness, int edges, enum edge_style style)
1910 struct frame *f = XFRAME (w->frame);
1911 struct device *d = XDEVICE (f->device);
1913 gtk_output_shadows (f, x, y, width, height, shadow_thickness);
1918 /* Make audible bell. */
1920 gtk_ring_bell (struct device *d, int volume, int pitch, int duration)
1922 /* Gdk does not allow us to control the duration / pitch / volume */
1927 /************************************************************************/
1928 /* initialization */
1929 /************************************************************************/
1932 console_type_create_redisplay_gtk (void)
1934 /* redisplay methods */
1935 CONSOLE_HAS_METHOD (gtk, text_width);
1936 CONSOLE_HAS_METHOD (gtk, output_display_block);
1937 CONSOLE_HAS_METHOD (gtk, divider_height);
1938 CONSOLE_HAS_METHOD (gtk, eol_cursor_width);
1939 CONSOLE_HAS_METHOD (gtk, output_vertical_divider);
1940 CONSOLE_HAS_METHOD (gtk, clear_to_window_end);
1941 CONSOLE_HAS_METHOD (gtk, clear_region);
1942 CONSOLE_HAS_METHOD (gtk, clear_frame);
1943 CONSOLE_HAS_METHOD (gtk, flash);
1944 CONSOLE_HAS_METHOD (gtk, ring_bell);
1945 CONSOLE_HAS_METHOD (gtk, bevel_area);
1946 CONSOLE_HAS_METHOD (gtk, output_string);
1947 /* CONSOLE_HAS_METHOD (gtk, output_pixmap); */
1950 /* This makes me feel incredibly dirty... but there is no other way to
1951 get this done right other than calling clear_area before every
1952 single $#!%@ing piece of text, which I do NOT want to do. */
1953 #define USE_X_SPECIFIC_DRAW_ROUTINES 1
1955 #include <gdk/gdkx.h>
1958 gdk_draw_text_image (GdkDrawable *drawable,
1966 #if !USE_X_SPECIFIC_DRAW_ROUTINES
1967 int width = gdk_text_measure (font, text, text_length);
1968 int height = gdk_text_height (font, text, text_length);
1970 gdk_draw_rectangle (drawable, gc, TRUE, x, y, width, height);
1971 gdk_draw_text (drawable, font, gc, x, y, text, text_length);
1973 GdkWindowPrivate *drawable_private;
1974 GdkFontPrivate *font_private;
1975 GdkGCPrivate *gc_private;
1977 g_return_if_fail (drawable != NULL);
1978 g_return_if_fail (font != NULL);
1979 g_return_if_fail (gc != NULL);
1980 g_return_if_fail (text != NULL);
1982 drawable_private = (GdkWindowPrivate*) drawable;
1983 if (drawable_private->destroyed)
1985 gc_private = (GdkGCPrivate*) gc;
1986 font_private = (GdkFontPrivate*) font;
1988 if (font->type == GDK_FONT_FONT)
1990 XFontStruct *xfont = (XFontStruct *) font_private->xfont;
1991 XSetFont(drawable_private->xdisplay, gc_private->xgc, xfont->fid);
1992 if ((xfont->min_byte1 == 0) && (xfont->max_byte1 == 0))
1994 XDrawImageString (drawable_private->xdisplay, drawable_private->xwindow,
1995 gc_private->xgc, x, y, text, text_length);
1999 XDrawImageString16 (drawable_private->xdisplay, drawable_private->xwindow,
2000 gc_private->xgc, x, y, (XChar2b *) text, text_length / 2);
2003 else if (font->type == GDK_FONT_FONTSET)
2005 XFontSet fontset = (XFontSet) font_private->xfont;
2006 XmbDrawImageString (drawable_private->xdisplay, drawable_private->xwindow,
2007 fontset, gc_private->xgc, x, y, text, text_length);
2010 g_error("undefined font type\n");
2015 our_draw_bitmap (GdkDrawable *drawable,
2025 GdkWindowPrivate *drawable_private;
2026 GdkWindowPrivate *src_private;
2027 GdkGCPrivate *gc_private;
2029 g_return_if_fail (drawable != NULL);
2030 g_return_if_fail (src != NULL);
2031 g_return_if_fail (gc != NULL);
2033 drawable_private = (GdkWindowPrivate*) drawable;
2034 src_private = (GdkWindowPrivate*) src;
2035 if (drawable_private->destroyed || src_private->destroyed)
2037 gc_private = (GdkGCPrivate*) gc;
2040 width = src_private->width;
2042 height = src_private->height;
2044 XCopyPlane (drawable_private->xdisplay,
2045 src_private->xwindow,
2046 drawable_private->xwindow,