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