428
+ − 1 /* mswindows 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 /* Authorship:
+ − 26
+ − 27 Chuck Thompson
+ − 28 Lots of work done by Ben Wing for Mule
442
+ − 29
+ − 30 Partially rewritten for mswindows by Jonathan Harris, November 1997
+ − 31 for 21.0. */
428
+ − 32
+ − 33 #include <config.h>
+ − 34 #include "lisp.h"
+ − 35
+ − 36 #include "console-msw.h"
+ − 37 #include "objects-msw.h"
+ − 38
+ − 39 #include "buffer.h"
+ − 40 #include "debug.h"
+ − 41 #include "events.h"
+ − 42 #include "faces.h"
+ − 43 #include "frame.h"
+ − 44 #include "glyphs-msw.h"
+ − 45 #include "gutter.h"
+ − 46 #include "redisplay.h"
+ − 47 #include "sysdep.h"
+ − 48 #include "window.h"
+ − 49
+ − 50 #ifdef MULE
+ − 51 #include "mule-ccl.h"
+ − 52 #include "mule-charset.h"
+ − 53 #endif
+ − 54
+ − 55 #define MSWINDOWS_EOL_CURSOR_WIDTH 5
+ − 56
+ − 57 /*
+ − 58 * Random forward declarations
+ − 59 */
440
+ − 60 static void mswindows_update_dc (HDC hdc, Lisp_Object fg, Lisp_Object bg,
+ − 61 Lisp_Object bg_pmap);
+ − 62 static void mswindows_set_dc_font (HDC hdc, Lisp_Object font,
+ − 63 int under, int strike);
428
+ − 64 static void mswindows_output_vertical_divider (struct window *w, int clear);
+ − 65 static void mswindows_redraw_exposed_windows (Lisp_Object window, int x,
+ − 66 int y, int width, int height);
+ − 67 static void mswindows_output_dibitmap (struct frame *f,
440
+ − 68 Lisp_Image_Instance *p,
428
+ − 69 struct display_box* db,
+ − 70 struct display_glyph_area* dga);
+ − 71
+ − 72 typedef struct textual_run
+ − 73 {
+ − 74 Lisp_Object charset;
+ − 75 unsigned char *ptr;
+ − 76 int len;
+ − 77 int dimension;
+ − 78 } textual_run;
+ − 79
+ − 80 /* Separate out the text in DYN into a series of textual runs of a
+ − 81 particular charset. Also convert the characters as necessary into
+ − 82 the format needed by XDrawImageString(), XDrawImageString16(), et
+ − 83 al. (This means converting to one or two byte format, possibly
+ − 84 tweaking the high bits, and possibly running a CCL program.) You
+ − 85 must pre-allocate the space used and pass it in. (This is done so
+ − 86 you can alloca() the space.) You need to allocate (2 * len) bytes
+ − 87 of TEXT_STORAGE and (len * sizeof (textual_run)) bytes of
+ − 88 RUN_STORAGE, where LEN is the length of the dynarr.
+ − 89
+ − 90 Returns the number of runs actually used. */
+ − 91
+ − 92 static int
+ − 93 separate_textual_runs (unsigned char *text_storage,
+ − 94 textual_run *run_storage,
442
+ − 95 const Emchar *str, Charcount len)
428
+ − 96 {
+ − 97 Lisp_Object prev_charset = Qunbound; /* not Qnil because that is a
+ − 98 possible valid charset when
+ − 99 MULE is not defined */
+ − 100 int runs_so_far = 0;
+ − 101 int i;
+ − 102 #ifdef MULE
+ − 103 struct ccl_program char_converter;
+ − 104 int need_ccl_conversion = 0;
+ − 105 #endif
+ − 106
+ − 107 for (i = 0; i < len; i++)
+ − 108 {
+ − 109 Emchar ch = str[i];
+ − 110 Lisp_Object charset;
+ − 111 int byte1, byte2;
+ − 112 int dimension;
+ − 113 int graphic;
+ − 114
+ − 115 BREAKUP_CHAR (ch, charset, byte1, byte2);
+ − 116 dimension = XCHARSET_DIMENSION (charset);
+ − 117 graphic = XCHARSET_GRAPHIC (charset);
+ − 118
+ − 119 if (!EQ (charset, prev_charset))
+ − 120 {
+ − 121 run_storage[runs_so_far].ptr = text_storage;
+ − 122 run_storage[runs_so_far].charset = charset;
+ − 123 run_storage[runs_so_far].dimension = dimension;
+ − 124
+ − 125 if (runs_so_far)
+ − 126 {
+ − 127 run_storage[runs_so_far - 1].len =
+ − 128 text_storage - run_storage[runs_so_far - 1].ptr;
+ − 129 if (run_storage[runs_so_far - 1].dimension == 2)
+ − 130 run_storage[runs_so_far - 1].len >>= 1;
+ − 131 }
+ − 132 runs_so_far++;
+ − 133 prev_charset = charset;
+ − 134 #ifdef MULE
+ − 135 {
+ − 136 Lisp_Object ccl_prog = XCHARSET_CCL_PROGRAM (charset);
444
+ − 137 if ((!NILP (ccl_prog))
+ − 138 && (setup_ccl_program (&char_converter, ccl_prog) >= 0))
+ − 139 need_ccl_conversion = 1;
428
+ − 140 }
+ − 141 #endif
+ − 142 }
+ − 143
+ − 144 if (graphic == 0)
+ − 145 {
+ − 146 byte1 &= 0x7F;
+ − 147 byte2 &= 0x7F;
+ − 148 }
+ − 149 else if (graphic == 1)
+ − 150 {
+ − 151 byte1 |= 0x80;
+ − 152 byte2 |= 0x80;
+ − 153 }
+ − 154 #ifdef MULE
+ − 155 if (need_ccl_conversion)
+ − 156 {
+ − 157 char_converter.reg[0] = XCHARSET_ID (charset);
+ − 158 char_converter.reg[1] = byte1;
+ − 159 char_converter.reg[2] = byte2;
+ − 160 char_converter.ic = 0; /* start at beginning each time */
+ − 161 ccl_driver (&char_converter, 0, 0, 0, 0, CCL_MODE_ENCODING);
+ − 162 byte1 = char_converter.reg[1];
+ − 163 byte2 = char_converter.reg[2];
+ − 164 }
+ − 165 #endif
+ − 166 *text_storage++ = (unsigned char) byte1;
+ − 167 if (dimension == 2)
+ − 168 *text_storage++ = (unsigned char) byte2;
+ − 169 }
+ − 170
+ − 171 if (runs_so_far)
+ − 172 {
+ − 173 run_storage[runs_so_far - 1].len =
+ − 174 text_storage - run_storage[runs_so_far - 1].ptr;
+ − 175 if (run_storage[runs_so_far - 1].dimension == 2)
+ − 176 run_storage[runs_so_far - 1].len >>= 1;
+ − 177 }
+ − 178
+ − 179 return runs_so_far;
+ − 180 }
+ − 181
+ − 182
+ − 183 static int
+ − 184 mswindows_text_width_single_run (HDC hdc, struct face_cachel *cachel,
+ − 185 textual_run *run)
+ − 186 {
+ − 187 Lisp_Object font_inst = FACE_CACHEL_FONT (cachel, run->charset);
440
+ − 188 Lisp_Font_Instance *fi = XFONT_INSTANCE (font_inst);
428
+ − 189 SIZE size;
+ − 190
+ − 191 if (!fi->proportional_p || !hdc)
+ − 192 return (fi->width * run->len);
+ − 193 else
+ − 194 {
+ − 195 assert(run->dimension == 1); /* #### FIXME! */
440
+ − 196 mswindows_set_dc_font (hdc, font_inst,
+ − 197 cachel->underline, cachel->strikethru);
593
+ − 198 /* !!#### more mule bogosity */
+ − 199 GetTextExtentPoint32 (hdc, (char *) run->ptr, run->len, &size);
428
+ − 200 return(size.cx);
+ − 201 }
+ − 202 }
+ − 203
440
+ − 204 /*
+ − 205 * Given F, retrieve device context. F can be a display frame, or
442
+ − 206 * a print job. For a print job, page is also started when printer's
+ − 207 * device context is first time requested.
440
+ − 208 */
+ − 209 static HDC
442
+ − 210 get_frame_dc (struct frame *f, int start_page_p)
440
+ − 211 {
+ − 212 if (FRAME_MSWINDOWS_P (f))
+ − 213 return FRAME_MSWINDOWS_DC (f);
+ − 214 else
442
+ − 215 {
+ − 216 if (start_page_p && !FRAME_MSPRINTER_PAGE_STARTED (f))
+ − 217 msprinter_start_page (f);
+ − 218 return DEVICE_MSPRINTER_HDC (XDEVICE (FRAME_DEVICE (f)));
+ − 219 }
440
+ − 220 }
+ − 221
+ − 222 /*
+ − 223 * Given F, retrieve compatible device context. F can be a display
+ − 224 * frame, or a print job.
+ − 225 */
+ − 226 static HDC
+ − 227 get_frame_compdc (struct frame *f)
+ − 228 {
442
+ − 229 struct device *d = XDEVICE (FRAME_DEVICE (f));
+ − 230 if (DEVICE_MSWINDOWS_P (d))
+ − 231 return DEVICE_MSWINDOWS_HCDC (d);
440
+ − 232 else
442
+ − 233 return DEVICE_MSPRINTER_HCDC (d);
440
+ − 234 }
428
+ − 235
+ − 236 /*****************************************************************************
+ − 237 mswindows_update_dc
+ − 238
+ − 239 Given a number of parameters munge the DC so it has those properties.
+ − 240 ****************************************************************************/
+ − 241 static void
440
+ − 242 mswindows_update_dc (HDC hdc, Lisp_Object fg, Lisp_Object bg,
+ − 243 Lisp_Object bg_pmap)
428
+ − 244 {
+ − 245 if (!NILP (fg))
+ − 246 {
+ − 247 SetTextColor (hdc, COLOR_INSTANCE_MSWINDOWS_COLOR
+ − 248 (XCOLOR_INSTANCE (fg)));
+ − 249 }
440
+ − 250
428
+ − 251 if (!NILP (bg))
+ − 252 {
+ − 253 SetBkMode (hdc, OPAQUE);
+ − 254 SetBkColor (hdc, COLOR_INSTANCE_MSWINDOWS_COLOR (XCOLOR_INSTANCE (bg)));
+ − 255 }
+ − 256 else
+ − 257 {
+ − 258 SetBkMode (hdc, TRANSPARENT);
+ − 259 }
+ − 260 }
+ − 261
440
+ − 262 static void mswindows_set_dc_font (HDC hdc, Lisp_Object font,
+ − 263 int under, int strike)
428
+ − 264 {
440
+ − 265 SelectObject(hdc, mswindows_get_hfont (XFONT_INSTANCE (font),
+ − 266 under, strike));
428
+ − 267 }
+ − 268
+ − 269 /*****************************************************************************
+ − 270 mswindows_output_hline
+ − 271
+ − 272 Output a horizontal line in the foreground of its face.
+ − 273 ****************************************************************************/
+ − 274 static void
+ − 275 mswindows_output_hline (struct window *w, struct display_line *dl, struct rune *rb)
+ − 276 { /* XXX Implement me */
+ − 277 }
+ − 278
+ − 279
+ − 280 /*****************************************************************************
+ − 281 mswindows_output_blank
+ − 282
+ − 283 Output a blank by clearing the area it covers in the background color
+ − 284 of its face.
+ − 285 ****************************************************************************/
+ − 286 static void
+ − 287 mswindows_output_blank (struct window *w, struct display_line *dl,
+ − 288 struct rune *rb, int start_pixpos)
+ − 289 {
+ − 290 struct frame *f = XFRAME (w->frame);
442
+ − 291 HDC hdc = get_frame_dc (f, 1);
428
+ − 292 RECT rect = { rb->xpos, DISPLAY_LINE_YPOS (dl),
+ − 293 rb->xpos+rb->width,
+ − 294 DISPLAY_LINE_YEND (dl) };
+ − 295 struct face_cachel *cachel = WINDOW_FACE_CACHEL (w, rb->findex);
+ − 296
+ − 297 Lisp_Object bg_pmap = WINDOW_FACE_CACHEL_BACKGROUND_PIXMAP (w, rb->findex);
+ − 298
+ − 299 /* Unmap all subwindows in the area we are going to blank. */
+ − 300 redisplay_unmap_subwindows_maybe (f, rb->xpos, DISPLAY_LINE_YPOS (dl),
+ − 301 rb->width, DISPLAY_LINE_HEIGHT (dl));
+ − 302
+ − 303 if (!IMAGE_INSTANCEP (bg_pmap)
+ − 304 || !IMAGE_INSTANCE_PIXMAP_TYPE_P (XIMAGE_INSTANCE (bg_pmap)))
+ − 305 bg_pmap = Qnil;
+ − 306
+ − 307 if (!NILP(bg_pmap))
+ − 308 {
+ − 309 struct display_box db;
+ − 310 struct display_glyph_area dga;
+ − 311 redisplay_calculate_display_boxes (dl, rb->xpos,
+ − 312 /*rb->object.dglyph.xoffset*/ 0,
+ − 313 start_pixpos, rb->width,
+ − 314 &db, &dga);
+ − 315 /* blank the background in the appropriate color */
440
+ − 316 mswindows_update_dc (hdc, cachel->foreground,
428
+ − 317 cachel->background, Qnil);
+ − 318 redisplay_output_pixmap (w, bg_pmap, &db, &dga, rb->findex,
+ − 319 0, 0, 0, TRUE);
+ − 320 }
+ − 321 else
+ − 322 {
440
+ − 323 mswindows_update_dc (hdc, Qnil, cachel->background, Qnil);
+ − 324 ExtTextOut (hdc, 0, 0, ETO_OPAQUE, &rect, NULL, 0, NULL);
428
+ − 325 }
+ − 326 }
+ − 327
+ − 328
+ − 329 /*****************************************************************************
+ − 330 mswindows_output_cursor
+ − 331
+ − 332 Draw a normal or end-of-line cursor. The end-of-line cursor is
+ − 333 narrower than the normal cursor.
+ − 334 ****************************************************************************/
+ − 335 static void
+ − 336 mswindows_output_cursor (struct window *w, struct display_line *dl, int xpos,
+ − 337 int width, face_index findex, Emchar ch, int image_p)
+ − 338 {
+ − 339 struct frame *f = XFRAME (w->frame);
+ − 340 struct device *d = XDEVICE (f->device);
+ − 341 struct face_cachel *cachel=0;
+ − 342 Lisp_Object font = Qnil;
+ − 343 int focus = EQ (w->frame, DEVICE_FRAME_WITH_FOCUS_REAL (d));
442
+ − 344 HDC hdc = get_frame_dc (f, 1);
440
+ − 345 unsigned int local_face_index=0;
428
+ − 346 char *p_char = NULL;
+ − 347 int n_char = 0;
+ − 348 RECT rect = { xpos,
+ − 349 DISPLAY_LINE_YPOS (dl),
+ − 350 xpos + width,
+ − 351 DISPLAY_LINE_YEND (dl) };
+ − 352 Lisp_Object bar = symbol_value_in_buffer (Qbar_cursor,
+ − 353 WINDOW_BUFFER (w));
+ − 354 int bar_p = image_p || !NILP (bar);
+ − 355 int cursor_p = !NILP (w->text_cursor_visible_p);
+ − 356 int real_char_p = ch != 0;
+ − 357
+ − 358 /* Unmap all subwindows in the area we are going to blank. */
+ − 359 redisplay_unmap_subwindows_maybe (f, xpos, DISPLAY_LINE_YPOS (dl),
+ − 360 width, DISPLAY_LINE_HEIGHT (dl));
+ − 361
+ − 362 if (real_char_p)
+ − 363 {
+ − 364 /* Use the font from the underlying character */
+ − 365 cachel = WINDOW_FACE_CACHEL (w, findex);
+ − 366
+ − 367 /* #### MULE: Need to know the charset! */
+ − 368 font = FACE_CACHEL_FONT (cachel, Vcharset_ascii);
+ − 369 }
+ − 370
+ − 371 if ((focus || bar_p) && real_char_p)
+ − 372 {
+ − 373 p_char = (char*) &ch;
+ − 374 n_char = 1;
+ − 375 }
+ − 376
+ − 377 if (!image_p)
+ − 378 {
+ − 379 struct face_cachel *color_cachel;
+ − 380
+ − 381 /* Use cursor fg/bg for block cursor, or character fg/bg for the bar
+ − 382 or when we need to erase the cursor. Output nothing at eol if bar
+ − 383 cursor */
440
+ − 384 local_face_index = get_builtin_face_cache_index (w, Vtext_cursor_face);
428
+ − 385 color_cachel = WINDOW_FACE_CACHEL (w, ((!cursor_p || bar_p) ?
440
+ − 386 findex : local_face_index));
+ − 387 mswindows_update_dc (hdc, color_cachel->foreground,
428
+ − 388 color_cachel->background, Qnil);
440
+ − 389 if (real_char_p)
+ − 390 mswindows_set_dc_font (hdc, font,
+ − 391 cachel->underline, cachel->strikethru);
+ − 392
428
+ − 393 ExtTextOut (hdc, xpos, dl->ypos, ETO_OPAQUE|ETO_CLIPPED, &rect, p_char, n_char, NULL);
+ − 394 }
+ − 395
+ − 396 if (!cursor_p)
+ − 397 return;
+ − 398
+ − 399 if (focus && bar_p)
+ − 400 {
+ − 401 rect.right = rect.left + (EQ (bar, Qt) ? 1 : min (2, width));
440
+ − 402 local_face_index = get_builtin_face_cache_index (w, Vtext_cursor_face);
+ − 403 cachel = WINDOW_FACE_CACHEL (w, local_face_index);
+ − 404 mswindows_update_dc (hdc, Qnil, cachel->background, Qnil);
428
+ − 405 ExtTextOut (hdc, xpos, dl->ypos, ETO_OPAQUE, &rect, NULL, 0, NULL);
+ − 406 }
+ − 407 else if (!focus)
+ − 408 {
+ − 409 /* Now have real character drawn in its own color. We deflate
+ − 410 the rectangle so character cell will be bounded by the
+ − 411 previously drawn cursor shape */
+ − 412 InflateRect (&rect, -1, -1);
+ − 413
+ − 414 if (real_char_p)
+ − 415 {
+ − 416 p_char = (char*) &ch;
+ − 417 n_char = 1;
+ − 418 }
+ − 419
440
+ − 420 local_face_index = get_builtin_face_cache_index (w, Vdefault_face);
+ − 421 cachel = WINDOW_FACE_CACHEL (w, (real_char_p ? findex : local_face_index));
+ − 422 mswindows_update_dc (hdc,
+ − 423 cachel->foreground, cachel->background, Qnil);
428
+ − 424 ExtTextOut (hdc, xpos, dl->ypos, ETO_OPAQUE | ETO_CLIPPED,
+ − 425 &rect, p_char, n_char, NULL);
+ − 426 }
+ − 427 }
+ − 428
+ − 429
+ − 430 /*****************************************************************************
+ − 431 mswindows_output_string
+ − 432
+ − 433 Given a string and a starting position, output that string in the
+ − 434 given face.
+ − 435 Correctly handles multiple charsets in the string.
+ − 436
+ − 437 The meaning of the parameters is something like this:
+ − 438
+ − 439 W Window that the text is to be displayed in.
+ − 440 DL Display line that this text is on. The values in the
+ − 441 structure are used to determine the vertical position and
+ − 442 clipping range of the text.
+ − 443 BUF Dynamic array of Emchars specifying what is actually to be
+ − 444 drawn.
+ − 445 XPOS X position in pixels where the text should start being drawn.
+ − 446 XOFFSET Number of pixels to be chopped off the left side of the
+ − 447 text. The effect is as if the text were shifted to the
+ − 448 left this many pixels and clipped at XPOS.
+ − 449 CLIP_START Clip everything left of this X position.
+ − 450 WIDTH Clip everything right of XPOS + WIDTH.
+ − 451 FINDEX Index for the face cache element describing how to display
+ − 452 the text.
+ − 453 ****************************************************************************/
440
+ − 454 static void
428
+ − 455 mswindows_output_string (struct window *w, struct display_line *dl,
+ − 456 Emchar_dynarr *buf, int xpos, int xoffset, int clip_start,
+ − 457 int width, face_index findex,
+ − 458 int cursor, int cursor_start, int cursor_width,
+ − 459 int cursor_height)
+ − 460 {
+ − 461 struct frame *f = XFRAME (w->frame);
+ − 462 /* struct device *d = XDEVICE (f->device);*/
+ − 463 Lisp_Object window;
442
+ − 464 HDC hdc = get_frame_dc (f, 1);
428
+ − 465 int clip_end;
+ − 466 Lisp_Object bg_pmap;
+ − 467 int len = Dynarr_length (buf);
+ − 468 unsigned char *text_storage = (unsigned char *) alloca (2 * len);
+ − 469 textual_run *runs = alloca_array (textual_run, len);
+ − 470 int nruns;
+ − 471 int i, height;
+ − 472 RECT rect;
+ − 473 struct face_cachel *cachel = WINDOW_FACE_CACHEL (w, findex);
+ − 474
+ − 475 XSETWINDOW (window, w);
+ − 476
+ − 477 #if 0 /* #### FIXME? */
+ − 478 /* We can't work out the width before we've set the font in the DC */
+ − 479 if (width < 0)
+ − 480 width = mswindows_text_width (cachel, Dynarr_atp (buf, 0), Dynarr_length (buf));
+ − 481 #else
+ − 482 assert(width>=0);
+ − 483 #endif
+ − 484
+ − 485 /* Regularize the variables passed in. */
+ − 486 if (clip_start < xpos)
+ − 487 clip_start = xpos;
+ − 488 clip_end = xpos + width;
+ − 489 if (clip_start >= clip_end)
+ − 490 /* It's all clipped out. */
+ − 491 return;
+ − 492
+ − 493 xpos -= xoffset;
+ − 494
+ − 495 /* sort out the destination rectangle */
+ − 496 height = DISPLAY_LINE_HEIGHT (dl);
+ − 497 rect.left = clip_start;
+ − 498 rect.top = DISPLAY_LINE_YPOS (dl);
+ − 499 rect.right = clip_end;
+ − 500 rect.bottom = rect.top + height;
+ − 501
+ − 502 /* make sure the area we are about to display is subwindow free. */
+ − 503 redisplay_unmap_subwindows_maybe (f, clip_start, DISPLAY_LINE_YPOS (dl),
+ − 504 clip_end - clip_start, DISPLAY_LINE_HEIGHT (dl));
+ − 505
+ − 506 /* output the background pixmap if there is one */
+ − 507 bg_pmap = cachel->background_pixmap;
+ − 508 if (!IMAGE_INSTANCEP (bg_pmap)
+ − 509 || !IMAGE_INSTANCE_PIXMAP_TYPE_P (XIMAGE_INSTANCE (bg_pmap)))
+ − 510 bg_pmap = Qnil;
+ − 511
+ − 512 if (!NILP(bg_pmap))
+ − 513 {
+ − 514 struct display_box db;
+ − 515 struct display_glyph_area dga;
+ − 516 redisplay_calculate_display_boxes (dl, xpos + xoffset, 0,
+ − 517 clip_start, width, &db, &dga);
+ − 518 /* blank the background in the appropriate color */
440
+ − 519 mswindows_update_dc (hdc,
+ − 520 cachel->foreground, cachel->background, Qnil);
428
+ − 521 redisplay_output_pixmap (w, bg_pmap, &db, &dga, findex,
+ − 522 0, 0, 0, TRUE);
+ − 523 /* output pixmap calls this so we have to recall to get correct
+ − 524 references */
+ − 525 cachel = WINDOW_FACE_CACHEL (w, findex);
+ − 526 }
+ − 527
+ − 528 nruns = separate_textual_runs (text_storage, runs, Dynarr_atp (buf, 0),
+ − 529 Dynarr_length (buf));
+ − 530
+ − 531 for (i = 0; i < nruns; i++)
+ − 532 {
+ − 533 Lisp_Object font = FACE_CACHEL_FONT (cachel, runs[i].charset);
440
+ − 534 Lisp_Font_Instance *fi = XFONT_INSTANCE (font);
428
+ − 535 int this_width;
+ − 536
+ − 537 if (EQ (font, Vthe_null_font_instance))
+ − 538 continue;
+ − 539
440
+ − 540 mswindows_update_dc (hdc, cachel->foreground,
428
+ − 541 NILP(bg_pmap) ? cachel->background : Qnil, Qnil);
440
+ − 542 mswindows_set_dc_font (hdc, font, cachel->underline, cachel->strikethru);
428
+ − 543
+ − 544 this_width = mswindows_text_width_single_run (hdc, cachel, runs + i);
+ − 545
+ − 546 /* cope with fonts taller than lines */
+ − 547 if ((int) fi->height < (int) (height + dl->clip + dl->top_clip))
+ − 548 {
+ − 549 int clear_start = max (xpos, clip_start);
+ − 550 int clear_end = min (xpos + this_width, clip_end);
+ − 551
+ − 552 {
+ − 553 redisplay_clear_region (window, findex, clear_start,
+ − 554 DISPLAY_LINE_YPOS (dl),
+ − 555 clear_end - clear_start,
+ − 556 height);
+ − 557 /* output pixmap calls this so we have to recall to get correct
+ − 558 references */
+ − 559 cachel = WINDOW_FACE_CACHEL (w, findex);
+ − 560 }
+ − 561 }
+ − 562
+ − 563 assert (runs[i].dimension == 1); /* #### FIXME: Broken when Mule? */
+ − 564 ExtTextOut (hdc, xpos, dl->ypos,
+ − 565 NILP(bg_pmap) ? ETO_CLIPPED | ETO_OPAQUE : ETO_CLIPPED,
+ − 566 &rect, (char *) runs[i].ptr, runs[i].len, NULL);
+ − 567
+ − 568 xpos += this_width;
+ − 569 }
+ − 570 }
+ − 571
+ − 572 static void
440
+ − 573 mswindows_output_dibitmap (struct frame *f, Lisp_Image_Instance *p,
428
+ − 574 struct display_box* db,
+ − 575 struct display_glyph_area* dga)
+ − 576 {
442
+ − 577 HDC hdc = get_frame_dc (f, 1);
440
+ − 578 HDC hcompdc = get_frame_compdc (f);
428
+ − 579 HGDIOBJ old=NULL;
442
+ − 580 const int real_x = IMAGE_INSTANCE_MSWINDOWS_BITMAP_REAL_WIDTH (p);
+ − 581 const int real_y = IMAGE_INSTANCE_MSWINDOWS_BITMAP_REAL_HEIGHT (p);
+ − 582 const int surface_x = IMAGE_INSTANCE_PIXMAP_WIDTH (p);
+ − 583 const int surface_y = IMAGE_INSTANCE_PIXMAP_HEIGHT (p);
428
+ − 584
442
+ − 585 /* first blit the mask */
428
+ − 586 if (IMAGE_INSTANCE_MSWINDOWS_MASK (p))
+ − 587 {
442
+ − 588 RGBQUAD bg;
+ − 589 COLORREF bgcolor;
428
+ − 590
440
+ − 591 old = SelectObject (hcompdc, IMAGE_INSTANCE_MSWINDOWS_MASK (p));
428
+ − 592
442
+ − 593 if (IMAGE_INSTANCE_TYPE (p) == IMAGE_MONO_PIXMAP)
+ − 594 {
+ − 595 COLORREF fgcolor;
+ − 596 RGBQUAD fg;
+ − 597
+ − 598 fgcolor = GetTextColor (hdc);
+ − 599 fg.rgbBlue = GetBValue (fgcolor);
+ − 600 fg.rgbRed = GetRValue (fgcolor);
+ − 601 fg.rgbGreen = GetGValue (fgcolor);
+ − 602 fg.rgbReserved = 0;
+ − 603 SetDIBColorTable (hcompdc, 0, 1, &fg);
+ − 604 }
428
+ − 605
442
+ − 606 bgcolor = GetBkColor (hdc);
+ − 607 bg.rgbBlue = GetBValue (bgcolor);
+ − 608 bg.rgbRed = GetRValue (bgcolor);
+ − 609 bg.rgbGreen = GetGValue (bgcolor);
+ − 610 bg.rgbReserved = 0;
+ − 611 SetDIBColorTable (hcompdc, 1, 1, &bg);
+ − 612
+ − 613 StretchBlt (hdc,
+ − 614 db->xpos, db->ypos,
+ − 615 dga->width, dga->height,
+ − 616 hcompdc,
+ − 617 MulDiv (dga->xoffset, real_x, surface_x),
+ − 618 MulDiv (dga->yoffset, real_y, surface_y),
+ − 619 MulDiv (dga->width, real_x, surface_x),
+ − 620 MulDiv (dga->height, real_y, surface_y),
+ − 621 SRCCOPY);
428
+ − 622
440
+ − 623 SelectObject (hcompdc, old);
428
+ − 624 }
+ − 625
442
+ − 626 /* Now blit the bitmap itself, or one of its slices. */
440
+ − 627 old = SelectObject (hcompdc,
428
+ − 628 IMAGE_INSTANCE_MSWINDOWS_BITMAP_SLICE
+ − 629 (p, IMAGE_INSTANCE_PIXMAP_SLICE (p)));
+ − 630
442
+ − 631 StretchBlt (hdc,
+ − 632 db->xpos, db->ypos,
+ − 633 dga->width, dga->height,
+ − 634 hcompdc,
+ − 635 MulDiv (dga->xoffset, real_x, surface_x),
+ − 636 MulDiv (dga->yoffset, real_y, surface_y),
+ − 637 MulDiv (dga->width, real_x, surface_x),
+ − 638 MulDiv (dga->height, real_y, surface_y),
+ − 639 IMAGE_INSTANCE_MSWINDOWS_MASK (p) ? SRCINVERT : SRCCOPY);
428
+ − 640
440
+ − 641 SelectObject (hcompdc, old);
428
+ − 642 }
+ − 643
+ − 644 /* X gc's have this nice property that setting the bg pixmap will
+ − 645 * output it offset relative to the window. Windows doesn't have this
+ − 646 * feature so we have to emulate this by outputting multiple pixmaps.
+ − 647 * This is only used for background pixmaps. Normal pixmaps are
+ − 648 * outputted once and are scrollable */
+ − 649 static void
+ − 650 mswindows_output_dibitmap_region (struct frame *f,
440
+ − 651 Lisp_Image_Instance *p,
428
+ − 652 struct display_box *db,
+ − 653 struct display_glyph_area *dga)
+ − 654 {
+ − 655 struct display_box xdb = { db->xpos, db->ypos, db->width, db->height };
+ − 656 struct display_glyph_area xdga
+ − 657 = { 0, 0, IMAGE_INSTANCE_PIXMAP_WIDTH (p),
+ − 658 IMAGE_INSTANCE_PIXMAP_HEIGHT (p) };
+ − 659 int pxoffset = 0, pyoffset = 0;
+ − 660
+ − 661 if (dga)
+ − 662 {
+ − 663 xdga.width = dga->width;
+ − 664 xdga.height = dga->height;
+ − 665 }
+ − 666 else if (!redisplay_normalize_glyph_area (&xdb, &xdga))
+ − 667 return;
+ − 668
+ − 669 /* when doing a bg pixmap do a partial pixmap first so that we
+ − 670 blt whole pixmaps thereafter */
+ − 671 xdga.height = min (xdga.height, IMAGE_INSTANCE_PIXMAP_HEIGHT (p) -
+ − 672 db->ypos % IMAGE_INSTANCE_PIXMAP_HEIGHT (p));
+ − 673
+ − 674 while (xdga.height > 0)
+ − 675 {
+ − 676 xdga.width = min (min (db->width, IMAGE_INSTANCE_PIXMAP_WIDTH (p)),
+ − 677 IMAGE_INSTANCE_PIXMAP_WIDTH (p) -
+ − 678 db->xpos % IMAGE_INSTANCE_PIXMAP_WIDTH (p));
+ − 679 pxoffset = 0;
+ − 680 while (xdga.width > 0)
+ − 681 {
+ − 682 xdb.xpos = db->xpos + pxoffset;
+ − 683 xdb.ypos = db->ypos + pyoffset;
+ − 684 /* do we need to offset the pixmap vertically? this is necessary
+ − 685 for background pixmaps. */
+ − 686 xdga.yoffset = xdb.ypos % IMAGE_INSTANCE_PIXMAP_HEIGHT (p);
+ − 687 xdga.xoffset = xdb.xpos % IMAGE_INSTANCE_PIXMAP_WIDTH (p);
+ − 688 /* the width is handled by mswindows_output_pixmap_region */
+ − 689 mswindows_output_dibitmap (f, p, &xdb, &xdga);
+ − 690 pxoffset += xdga.width;
+ − 691 xdga.width = min ((db->width - pxoffset),
+ − 692 IMAGE_INSTANCE_PIXMAP_WIDTH (p));
+ − 693 }
+ − 694 pyoffset += xdga.height;
+ − 695 xdga.height = min ((db->height - pyoffset),
+ − 696 IMAGE_INSTANCE_PIXMAP_HEIGHT (p));
+ − 697 }
+ − 698 }
+ − 699
+ − 700 /* Output a pixmap at the desired location.
+ − 701 DB normalized display_box.
+ − 702 DGA normalized display_glyph_area. */
+ − 703 static void
+ − 704 mswindows_output_pixmap (struct window *w, Lisp_Object image_instance,
+ − 705 struct display_box *db, struct display_glyph_area *dga,
+ − 706 face_index findex, int cursor_start, int cursor_width,
+ − 707 int cursor_height, int bg_pixmap)
+ − 708 {
+ − 709 struct frame *f = XFRAME (w->frame);
442
+ − 710 HDC hdc = get_frame_dc (f, 1);
428
+ − 711
440
+ − 712 Lisp_Image_Instance *p = XIMAGE_INSTANCE (image_instance);
428
+ − 713 Lisp_Object window;
+ − 714
+ − 715 XSETWINDOW (window, w);
+ − 716
+ − 717 /* Output the pixmap. Have to do this as many times as is required
+ − 718 to fill the given area */
440
+ − 719 mswindows_update_dc (hdc,
428
+ − 720 WINDOW_FACE_CACHEL_FOREGROUND (w, findex),
+ − 721 WINDOW_FACE_CACHEL_BACKGROUND (w, findex), Qnil);
+ − 722
+ − 723 if (bg_pixmap)
+ − 724 mswindows_output_dibitmap_region (f, p, db, dga);
+ − 725 else
+ − 726 mswindows_output_dibitmap (f, p, db, dga);
+ − 727 }
+ − 728
+ − 729 #ifdef HAVE_SCROLLBARS
+ − 730 /*
+ − 731 * This function paints window's deadbox, a rectangle between window
+ − 732 * borders and two short edges of both scrollbars.
+ − 733 *
+ − 734 * Function checks whether deadbox intersects with the rectangle pointed
+ − 735 * to by PRC, and paints only the intersection
+ − 736 */
+ − 737 static void
442
+ − 738 mswindows_redisplay_deadbox_maybe (struct window *w, const RECT* prc)
428
+ − 739 {
+ − 740 int sbh = window_scrollbar_height (w);
+ − 741 int sbw = window_scrollbar_width (w);
+ − 742 RECT rect_dead, rect_paint;
+ − 743 if (sbh == 0 || sbw == 0)
+ − 744 return;
+ − 745
+ − 746 if (!NILP (w->scrollbar_on_left_p))
+ − 747 rect_dead.left = WINDOW_LEFT (w);
+ − 748 else
+ − 749 rect_dead.left = WINDOW_TEXT_RIGHT (w);
+ − 750 rect_dead.right = rect_dead.left + sbw;
+ − 751
+ − 752 if (!NILP (w->scrollbar_on_top_p))
+ − 753 rect_dead.top = WINDOW_TOP (w);
+ − 754 else
+ − 755 rect_dead.top = WINDOW_TEXT_BOTTOM (w);
+ − 756 rect_dead.bottom = rect_dead.top + sbh;
+ − 757
+ − 758 if (IntersectRect (&rect_paint, &rect_dead, prc))
+ − 759 {
+ − 760 struct frame *f = XFRAME (WINDOW_FRAME (w));
442
+ − 761 FillRect (get_frame_dc (f, 1), &rect_paint,
428
+ − 762 (HBRUSH) (COLOR_BTNFACE+1));
+ − 763 }
+ − 764 }
+ − 765
+ − 766 #endif /* HAVE_SCROLLBARS */
+ − 767
+ − 768 /*****************************************************************************
+ − 769 mswindows_redraw_exposed_window
+ − 770
+ − 771 Given a bounding box for an area that needs to be redrawn, determine
+ − 772 what parts of what lines are contained within and re-output their
+ − 773 contents.
+ − 774 Copied from redisplay-x.c
+ − 775 ****************************************************************************/
+ − 776 static void
+ − 777 mswindows_redraw_exposed_window (struct window *w, int x, int y, int width,
+ − 778 int height)
+ − 779 {
+ − 780 struct frame *f = XFRAME (w->frame);
+ − 781 int line;
+ − 782 int orig_windows_structure_changed;
+ − 783 RECT rect_window = { WINDOW_LEFT (w), WINDOW_TOP (w),
+ − 784 WINDOW_RIGHT (w), WINDOW_BOTTOM (w) };
+ − 785 RECT rect_expose = { x, y, x + width, y + height };
+ − 786 RECT rect_draw;
+ − 787
+ − 788 display_line_dynarr *cdla = window_display_lines (w, CURRENT_DISP);
+ − 789
+ − 790 if (!NILP (w->vchild))
+ − 791 {
+ − 792 mswindows_redraw_exposed_windows (w->vchild, x, y, width, height);
+ − 793 return;
+ − 794 }
+ − 795 else if (!NILP (w->hchild))
+ − 796 {
+ − 797 mswindows_redraw_exposed_windows (w->hchild, x, y, width, height);
+ − 798 return;
+ − 799 }
+ − 800
+ − 801 /* If the window doesn't intersect the exposed region, we're done here. */
+ − 802 if (!IntersectRect (&rect_draw, &rect_window, &rect_expose))
+ − 803 return;
+ − 804
+ − 805 /* We do this to make sure that the 3D modelines get redrawn if
+ − 806 they are in the exposed region. */
+ − 807 orig_windows_structure_changed = f->windows_structure_changed;
+ − 808 f->windows_structure_changed = 1;
+ − 809
+ − 810 if (window_needs_vertical_divider (w))
+ − 811 {
+ − 812 mswindows_output_vertical_divider (w, 0);
+ − 813 }
+ − 814
+ − 815 for (line = 0; line < Dynarr_length (cdla); line++)
+ − 816 {
+ − 817 struct display_line *cdl = Dynarr_atp (cdla, line);
+ − 818
+ − 819 if (DISPLAY_LINE_YPOS (cdl) + DISPLAY_LINE_HEIGHT (cdl)
+ − 820 >= rect_draw.top)
+ − 821 {
+ − 822 if (DISPLAY_LINE_YPOS (cdl) > rect_draw.bottom)
+ − 823 {
+ − 824 if (line == 0)
+ − 825 continue;
+ − 826 else
+ − 827 break;
+ − 828 }
+ − 829 else
+ − 830 {
+ − 831 output_display_line (w, 0, cdla, line,
+ − 832 rect_draw.left, rect_draw.right);
+ − 833 }
+ − 834 }
+ − 835 }
+ − 836
+ − 837 f->windows_structure_changed = orig_windows_structure_changed;
+ − 838
+ − 839 /* If there have never been any face cache_elements created, then this
+ − 840 expose event doesn't actually have anything to do. */
+ − 841 if (Dynarr_largest (w->face_cachels))
+ − 842 redisplay_clear_bottom_of_window (w, cdla, rect_draw.top, rect_draw.bottom);
+ − 843
+ − 844 #ifdef HAVE_SCROLLBARS
+ − 845 mswindows_redisplay_deadbox_maybe (w, &rect_expose);
+ − 846 #endif
+ − 847 }
+ − 848
+ − 849 /*****************************************************************************
+ − 850 mswindows_redraw_exposed_windows
+ − 851
+ − 852 For each window beneath the given window in the window hierarchy,
+ − 853 ensure that it is redrawn if necessary after an Expose event.
+ − 854 ****************************************************************************/
+ − 855 static void
+ − 856 mswindows_redraw_exposed_windows (Lisp_Object window, int x, int y, int width,
+ − 857 int height)
+ − 858 {
+ − 859 for (; !NILP (window); window = XWINDOW (window)->next)
+ − 860 mswindows_redraw_exposed_window (XWINDOW (window), x, y, width, height);
+ − 861 }
+ − 862
+ − 863 /*****************************************************************************
+ − 864 mswindows_redraw_exposed_area
+ − 865
+ − 866 For each window on the given frame, ensure that any area in the
+ − 867 Exposed area is redrawn.
+ − 868 ****************************************************************************/
+ − 869 void
+ − 870 mswindows_redraw_exposed_area (struct frame *f, int x, int y, int width, int height)
+ − 871 {
+ − 872 /* If any window on the frame has had its face cache reset then the
+ − 873 redisplay structures are effectively invalid. If we attempt to
+ − 874 use them we'll blow up. We mark the frame as changed to ensure
+ − 875 that redisplay will do a full update. This probably isn't
+ − 876 necessary but it can't hurt. */
+ − 877 #ifdef HAVE_TOOLBARS
+ − 878 /* #### We would rather put these off as well but there is currently
+ − 879 no combination of flags which will force an unchanged toolbar to
+ − 880 redraw anyhow. */
+ − 881 MAYBE_FRAMEMETH (f, redraw_exposed_toolbars, (f, x, y, width, height));
+ − 882 #endif
+ − 883 redraw_exposed_gutters (f, x, y, width, height);
+ − 884
+ − 885 if (!f->window_face_cache_reset)
+ − 886 {
+ − 887 mswindows_redraw_exposed_windows (f->root_window, x, y, width, height);
+ − 888 GdiFlush();
+ − 889 }
+ − 890 else
+ − 891 MARK_FRAME_CHANGED (f);
+ − 892 }
+ − 893
+ − 894
+ − 895 /*****************************************************************************
+ − 896 mswindows_bevel_area
+ − 897
+ − 898 Draw a 3d border around the specified area on window W.
+ − 899 ****************************************************************************/
+ − 900 static void
+ − 901 mswindows_bevel_area (struct window *w, face_index findex, int x, int y,
+ − 902 int width, int height, int thickness,
+ − 903 int edges, enum edge_style style)
+ − 904 {
+ − 905 struct frame *f = XFRAME (w->frame);
+ − 906 UINT edge;
+ − 907 UINT border = 0;
+ − 908
+ − 909 if (style == EDGE_ETCHED_IN)
+ − 910 edge = EDGE_ETCHED;
+ − 911 else if (style == EDGE_ETCHED_OUT)
+ − 912 edge = EDGE_BUMP;
+ − 913 else if (style == EDGE_BEVEL_IN)
+ − 914 {
+ − 915 if (thickness == 1)
+ − 916 edge = BDR_SUNKENINNER;
+ − 917 else
+ − 918 edge = EDGE_SUNKEN;
+ − 919 }
+ − 920 else /* EDGE_BEVEL_OUT */
+ − 921 {
+ − 922 if (thickness == 1)
+ − 923 edge = BDR_RAISEDINNER;
+ − 924 else
+ − 925 edge = EDGE_RAISED;
+ − 926 }
+ − 927
+ − 928 if (edges & EDGE_TOP)
+ − 929 border |= BF_TOP;
+ − 930 if (edges & EDGE_LEFT)
+ − 931 border |= BF_LEFT;
+ − 932 if (edges & EDGE_BOTTOM)
+ − 933 border |= BF_BOTTOM;
+ − 934 if (edges & EDGE_RIGHT)
+ − 935 border |= BF_RIGHT;
+ − 936
+ − 937 {
+ − 938 RECT rect = { x, y, x + width, y + height };
+ − 939 Lisp_Object color = WINDOW_FACE_CACHEL_BACKGROUND (w, findex);
442
+ − 940 HDC hdc = get_frame_dc (f, 1);
428
+ − 941
440
+ − 942 mswindows_update_dc (hdc, Qnil, color, Qnil);
+ − 943 DrawEdge (hdc, &rect, edge, border);
428
+ − 944 }
+ − 945 }
+ − 946
+ − 947
+ − 948 /*****************************************************************************
+ − 949 Display methods
+ − 950 *****************************************************************************/
+ − 951
+ − 952 /*****************************************************************************
+ − 953 mswindows_divider_height
+ − 954
+ − 955 Return the height of the horizontal divider.
+ − 956 ****************************************************************************/
+ − 957 static int
+ − 958 mswindows_divider_height (void)
+ − 959 {
+ − 960 return 1; /* XXX Copied from redisplay-X.c. What is this? */
+ − 961 }
+ − 962
+ − 963 /*****************************************************************************
+ − 964 mswindows_eol_cursor_width
+ − 965
+ − 966 Return the width of the end-of-line cursor.
+ − 967 ****************************************************************************/
+ − 968 static int
+ − 969 mswindows_eol_cursor_width (void)
+ − 970 {
+ − 971 return MSWINDOWS_EOL_CURSOR_WIDTH;
+ − 972 }
+ − 973
+ − 974 /*****************************************************************************
442
+ − 975 mswindows_frame_output_begin
428
+ − 976
+ − 977 Perform any necessary initialization prior to an update.
+ − 978 ****************************************************************************/
+ − 979 static void
442
+ − 980 mswindows_frame_output_begin (struct frame *f)
428
+ − 981 {
+ − 982 }
+ − 983
+ − 984 /*****************************************************************************
442
+ − 985 mswindows_frame_output_end
428
+ − 986
+ − 987 Perform any necessary flushing of queues when an update has completed.
+ − 988 ****************************************************************************/
+ − 989 static void
442
+ − 990 mswindows_frame_output_end (struct frame *f)
+ − 991 {
+ − 992 #ifdef DEFER_WINDOW_POS
+ − 993 HDWP hdwp = FRAME_MSWINDOWS_DATA (f)->hdwp;
+ − 994
+ − 995 if (hdwp != 0)
+ − 996 {
+ − 997 EndDeferWindowPos (hdwp);
+ − 998 FRAME_MSWINDOWS_DATA (f)->hdwp = 0;
+ − 999 }
+ − 1000 #endif
+ − 1001 GdiFlush();
+ − 1002 }
+ − 1003
+ − 1004 /* Printer version is more lightweight. */
+ − 1005 static void
+ − 1006 msprinter_frame_output_end (struct frame *f)
428
+ − 1007 {
+ − 1008 GdiFlush();
+ − 1009 }
+ − 1010
+ − 1011 static int
+ − 1012 mswindows_flash (struct device *d)
+ − 1013 {
+ − 1014 struct frame *f = device_selected_frame (d);
442
+ − 1015 HDC hdc = get_frame_dc (f, 1);
428
+ − 1016 RECT rc;
+ − 1017
+ − 1018 GetClientRect (FRAME_MSWINDOWS_HANDLE (f), &rc);
440
+ − 1019 InvertRect (hdc, &rc);
428
+ − 1020 GdiFlush ();
+ − 1021 Sleep (25);
440
+ − 1022 InvertRect (hdc, &rc);
428
+ − 1023
+ − 1024 return 1;
+ − 1025 }
+ − 1026
+ − 1027 static void
+ − 1028 mswindows_ring_bell (struct device *d, int volume, int pitch, int duration)
+ − 1029 {
+ − 1030 /* Beep does not work at all, anyways! -kkm */
+ − 1031 MessageBeep (MB_OK);
+ − 1032 }
+ − 1033
+ − 1034 /*****************************************************************************
+ − 1035 mswindows_output_display_block
+ − 1036
+ − 1037 Given a display line, a block number for that start line, output all
+ − 1038 runes between start and end in the specified display block.
+ − 1039 Ripped off with minimal thought from the corresponding X routine.
+ − 1040 ****************************************************************************/
+ − 1041 static void
+ − 1042 mswindows_output_display_block (struct window *w, struct display_line *dl, int block,
+ − 1043 int start, int end, int start_pixpos, int cursor_start,
+ − 1044 int cursor_width, int cursor_height)
+ − 1045 {
+ − 1046 struct frame *f = XFRAME (w->frame);
+ − 1047 Emchar_dynarr *buf = Dynarr_new (Emchar);
+ − 1048 Lisp_Object window;
+ − 1049
+ − 1050 struct display_block *db = Dynarr_atp (dl->display_blocks, block);
+ − 1051 rune_dynarr *rba = db->runes;
+ − 1052 struct rune *rb;
+ − 1053
+ − 1054 int elt = start;
+ − 1055 face_index findex;
+ − 1056 int xpos, width;
+ − 1057 Lisp_Object charset = Qunbound; /* Qnil is a valid charset when
+ − 1058 MULE is not defined */
+ − 1059 XSETWINDOW (window, w);
+ − 1060 rb = Dynarr_atp (rba, start);
+ − 1061
+ − 1062 if (!rb)
+ − 1063 /* Nothing to do so don't do anything. */
+ − 1064 return;
+ − 1065
+ − 1066 findex = rb->findex;
+ − 1067 xpos = rb->xpos;
+ − 1068 width = 0;
+ − 1069 if (rb->type == RUNE_CHAR)
+ − 1070 charset = CHAR_CHARSET (rb->object.chr.ch);
+ − 1071
+ − 1072 if (end < 0)
+ − 1073 end = Dynarr_length (rba);
+ − 1074 Dynarr_reset (buf);
+ − 1075
+ − 1076 while (elt < end)
+ − 1077 {
+ − 1078 rb = Dynarr_atp (rba, elt);
+ − 1079
+ − 1080 if (rb->findex == findex && rb->type == RUNE_CHAR
+ − 1081 && rb->object.chr.ch != '\n' && rb->cursor_type != CURSOR_ON
+ − 1082 && EQ (charset, CHAR_CHARSET (rb->object.chr.ch)))
+ − 1083 {
+ − 1084 Dynarr_add (buf, rb->object.chr.ch);
+ − 1085 width += rb->width;
+ − 1086 elt++;
+ − 1087 }
+ − 1088 else
+ − 1089 {
+ − 1090 if (Dynarr_length (buf))
+ − 1091 {
+ − 1092 mswindows_output_string (w, dl, buf, xpos, 0, start_pixpos, width,
+ − 1093 findex, 0, 0, 0, 0);
+ − 1094 xpos = rb->xpos;
+ − 1095 width = 0;
+ − 1096 }
+ − 1097 Dynarr_reset (buf);
+ − 1098 width = 0;
+ − 1099
+ − 1100 if (rb->type == RUNE_CHAR)
+ − 1101 {
+ − 1102 findex = rb->findex;
+ − 1103 xpos = rb->xpos;
+ − 1104 charset = CHAR_CHARSET (rb->object.chr.ch);
+ − 1105
+ − 1106 if (rb->cursor_type == CURSOR_ON)
+ − 1107 {
+ − 1108 if (rb->object.chr.ch == '\n')
+ − 1109 {
+ − 1110 mswindows_output_cursor (w, dl, xpos, cursor_width,
+ − 1111 findex, 0, 0);
+ − 1112 }
+ − 1113 else
+ − 1114 {
+ − 1115 Dynarr_add (buf, rb->object.chr.ch);
+ − 1116 mswindows_output_cursor (w, dl, xpos, cursor_width,
+ − 1117 findex, rb->object.chr.ch, 0);
+ − 1118 Dynarr_reset (buf);
+ − 1119 }
+ − 1120
+ − 1121 xpos += rb->width;
+ − 1122 elt++;
+ − 1123 }
+ − 1124 else if (rb->object.chr.ch == '\n')
+ − 1125 {
+ − 1126 /* Clear in case a cursor was formerly here. */
+ − 1127 redisplay_clear_region (window, findex, xpos,
+ − 1128 DISPLAY_LINE_YPOS (dl),
+ − 1129 rb->width, DISPLAY_LINE_HEIGHT (dl));
+ − 1130 elt++;
+ − 1131 }
+ − 1132 }
+ − 1133 else if (rb->type == RUNE_BLANK || rb->type == RUNE_HLINE)
+ − 1134 {
+ − 1135 if (rb->type == RUNE_BLANK)
+ − 1136 mswindows_output_blank (w, dl, rb, start_pixpos);
+ − 1137 else
+ − 1138 {
+ − 1139 /* #### Our flagging of when we need to redraw the
+ − 1140 modeline shadows sucks. Since RUNE_HLINE is only used
+ − 1141 by the modeline at the moment it is a good bet
+ − 1142 that if it gets redrawn then we should also
+ − 1143 redraw the shadows. This won't be true forever.
+ − 1144 We borrow the shadow_thickness_changed flag for
+ − 1145 now. */
+ − 1146 w->shadow_thickness_changed = 1;
+ − 1147 mswindows_output_hline (w, dl, rb);
+ − 1148 }
+ − 1149
+ − 1150 if (rb->cursor_type == CURSOR_ON)
+ − 1151 mswindows_output_cursor (w, dl, xpos, cursor_width, rb->findex, 0, 0);
+ − 1152
+ − 1153 elt++;
+ − 1154 if (elt < end)
+ − 1155 {
+ − 1156 rb = Dynarr_atp (rba, elt);
+ − 1157
+ − 1158 findex = rb->findex;
+ − 1159 xpos = rb->xpos;
+ − 1160 }
+ − 1161 }
+ − 1162 else if (rb->type == RUNE_DGLYPH)
+ − 1163 {
+ − 1164 Lisp_Object instance;
440
+ − 1165 struct display_box dbox;
428
+ − 1166 struct display_glyph_area dga;
442
+ − 1167
428
+ − 1168 redisplay_calculate_display_boxes (dl, rb->xpos, rb->object.dglyph.xoffset,
+ − 1169 start_pixpos, rb->width,
440
+ − 1170 &dbox, &dga);
428
+ − 1171
+ − 1172 XSETWINDOW (window, w);
+ − 1173 instance = glyph_image_instance (rb->object.dglyph.glyph,
+ − 1174 window, ERROR_ME_NOT, 1);
+ − 1175 findex = rb->findex;
+ − 1176
+ − 1177 if (IMAGE_INSTANCEP (instance))
442
+ − 1178 {
+ − 1179 switch (XIMAGE_INSTANCE_TYPE (instance))
428
+ − 1180 {
442
+ − 1181 case IMAGE_MONO_PIXMAP:
+ − 1182 case IMAGE_COLOR_PIXMAP:
+ − 1183 redisplay_output_pixmap (w, instance, &dbox, &dga, findex,
+ − 1184 cursor_start, cursor_width,
+ − 1185 cursor_height, 0);
428
+ − 1186 if (rb->cursor_type == CURSOR_ON)
+ − 1187 mswindows_output_cursor (w, dl, xpos, cursor_width,
442
+ − 1188 findex, 0, 1);
+ − 1189 break;
+ − 1190
+ − 1191 case IMAGE_WIDGET:
+ − 1192 if (EQ (XIMAGE_INSTANCE_WIDGET_TYPE (instance),
+ − 1193 Qlayout))
+ − 1194 {
+ − 1195 redisplay_output_layout (window, instance, &dbox, &dga, findex,
+ − 1196 cursor_start, cursor_width,
+ − 1197 cursor_height);
+ − 1198 if (rb->cursor_type == CURSOR_ON)
+ − 1199 mswindows_output_cursor (w, dl, xpos, cursor_width,
+ − 1200 findex, 0, 1);
+ − 1201 break;
+ − 1202 }
+ − 1203 case IMAGE_SUBWINDOW:
+ − 1204 redisplay_output_subwindow (w, instance, &dbox, &dga, findex,
+ − 1205 cursor_start, cursor_width,
+ − 1206 cursor_height);
+ − 1207 if (rb->cursor_type == CURSOR_ON)
+ − 1208 mswindows_output_cursor (w, dl, xpos, cursor_width,
+ − 1209 findex, 0, 1);
+ − 1210 break;
+ − 1211
+ − 1212 case IMAGE_NOTHING:
+ − 1213 /* nothing is as nothing does */
+ − 1214 break;
428
+ − 1215
442
+ − 1216 case IMAGE_TEXT:
+ − 1217 case IMAGE_POINTER:
+ − 1218 default:
+ − 1219 abort ();
+ − 1220 }
+ − 1221 IMAGE_INSTANCE_OPTIMIZE_OUTPUT
+ − 1222 (XIMAGE_INSTANCE (instance)) = 0;
+ − 1223 }
428
+ − 1224 xpos += rb->width;
+ − 1225 elt++;
+ − 1226 }
+ − 1227 else
+ − 1228 abort ();
+ − 1229 }
+ − 1230 }
+ − 1231
+ − 1232 if (Dynarr_length (buf))
+ − 1233 mswindows_output_string (w, dl, buf, xpos, 0, start_pixpos, width, findex,
+ − 1234 0, 0, 0, 0);
+ − 1235
+ − 1236 if (dl->modeline
+ − 1237 && !EQ (Qzero, w->modeline_shadow_thickness)
+ − 1238 && (f->clear
+ − 1239 || f->windows_structure_changed
+ − 1240 || w->shadow_thickness_changed))
+ − 1241 bevel_modeline (w, dl);
+ − 1242
+ − 1243 Dynarr_free (buf);
+ − 1244 }
+ − 1245
+ − 1246
+ − 1247 /*****************************************************************************
+ − 1248 mswindows_output_vertical_divider
+ − 1249
+ − 1250 Draw a vertical divider down the right side of the given window.
+ − 1251 ****************************************************************************/
+ − 1252 static void
+ − 1253 mswindows_output_vertical_divider (struct window *w, int clear_unused)
+ − 1254 {
+ − 1255 struct frame *f = XFRAME (w->frame);
442
+ − 1256 HDC hdc = get_frame_dc (f, 1);
428
+ − 1257 RECT rect;
+ − 1258 int spacing = XINT (w->vertical_divider_spacing);
+ − 1259 int shadow = XINT (w->vertical_divider_shadow_thickness);
+ − 1260 int abs_shadow = abs (shadow);
+ − 1261 int line_width = XINT (w->vertical_divider_line_width);
+ − 1262 int div_left = WINDOW_RIGHT (w) - window_divider_width (w);
442
+ − 1263 int y1 = WINDOW_TOP (w);
+ − 1264 int y2 = WINDOW_BOTTOM (w);
428
+ − 1265
+ − 1266 /* Clear left and right spacing areas */
+ − 1267 if (spacing)
+ − 1268 {
+ − 1269 rect.top = y1;
+ − 1270 rect.bottom = y2;
440
+ − 1271 mswindows_update_dc (hdc, Qnil,
428
+ − 1272 WINDOW_FACE_CACHEL_BACKGROUND (w, DEFAULT_INDEX), Qnil);
+ − 1273 rect.right = WINDOW_RIGHT (w);
+ − 1274 rect.left = rect.right - spacing;
440
+ − 1275 ExtTextOut (hdc, 0, 0, ETO_OPAQUE,
428
+ − 1276 &rect, NULL, 0, NULL);
+ − 1277 rect.left = div_left;
+ − 1278 rect.right = div_left + spacing;
440
+ − 1279 ExtTextOut (hdc, 0, 0, ETO_OPAQUE,
428
+ − 1280 &rect, NULL, 0, NULL);
+ − 1281 }
+ − 1282
+ − 1283 /* Clear divider face */
+ − 1284 rect.top = y1 + abs_shadow;
+ − 1285 rect.bottom = y2 - abs_shadow;
+ − 1286 rect.left = div_left + spacing + abs_shadow;
+ − 1287 rect.right = rect.left + line_width;
+ − 1288 if (rect.left < rect.right)
+ − 1289 {
+ − 1290 face_index div_face
+ − 1291 = get_builtin_face_cache_index (w, Vvertical_divider_face);
440
+ − 1292 mswindows_update_dc (hdc, Qnil,
428
+ − 1293 WINDOW_FACE_CACHEL_BACKGROUND (w, div_face), Qnil);
440
+ − 1294 ExtTextOut (hdc, 0, 0, ETO_OPAQUE, &rect, NULL, 0, NULL);
428
+ − 1295 }
+ − 1296
+ − 1297 /* Draw a shadow around the divider */
+ − 1298 if (shadow != 0)
+ − 1299 {
+ − 1300 /* #### This will be fixed to support arbitrary thickness */
+ − 1301 InflateRect (&rect, abs_shadow, abs_shadow);
440
+ − 1302 DrawEdge (hdc, &rect,
428
+ − 1303 shadow > 0 ? EDGE_RAISED : EDGE_SUNKEN, BF_RECT);
+ − 1304 }
+ − 1305 }
+ − 1306
+ − 1307 /****************************************************************************
+ − 1308 mswindows_text_width
+ − 1309
+ − 1310 Given a string and a face, return the string's length in pixels when
+ − 1311 displayed in the font associated with the face.
+ − 1312 ****************************************************************************/
+ − 1313 static int
+ − 1314 mswindows_text_width (struct frame *f, struct face_cachel *cachel,
442
+ − 1315 const Emchar *str, Charcount len)
428
+ − 1316 {
442
+ − 1317 HDC hdc = get_frame_dc (f, 0);
428
+ − 1318 int width_so_far = 0;
+ − 1319 unsigned char *text_storage = (unsigned char *) alloca (2 * len);
+ − 1320 textual_run *runs = alloca_array (textual_run, len);
+ − 1321 int nruns;
+ − 1322 int i;
+ − 1323
+ − 1324 nruns = separate_textual_runs (text_storage, runs, str, len);
+ − 1325
+ − 1326 for (i = 0; i < nruns; i++)
440
+ − 1327 width_so_far += mswindows_text_width_single_run (hdc,
428
+ − 1328 cachel, runs + i);
+ − 1329
+ − 1330 return width_so_far;
+ − 1331 }
+ − 1332
+ − 1333
+ − 1334 /****************************************************************************
+ − 1335 mswindows_clear_region
+ − 1336
+ − 1337 Clear the area in the box defined by the given parameters using the
+ − 1338 given face.
+ − 1339 ****************************************************************************/
+ − 1340 static void
+ − 1341 mswindows_clear_region (Lisp_Object locale, struct device* d, struct frame* f,
+ − 1342 face_index findex, int x, int y,
+ − 1343 int width, int height, Lisp_Object fcolor, Lisp_Object bcolor,
+ − 1344 Lisp_Object background_pixmap)
+ − 1345 {
+ − 1346 RECT rect = { x, y, x+width, y+height };
442
+ − 1347 HDC hdc = get_frame_dc (f, 1);
428
+ − 1348
+ − 1349 if (!NILP (background_pixmap))
+ − 1350 {
+ − 1351 struct display_box db = { x, y, width, height };
440
+ − 1352 mswindows_update_dc (hdc,
+ − 1353 fcolor, bcolor, background_pixmap);
428
+ − 1354 mswindows_output_dibitmap_region
+ − 1355 ( f, XIMAGE_INSTANCE (background_pixmap), &db, 0);
+ − 1356 }
+ − 1357 else
+ − 1358 {
440
+ − 1359 mswindows_update_dc (hdc, Qnil, fcolor, Qnil);
+ − 1360 ExtTextOut (hdc, 0, 0, ETO_OPAQUE,
428
+ − 1361 &rect, NULL, 0, NULL);
+ − 1362 }
+ − 1363
+ − 1364 #ifdef HAVE_SCROLLBARS
+ − 1365 if (WINDOWP (locale))
+ − 1366 mswindows_redisplay_deadbox_maybe (XWINDOW (locale), &rect);
+ − 1367 #endif
+ − 1368 }
+ − 1369
+ − 1370 /* XXX Implement me! */
+ − 1371 static void
+ − 1372 mswindows_clear_frame (struct frame *f)
+ − 1373 {
+ − 1374 GdiFlush();
+ − 1375 }
+ − 1376
+ − 1377
+ − 1378
+ − 1379 /************************************************************************/
+ − 1380 /* initialization */
+ − 1381 /************************************************************************/
+ − 1382
+ − 1383 void
+ − 1384 console_type_create_redisplay_mswindows (void)
+ − 1385 {
440
+ − 1386 /* redisplay methods - display*/
428
+ − 1387 CONSOLE_HAS_METHOD (mswindows, text_width);
+ − 1388 CONSOLE_HAS_METHOD (mswindows, output_display_block);
+ − 1389 CONSOLE_HAS_METHOD (mswindows, divider_height);
+ − 1390 CONSOLE_HAS_METHOD (mswindows, eol_cursor_width);
+ − 1391 CONSOLE_HAS_METHOD (mswindows, output_vertical_divider);
+ − 1392 CONSOLE_HAS_METHOD (mswindows, clear_region);
+ − 1393 CONSOLE_HAS_METHOD (mswindows, clear_frame);
442
+ − 1394 CONSOLE_HAS_METHOD (mswindows, frame_output_begin);
+ − 1395 CONSOLE_HAS_METHOD (mswindows, frame_output_end);
428
+ − 1396 CONSOLE_HAS_METHOD (mswindows, flash);
+ − 1397 CONSOLE_HAS_METHOD (mswindows, ring_bell);
+ − 1398 CONSOLE_HAS_METHOD (mswindows, bevel_area);
+ − 1399 CONSOLE_HAS_METHOD (mswindows, output_string);
+ − 1400 CONSOLE_HAS_METHOD (mswindows, output_pixmap);
440
+ − 1401
+ − 1402 /* redisplay methods - printer */
442
+ − 1403 CONSOLE_HAS_METHOD (msprinter, frame_output_end);
440
+ − 1404 CONSOLE_INHERITS_METHOD (msprinter, mswindows, text_width);
+ − 1405 CONSOLE_INHERITS_METHOD (msprinter, mswindows, output_display_block);
+ − 1406 CONSOLE_INHERITS_METHOD (msprinter, mswindows, divider_height);
+ − 1407 CONSOLE_INHERITS_METHOD (msprinter, mswindows, eol_cursor_width);
+ − 1408 CONSOLE_INHERITS_METHOD (msprinter, mswindows, output_vertical_divider);
+ − 1409 CONSOLE_INHERITS_METHOD (msprinter, mswindows, clear_region);
+ − 1410 CONSOLE_INHERITS_METHOD (msprinter, mswindows, clear_frame);
442
+ − 1411 CONSOLE_INHERITS_METHOD (msprinter, mswindows, frame_output_begin);
440
+ − 1412 CONSOLE_INHERITS_METHOD (msprinter, mswindows, bevel_area);
+ − 1413 CONSOLE_INHERITS_METHOD (msprinter, mswindows, output_string);
+ − 1414 CONSOLE_INHERITS_METHOD (msprinter, mswindows, output_pixmap);
428
+ − 1415 }