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