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