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