comparison src/redisplay-msw.c @ 428:3ecd8885ac67 r21-2-22

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