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.
6 This file is part of XEmacs.
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
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
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. */
23 /* Synched up with: Not in FSF. */
28 Lots of work done by Ben Wing for Mule
29 Partially rewritten for mswindows by Jonathan Harris, November 1997 for 21.0.
35 #include "console-msw.h"
36 #include "objects-msw.h"
43 #include "glyphs-msw.h"
45 #include "redisplay.h"
51 #include "mule-charset.h"
54 #define MSWINDOWS_EOL_CURSOR_WIDTH 5
57 * Random forward declarations
59 static void mswindows_update_dc (HDC hdc, Lisp_Object fg, Lisp_Object bg,
61 static void mswindows_set_dc_font (HDC hdc, Lisp_Object font,
62 int under, int strike);
63 static void mswindows_output_vertical_divider (struct window *w, int clear);
64 static void mswindows_redraw_exposed_windows (Lisp_Object window, int x,
65 int y, int width, int height);
66 static void mswindows_output_dibitmap (struct frame *f,
67 Lisp_Image_Instance *p,
68 struct display_box* db,
69 struct display_glyph_area* dga);
71 typedef struct textual_run
79 /* Separate out the text in DYN into a series of textual runs of a
80 particular charset. Also convert the characters as necessary into
81 the format needed by XDrawImageString(), XDrawImageString16(), et
82 al. (This means converting to one or two byte format, possibly
83 tweaking the high bits, and possibly running a CCL program.) You
84 must pre-allocate the space used and pass it in. (This is done so
85 you can alloca() the space.) You need to allocate (2 * len) bytes
86 of TEXT_STORAGE and (len * sizeof (textual_run)) bytes of
87 RUN_STORAGE, where LEN is the length of the dynarr.
89 Returns the number of runs actually used. */
92 separate_textual_runs (unsigned char *text_storage,
93 textual_run *run_storage,
94 CONST Emchar *str, Charcount len)
96 Lisp_Object prev_charset = Qunbound; /* not Qnil because that is a
97 possible valid charset when
98 MULE is not defined */
102 struct ccl_program char_converter;
103 int need_ccl_conversion = 0;
106 for (i = 0; i < len; i++)
114 BREAKUP_CHAR (ch, charset, byte1, byte2);
115 dimension = XCHARSET_DIMENSION (charset);
116 graphic = XCHARSET_GRAPHIC (charset);
118 if (!EQ (charset, prev_charset))
120 run_storage[runs_so_far].ptr = text_storage;
121 run_storage[runs_so_far].charset = charset;
122 run_storage[runs_so_far].dimension = dimension;
126 run_storage[runs_so_far - 1].len =
127 text_storage - run_storage[runs_so_far - 1].ptr;
128 if (run_storage[runs_so_far - 1].dimension == 2)
129 run_storage[runs_so_far - 1].len >>= 1;
132 prev_charset = charset;
135 Lisp_Object ccl_prog = XCHARSET_CCL_PROGRAM (charset);
136 need_ccl_conversion = !NILP (ccl_prog);
137 if (need_ccl_conversion)
138 setup_ccl_program (&char_converter, ccl_prog);
148 else if (graphic == 1)
154 if (need_ccl_conversion)
156 char_converter.reg[0] = XCHARSET_ID (charset);
157 char_converter.reg[1] = byte1;
158 char_converter.reg[2] = byte2;
159 char_converter.ic = 0; /* start at beginning each time */
160 ccl_driver (&char_converter, 0, 0, 0, 0, CCL_MODE_ENCODING);
161 byte1 = char_converter.reg[1];
162 byte2 = char_converter.reg[2];
165 *text_storage++ = (unsigned char) byte1;
167 *text_storage++ = (unsigned char) byte2;
172 run_storage[runs_so_far - 1].len =
173 text_storage - run_storage[runs_so_far - 1].ptr;
174 if (run_storage[runs_so_far - 1].dimension == 2)
175 run_storage[runs_so_far - 1].len >>= 1;
183 mswindows_text_width_single_run (HDC hdc, struct face_cachel *cachel,
186 Lisp_Object font_inst = FACE_CACHEL_FONT (cachel, run->charset);
187 Lisp_Font_Instance *fi = XFONT_INSTANCE (font_inst);
190 if (!fi->proportional_p || !hdc)
191 return (fi->width * run->len);
194 assert(run->dimension == 1); /* #### FIXME! */
195 mswindows_set_dc_font (hdc, font_inst,
196 cachel->underline, cachel->strikethru);
197 GetTextExtentPoint32 (hdc, run->ptr, run->len, &size);
203 * Given F, retrieve device context. F can be a display frame, or
207 get_frame_dc (struct frame *f)
209 if (FRAME_MSWINDOWS_P (f))
210 return FRAME_MSWINDOWS_DC (f);
212 return DEVICE_MSPRINTER_HDC (XDEVICE (FRAME_DEVICE (f)));
216 * Given F, retrieve compatible device context. F can be a display
217 * frame, or a print job.
220 get_frame_compdc (struct frame *f)
222 if (FRAME_MSWINDOWS_P (f))
223 return FRAME_MSWINDOWS_CDC (f);
225 return FRAME_MSPRINTER_CDC (f);
228 /*****************************************************************************
231 Given a number of parameters munge the DC so it has those properties.
232 ****************************************************************************/
234 mswindows_update_dc (HDC hdc, Lisp_Object fg, Lisp_Object bg,
239 SetTextColor (hdc, COLOR_INSTANCE_MSWINDOWS_COLOR
240 (XCOLOR_INSTANCE (fg)));
245 SetBkMode (hdc, OPAQUE);
246 SetBkColor (hdc, COLOR_INSTANCE_MSWINDOWS_COLOR (XCOLOR_INSTANCE (bg)));
250 SetBkMode (hdc, TRANSPARENT);
254 static void mswindows_set_dc_font (HDC hdc, Lisp_Object font,
255 int under, int strike)
257 SelectObject(hdc, mswindows_get_hfont (XFONT_INSTANCE (font),
261 /*****************************************************************************
262 mswindows_output_hline
264 Output a horizontal line in the foreground of its face.
265 ****************************************************************************/
267 mswindows_output_hline (struct window *w, struct display_line *dl, struct rune *rb)
268 { /* XXX Implement me */
272 /*****************************************************************************
273 mswindows_output_blank
275 Output a blank by clearing the area it covers in the background color
277 ****************************************************************************/
279 mswindows_output_blank (struct window *w, struct display_line *dl,
280 struct rune *rb, int start_pixpos)
282 struct frame *f = XFRAME (w->frame);
283 HDC hdc = get_frame_dc (f);
284 RECT rect = { rb->xpos, DISPLAY_LINE_YPOS (dl),
286 DISPLAY_LINE_YEND (dl) };
287 struct face_cachel *cachel = WINDOW_FACE_CACHEL (w, rb->findex);
289 Lisp_Object bg_pmap = WINDOW_FACE_CACHEL_BACKGROUND_PIXMAP (w, rb->findex);
291 /* Unmap all subwindows in the area we are going to blank. */
292 redisplay_unmap_subwindows_maybe (f, rb->xpos, DISPLAY_LINE_YPOS (dl),
293 rb->width, DISPLAY_LINE_HEIGHT (dl));
295 if (!IMAGE_INSTANCEP (bg_pmap)
296 || !IMAGE_INSTANCE_PIXMAP_TYPE_P (XIMAGE_INSTANCE (bg_pmap)))
301 struct display_box db;
302 struct display_glyph_area dga;
303 redisplay_calculate_display_boxes (dl, rb->xpos,
304 /*rb->object.dglyph.xoffset*/ 0,
305 start_pixpos, rb->width,
307 /* blank the background in the appropriate color */
308 mswindows_update_dc (hdc, cachel->foreground,
309 cachel->background, Qnil);
310 redisplay_output_pixmap (w, bg_pmap, &db, &dga, rb->findex,
315 mswindows_update_dc (hdc, Qnil, cachel->background, Qnil);
316 ExtTextOut (hdc, 0, 0, ETO_OPAQUE, &rect, NULL, 0, NULL);
321 /*****************************************************************************
322 mswindows_output_cursor
324 Draw a normal or end-of-line cursor. The end-of-line cursor is
325 narrower than the normal cursor.
326 ****************************************************************************/
328 mswindows_output_cursor (struct window *w, struct display_line *dl, int xpos,
329 int width, face_index findex, Emchar ch, int image_p)
331 struct frame *f = XFRAME (w->frame);
332 struct device *d = XDEVICE (f->device);
333 struct face_cachel *cachel=0;
334 Lisp_Object font = Qnil;
335 int focus = EQ (w->frame, DEVICE_FRAME_WITH_FOCUS_REAL (d));
336 HDC hdc = get_frame_dc (f);
337 unsigned int local_face_index=0;
341 DISPLAY_LINE_YPOS (dl),
343 DISPLAY_LINE_YEND (dl) };
344 Lisp_Object bar = symbol_value_in_buffer (Qbar_cursor,
346 int bar_p = image_p || !NILP (bar);
347 int cursor_p = !NILP (w->text_cursor_visible_p);
348 int real_char_p = ch != 0;
350 /* Unmap all subwindows in the area we are going to blank. */
351 redisplay_unmap_subwindows_maybe (f, xpos, DISPLAY_LINE_YPOS (dl),
352 width, DISPLAY_LINE_HEIGHT (dl));
356 /* Use the font from the underlying character */
357 cachel = WINDOW_FACE_CACHEL (w, findex);
359 /* #### MULE: Need to know the charset! */
360 font = FACE_CACHEL_FONT (cachel, Vcharset_ascii);
363 if ((focus || bar_p) && real_char_p)
365 p_char = (char*) &ch;
371 struct face_cachel *color_cachel;
373 /* Use cursor fg/bg for block cursor, or character fg/bg for the bar
374 or when we need to erase the cursor. Output nothing at eol if bar
376 local_face_index = get_builtin_face_cache_index (w, Vtext_cursor_face);
377 color_cachel = WINDOW_FACE_CACHEL (w, ((!cursor_p || bar_p) ?
378 findex : local_face_index));
379 mswindows_update_dc (hdc, color_cachel->foreground,
380 color_cachel->background, Qnil);
382 mswindows_set_dc_font (hdc, font,
383 cachel->underline, cachel->strikethru);
385 ExtTextOut (hdc, xpos, dl->ypos, ETO_OPAQUE|ETO_CLIPPED, &rect, p_char, n_char, NULL);
393 rect.right = rect.left + (EQ (bar, Qt) ? 1 : min (2, width));
394 local_face_index = get_builtin_face_cache_index (w, Vtext_cursor_face);
395 cachel = WINDOW_FACE_CACHEL (w, local_face_index);
396 mswindows_update_dc (hdc, Qnil, cachel->background, Qnil);
397 ExtTextOut (hdc, xpos, dl->ypos, ETO_OPAQUE, &rect, NULL, 0, NULL);
401 /* Now have real character drawn in its own color. We deflate
402 the rectangle so character cell will be bounded by the
403 previously drawn cursor shape */
404 InflateRect (&rect, -1, -1);
408 p_char = (char*) &ch;
412 local_face_index = get_builtin_face_cache_index (w, Vdefault_face);
413 cachel = WINDOW_FACE_CACHEL (w, (real_char_p ? findex : local_face_index));
414 mswindows_update_dc (hdc,
415 cachel->foreground, cachel->background, Qnil);
416 ExtTextOut (hdc, xpos, dl->ypos, ETO_OPAQUE | ETO_CLIPPED,
417 &rect, p_char, n_char, NULL);
422 /*****************************************************************************
423 mswindows_output_string
425 Given a string and a starting position, output that string in the
427 Correctly handles multiple charsets in the string.
429 The meaning of the parameters is something like this:
431 W Window that the text is to be displayed in.
432 DL Display line that this text is on. The values in the
433 structure are used to determine the vertical position and
434 clipping range of the text.
435 BUF Dynamic array of Emchars specifying what is actually to be
437 XPOS X position in pixels where the text should start being drawn.
438 XOFFSET Number of pixels to be chopped off the left side of the
439 text. The effect is as if the text were shifted to the
440 left this many pixels and clipped at XPOS.
441 CLIP_START Clip everything left of this X position.
442 WIDTH Clip everything right of XPOS + WIDTH.
443 FINDEX Index for the face cache element describing how to display
445 ****************************************************************************/
447 mswindows_output_string (struct window *w, struct display_line *dl,
448 Emchar_dynarr *buf, int xpos, int xoffset, int clip_start,
449 int width, face_index findex,
450 int cursor, int cursor_start, int cursor_width,
453 struct frame *f = XFRAME (w->frame);
454 /* struct device *d = XDEVICE (f->device);*/
456 HDC hdc = get_frame_dc (f);
459 int len = Dynarr_length (buf);
460 unsigned char *text_storage = (unsigned char *) alloca (2 * len);
461 textual_run *runs = alloca_array (textual_run, len);
465 struct face_cachel *cachel = WINDOW_FACE_CACHEL (w, findex);
467 XSETWINDOW (window, w);
469 #if 0 /* #### FIXME? */
470 /* We can't work out the width before we've set the font in the DC */
472 width = mswindows_text_width (cachel, Dynarr_atp (buf, 0), Dynarr_length (buf));
477 /* Regularize the variables passed in. */
478 if (clip_start < xpos)
480 clip_end = xpos + width;
481 if (clip_start >= clip_end)
482 /* It's all clipped out. */
487 /* sort out the destination rectangle */
488 height = DISPLAY_LINE_HEIGHT (dl);
489 rect.left = clip_start;
490 rect.top = DISPLAY_LINE_YPOS (dl);
491 rect.right = clip_end;
492 rect.bottom = rect.top + height;
494 /* make sure the area we are about to display is subwindow free. */
495 redisplay_unmap_subwindows_maybe (f, clip_start, DISPLAY_LINE_YPOS (dl),
496 clip_end - clip_start, DISPLAY_LINE_HEIGHT (dl));
498 /* output the background pixmap if there is one */
499 bg_pmap = cachel->background_pixmap;
500 if (!IMAGE_INSTANCEP (bg_pmap)
501 || !IMAGE_INSTANCE_PIXMAP_TYPE_P (XIMAGE_INSTANCE (bg_pmap)))
506 struct display_box db;
507 struct display_glyph_area dga;
508 redisplay_calculate_display_boxes (dl, xpos + xoffset, 0,
509 clip_start, width, &db, &dga);
510 /* blank the background in the appropriate color */
511 mswindows_update_dc (hdc,
512 cachel->foreground, cachel->background, Qnil);
513 redisplay_output_pixmap (w, bg_pmap, &db, &dga, findex,
515 /* output pixmap calls this so we have to recall to get correct
517 cachel = WINDOW_FACE_CACHEL (w, findex);
520 nruns = separate_textual_runs (text_storage, runs, Dynarr_atp (buf, 0),
521 Dynarr_length (buf));
523 for (i = 0; i < nruns; i++)
525 Lisp_Object font = FACE_CACHEL_FONT (cachel, runs[i].charset);
526 Lisp_Font_Instance *fi = XFONT_INSTANCE (font);
529 if (EQ (font, Vthe_null_font_instance))
532 mswindows_update_dc (hdc, cachel->foreground,
533 NILP(bg_pmap) ? cachel->background : Qnil, Qnil);
534 mswindows_set_dc_font (hdc, font, cachel->underline, cachel->strikethru);
536 this_width = mswindows_text_width_single_run (hdc, cachel, runs + i);
538 /* cope with fonts taller than lines */
539 if ((int) fi->height < (int) (height + dl->clip + dl->top_clip))
541 int clear_start = max (xpos, clip_start);
542 int clear_end = min (xpos + this_width, clip_end);
545 redisplay_clear_region (window, findex, clear_start,
546 DISPLAY_LINE_YPOS (dl),
547 clear_end - clear_start,
549 /* output pixmap calls this so we have to recall to get correct
551 cachel = WINDOW_FACE_CACHEL (w, findex);
555 assert (runs[i].dimension == 1); /* #### FIXME: Broken when Mule? */
556 ExtTextOut (hdc, xpos, dl->ypos,
557 NILP(bg_pmap) ? ETO_CLIPPED | ETO_OPAQUE : ETO_CLIPPED,
558 &rect, (char *) runs[i].ptr, runs[i].len, NULL);
565 mswindows_output_dibitmap (struct frame *f, Lisp_Image_Instance *p,
566 struct display_box* db,
567 struct display_glyph_area* dga)
569 HDC hdc = get_frame_dc (f);
570 HDC hcompdc = get_frame_compdc (f);
572 COLORREF bgcolor = GetBkColor (hdc);
574 /* first blt the mask */
575 if (IMAGE_INSTANCE_MSWINDOWS_MASK (p))
578 col.rgbBlue = GetBValue (bgcolor);
579 col.rgbRed = GetRValue (bgcolor);
580 col.rgbGreen = GetGValue (bgcolor);
583 old = SelectObject (hcompdc, IMAGE_INSTANCE_MSWINDOWS_MASK (p));
585 SetDIBColorTable (hcompdc, 1, 1, &col);
589 dga->width, dga->height,
591 dga->xoffset, dga->yoffset,
594 SelectObject (hcompdc, old);
597 /* Now blt the bitmap itself, or one of its slices. */
598 old = SelectObject (hcompdc,
599 IMAGE_INSTANCE_MSWINDOWS_BITMAP_SLICE
600 (p, IMAGE_INSTANCE_PIXMAP_SLICE (p)));
604 dga->width, dga->height,
606 dga->xoffset, dga->yoffset,
607 IMAGE_INSTANCE_MSWINDOWS_MASK (p) ? SRCINVERT : SRCCOPY);
609 SelectObject (hcompdc, old);
612 /* X gc's have this nice property that setting the bg pixmap will
613 * output it offset relative to the window. Windows doesn't have this
614 * feature so we have to emulate this by outputting multiple pixmaps.
615 * This is only used for background pixmaps. Normal pixmaps are
616 * outputted once and are scrollable */
618 mswindows_output_dibitmap_region (struct frame *f,
619 Lisp_Image_Instance *p,
620 struct display_box *db,
621 struct display_glyph_area *dga)
623 struct display_box xdb = { db->xpos, db->ypos, db->width, db->height };
624 struct display_glyph_area xdga
625 = { 0, 0, IMAGE_INSTANCE_PIXMAP_WIDTH (p),
626 IMAGE_INSTANCE_PIXMAP_HEIGHT (p) };
627 int pxoffset = 0, pyoffset = 0;
631 xdga.width = dga->width;
632 xdga.height = dga->height;
634 else if (!redisplay_normalize_glyph_area (&xdb, &xdga))
637 /* when doing a bg pixmap do a partial pixmap first so that we
638 blt whole pixmaps thereafter */
639 xdga.height = min (xdga.height, IMAGE_INSTANCE_PIXMAP_HEIGHT (p) -
640 db->ypos % IMAGE_INSTANCE_PIXMAP_HEIGHT (p));
642 while (xdga.height > 0)
644 xdga.width = min (min (db->width, IMAGE_INSTANCE_PIXMAP_WIDTH (p)),
645 IMAGE_INSTANCE_PIXMAP_WIDTH (p) -
646 db->xpos % IMAGE_INSTANCE_PIXMAP_WIDTH (p));
648 while (xdga.width > 0)
650 xdb.xpos = db->xpos + pxoffset;
651 xdb.ypos = db->ypos + pyoffset;
652 /* do we need to offset the pixmap vertically? this is necessary
653 for background pixmaps. */
654 xdga.yoffset = xdb.ypos % IMAGE_INSTANCE_PIXMAP_HEIGHT (p);
655 xdga.xoffset = xdb.xpos % IMAGE_INSTANCE_PIXMAP_WIDTH (p);
656 /* the width is handled by mswindows_output_pixmap_region */
657 mswindows_output_dibitmap (f, p, &xdb, &xdga);
658 pxoffset += xdga.width;
659 xdga.width = min ((db->width - pxoffset),
660 IMAGE_INSTANCE_PIXMAP_WIDTH (p));
662 pyoffset += xdga.height;
663 xdga.height = min ((db->height - pyoffset),
664 IMAGE_INSTANCE_PIXMAP_HEIGHT (p));
668 /* Output a pixmap at the desired location.
669 DB normalized display_box.
670 DGA normalized display_glyph_area. */
672 mswindows_output_pixmap (struct window *w, Lisp_Object image_instance,
673 struct display_box *db, struct display_glyph_area *dga,
674 face_index findex, int cursor_start, int cursor_width,
675 int cursor_height, int bg_pixmap)
677 struct frame *f = XFRAME (w->frame);
678 HDC hdc = get_frame_dc (f);
680 Lisp_Image_Instance *p = XIMAGE_INSTANCE (image_instance);
683 XSETWINDOW (window, w);
685 /* Output the pixmap. Have to do this as many times as is required
686 to fill the given area */
687 mswindows_update_dc (hdc,
688 WINDOW_FACE_CACHEL_FOREGROUND (w, findex),
689 WINDOW_FACE_CACHEL_BACKGROUND (w, findex), Qnil);
692 mswindows_output_dibitmap_region (f, p, db, dga);
694 mswindows_output_dibitmap (f, p, db, dga);
697 #ifdef HAVE_SCROLLBARS
699 * This function paints window's deadbox, a rectangle between window
700 * borders and two short edges of both scrollbars.
702 * Function checks whether deadbox intersects with the rectangle pointed
703 * to by PRC, and paints only the intersection
706 mswindows_redisplay_deadbox_maybe (struct window *w, CONST RECT* prc)
708 int sbh = window_scrollbar_height (w);
709 int sbw = window_scrollbar_width (w);
710 RECT rect_dead, rect_paint;
711 if (sbh == 0 || sbw == 0)
714 if (!NILP (w->scrollbar_on_left_p))
715 rect_dead.left = WINDOW_LEFT (w);
717 rect_dead.left = WINDOW_TEXT_RIGHT (w);
718 rect_dead.right = rect_dead.left + sbw;
720 if (!NILP (w->scrollbar_on_top_p))
721 rect_dead.top = WINDOW_TOP (w);
723 rect_dead.top = WINDOW_TEXT_BOTTOM (w);
724 rect_dead.bottom = rect_dead.top + sbh;
726 if (IntersectRect (&rect_paint, &rect_dead, prc))
728 struct frame *f = XFRAME (WINDOW_FRAME (w));
729 FillRect (get_frame_dc (f), &rect_paint,
730 (HBRUSH) (COLOR_BTNFACE+1));
734 #endif /* HAVE_SCROLLBARS */
736 /*****************************************************************************
737 mswindows_redraw_exposed_window
739 Given a bounding box for an area that needs to be redrawn, determine
740 what parts of what lines are contained within and re-output their
742 Copied from redisplay-x.c
743 ****************************************************************************/
745 mswindows_redraw_exposed_window (struct window *w, int x, int y, int width,
748 struct frame *f = XFRAME (w->frame);
750 int orig_windows_structure_changed;
751 RECT rect_window = { WINDOW_LEFT (w), WINDOW_TOP (w),
752 WINDOW_RIGHT (w), WINDOW_BOTTOM (w) };
753 RECT rect_expose = { x, y, x + width, y + height };
756 display_line_dynarr *cdla = window_display_lines (w, CURRENT_DISP);
758 if (!NILP (w->vchild))
760 mswindows_redraw_exposed_windows (w->vchild, x, y, width, height);
763 else if (!NILP (w->hchild))
765 mswindows_redraw_exposed_windows (w->hchild, x, y, width, height);
769 /* If the window doesn't intersect the exposed region, we're done here. */
770 if (!IntersectRect (&rect_draw, &rect_window, &rect_expose))
773 /* We do this to make sure that the 3D modelines get redrawn if
774 they are in the exposed region. */
775 orig_windows_structure_changed = f->windows_structure_changed;
776 f->windows_structure_changed = 1;
778 if (window_needs_vertical_divider (w))
780 mswindows_output_vertical_divider (w, 0);
783 for (line = 0; line < Dynarr_length (cdla); line++)
785 struct display_line *cdl = Dynarr_atp (cdla, line);
787 if (DISPLAY_LINE_YPOS (cdl) + DISPLAY_LINE_HEIGHT (cdl)
790 if (DISPLAY_LINE_YPOS (cdl) > rect_draw.bottom)
799 output_display_line (w, 0, cdla, line,
800 rect_draw.left, rect_draw.right);
805 f->windows_structure_changed = orig_windows_structure_changed;
807 /* If there have never been any face cache_elements created, then this
808 expose event doesn't actually have anything to do. */
809 if (Dynarr_largest (w->face_cachels))
810 redisplay_clear_bottom_of_window (w, cdla, rect_draw.top, rect_draw.bottom);
812 #ifdef HAVE_SCROLLBARS
813 mswindows_redisplay_deadbox_maybe (w, &rect_expose);
817 /*****************************************************************************
818 mswindows_redraw_exposed_windows
820 For each window beneath the given window in the window hierarchy,
821 ensure that it is redrawn if necessary after an Expose event.
822 ****************************************************************************/
824 mswindows_redraw_exposed_windows (Lisp_Object window, int x, int y, int width,
827 for (; !NILP (window); window = XWINDOW (window)->next)
828 mswindows_redraw_exposed_window (XWINDOW (window), x, y, width, height);
831 /*****************************************************************************
832 mswindows_redraw_exposed_area
834 For each window on the given frame, ensure that any area in the
835 Exposed area is redrawn.
836 ****************************************************************************/
838 mswindows_redraw_exposed_area (struct frame *f, int x, int y, int width, int height)
840 /* If any window on the frame has had its face cache reset then the
841 redisplay structures are effectively invalid. If we attempt to
842 use them we'll blow up. We mark the frame as changed to ensure
843 that redisplay will do a full update. This probably isn't
844 necessary but it can't hurt. */
846 /* #### We would rather put these off as well but there is currently
847 no combination of flags which will force an unchanged toolbar to
849 MAYBE_FRAMEMETH (f, redraw_exposed_toolbars, (f, x, y, width, height));
851 redraw_exposed_gutters (f, x, y, width, height);
853 if (!f->window_face_cache_reset)
855 mswindows_redraw_exposed_windows (f->root_window, x, y, width, height);
859 MARK_FRAME_CHANGED (f);
863 /*****************************************************************************
866 Draw a 3d border around the specified area on window W.
867 ****************************************************************************/
869 mswindows_bevel_area (struct window *w, face_index findex, int x, int y,
870 int width, int height, int thickness,
871 int edges, enum edge_style style)
873 struct frame *f = XFRAME (w->frame);
877 if (style == EDGE_ETCHED_IN)
879 else if (style == EDGE_ETCHED_OUT)
881 else if (style == EDGE_BEVEL_IN)
884 edge = BDR_SUNKENINNER;
888 else /* EDGE_BEVEL_OUT */
891 edge = BDR_RAISEDINNER;
896 if (edges & EDGE_TOP)
898 if (edges & EDGE_LEFT)
900 if (edges & EDGE_BOTTOM)
902 if (edges & EDGE_RIGHT)
906 RECT rect = { x, y, x + width, y + height };
907 Lisp_Object color = WINDOW_FACE_CACHEL_BACKGROUND (w, findex);
908 HDC hdc = get_frame_dc (f);
910 mswindows_update_dc (hdc, Qnil, color, Qnil);
911 DrawEdge (hdc, &rect, edge, border);
916 /*****************************************************************************
918 *****************************************************************************/
920 /*****************************************************************************
921 mswindows_divider_height
923 Return the height of the horizontal divider.
924 ****************************************************************************/
926 mswindows_divider_height (void)
928 return 1; /* XXX Copied from redisplay-X.c. What is this? */
931 /*****************************************************************************
932 mswindows_eol_cursor_width
934 Return the width of the end-of-line cursor.
935 ****************************************************************************/
937 mswindows_eol_cursor_width (void)
939 return MSWINDOWS_EOL_CURSOR_WIDTH;
942 /*****************************************************************************
943 mswindows_output_begin
945 Perform any necessary initialization prior to an update.
946 ****************************************************************************/
948 mswindows_output_begin (struct device *d)
952 /*****************************************************************************
955 Perform any necessary flushing of queues when an update has completed.
956 ****************************************************************************/
958 mswindows_output_end (struct device *d)
964 mswindows_flash (struct device *d)
966 struct frame *f = device_selected_frame (d);
967 HDC hdc = get_frame_dc (f);
970 GetClientRect (FRAME_MSWINDOWS_HANDLE (f), &rc);
971 InvertRect (hdc, &rc);
974 InvertRect (hdc, &rc);
980 mswindows_ring_bell (struct device *d, int volume, int pitch, int duration)
982 /* Beep does not work at all, anyways! -kkm */
986 /*****************************************************************************
987 mswindows_output_display_block
989 Given a display line, a block number for that start line, output all
990 runes between start and end in the specified display block.
991 Ripped off with minimal thought from the corresponding X routine.
992 ****************************************************************************/
994 mswindows_output_display_block (struct window *w, struct display_line *dl, int block,
995 int start, int end, int start_pixpos, int cursor_start,
996 int cursor_width, int cursor_height)
998 struct frame *f = XFRAME (w->frame);
999 Emchar_dynarr *buf = Dynarr_new (Emchar);
1002 struct display_block *db = Dynarr_atp (dl->display_blocks, block);
1003 rune_dynarr *rba = db->runes;
1009 Lisp_Object charset = Qunbound; /* Qnil is a valid charset when
1010 MULE is not defined */
1011 XSETWINDOW (window, w);
1012 rb = Dynarr_atp (rba, start);
1015 /* Nothing to do so don't do anything. */
1018 findex = rb->findex;
1021 if (rb->type == RUNE_CHAR)
1022 charset = CHAR_CHARSET (rb->object.chr.ch);
1025 end = Dynarr_length (rba);
1030 rb = Dynarr_atp (rba, elt);
1032 if (rb->findex == findex && rb->type == RUNE_CHAR
1033 && rb->object.chr.ch != '\n' && rb->cursor_type != CURSOR_ON
1034 && EQ (charset, CHAR_CHARSET (rb->object.chr.ch)))
1036 Dynarr_add (buf, rb->object.chr.ch);
1042 if (Dynarr_length (buf))
1044 mswindows_output_string (w, dl, buf, xpos, 0, start_pixpos, width,
1045 findex, 0, 0, 0, 0);
1052 if (rb->type == RUNE_CHAR)
1054 findex = rb->findex;
1056 charset = CHAR_CHARSET (rb->object.chr.ch);
1058 if (rb->cursor_type == CURSOR_ON)
1060 if (rb->object.chr.ch == '\n')
1062 mswindows_output_cursor (w, dl, xpos, cursor_width,
1067 Dynarr_add (buf, rb->object.chr.ch);
1068 mswindows_output_cursor (w, dl, xpos, cursor_width,
1069 findex, rb->object.chr.ch, 0);
1076 else if (rb->object.chr.ch == '\n')
1078 /* Clear in case a cursor was formerly here. */
1079 redisplay_clear_region (window, findex, xpos,
1080 DISPLAY_LINE_YPOS (dl),
1081 rb->width, DISPLAY_LINE_HEIGHT (dl));
1085 else if (rb->type == RUNE_BLANK || rb->type == RUNE_HLINE)
1087 if (rb->type == RUNE_BLANK)
1088 mswindows_output_blank (w, dl, rb, start_pixpos);
1091 /* #### Our flagging of when we need to redraw the
1092 modeline shadows sucks. Since RUNE_HLINE is only used
1093 by the modeline at the moment it is a good bet
1094 that if it gets redrawn then we should also
1095 redraw the shadows. This won't be true forever.
1096 We borrow the shadow_thickness_changed flag for
1098 w->shadow_thickness_changed = 1;
1099 mswindows_output_hline (w, dl, rb);
1102 if (rb->cursor_type == CURSOR_ON)
1103 mswindows_output_cursor (w, dl, xpos, cursor_width, rb->findex, 0, 0);
1108 rb = Dynarr_atp (rba, elt);
1110 findex = rb->findex;
1114 else if (rb->type == RUNE_DGLYPH)
1116 Lisp_Object instance;
1117 struct display_box dbox;
1118 struct display_glyph_area dga;
1119 redisplay_calculate_display_boxes (dl, rb->xpos, rb->object.dglyph.xoffset,
1120 start_pixpos, rb->width,
1123 XSETWINDOW (window, w);
1124 instance = glyph_image_instance (rb->object.dglyph.glyph,
1125 window, ERROR_ME_NOT, 1);
1126 findex = rb->findex;
1128 if (IMAGE_INSTANCEP (instance))
1129 switch (XIMAGE_INSTANCE_TYPE (instance))
1133 /* #### This is way losing. See the comment in
1134 add_glyph_rune(). */
1135 Lisp_Object string =
1136 XIMAGE_INSTANCE_TEXT_STRING (instance);
1137 convert_bufbyte_string_into_emchar_dynarr
1138 (XSTRING_DATA (string), XSTRING_LENGTH (string), buf);
1140 if (rb->cursor_type == CURSOR_ON)
1141 mswindows_output_cursor (w, dl, xpos, cursor_width,
1142 findex, Dynarr_at (buf, 0), 0);
1143 else /* #### redisplay-x passes -1 as the width: why ? */
1144 mswindows_output_string (w, dl, buf, xpos,
1145 rb->object.dglyph.xoffset,
1146 start_pixpos, rb->width, findex,
1152 case IMAGE_MONO_PIXMAP:
1153 case IMAGE_COLOR_PIXMAP:
1154 redisplay_output_pixmap (w, instance, &dbox, &dga, findex,
1155 cursor_start, cursor_width,
1157 if (rb->cursor_type == CURSOR_ON)
1158 mswindows_output_cursor (w, dl, xpos, cursor_width,
1165 case IMAGE_SUBWINDOW:
1167 redisplay_output_subwindow (w, instance, &dbox, &dga, findex,
1168 cursor_start, cursor_width,
1170 if (rb->cursor_type == CURSOR_ON)
1171 mswindows_output_cursor (w, dl, xpos, cursor_width,
1176 redisplay_output_layout (w, instance, &dbox, &dga, findex,
1177 cursor_start, cursor_width,
1179 if (rb->cursor_type == CURSOR_ON)
1180 mswindows_output_cursor (w, dl, xpos, cursor_width,
1185 /* nothing is as nothing does */
1200 if (Dynarr_length (buf))
1201 mswindows_output_string (w, dl, buf, xpos, 0, start_pixpos, width, findex,
1205 && !EQ (Qzero, w->modeline_shadow_thickness)
1207 || f->windows_structure_changed
1208 || w->shadow_thickness_changed))
1209 bevel_modeline (w, dl);
1215 /*****************************************************************************
1216 mswindows_output_vertical_divider
1218 Draw a vertical divider down the right side of the given window.
1219 ****************************************************************************/
1221 mswindows_output_vertical_divider (struct window *w, int clear_unused)
1223 struct frame *f = XFRAME (w->frame);
1224 HDC hdc = get_frame_dc (f);
1226 int spacing = XINT (w->vertical_divider_spacing);
1227 int shadow = XINT (w->vertical_divider_shadow_thickness);
1228 int abs_shadow = abs (shadow);
1229 int line_width = XINT (w->vertical_divider_line_width);
1230 int div_left = WINDOW_RIGHT (w) - window_divider_width (w);
1231 int y1 = WINDOW_TOP (w) + FRAME_TOP_GUTTER_BOUNDS (f);
1232 int y2 = WINDOW_BOTTOM (w) + FRAME_BOTTOM_GUTTER_BOUNDS (f);
1234 /* Clear left and right spacing areas */
1239 mswindows_update_dc (hdc, Qnil,
1240 WINDOW_FACE_CACHEL_BACKGROUND (w, DEFAULT_INDEX), Qnil);
1241 rect.right = WINDOW_RIGHT (w);
1242 rect.left = rect.right - spacing;
1243 ExtTextOut (hdc, 0, 0, ETO_OPAQUE,
1244 &rect, NULL, 0, NULL);
1245 rect.left = div_left;
1246 rect.right = div_left + spacing;
1247 ExtTextOut (hdc, 0, 0, ETO_OPAQUE,
1248 &rect, NULL, 0, NULL);
1251 /* Clear divider face */
1252 rect.top = y1 + abs_shadow;
1253 rect.bottom = y2 - abs_shadow;
1254 rect.left = div_left + spacing + abs_shadow;
1255 rect.right = rect.left + line_width;
1256 if (rect.left < rect.right)
1259 = get_builtin_face_cache_index (w, Vvertical_divider_face);
1260 mswindows_update_dc (hdc, Qnil,
1261 WINDOW_FACE_CACHEL_BACKGROUND (w, div_face), Qnil);
1262 ExtTextOut (hdc, 0, 0, ETO_OPAQUE, &rect, NULL, 0, NULL);
1265 /* Draw a shadow around the divider */
1268 /* #### This will be fixed to support arbitrary thickness */
1269 InflateRect (&rect, abs_shadow, abs_shadow);
1270 DrawEdge (hdc, &rect,
1271 shadow > 0 ? EDGE_RAISED : EDGE_SUNKEN, BF_RECT);
1275 /****************************************************************************
1276 mswindows_text_width
1278 Given a string and a face, return the string's length in pixels when
1279 displayed in the font associated with the face.
1280 ****************************************************************************/
1282 mswindows_text_width (struct frame *f, struct face_cachel *cachel,
1283 CONST Emchar *str, Charcount len)
1285 HDC hdc = get_frame_dc (f);
1286 int width_so_far = 0;
1287 unsigned char *text_storage = (unsigned char *) alloca (2 * len);
1288 textual_run *runs = alloca_array (textual_run, len);
1292 nruns = separate_textual_runs (text_storage, runs, str, len);
1294 for (i = 0; i < nruns; i++)
1295 width_so_far += mswindows_text_width_single_run (hdc,
1298 return width_so_far;
1302 /****************************************************************************
1303 mswindows_clear_region
1305 Clear the area in the box defined by the given parameters using the
1307 ****************************************************************************/
1309 mswindows_clear_region (Lisp_Object locale, struct device* d, struct frame* f,
1310 face_index findex, int x, int y,
1311 int width, int height, Lisp_Object fcolor, Lisp_Object bcolor,
1312 Lisp_Object background_pixmap)
1314 RECT rect = { x, y, x+width, y+height };
1315 HDC hdc = get_frame_dc (f);
1317 if (!NILP (background_pixmap))
1319 struct display_box db = { x, y, width, height };
1320 mswindows_update_dc (hdc,
1321 fcolor, bcolor, background_pixmap);
1322 mswindows_output_dibitmap_region
1323 ( f, XIMAGE_INSTANCE (background_pixmap), &db, 0);
1327 mswindows_update_dc (hdc, Qnil, fcolor, Qnil);
1328 ExtTextOut (hdc, 0, 0, ETO_OPAQUE,
1329 &rect, NULL, 0, NULL);
1332 #ifdef HAVE_SCROLLBARS
1333 if (WINDOWP (locale))
1334 mswindows_redisplay_deadbox_maybe (XWINDOW (locale), &rect);
1338 /* XXX Implement me! */
1340 mswindows_clear_frame (struct frame *f)
1347 /************************************************************************/
1348 /* initialization */
1349 /************************************************************************/
1352 console_type_create_redisplay_mswindows (void)
1354 /* redisplay methods - display*/
1355 CONSOLE_HAS_METHOD (mswindows, text_width);
1356 CONSOLE_HAS_METHOD (mswindows, output_display_block);
1357 CONSOLE_HAS_METHOD (mswindows, divider_height);
1358 CONSOLE_HAS_METHOD (mswindows, eol_cursor_width);
1359 CONSOLE_HAS_METHOD (mswindows, output_vertical_divider);
1360 CONSOLE_HAS_METHOD (mswindows, clear_region);
1361 CONSOLE_HAS_METHOD (mswindows, clear_frame);
1362 CONSOLE_HAS_METHOD (mswindows, output_begin);
1363 CONSOLE_HAS_METHOD (mswindows, output_end);
1364 CONSOLE_HAS_METHOD (mswindows, flash);
1365 CONSOLE_HAS_METHOD (mswindows, ring_bell);
1366 CONSOLE_HAS_METHOD (mswindows, bevel_area);
1367 CONSOLE_HAS_METHOD (mswindows, output_string);
1368 CONSOLE_HAS_METHOD (mswindows, output_pixmap);
1370 /* redisplay methods - printer */
1371 CONSOLE_INHERITS_METHOD (msprinter, mswindows, text_width);
1372 CONSOLE_INHERITS_METHOD (msprinter, mswindows, output_display_block);
1373 CONSOLE_INHERITS_METHOD (msprinter, mswindows, divider_height);
1374 CONSOLE_INHERITS_METHOD (msprinter, mswindows, eol_cursor_width);
1375 CONSOLE_INHERITS_METHOD (msprinter, mswindows, output_vertical_divider);
1376 CONSOLE_INHERITS_METHOD (msprinter, mswindows, clear_region);
1377 CONSOLE_INHERITS_METHOD (msprinter, mswindows, clear_frame);
1378 CONSOLE_INHERITS_METHOD (msprinter, mswindows, output_begin);
1379 CONSOLE_INHERITS_METHOD (msprinter, mswindows, output_end);
1380 CONSOLE_INHERITS_METHOD (msprinter, mswindows, bevel_area);
1381 CONSOLE_INHERITS_METHOD (msprinter, mswindows, output_string);
1382 CONSOLE_INHERITS_METHOD (msprinter, mswindows, output_pixmap);