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