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