462
+ − 1 /* X output and frame manipulation routines.
+ − 2 Copyright (C) 1994, 1995 Board of Trustees, University of Illinois.
+ − 3 Copyright (C) 1994 Lucid, Inc.
+ − 4 Copyright (C) 1995 Sun Microsystems, Inc.
+ − 5
+ − 6 This file is part of XEmacs.
+ − 7
+ − 8 XEmacs is free software; you can redistribute it and/or modify it
+ − 9 under the terms of the GNU General Public License as published by the
+ − 10 Free Software Foundation; either version 2, or (at your option) any
+ − 11 later version.
+ − 12
+ − 13 XEmacs is distributed in the hope that it will be useful, but WITHOUT
+ − 14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ − 15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ − 16 for more details.
+ − 17
+ − 18 You should have received a copy of the GNU General Public License
+ − 19 along with XEmacs; see the file COPYING. If not, write to
+ − 20 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ − 21 Boston, MA 02111-1307, USA. */
+ − 22
+ − 23 /* Synched up with: Not in FSF. */
+ − 24
+ − 25 /* Author: Chuck Thompson */
+ − 26 /* Gtk flavor by William Perry */
+ − 27
+ − 28 /* Lots of work done by Ben Wing for Mule */
+ − 29
+ − 30 #include <config.h>
+ − 31 #include "lisp.h"
+ − 32
+ − 33 #include "console-gtk.h"
+ − 34 #include "gccache-gtk.h"
+ − 35 #include "glyphs-gtk.h"
+ − 36 #include "objects-gtk.h"
+ − 37
+ − 38 #include "buffer.h"
+ − 39 #include "debug.h"
+ − 40 #include "faces.h"
+ − 41 #include "frame.h"
+ − 42 #include "gutter.h"
+ − 43 #include "redisplay.h"
+ − 44 #include "sysdep.h"
+ − 45 #include "window.h"
+ − 46
+ − 47 #include "sysproc.h" /* for select() */
+ − 48
+ − 49 #ifdef MULE
+ − 50 #include "mule-ccl.h"
+ − 51 #include "file-coding.h" /* for CCL conversion */
+ − 52 #endif
+ − 53
+ − 54 #define CONST const
+ − 55
+ − 56 #define EOL_CURSOR_WIDTH 5
+ − 57
+ − 58 static void gtk_output_pixmap (struct window *w, struct display_line *dl,
+ − 59 Lisp_Object image_instance, int xpos,
+ − 60 int xoffset,
+ − 61 int start_pixpos, int width, face_index findex,
+ − 62 int cursor_start, int cursor_width,
+ − 63 int cursor_height);
+ − 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,
+ − 69 struct rune *rb);
+ − 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);
+ − 83
+ − 84 #if 0
+ − 85 static void __describe_gc (GdkGC *);
+ − 86 #endif
+ − 87
+ − 88 struct textual_run
+ − 89 {
+ − 90 Lisp_Object charset;
+ − 91 unsigned char *ptr;
+ − 92 int len;
+ − 93 int dimension;
+ − 94 };
+ − 95
+ − 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.
+ − 105
+ − 106 Returns the number of runs actually used. */
+ − 107
+ − 108 static int
+ − 109 separate_textual_runs (unsigned char *text_storage,
+ − 110 struct textual_run *run_storage,
+ − 111 CONST Emchar *str, Charcount len)
+ − 112 {
+ − 113 Lisp_Object prev_charset = Qunbound; /* not Qnil because that is a
+ − 114 possible valid charset when
+ − 115 MULE is not defined */
+ − 116 int runs_so_far = 0;
+ − 117 int i;
+ − 118 #ifdef MULE
+ − 119 struct ccl_program char_converter;
+ − 120 int need_ccl_conversion = 0;
+ − 121 #endif
+ − 122
+ − 123 for (i = 0; i < len; i++)
+ − 124 {
+ − 125 Emchar ch = str[i];
+ − 126 Lisp_Object charset;
+ − 127 int byte1, byte2;
+ − 128 int dimension;
+ − 129 int graphic;
+ − 130
+ − 131 BREAKUP_CHAR (ch, charset, byte1, byte2);
+ − 132 dimension = XCHARSET_DIMENSION (charset);
+ − 133 graphic = XCHARSET_GRAPHIC (charset);
+ − 134
+ − 135 if (!EQ (charset, prev_charset))
+ − 136 {
+ − 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;
+ − 140
+ − 141 if (runs_so_far)
+ − 142 {
+ − 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;
+ − 147 }
+ − 148 runs_so_far++;
+ − 149 prev_charset = charset;
+ − 150 #ifdef MULE
+ − 151 {
+ − 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);
+ − 156 }
+ − 157 #endif
+ − 158 }
+ − 159
+ − 160 if (graphic == 0)
+ − 161 {
+ − 162 byte1 &= 0x7F;
+ − 163 byte2 &= 0x7F;
+ − 164 }
+ − 165 else if (graphic == 1)
+ − 166 {
+ − 167 byte1 |= 0x80;
+ − 168 byte2 |= 0x80;
+ − 169 }
+ − 170 #ifdef MULE
+ − 171 if (need_ccl_conversion)
+ − 172 {
+ − 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];
+ − 179 }
+ − 180 #endif
+ − 181 *text_storage++ = (unsigned char) byte1;
+ − 182 if (dimension == 2)
+ − 183 *text_storage++ = (unsigned char) byte2;
+ − 184 }
+ − 185
+ − 186 if (runs_so_far)
+ − 187 {
+ − 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;
+ − 192 }
+ − 193
+ − 194 return runs_so_far;
+ − 195 }
+ − 196
+ − 197 /****************************************************************************/
+ − 198 /* */
+ − 199 /* Gtk output routines */
+ − 200 /* */
+ − 201 /****************************************************************************/
+ − 202
+ − 203 static int
+ − 204 gtk_text_width_single_run (struct face_cachel *cachel, struct textual_run *run)
+ − 205 {
+ − 206 Lisp_Object font_inst = FACE_CACHEL_FONT (cachel, run->charset);
+ − 207 struct Lisp_Font_Instance *fi = XFONT_INSTANCE (font_inst);
+ − 208
+ − 209 if (!fi->proportional_p)
+ − 210 {
+ − 211 return fi->width * run->len;
+ − 212 }
+ − 213 else
+ − 214 {
+ − 215 if (run->dimension == 2)
+ − 216 {
+ − 217 stderr_out ("Measuring wide characters\n");
+ − 218 return gdk_text_width_wc (FONT_INSTANCE_GTK_FONT (fi),
+ − 219 (GdkWChar *) run->ptr, run->len);
+ − 220 }
+ − 221 else
+ − 222 {
+ − 223 return gdk_text_width (FONT_INSTANCE_GTK_FONT (fi),
+ − 224 (char *) run->ptr, run->len);
+ − 225 }
+ − 226 }
+ − 227 }
+ − 228
+ − 229 /*
+ − 230 gtk_text_width
+ − 231
+ − 232 Given a string and a face, return the string's length in pixels when
+ − 233 displayed in the font associated with the face.
+ − 234 */
+ − 235
+ − 236 static int
+ − 237 gtk_text_width (struct frame *f, struct face_cachel *cachel, CONST Emchar *str,
+ − 238 Charcount len)
+ − 239 {
+ − 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);
+ − 243 int nruns;
+ − 244 int i;
+ − 245
+ − 246 nruns = separate_textual_runs (text_storage, runs, str, len);
+ − 247
+ − 248 for (i = 0; i < nruns; i++)
+ − 249 width_so_far += gtk_text_width_single_run (cachel, runs + i);
+ − 250
+ − 251 return width_so_far;
+ − 252 }
+ − 253
+ − 254 /*****************************************************************************
+ − 255 gtk_divider_height
+ − 256
+ − 257 Return the height of the horizontal divider. This is a function because
+ − 258 divider_height is a device method.
+ − 259
+ − 260 #### If we add etched horizontal divider lines this will have to get
+ − 261 smarter.
+ − 262 ****************************************************************************/
+ − 263 static int
+ − 264 gtk_divider_height (void)
+ − 265 {
+ − 266 return 2;
+ − 267 }
+ − 268
+ − 269 /*****************************************************************************
+ − 270 gtk_eol_cursor_width
+ − 271
+ − 272 Return the width of the end-of-line cursor. This is a function
+ − 273 because eol_cursor_width is a device method.
+ − 274 ****************************************************************************/
+ − 275 static int
+ − 276 gtk_eol_cursor_width (void)
+ − 277 {
+ − 278 return EOL_CURSOR_WIDTH;
+ − 279 }
+ − 280
+ − 281 /*****************************************************************************
+ − 282 gtk_output_display_block
+ − 283
+ − 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 ****************************************************************************/
+ − 287 static void
+ − 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)
+ − 291 {
+ − 292 struct frame *f = XFRAME (w->frame);
+ − 293 Emchar_dynarr *buf = Dynarr_new (Emchar);
+ − 294 Lisp_Object window;
+ − 295
+ − 296 struct display_block *db = Dynarr_atp (dl->display_blocks, block);
+ − 297 rune_dynarr *rba = db->runes;
+ − 298 struct rune *rb;
+ − 299
+ − 300 int elt = start;
+ − 301 face_index findex;
+ − 302 int xpos, width;
+ − 303 Lisp_Object charset = Qunbound; /* Qnil is a valid charset when
+ − 304 MULE is not defined */
+ − 305
+ − 306 XSETWINDOW (window, w);
+ − 307 rb = Dynarr_atp (rba, start);
+ − 308
+ − 309 if (!rb)
+ − 310 {
+ − 311 /* Nothing to do so don't do anything. */
+ − 312 return;
+ − 313 }
+ − 314 else
+ − 315 {
+ − 316 findex = rb->findex;
+ − 317 xpos = rb->xpos;
+ − 318 width = 0;
+ − 319 if (rb->type == RUNE_CHAR)
+ − 320 charset = CHAR_CHARSET (rb->object.chr.ch);
+ − 321 }
+ − 322
+ − 323 if (end < 0)
+ − 324 end = Dynarr_length (rba);
+ − 325 Dynarr_reset (buf);
+ − 326
+ − 327 while (elt < end)
+ − 328 {
+ − 329 rb = Dynarr_atp (rba, elt);
+ − 330
+ − 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)))
+ − 334 {
+ − 335 Dynarr_add (buf, rb->object.chr.ch);
+ − 336 width += rb->width;
+ − 337 elt++;
+ − 338 }
+ − 339 else
+ − 340 {
+ − 341 if (Dynarr_length (buf))
+ − 342 {
+ − 343 gtk_output_string (w, dl, buf, xpos, 0, start_pixpos, width,
+ − 344 findex, 0, cursor_start, cursor_width,
+ − 345 cursor_height);
+ − 346 xpos = rb->xpos;
+ − 347 width = 0;
+ − 348 }
+ − 349 Dynarr_reset (buf);
+ − 350 width = 0;
+ − 351
+ − 352 if (rb->type == RUNE_CHAR)
+ − 353 {
+ − 354 findex = rb->findex;
+ − 355 xpos = rb->xpos;
+ − 356 charset = CHAR_CHARSET (rb->object.chr.ch);
+ − 357
+ − 358 if (rb->cursor_type == CURSOR_ON)
+ − 359 {
+ − 360 if (rb->object.chr.ch == '\n')
+ − 361 {
+ − 362 gtk_output_eol_cursor (w, dl, xpos, findex);
+ − 363 }
+ − 364 else
+ − 365 {
+ − 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,
+ − 370 cursor_height);
+ − 371 Dynarr_reset (buf);
+ − 372 }
+ − 373
+ − 374 xpos += rb->width;
+ − 375 elt++;
+ − 376 }
+ − 377 else if (rb->object.chr.ch == '\n')
+ − 378 {
+ − 379 /* Clear in case a cursor was formerly here. */
+ − 380 int height = dl->ascent + dl->descent - dl->clip;
+ − 381
+ − 382 redisplay_clear_region (window, findex, xpos, dl->ypos - dl->ascent,
+ − 383 rb->width, height);
+ − 384 elt++;
+ − 385 }
+ − 386 }
+ − 387 else if (rb->type == RUNE_BLANK || rb->type == RUNE_HLINE)
+ − 388 {
+ − 389 if (rb->type == RUNE_BLANK)
+ − 390 gtk_output_blank (w, dl, rb, start_pixpos, cursor_start,
+ − 391 cursor_width);
+ − 392 else
+ − 393 {
+ − 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
+ − 400 now. */
+ − 401 w->shadow_thickness_changed = 1;
+ − 402 gtk_output_hline (w, dl, rb);
+ − 403 }
+ − 404
+ − 405 elt++;
+ − 406 if (elt < end)
+ − 407 {
+ − 408 rb = Dynarr_atp (rba, elt);
+ − 409
+ − 410 findex = rb->findex;
+ − 411 xpos = rb->xpos;
+ − 412 }
+ − 413 }
+ − 414 else if (rb->type == RUNE_DGLYPH)
+ − 415 {
+ − 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,
+ − 421 &dbox, &dga);
+ − 422
+ − 423 XSETWINDOW (window, w);
+ − 424 instance = glyph_image_instance (rb->object.dglyph.glyph,
+ − 425 window, ERROR_ME_NOT, 1);
+ − 426 findex = rb->findex;
+ − 427
+ − 428 if (IMAGE_INSTANCEP (instance))
+ − 429 switch (XIMAGE_INSTANCE_TYPE (instance))
+ − 430 {
+ − 431 case IMAGE_TEXT:
+ − 432 {
+ − 433 /* #### This is way losing. See the comment in
+ − 434 add_glyph_rune(). */
+ − 435 Lisp_Object string =
+ − 436 XIMAGE_INSTANCE_TEXT_STRING (instance);
+ − 437 convert_bufbyte_string_into_emchar_dynarr
+ − 438 (XSTRING_DATA (string), XSTRING_LENGTH (string), buf);
+ − 439
+ − 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,
+ − 445 cursor_height);
+ − 446 Dynarr_reset (buf);
+ − 447 }
+ − 448 break;
+ − 449
+ − 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);
+ − 456 break;
+ − 457
+ − 458 case IMAGE_POINTER:
+ − 459 abort ();
+ − 460
+ − 461 case IMAGE_WIDGET:
+ − 462 if (EQ (XIMAGE_INSTANCE_WIDGET_TYPE (instance),
+ − 463 Qlayout))
+ − 464 {
+ − 465 redisplay_output_layout (window, instance, &dbox,
+ − 466 &dga, findex,
+ − 467 cursor_start, cursor_width,
+ − 468 cursor_height);
+ − 469 break;
+ − 470 }
+ − 471
+ − 472 case IMAGE_SUBWINDOW:
+ − 473 redisplay_output_subwindow (w, instance, &dbox, &dga,
+ − 474 findex, cursor_start,
+ − 475 cursor_width, cursor_height);
+ − 476 break;
+ − 477
+ − 478 case IMAGE_NOTHING:
+ − 479 /* nothing is as nothing does */
+ − 480 break;
+ − 481
+ − 482 default:
+ − 483 abort ();
+ − 484 }
+ − 485
+ − 486 xpos += rb->width;
+ − 487 elt++;
+ − 488 }
+ − 489 else
+ − 490 abort ();
+ − 491 }
+ − 492 }
+ − 493
+ − 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);
+ − 497
+ − 498 /* #### This is really conditionalized well for optimized
+ − 499 performance. */
+ − 500 if (dl->modeline
+ − 501 && !EQ (Qzero, w->modeline_shadow_thickness)
+ − 502 && (f->clear
+ − 503 || f->windows_structure_changed
+ − 504 || w->shadow_thickness_changed))
+ − 505 gtk_bevel_modeline (w, dl);
+ − 506
+ − 507 Dynarr_free (buf);
+ − 508 }
+ − 509
+ − 510 /*****************************************************************************
+ − 511 gtk_bevel_modeline
+ − 512
+ − 513 Draw a 3d border around the modeline on window W.
+ − 514 ****************************************************************************/
+ − 515 static void
+ − 516 gtk_bevel_modeline (struct window *w, struct display_line *dl)
+ − 517 {
+ − 518 struct frame *f = XFRAME (w->frame);
+ − 519 int shadow_thickness = MODELINE_SHADOW_THICKNESS (w);
+ − 520 int x,y, width, height;
+ − 521
+ − 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;
+ − 526
+ − 527 gtk_output_shadows (f, x, y, width, height, shadow_thickness);
+ − 528 }
+ − 529
+ − 530 /*****************************************************************************
+ − 531 gtk_get_gc
+ − 532
+ − 533 Given a number of parameters return a GC with those properties.
+ − 534 ****************************************************************************/
+ − 535 GdkGC *
+ − 536 gtk_get_gc (struct device *d, Lisp_Object font, Lisp_Object fg, Lisp_Object bg,
+ − 537 Lisp_Object bg_pmap, Lisp_Object lwidth)
+ − 538 {
+ − 539 GdkGCValues gcv;
+ − 540 unsigned long mask;
+ − 541
+ − 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. */
+ − 546 gcv.clip_mask = 0;
+ − 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;
+ − 551 mask |= GDK_GC_FILL;
+ − 552
+ − 553 if (!NILP (font))
+ − 554 {
+ − 555 gcv.font = FONT_INSTANCE_GTK_FONT (XFONT_INSTANCE (font));
+ − 556 mask |= GDK_GC_FONT;
+ − 557 }
+ − 558
+ − 559 /* evil kludge! */
+ − 560 if (!NILP (fg) && !COLOR_INSTANCEP (fg) && !INTP (fg))
+ − 561 {
+ − 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 = ");
+ − 565 debug_print (fg);
+ − 566 fg = Qnil;
+ − 567 }
+ − 568
+ − 569 if (!NILP (fg))
+ − 570 {
+ − 571 if (COLOR_INSTANCEP (fg))
+ − 572 gcv.foreground = * COLOR_INSTANCE_GTK_COLOR (XCOLOR_INSTANCE (fg));
+ − 573 else
+ − 574 gcv.foreground.pixel = XINT (fg);
+ − 575 mask |= GDK_GC_FOREGROUND;
+ − 576 }
+ − 577
+ − 578 if (!NILP (bg))
+ − 579 {
+ − 580 if (COLOR_INSTANCEP (bg))
+ − 581 gcv.background = * COLOR_INSTANCE_GTK_COLOR (XCOLOR_INSTANCE (bg));
+ − 582 else
+ − 583 gcv.background.pixel = XINT (fg);
+ − 584 mask |= GDK_GC_BACKGROUND;
+ − 585 }
+ − 586
+ − 587 if (IMAGE_INSTANCEP (bg_pmap)
+ − 588 && IMAGE_INSTANCE_PIXMAP_TYPE_P (XIMAGE_INSTANCE (bg_pmap)))
+ − 589 {
+ − 590 if (XIMAGE_INSTANCE_PIXMAP_DEPTH (bg_pmap) == 0)
+ − 591 {
+ − 592 gcv.fill = GDK_OPAQUE_STIPPLED;
+ − 593 gcv.stipple = XIMAGE_INSTANCE_GTK_PIXMAP (bg_pmap);
+ − 594 mask |= (GDK_GC_STIPPLE | GDK_GC_FILL);
+ − 595 }
+ − 596 else
+ − 597 {
+ − 598 gcv.fill = GDK_TILED;
+ − 599 gcv.tile = XIMAGE_INSTANCE_GTK_PIXMAP (bg_pmap);
+ − 600 mask |= (GDK_GC_TILE | GDK_GC_FILL);
+ − 601 }
+ − 602 }
+ − 603
+ − 604 if (!NILP (lwidth))
+ − 605 {
+ − 606 gcv.line_width = XINT (lwidth);
+ − 607 mask |= GDK_GC_LINE_WIDTH;
+ − 608 }
+ − 609
+ − 610 return gc_cache_lookup (DEVICE_GTK_GC_CACHE (d), &gcv, mask);
+ − 611 }
+ − 612
+ − 613 /*****************************************************************************
+ − 614 gtk_output_string
+ − 615
+ − 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.
+ − 619
+ − 620 The meaning of the parameters is something like this:
+ − 621
+ − 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
+ − 627 drawn.
+ − 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
+ − 635 the text.
+ − 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.
+ − 642
+ − 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 ****************************************************************************/
+ − 646 void
+ − 647 gdk_draw_text_image (GdkDrawable *drawable,
+ − 648 GdkFont *font,
+ − 649 GdkGC *gc,
+ − 650 gint x,
+ − 651 gint y,
+ − 652 const gchar *text,
+ − 653 gint text_length);
+ − 654
+ − 655 void
+ − 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)
+ − 660 {
+ − 661 /* General variables */
+ − 662 struct frame *f = XFRAME (w->frame);
+ − 663 struct device *d = XDEVICE (f->device);
+ − 664 Lisp_Object device;
+ − 665 Lisp_Object window;
+ − 666 GdkWindow *x_win = GET_GTK_WIDGET_WINDOW (FRAME_GTK_TEXT_WIDGET (f));
+ − 667
+ − 668 int clip_end;
+ − 669
+ − 670 /* Cursor-related variables */
+ − 671 int focus = EQ (w->frame, DEVICE_FRAME_WITH_FOCUS_REAL (d));
+ − 672 int cursor_clip;
+ − 673 Lisp_Object bar_cursor_value = symbol_value_in_buffer (Qbar_cursor,
+ − 674 WINDOW_BUFFER (w));
+ − 675 struct face_cachel *cursor_cachel = 0;
+ − 676
+ − 677 /* Text-related variables */
+ − 678 Lisp_Object bg_pmap;
+ − 679 GdkGC *bgc, *gc;
+ − 680 int height;
+ − 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);
+ − 684 int nruns;
+ − 685 int i;
+ − 686 struct face_cachel *cachel = WINDOW_FACE_CACHEL (w, findex);
+ − 687
+ − 688 XSETDEVICE (device, d);
+ − 689 XSETWINDOW (window, w);
+ − 690
+ − 691 if (width < 0)
+ − 692 width = gtk_text_width (f, cachel, Dynarr_atp (buf, 0), Dynarr_length (buf));
+ − 693 height = dl->ascent + dl->descent - dl->clip;
+ − 694
+ − 695 /* Regularize the variables passed in. */
+ − 696
+ − 697 if (clip_start < xpos)
+ − 698 clip_start = xpos;
+ − 699 clip_end = xpos + width;
+ − 700 if (clip_start >= clip_end)
+ − 701 /* It's all clipped out. */
+ − 702 return;
+ − 703
+ − 704 xpos -= xoffset;
+ − 705
+ − 706 nruns = separate_textual_runs (text_storage, runs, Dynarr_atp (buf, 0),
+ − 707 Dynarr_length (buf));
+ − 708
+ − 709 cursor_clip = (cursor_start >= clip_start &&
+ − 710 cursor_start < clip_end);
+ − 711
+ − 712 /* This cursor code is really a mess. */
+ − 713 if (!NILP (w->text_cursor_visible_p)
+ − 714 && (cursor
+ − 715 || cursor_clip
+ − 716 || (cursor_width
+ − 717 && (cursor_start + cursor_width >= clip_start)
+ − 718 && !NILP (bar_cursor_value))))
+ − 719 {
+ − 720 /* These have to be in separate statements in order to avoid a
+ − 721 compiler bug. */
+ − 722 face_index sucks = get_builtin_face_cache_index (w, Vtext_cursor_face);
+ − 723 cursor_cachel = WINDOW_FACE_CACHEL (w, sucks);
+ − 724
+ − 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
+ − 727 become invalid. */
+ − 728 cachel = WINDOW_FACE_CACHEL (w, findex);
+ − 729 }
+ − 730
+ − 731 bg_pmap = cachel->background_pixmap;
+ − 732 if (!IMAGE_INSTANCEP (bg_pmap)
+ − 733 || !IMAGE_INSTANCE_PIXMAP_TYPE_P (XIMAGE_INSTANCE (bg_pmap)))
+ − 734 bg_pmap = Qnil;
+ − 735
+ − 736 if ((cursor && focus && NILP (bar_cursor_value)
+ − 737 && !NILP (w->text_cursor_visible_p)) || NILP (bg_pmap))
+ − 738 bgc = 0;
+ − 739 else
+ − 740 bgc = gtk_get_gc (d, Qnil, cachel->foreground, cachel->background,
+ − 741 bg_pmap, Qnil);
+ − 742
+ − 743 if (bgc)
+ − 744 gdk_draw_rectangle (GDK_DRAWABLE (x_win), bgc, TRUE, clip_start,
+ − 745 dl->ypos - dl->ascent, clip_end - clip_start,
+ − 746 height);
+ − 747
+ − 748 for (i = 0; i < nruns; i++)
+ − 749 {
+ − 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);
+ − 753 int this_width;
+ − 754 int need_clipping;
+ − 755
+ − 756 if (EQ (font, Vthe_null_font_instance))
+ − 757 continue;
+ − 758
+ − 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);
+ − 762
+ − 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
+ − 766 clear some areas. */
+ − 767 if ((int) fi->height < (int) (height + dl->clip))
+ − 768 {
+ − 769 int clear_start = max (xpos, clip_start);
+ − 770 int clear_end = min (xpos + this_width, clip_end);
+ − 771
+ − 772 if (cursor)
+ − 773 {
+ − 774 int ypos1_line, ypos1_string, ypos2_line, ypos2_string;
+ − 775
+ − 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;
+ − 780
+ − 781 /* Make sure we don't clear below the real bottom of the
+ − 782 line. */
+ − 783 if (ypos1_string > ypos2_line)
+ − 784 ypos1_string = ypos2_line;
+ − 785 if (ypos2_string > ypos2_line)
+ − 786 ypos2_string = ypos2_line;
+ − 787
+ − 788 if (ypos1_line < ypos1_string)
+ − 789 {
+ − 790 redisplay_clear_region (window, findex, clear_start, ypos1_line,
+ − 791 clear_end - clear_start,
+ − 792 ypos1_string - ypos1_line);
+ − 793 }
+ − 794
+ − 795 if (ypos2_line > ypos2_string)
+ − 796 {
+ − 797 redisplay_clear_region (window, findex, clear_start, ypos2_string,
+ − 798 clear_end - clear_start,
+ − 799 ypos2_line - ypos2_string);
+ − 800 }
+ − 801 }
+ − 802 else
+ − 803 {
+ − 804 redisplay_clear_region (window, findex, clear_start,
+ − 805 dl->ypos - dl->ascent, clear_end - clear_start,
+ − 806 height);
+ − 807 }
+ − 808 }
+ − 809
+ − 810 if (cursor && cursor_cachel && focus && NILP (bar_cursor_value))
+ − 811 {
+ − 812 gc = gtk_get_gc (d, font, cursor_cachel->foreground,
+ − 813 cursor_cachel->background, Qnil, Qnil);
+ − 814 }
+ − 815 else
+ − 816 {
+ − 817 gc = gtk_get_gc (d, font, cachel->foreground, cachel->background,
+ − 818 Qnil, Qnil);
+ − 819 }
+ − 820
+ − 821 if (need_clipping)
+ − 822 {
+ − 823 GdkRectangle clip_box;
+ − 824
+ − 825 clip_box.x = 0;
+ − 826 clip_box.y = 0;
+ − 827 clip_box.width = clip_end - clip_start;
+ − 828 clip_box.height = height;
+ − 829
+ − 830 gdk_gc_set_clip_rectangle (gc, &clip_box);
+ − 831 gdk_gc_set_clip_origin (gc, clip_start, dl->ypos - dl->ascent);
+ − 832 }
+ − 833
+ − 834 /* The X specific called different functions (XDraw*String
+ − 835 vs. XDraw*String16), but apparently gdk_draw_text takes care
+ − 836 of that for us.
+ − 837
+ − 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.
+ − 842 */
+ − 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);
+ − 846
+ − 847 /* We draw underlines in the same color as the text. */
+ − 848 if (cachel->underline)
+ − 849 {
+ − 850 unsigned long upos, uthick;
+ − 851
+ − 852 /* Cannot get at font properties in Gtk, so we resort to
+ − 853 guessing */
+ − 854 upos = dl->descent / 2;
+ − 855 uthick = 1;
+ − 856
+ − 857 if (dl->ypos + upos < dl->ypos + dl->descent - dl->clip)
+ − 858 {
+ − 859 if (dl->ypos + upos + uthick > dl->ypos + dl->descent - dl->clip)
+ − 860 uthick = dl->descent - dl->clip - upos;
+ − 861
+ − 862 if (uthick == 1)
+ − 863 {
+ − 864 gdk_draw_line (GDK_DRAWABLE (x_win), gc, xpos, dl->ypos + upos,
+ − 865 xpos + this_width, dl->ypos + upos);
+ − 866 }
+ − 867 else if (uthick > 1)
+ − 868 {
+ − 869 gdk_draw_rectangle (GDK_DRAWABLE (x_win), gc, TRUE, xpos,
+ − 870 dl->ypos + upos, this_width, uthick);
+ − 871 }
+ − 872 }
+ − 873 }
+ − 874
+ − 875 if (cachel->strikethru) {
+ − 876 unsigned long ascent,descent,upos, uthick;
+ − 877 GdkFont *gfont = FONT_INSTANCE_GTK_FONT (XFONT_INSTANCE (font));
+ − 878
+ − 879 /* Cannot get at font properties in Gtk, so we resort to
+ − 880 guessing */
+ − 881
+ − 882 ascent = gfont->ascent;
+ − 883 descent = gfont->descent;
+ − 884 uthick = 1;
+ − 885
+ − 886 upos = ascent - ((ascent + descent) / 2) + 1;
+ − 887
+ − 888 /* Generally, upos will be positive (above the baseline),so subtract */
+ − 889 if (dl->ypos - upos < dl->ypos + dl->descent - dl->clip)
+ − 890 {
+ − 891 if (dl->ypos - upos + uthick > dl->ypos + dl->descent - dl->clip)
+ − 892 uthick = dl->descent - dl->clip + upos;
+ − 893
+ − 894 if (uthick == 1)
+ − 895 {
+ − 896 gdk_draw_line (GDK_DRAWABLE (x_win), gc, xpos, dl->ypos - upos,
+ − 897 xpos + this_width, dl->ypos - upos);
+ − 898 }
+ − 899 else if (uthick > 1)
+ − 900 {
+ − 901 gdk_draw_rectangle (GDK_DRAWABLE (x_win), gc, TRUE, xpos, dl->ypos + upos,
+ − 902 this_width, uthick);
+ − 903 }
+ − 904 }
+ − 905 }
+ − 906
+ − 907 /* Restore the GC */
+ − 908 if (need_clipping)
+ − 909 {
+ − 910 gdk_gc_set_clip_rectangle (gc, NULL);
+ − 911 gdk_gc_set_clip_origin (gc, 0, 0);
+ − 912 }
+ − 913
+ − 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)
+ − 917 {
+ − 918 GdkGC *cgc;
+ − 919 GdkRectangle clip_box;
+ − 920
+ − 921 cgc = gtk_get_gc (d, font, cursor_cachel->foreground,
+ − 922 cursor_cachel->background, Qnil, Qnil);
+ − 923
+ − 924 clip_box.x = 0;
+ − 925 clip_box.y = 0;
+ − 926 clip_box.width = cursor_width;
+ − 927 clip_box.height = height;
+ − 928
+ − 929 gdk_gc_set_clip_rectangle (cgc, &clip_box);
+ − 930 gdk_gc_set_clip_origin (cgc, cursor_start, dl->ypos - dl->ascent);
+ − 931
+ − 932 /* The X specific called different functions (XDraw*String
+ − 933 vs. XDraw*String16), but apparently gdk_draw_text takes care
+ − 934 of that for us.
+ − 935
+ − 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.
+ − 940 */
+ − 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);
+ − 944
+ − 945 gdk_gc_set_clip_rectangle (cgc, NULL);
+ − 946 gdk_gc_set_clip_origin (cgc, 0, 0);
+ − 947 }
+ − 948
+ − 949 xpos += this_width;
+ − 950 }
+ − 951
+ − 952 /* Draw the non-focus box or bar-cursor as needed. */
+ − 953 /* Can't this logic be simplified? */
+ − 954 if (cursor_cachel
+ − 955 && ((cursor && !focus && NILP (bar_cursor_value))
+ − 956 || (cursor_width
+ − 957 && (cursor_start + cursor_width >= clip_start)
+ − 958 && !NILP (bar_cursor_value))))
+ − 959 {
+ − 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);
+ − 964
+ − 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].
+ − 969
+ − 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;
+ − 981
+ − 982 if (!NILP (bar_cursor_value))
+ − 983 {
+ − 984 gc = gtk_get_gc (d, Qnil, cursor_cachel->background, Qnil, Qnil,
+ − 985 make_int (bar_width));
+ − 986 }
+ − 987 else
+ − 988 {
+ − 989 gc = gtk_get_gc (d, Qnil, cursor_cachel->background,
+ − 990 Qnil, Qnil, Qnil);
+ − 991 }
+ − 992
+ − 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))
+ − 996 {
+ − 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;
+ − 1001 }
+ − 1002
+ − 1003 if (need_clipping)
+ − 1004 {
+ − 1005 GdkRectangle clip_box;
+ − 1006 clip_box.x = 0;
+ − 1007 clip_box.y = 0;
+ − 1008 clip_box.width = clip_end - clip_start;
+ − 1009 clip_box.height = tmp_height;
+ − 1010
+ − 1011 gdk_gc_set_clip_rectangle (gc, &clip_box);
+ − 1012 gdk_gc_set_clip_origin (gc, clip_start, tmp_y);
+ − 1013 }
+ − 1014
+ − 1015 if (!focus && NILP (bar_cursor_value))
+ − 1016 {
+ − 1017 gdk_draw_rectangle (GDK_DRAWABLE (x_win), gc, FALSE,
+ − 1018 cursor_start, tmp_y,
+ − 1019 cursor_width - 1, tmp_height - 1);
+ − 1020 }
+ − 1021 else if (focus && !NILP (bar_cursor_value))
+ − 1022 {
+ − 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);
+ − 1026 }
+ − 1027
+ − 1028 /* Restore the GC */
+ − 1029 if (need_clipping)
+ − 1030 {
+ − 1031 gdk_gc_set_clip_rectangle (gc, NULL);
+ − 1032 gdk_gc_set_clip_origin (gc, 0, 0);
+ − 1033 }
+ − 1034 }
+ − 1035 }
+ − 1036
+ − 1037 static void
+ − 1038 our_draw_bitmap (GdkDrawable *drawable,
+ − 1039 GdkGC *gc,
+ − 1040 GdkPixmap *src,
+ − 1041 gint xsrc,
+ − 1042 gint ysrc,
+ − 1043 gint xdest,
+ − 1044 gint ydest,
+ − 1045 gint width,
+ − 1046 gint height);
+ − 1047
+ − 1048 void
+ − 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)
+ − 1053 {
+ − 1054 struct device *d = XDEVICE (f->device);
+ − 1055 GdkWindow *x_win = GET_GTK_WIDGET_WINDOW (FRAME_GTK_TEXT_WIDGET (f));
+ − 1056
+ − 1057 GdkGC *gc;
+ − 1058 GdkGCValues gcv;
+ − 1059 unsigned long pixmap_mask;
+ − 1060 int need_clipping = (clip_x || clip_y);
+ − 1061
+ − 1062 if (!override_gc)
+ − 1063 {
+ − 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;
+ − 1069
+ − 1070 if (IMAGE_INSTANCE_GTK_MASK (p))
+ − 1071 {
+ − 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 */
+ − 1084 need_clipping = 0;
+ − 1085 }
+ − 1086
+ − 1087 gc = gc_cache_lookup (DEVICE_GTK_GC_CACHE (d), &gcv, pixmap_mask);
+ − 1088 }
+ − 1089 else
+ − 1090 {
+ − 1091 gc = override_gc;
+ − 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. */
+ − 1095 need_clipping = 0;
+ − 1096 }
+ − 1097
+ − 1098 if (need_clipping)
+ − 1099 {
+ − 1100 GdkRectangle clip_box;
+ − 1101
+ − 1102 clip_box.x = clip_x;
+ − 1103 clip_box.y = clip_y;
+ − 1104 clip_box.width = clip_width;
+ − 1105 clip_box.height = clip_height;
+ − 1106
+ − 1107 gdk_gc_set_clip_rectangle (gc, &clip_box);
+ − 1108 gdk_gc_set_clip_origin (gc, x, y);
+ − 1109 }
+ − 1110
+ − 1111 if (IMAGE_INSTANCE_PIXMAP_DEPTH (p) > 0)
+ − 1112 {
+ − 1113 gdk_draw_pixmap (GDK_DRAWABLE (x_win), gc,
+ − 1114 IMAGE_INSTANCE_GTK_PIXMAP (p),
+ − 1115 0, pixmap_offset, x, y, width, height);
+ − 1116 }
+ − 1117 else
+ − 1118 {
+ − 1119 our_draw_bitmap (GDK_DRAWABLE (x_win), gc,
+ − 1120 IMAGE_INSTANCE_GTK_PIXMAP (p),
+ − 1121 0, pixmap_offset, x, y, width, height);
+ − 1122 }
+ − 1123
+ − 1124 if (need_clipping)
+ − 1125 {
+ − 1126 gdk_gc_set_clip_rectangle (gc, NULL);
+ − 1127 gdk_gc_set_clip_origin (gc, 0, 0);
+ − 1128 }
+ − 1129 }
+ − 1130
+ − 1131 static void
+ − 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)
+ − 1136 {
+ − 1137 struct frame *f = XFRAME (w->frame);
+ − 1138 struct device *d = XDEVICE (f->device);
+ − 1139 struct Lisp_Image_Instance *p = XIMAGE_INSTANCE (image_instance);
+ − 1140 Lisp_Object window;
+ − 1141
+ − 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;
+ − 1148
+ − 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. */
+ − 1152 #if 0
+ − 1153 int pixmap_offset = (int) (IMAGE_INSTANCE_PIXMAP_HEIGHT (p) - lheight) / 2;
+ − 1154 #else
+ − 1155 int pixmap_offset = 0;
+ − 1156 #endif
+ − 1157
+ − 1158 XSETWINDOW (window, w);
+ − 1159
+ − 1160 if ((start_pixpos >= 0 && start_pixpos > xpos) || xoffset)
+ − 1161 {
+ − 1162 if (start_pixpos > xpos && start_pixpos > xpos + width)
+ − 1163 return;
+ − 1164
+ − 1165 clip_x = xoffset;
+ − 1166 clip_width = width;
+ − 1167 if (start_pixpos > xpos)
+ − 1168 {
+ − 1169 clip_x += (start_pixpos - xpos);
+ − 1170 clip_width -= (start_pixpos - xpos);
+ − 1171 }
+ − 1172 }
+ − 1173 else
+ − 1174 {
+ − 1175 clip_x = 0;
+ − 1176 clip_width = 0;
+ − 1177 }
+ − 1178
+ − 1179 /* Place markers for possible future functionality (clipping the top
+ − 1180 half instead of the bottom half; think pixel scrolling). */
+ − 1181 clip_y = 0;
+ − 1182 clip_height = pheight;
+ − 1183
+ − 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))
+ − 1197 {
+ − 1198 int clear_x, clear_y, clear_width, clear_height;
+ − 1199
+ − 1200 if (IMAGE_INSTANCE_GTK_MASK (p))
+ − 1201 {
+ − 1202 clear_y = dl->ypos - dl->ascent;
+ − 1203 clear_height = lheight;
+ − 1204 }
+ − 1205 else
+ − 1206 {
+ − 1207 clear_y = dl->ypos - dl->ascent + pheight;
+ − 1208 clear_height = lheight - pheight;
+ − 1209 }
+ − 1210
+ − 1211 if (start_pixpos >= 0 && start_pixpos > xpos)
+ − 1212 {
+ − 1213 clear_x = start_pixpos;
+ − 1214 clear_width = xpos + width - start_pixpos;
+ − 1215 }
+ − 1216 else
+ − 1217 {
+ − 1218 clear_x = xpos;
+ − 1219 clear_width = width;
+ − 1220 }
+ − 1221
+ − 1222 redisplay_clear_region (window, findex, clear_x, clear_y,
+ − 1223 clear_width, clear_height);
+ − 1224 }
+ − 1225
+ − 1226 /* Output the pixmap. */
+ − 1227 {
+ − 1228 Lisp_Object tmp_pixel;
+ − 1229 GdkColor *tmp_bcolor, *tmp_fcolor;
+ − 1230
+ − 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));
+ − 1235
+ − 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);
+ − 1240 }
+ − 1241
+ − 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))
+ − 1246 {
+ − 1247 GdkGC *gc;
+ − 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));
+ − 1254
+ − 1255 gc = gtk_get_gc (d, Qnil, cursor_cachel->background, Qnil, Qnil, Qnil);
+ − 1256
+ − 1257 if (cursor_width > xpos + pwidth - cursor_start)
+ − 1258 cursor_width = xpos + pwidth - cursor_start;
+ − 1259
+ − 1260 gdk_draw_rectangle (GDK_DRAWABLE (x_win), gc, focus ? TRUE : FALSE,
+ − 1261 cursor_start, y, cursor_width,
+ − 1262 cursor_height);
+ − 1263 }
+ − 1264 }
+ − 1265
+ − 1266 /*****************************************************************************
+ − 1267 gtk_output_vertical_divider
+ − 1268
+ − 1269 Draw a vertical divider down the right side of the given window.
+ − 1270 ****************************************************************************/
+ − 1271 static void
+ − 1272 gtk_output_vertical_divider (struct window *w, int clear)
+ − 1273 {
+ − 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;
+ − 1279 GdkGCValues gcv;
+ − 1280 unsigned long mask;
+ − 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);
+ − 1283
+ − 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);
+ − 1291
+ − 1292 memset (&gcv, ~0, sizeof (gcv));
+ − 1293
+ − 1294 tmp_pixel = WINDOW_FACE_CACHEL_BACKGROUND (w, div_face);
+ − 1295
+ − 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;
+ − 1300
+ − 1301 background_gc = gc_cache_lookup (DEVICE_GTK_GC_CACHE (d), &gcv, mask);
+ − 1302
+ − 1303 /* Clear the divider area first. This needs to be done when a
+ − 1304 window split occurs. */
+ − 1305 /* if (clear) */
+ − 1306 gdk_draw_rectangle (GDK_DRAWABLE (x_win), background_gc, TRUE,
+ − 1307 x, y1, width, y2 - y1);
+ − 1308
+ − 1309 #if 0
+ − 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);
+ − 1314 #endif
+ − 1315
+ − 1316 /* Draw the shadows around the divider line */
+ − 1317 gtk_output_shadows (f, x + spacing, y1,
+ − 1318 width - 2 * spacing, y2 - y1,
+ − 1319 shadow_thickness);
+ − 1320 }
+ − 1321
+ − 1322 /*****************************************************************************
+ − 1323 gtk_output_blank
+ − 1324
+ − 1325 Output a blank by clearing the area it covers in the foreground color
+ − 1326 of its face.
+ − 1327 ****************************************************************************/
+ − 1328 static void
+ − 1329 gtk_output_blank (struct window *w, struct display_line *dl, struct rune *rb,
+ − 1330 int start_pixpos, int cursor_start, int cursor_width)
+ − 1331 {
+ − 1332 struct frame *f = XFRAME (w->frame);
+ − 1333 struct device *d = XDEVICE (f->device);
+ − 1334
+ − 1335 GdkWindow *x_win = GET_GTK_WIDGET_WINDOW (FRAME_GTK_TEXT_WIDGET (f));
+ − 1336 GdkGC *gc;
+ − 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,
+ − 1344 buffer);
+ − 1345
+ − 1346 int x = rb->xpos;
+ − 1347 int y = dl->ypos - dl->ascent;
+ − 1348 int width = rb->width;
+ − 1349 int height = dl->ascent + dl->descent - dl->clip;
+ − 1350
+ − 1351 if (start_pixpos > x)
+ − 1352 {
+ − 1353 if (start_pixpos >= (x + width))
+ − 1354 return;
+ − 1355 else
+ − 1356 {
+ − 1357 width -= (start_pixpos - x);
+ − 1358 x = start_pixpos;
+ − 1359 }
+ − 1360 }
+ − 1361
+ − 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)))
+ − 1365 bg_pmap = Qnil;
+ − 1366
+ − 1367 if (NILP (bg_pmap))
+ − 1368 gc = gtk_get_gc (d, Qnil, WINDOW_FACE_CACHEL_BACKGROUND (w, rb->findex),
+ − 1369 Qnil, Qnil, Qnil);
+ − 1370 else
+ − 1371 gc = gtk_get_gc (d, Qnil, WINDOW_FACE_CACHEL_FOREGROUND (w, rb->findex),
+ − 1372 WINDOW_FACE_CACHEL_BACKGROUND (w, rb->findex), bg_pmap,
+ − 1373 Qnil);
+ − 1374
+ − 1375 gdk_draw_rectangle (GDK_DRAWABLE (x_win), gc, TRUE, x, y, width, height);
+ − 1376
+ − 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
+ − 1381 || (cursor_width
+ − 1382 && (cursor_start + cursor_width > x)
+ − 1383 && cursor_start < (x + width))))
+ − 1384 {
+ − 1385 int cursor_height, cursor_y;
+ − 1386 int focus = EQ (w->frame, DEVICE_FRAME_WITH_FOCUS_REAL (d));
+ − 1387 struct Lisp_Font_Instance *fi;
+ − 1388
+ − 1389 fi = XFONT_INSTANCE (FACE_CACHEL_FONT
+ − 1390 (WINDOW_FACE_CACHEL (w, rb->findex),
+ − 1391 Vcharset_ascii));
+ − 1392
+ − 1393 gc = gtk_get_gc (d, Qnil, cursor_cachel->background, Qnil, Qnil, Qnil);
+ − 1394
+ − 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;
+ − 1399
+ − 1400 if (focus)
+ − 1401 {
+ − 1402 if (NILP (bar_cursor_value))
+ − 1403 {
+ − 1404 gdk_draw_rectangle (GDK_DRAWABLE (x_win), gc, TRUE,
+ − 1405 cursor_start, cursor_y,
+ − 1406 fi->width, cursor_height);
+ − 1407 }
+ − 1408 else
+ − 1409 {
+ − 1410 int bar_width = EQ (bar_cursor_value, Qt) ? 1 : 2;
+ − 1411
+ − 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);
+ − 1417 }
+ − 1418 }
+ − 1419 else if (NILP (bar_cursor_value))
+ − 1420 {
+ − 1421 gdk_draw_rectangle (GDK_DRAWABLE (x_win), gc, FALSE,
+ − 1422 cursor_start, cursor_y,
+ − 1423 fi->width - 1, cursor_height - 1);
+ − 1424 }
+ − 1425 }
+ − 1426 }
+ − 1427
+ − 1428 /*****************************************************************************
+ − 1429 gtk_output_hline
+ − 1430
+ − 1431 Output a horizontal line in the foreground of its face.
+ − 1432 ****************************************************************************/
+ − 1433 static void
+ − 1434 gtk_output_hline (struct window *w, struct display_line *dl, struct rune *rb)
+ − 1435 {
+ − 1436 struct frame *f = XFRAME (w->frame);
+ − 1437 struct device *d = XDEVICE (f->device);
+ − 1438 GtkStyle *style = FRAME_GTK_TEXT_WIDGET (f)->style;
+ − 1439
+ − 1440 GdkWindow *x_win = GET_GTK_WIDGET_WINDOW (FRAME_GTK_TEXT_WIDGET (f));
+ − 1441 GdkGC *gc;
+ − 1442
+ − 1443 int x = rb->xpos;
+ − 1444 int width = rb->width;
+ − 1445 int height = dl->ascent + dl->descent - dl->clip;
+ − 1446
+ − 1447 int ypos1, ypos2, ypos3, ypos4;
+ − 1448
+ − 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;
+ − 1453
+ − 1454 /* First clear the area not covered by the line. */
+ − 1455 if (height - rb->object.hline.thickness > 0)
+ − 1456 {
+ − 1457 gc = gtk_get_gc (d, Qnil, WINDOW_FACE_CACHEL_FOREGROUND (w, rb->findex),
+ − 1458 Qnil, Qnil, Qnil);
+ − 1459
+ − 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);
+ − 1464 }
+ − 1465
+ − 1466 gtk_paint_hline (style, x_win, GTK_STATE_NORMAL, NULL, FRAME_GTK_TEXT_WIDGET (f),
+ − 1467 "hline", x, x + width, ypos2);
+ − 1468 #if 0
+ − 1469 /* Now draw the line. */
+ − 1470 gc = gtk_get_gc (d, Qnil, WINDOW_FACE_CACHEL_BACKGROUND (w, rb->findex),
+ − 1471 Qnil, Qnil, Qnil);
+ − 1472
+ − 1473 if (ypos2 < ypos1)
+ − 1474 ypos2 = ypos1;
+ − 1475 if (ypos3 > ypos4)
+ − 1476 ypos3 = ypos4;
+ − 1477
+ − 1478 if (ypos3 - ypos2 > 0)
+ − 1479 gdk_draw_rectangle (GDK_DRAWABLE (x_win), gc, TRUE, x, ypos2, width, ypos3 - ypos2);
+ − 1480 #endif
+ − 1481 }
+ − 1482
+ − 1483 /*****************************************************************************
+ − 1484 gtk_output_shadows
+ − 1485
+ − 1486 Draw a shadow around the given area using the standard theme engine routines.
+ − 1487 ****************************************************************************/
+ − 1488 void
+ − 1489 gtk_output_shadows (struct frame *f, int x, int y, int width, int height,
+ − 1490 int shadow_thickness)
+ − 1491 {
+ − 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;
+ − 1495
+ − 1496 if (shadow_thickness < 0)
+ − 1497 {
+ − 1498 stype = GTK_SHADOW_IN;
+ − 1499 }
+ − 1500 else if (shadow_thickness == 0)
+ − 1501 {
+ − 1502 stype = GTK_SHADOW_NONE;
+ − 1503 }
+ − 1504
+ − 1505 /* Do we want to have some magic constants to set
+ − 1506 GTK_SHADOW_ETCHED_IN or GTK_SHADOW_ETCHED_OUT? */
+ − 1507
+ − 1508 gtk_paint_shadow (style, x_win, GTK_STATE_NORMAL, stype, NULL,
+ − 1509 FRAME_GTK_TEXT_WIDGET (f), "modeline",
+ − 1510 x, y, width, height);
+ − 1511 }
+ − 1512
+ − 1513 /*****************************************************************************
+ − 1514 gtk_clear_to_window_end
+ − 1515
+ − 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
+ − 1518 background color.
+ − 1519 ****************************************************************************/
+ − 1520 static void
+ − 1521 gtk_clear_to_window_end (struct window *w, int ypos1, int ypos2)
+ − 1522 {
+ − 1523 int height = ypos2 - ypos1;
+ − 1524
+ − 1525 if (height)
+ − 1526 {
+ − 1527 struct frame *f = XFRAME (w->frame);
+ − 1528 Lisp_Object window;
+ − 1529 int bflag = (window_needs_vertical_divider (w) ? 0 : 1);
+ − 1530 layout_bounds bounds;
+ − 1531
+ − 1532 bounds = calculate_display_line_boundaries (w, bflag);
+ − 1533 XSETWINDOW (window, w);
+ − 1534
+ − 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);
+ − 1538
+ − 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);
+ − 1544
+ − 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);
+ − 1548
+ − 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);
+ − 1554
+ − 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);
+ − 1558 }
+ − 1559 }
+ − 1560
+ − 1561 /*****************************************************************************
+ − 1562 gtk_redraw_exposed_window
+ − 1563
+ − 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
+ − 1566 contents.
+ − 1567 ****************************************************************************/
+ − 1568 static void
+ − 1569 gtk_redraw_exposed_window (struct window *w, int x, int y, int width, int height)
+ − 1570 {
+ − 1571 struct frame *f = XFRAME (w->frame);
+ − 1572 int line;
+ − 1573 int start_x, start_y, end_x, end_y;
+ − 1574 int orig_windows_structure_changed;
+ − 1575
+ − 1576 display_line_dynarr *cdla = window_display_lines (w, CURRENT_DISP);
+ − 1577
+ − 1578 if (!NILP (w->vchild))
+ − 1579 {
+ − 1580 gtk_redraw_exposed_windows (w->vchild, x, y, width, height);
+ − 1581 return;
+ − 1582 }
+ − 1583 else if (!NILP (w->hchild))
+ − 1584 {
+ − 1585 gtk_redraw_exposed_windows (w->hchild, x, y, width, height);
+ − 1586 return;
+ − 1587 }
+ − 1588
+ − 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))
+ − 1592 {
+ − 1593 return;
+ − 1594 }
+ − 1595 else
+ − 1596 {
+ − 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);
+ − 1601
+ − 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;
+ − 1606 }
+ − 1607
+ − 1608 if (window_needs_vertical_divider (w))
+ − 1609 {
+ − 1610 gtk_output_vertical_divider (w, 0);
+ − 1611 }
+ − 1612
+ − 1613 for (line = 0; line < Dynarr_length (cdla); line++)
+ − 1614 {
+ − 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;
+ − 1618
+ − 1619 if (bottom_y >= start_y)
+ − 1620 {
+ − 1621 if (top_y > end_y)
+ − 1622 {
+ − 1623 if (line == 0)
+ − 1624 continue;
+ − 1625 else
+ − 1626 break;
+ − 1627 }
+ − 1628 else
+ − 1629 {
+ − 1630 output_display_line (w, 0, cdla, line, start_x, end_x);
+ − 1631 }
+ − 1632 }
+ − 1633 }
+ − 1634
+ − 1635 f->windows_structure_changed = orig_windows_structure_changed;
+ − 1636
+ − 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);
+ − 1641 }
+ − 1642
+ − 1643 /*****************************************************************************
+ − 1644 gtk_redraw_exposed_windows
+ − 1645
+ − 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 ****************************************************************************/
+ − 1649 static void
+ − 1650 gtk_redraw_exposed_windows (Lisp_Object window, int x, int y, int width,
+ − 1651 int height)
+ − 1652 {
+ − 1653 for (; !NILP (window); window = XWINDOW (window)->next)
+ − 1654 gtk_redraw_exposed_window (XWINDOW (window), x, y, width, height);
+ − 1655 }
+ − 1656
+ − 1657 /*****************************************************************************
+ − 1658 gtk_redraw_exposed_area
+ − 1659
+ − 1660 For each window on the given frame, ensure that any area in the
+ − 1661 Exposed area is redrawn.
+ − 1662 ****************************************************************************/
+ − 1663 void
+ − 1664 gtk_redraw_exposed_area (struct frame *f, int x, int y, int width, int height)
+ − 1665 {
+ − 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. */
+ − 1671
+ − 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
+ − 1675 redraw anyhow. */
+ − 1676 MAYBE_FRAMEMETH (f, redraw_exposed_toolbars, (f, x, y, width, height));
+ − 1677 #endif
+ − 1678 redraw_exposed_gutters (f, x, y, width, height);
+ − 1679
+ − 1680 if (!f->window_face_cache_reset)
+ − 1681 {
+ − 1682 gtk_redraw_exposed_windows (f->root_window, x, y, width, height);
+ − 1683 }
+ − 1684 else
+ − 1685 MARK_FRAME_CHANGED (f);
+ − 1686 }
+ − 1687
+ − 1688 /****************************************************************************
+ − 1689 gtk_clear_region
+ − 1690
+ − 1691 Clear the area in the box defined by the given parameters using the
+ − 1692 given face.
+ − 1693 ****************************************************************************/
+ − 1694 static void
+ − 1695 gtk_clear_region (Lisp_Object locale, struct device* d, struct frame* f, face_index findex,
+ − 1696 int x, int y,
+ − 1697 int width, int height, Lisp_Object fcolor, Lisp_Object bcolor,
+ − 1698 Lisp_Object background_pixmap)
+ − 1699 {
+ − 1700 GdkWindow *x_win;
+ − 1701 GdkGC *gc = NULL;
+ − 1702
+ − 1703 x_win = GET_GTK_WIDGET_WINDOW (FRAME_GTK_TEXT_WIDGET (f));
+ − 1704
+ − 1705 if (!UNBOUNDP (background_pixmap))
+ − 1706 {
+ − 1707 gc = gtk_get_gc (d, Qnil, fcolor, bcolor, background_pixmap, Qnil);
+ − 1708 }
+ − 1709
+ − 1710 if (gc)
+ − 1711 {
+ − 1712 gdk_draw_rectangle (GDK_DRAWABLE (x_win), gc,TRUE,
+ − 1713 x, y, width, height);
+ − 1714 }
+ − 1715 else
+ − 1716 {
+ − 1717 gdk_window_clear_area (x_win, x, y, width, height);
+ − 1718 }
+ − 1719 }
+ − 1720
+ − 1721 /*****************************************************************************
+ − 1722 gtk_output_eol_cursor
+ − 1723
+ − 1724 Draw a cursor at the end of a line. The end-of-line cursor is
+ − 1725 narrower than the normal cursor.
+ − 1726 ****************************************************************************/
+ − 1727 static void
+ − 1728 gtk_output_eol_cursor (struct window *w, struct display_line *dl, int xpos,
+ − 1729 face_index findex)
+ − 1730 {
+ − 1731 struct frame *f = XFRAME (w->frame);
+ − 1732 struct device *d = XDEVICE (f->device);
+ − 1733 Lisp_Object window;
+ − 1734
+ − 1735 GdkWindow *x_win = GET_GTK_WIDGET_WINDOW (FRAME_GTK_TEXT_WIDGET (f));
+ − 1736 GdkGC *gc;
+ − 1737 face_index elt = get_builtin_face_cache_index (w, Vtext_cursor_face);
+ − 1738 struct face_cachel *cursor_cachel = WINDOW_FACE_CACHEL (w, elt);
+ − 1739
+ − 1740 int focus = EQ (w->frame, DEVICE_FRAME_WITH_FOCUS_REAL (d));
+ − 1741 Lisp_Object bar_cursor_value = symbol_value_in_buffer (Qbar_cursor,
+ − 1742 WINDOW_BUFFER (w));
+ − 1743
+ − 1744 int x = xpos;
+ − 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;
+ − 1750
+ − 1751 XSETWINDOW (window, w);
+ − 1752 redisplay_clear_region (window, findex, x, y, width, height);
+ − 1753
+ − 1754 if (NILP (w->text_cursor_visible_p))
+ − 1755 return;
+ − 1756
+ − 1757 gc = gtk_get_gc (d, Qnil, cursor_cachel->background, Qnil, Qnil, Qnil);
+ − 1758
+ − 1759 default_face_font_info (window, &defascent, 0, &defheight, 0, 0);
+ − 1760
+ − 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));
+ − 1765
+ − 1766 if (focus)
+ − 1767 {
+ − 1768 if (NILP (bar_cursor_value))
+ − 1769 {
+ − 1770 gdk_draw_rectangle (GDK_DRAWABLE (x_win), gc, TRUE, x, cursor_y, width, cursor_height);
+ − 1771 }
+ − 1772 else
+ − 1773 {
+ − 1774 int bar_width = EQ (bar_cursor_value, Qt) ? 1 : 2;
+ − 1775
+ − 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);
+ − 1780 }
+ − 1781 }
+ − 1782 else if (NILP (bar_cursor_value))
+ − 1783 {
+ − 1784 gdk_draw_rectangle (GDK_DRAWABLE (x_win), gc, FALSE, x, cursor_y, width - 1,
+ − 1785 cursor_height - 1);
+ − 1786 }
+ − 1787 }
+ − 1788
+ − 1789 static void
+ − 1790 gtk_clear_frame_window (Lisp_Object window)
+ − 1791 {
+ − 1792 struct window *w = XWINDOW (window);
+ − 1793
+ − 1794 if (!NILP (w->vchild))
+ − 1795 {
+ − 1796 gtk_clear_frame_windows (w->vchild);
+ − 1797 return;
+ − 1798 }
+ − 1799
+ − 1800 if (!NILP (w->hchild))
+ − 1801 {
+ − 1802 gtk_clear_frame_windows (w->hchild);
+ − 1803 return;
+ − 1804 }
+ − 1805
+ − 1806 gtk_clear_to_window_end (w, WINDOW_TEXT_TOP (w), WINDOW_TEXT_BOTTOM (w));
+ − 1807 }
+ − 1808
+ − 1809 static void
+ − 1810 gtk_clear_frame_windows (Lisp_Object window)
+ − 1811 {
+ − 1812 for (; !NILP (window); window = XWINDOW (window)->next)
+ − 1813 gtk_clear_frame_window (window);
+ − 1814 }
+ − 1815
+ − 1816 static void
+ − 1817 gtk_clear_frame (struct frame *f)
+ − 1818 {
+ − 1819 GdkWindow *x_win = GET_GTK_WIDGET_WINDOW (FRAME_GTK_TEXT_WIDGET (f));
+ − 1820 int x, y, width, height;
+ − 1821 Lisp_Object frame;
+ − 1822
+ − 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;
+ − 1836
+ − 1837 gdk_window_clear_area (x_win, x, y, width, height);
+ − 1838
+ − 1839 XSETFRAME (frame, f);
+ − 1840
+ − 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)))
+ − 1844 {
+ − 1845 gtk_clear_frame_windows (f->root_window);
+ − 1846 }
+ − 1847 }
+ − 1848
+ − 1849 static int
+ − 1850 gtk_flash (struct device *d)
+ − 1851 {
+ − 1852 GdkGCValues gcv;
+ − 1853 GdkGC *gc;
+ − 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));
+ − 1858
+ − 1859 XSETFRAME (frame, f);
+ − 1860
+ − 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)));
+ − 1865
+ − 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);
+ − 1872
+ − 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);
+ − 1876
+ − 1877 gdk_flush ();
+ − 1878
+ − 1879 #ifdef HAVE_POLL
+ − 1880 poll (0, 0, 100);
+ − 1881 #else /* !HAVE_POLL */
+ − 1882 #ifdef HAVE_SELECT
+ − 1883 {
+ − 1884 int usecs = 100000;
+ − 1885 struct timeval tv;
+ − 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);
+ − 1890 }
+ − 1891 #else
+ − 1892 bite me
+ − 1893 #endif /* HAVE_POLL */
+ − 1894 #endif /* HAVE_SELECT */
+ − 1895
+ − 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);
+ − 1899
+ − 1900 gdk_flush ();
+ − 1901
+ − 1902 return 1;
+ − 1903 }
+ − 1904
+ − 1905 static void
+ − 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)
+ − 1909 {
+ − 1910 struct frame *f = XFRAME (w->frame);
+ − 1911 struct device *d = XDEVICE (f->device);
+ − 1912
+ − 1913 gtk_output_shadows (f, x, y, width, height, shadow_thickness);
+ − 1914 }
+ − 1915
+ − 1916
+ − 1917
+ − 1918 /* Make audible bell. */
+ − 1919 static void
+ − 1920 gtk_ring_bell (struct device *d, int volume, int pitch, int duration)
+ − 1921 {
+ − 1922 /* Gdk does not allow us to control the duration / pitch / volume */
+ − 1923 gdk_beep ();
+ − 1924 }
+ − 1925
+ − 1926
+ − 1927 /************************************************************************/
+ − 1928 /* initialization */
+ − 1929 /************************************************************************/
+ − 1930
+ − 1931 void
+ − 1932 console_type_create_redisplay_gtk (void)
+ − 1933 {
+ − 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); */
+ − 1948 }
+ − 1949
+ − 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
+ − 1954
+ − 1955 #include <gdk/gdkx.h>
+ − 1956
+ − 1957 void
+ − 1958 gdk_draw_text_image (GdkDrawable *drawable,
+ − 1959 GdkFont *font,
+ − 1960 GdkGC *gc,
+ − 1961 gint x,
+ − 1962 gint y,
+ − 1963 const gchar *text,
+ − 1964 gint text_length)
+ − 1965 {
+ − 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);
+ − 1969
+ − 1970 gdk_draw_rectangle (drawable, gc, TRUE, x, y, width, height);
+ − 1971 gdk_draw_text (drawable, font, gc, x, y, text, text_length);
+ − 1972 #else
+ − 1973 GdkWindowPrivate *drawable_private;
+ − 1974 GdkFontPrivate *font_private;
+ − 1975 GdkGCPrivate *gc_private;
+ − 1976
+ − 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);
+ − 1981
+ − 1982 drawable_private = (GdkWindowPrivate*) drawable;
+ − 1983 if (drawable_private->destroyed)
+ − 1984 return;
+ − 1985 gc_private = (GdkGCPrivate*) gc;
+ − 1986 font_private = (GdkFontPrivate*) font;
+ − 1987
+ − 1988 if (font->type == GDK_FONT_FONT)
+ − 1989 {
+ − 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))
+ − 1993 {
+ − 1994 XDrawImageString (drawable_private->xdisplay, drawable_private->xwindow,
+ − 1995 gc_private->xgc, x, y, text, text_length);
+ − 1996 }
+ − 1997 else
+ − 1998 {
+ − 1999 XDrawImageString16 (drawable_private->xdisplay, drawable_private->xwindow,
+ − 2000 gc_private->xgc, x, y, (XChar2b *) text, text_length / 2);
+ − 2001 }
+ − 2002 }
+ − 2003 else if (font->type == GDK_FONT_FONTSET)
+ − 2004 {
+ − 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);
+ − 2008 }
+ − 2009 else
+ − 2010 g_error("undefined font type\n");
+ − 2011 #endif
+ − 2012 }
+ − 2013
+ − 2014 static void
+ − 2015 our_draw_bitmap (GdkDrawable *drawable,
+ − 2016 GdkGC *gc,
+ − 2017 GdkPixmap *src,
+ − 2018 gint xsrc,
+ − 2019 gint ysrc,
+ − 2020 gint xdest,
+ − 2021 gint ydest,
+ − 2022 gint width,
+ − 2023 gint height)
+ − 2024 {
+ − 2025 GdkWindowPrivate *drawable_private;
+ − 2026 GdkWindowPrivate *src_private;
+ − 2027 GdkGCPrivate *gc_private;
+ − 2028
+ − 2029 g_return_if_fail (drawable != NULL);
+ − 2030 g_return_if_fail (src != NULL);
+ − 2031 g_return_if_fail (gc != NULL);
+ − 2032
+ − 2033 drawable_private = (GdkWindowPrivate*) drawable;
+ − 2034 src_private = (GdkWindowPrivate*) src;
+ − 2035 if (drawable_private->destroyed || src_private->destroyed)
+ − 2036 return;
+ − 2037 gc_private = (GdkGCPrivate*) gc;
+ − 2038
+ − 2039 if (width == -1)
+ − 2040 width = src_private->width;
+ − 2041 if (height == -1)
+ − 2042 height = src_private->height;
+ − 2043
+ − 2044 XCopyPlane (drawable_private->xdisplay,
+ − 2045 src_private->xwindow,
+ − 2046 drawable_private->xwindow,
+ − 2047 gc_private->xgc,
+ − 2048 xsrc, ysrc,
+ − 2049 width, height,
+ − 2050 xdest, ydest, 1L);
+ − 2051 }