Mercurial > hg > xemacs-beta
annotate src/redisplay-msw.c @ 5891:a0e751d6c3ad
Import the #'clear-string API from GNU, use it in tls.c
src/ChangeLog addition:
2015-04-18 Aidan Kehoe <kehoea@parhasard.net>
* sequence.c (Fclear_string): New, API from GNU. Zero a string's
contents, making sure the text is not kept around even when the
string's data is reallocated because of a changed character
length.
* sequence.c (syms_of_sequence): Make it available to Lisp.
* lisp.h: Make it available to C code.
* tls.c (nss_pk11_password): Use it.
* tls.c (gnutls_pk11_password): Use it.
* tls.c (openssl_password): Use it.
tests/ChangeLog addition:
2015-04-18 Aidan Kehoe <kehoea@parhasard.net>
* automated/lisp-tests.el:
Test #'clear-string, just added. Unfortunately there's no way to
be certain from Lisp that the old password data has been erased
after realloc; it may be worth adding a test to tests.c, but
*we'll be reading memory we shouldn't be*, so that gives me pause.
author | Aidan Kehoe <kehoea@parhasard.net> |
---|---|
date | Sat, 18 Apr 2015 23:00:14 +0100 |
parents | 81fee4aee9b6 |
children |
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 */ | |
5624
c39052c921b5
New "foreback" face property.
Didier Verna <didier@xemacs.org>
parents:
5581
diff
changeset
|
296 mswindows_update_dc (hdc, cachel->foreback, |
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) | |
5628
81fee4aee9b6
text_width methods interface cleanup.
Didier Verna <didier@xemacs.org>
parents:
5624
diff
changeset
|
470 width = mswindows_text_width (f, 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 */ | |
5624
c39052c921b5
New "foreback" face property.
Didier Verna <didier@xemacs.org>
parents:
5581
diff
changeset
|
510 mswindows_update_dc (hdc, cachel->foreback, cachel->background, Qnil); |
428 | 511 redisplay_output_pixmap (w, bg_pmap, &db, &dga, findex, |
512 0, 0, 0, TRUE); | |
513 /* output pixmap calls this so we have to recall to get correct | |
514 references */ | |
515 cachel = WINDOW_FACE_CACHEL (w, findex); | |
516 } | |
517 | |
4967 | 518 nruns = separate_textual_runs (&runs, Dynarr_begin (buf), |
428 | 519 Dynarr_length (buf)); |
520 | |
521 for (i = 0; i < nruns; i++) | |
522 { | |
523 Lisp_Object font = FACE_CACHEL_FONT (cachel, runs[i].charset); | |
440 | 524 Lisp_Font_Instance *fi = XFONT_INSTANCE (font); |
428 | 525 int this_width; |
526 | |
527 if (EQ (font, Vthe_null_font_instance)) | |
528 continue; | |
529 | |
440 | 530 mswindows_update_dc (hdc, cachel->foreground, |
428 | 531 NILP(bg_pmap) ? cachel->background : Qnil, Qnil); |
440 | 532 mswindows_set_dc_font (hdc, font, cachel->underline, cachel->strikethru); |
428 | 533 |
534 this_width = mswindows_text_width_single_run (hdc, cachel, runs + i); | |
535 | |
536 /* cope with fonts taller than lines */ | |
537 if ((int) fi->height < (int) (height + dl->clip + dl->top_clip)) | |
538 { | |
539 int clear_start = max (xpos, clip_start); | |
540 int clear_end = min (xpos + this_width, clip_end); | |
541 | |
542 { | |
543 redisplay_clear_region (window, findex, clear_start, | |
544 DISPLAY_LINE_YPOS (dl), | |
545 clear_end - clear_start, | |
546 height); | |
547 /* output pixmap calls this so we have to recall to get correct | |
548 references */ | |
549 cachel = WINDOW_FACE_CACHEL (w, findex); | |
550 } | |
551 } | |
552 | |
771 | 553 ExtTextOutW (hdc, xpos, dl->ypos, |
554 NILP(bg_pmap) ? ETO_CLIPPED | ETO_OPAQUE : ETO_CLIPPED, | |
555 &rect, runs[i].ptr, runs[i].nwchars, NULL); | |
428 | 556 |
557 xpos += this_width; | |
558 } | |
559 } | |
560 | |
561 static void | |
440 | 562 mswindows_output_dibitmap (struct frame *f, Lisp_Image_Instance *p, |
771 | 563 struct display_box *db, |
564 struct display_glyph_area *dga) | |
428 | 565 { |
442 | 566 HDC hdc = get_frame_dc (f, 1); |
440 | 567 HDC hcompdc = get_frame_compdc (f); |
428 | 568 HGDIOBJ old=NULL; |
442 | 569 const int real_x = IMAGE_INSTANCE_MSWINDOWS_BITMAP_REAL_WIDTH (p); |
570 const int real_y = IMAGE_INSTANCE_MSWINDOWS_BITMAP_REAL_HEIGHT (p); | |
571 const int surface_x = IMAGE_INSTANCE_PIXMAP_WIDTH (p); | |
572 const int surface_y = IMAGE_INSTANCE_PIXMAP_HEIGHT (p); | |
428 | 573 |
442 | 574 /* first blit the mask */ |
428 | 575 if (IMAGE_INSTANCE_MSWINDOWS_MASK (p)) |
576 { | |
442 | 577 RGBQUAD bg; |
578 COLORREF bgcolor; | |
428 | 579 |
440 | 580 old = SelectObject (hcompdc, IMAGE_INSTANCE_MSWINDOWS_MASK (p)); |
428 | 581 |
442 | 582 if (IMAGE_INSTANCE_TYPE (p) == IMAGE_MONO_PIXMAP) |
583 { | |
584 COLORREF fgcolor; | |
585 RGBQUAD fg; | |
586 | |
587 fgcolor = GetTextColor (hdc); | |
588 fg.rgbBlue = GetBValue (fgcolor); | |
589 fg.rgbRed = GetRValue (fgcolor); | |
590 fg.rgbGreen = GetGValue (fgcolor); | |
591 fg.rgbReserved = 0; | |
592 SetDIBColorTable (hcompdc, 0, 1, &fg); | |
593 } | |
428 | 594 |
442 | 595 bgcolor = GetBkColor (hdc); |
596 bg.rgbBlue = GetBValue (bgcolor); | |
597 bg.rgbRed = GetRValue (bgcolor); | |
598 bg.rgbGreen = GetGValue (bgcolor); | |
599 bg.rgbReserved = 0; | |
600 SetDIBColorTable (hcompdc, 1, 1, &bg); | |
601 | |
602 StretchBlt (hdc, | |
603 db->xpos, db->ypos, | |
604 dga->width, dga->height, | |
605 hcompdc, | |
606 MulDiv (dga->xoffset, real_x, surface_x), | |
607 MulDiv (dga->yoffset, real_y, surface_y), | |
608 MulDiv (dga->width, real_x, surface_x), | |
609 MulDiv (dga->height, real_y, surface_y), | |
610 SRCCOPY); | |
428 | 611 |
440 | 612 SelectObject (hcompdc, old); |
428 | 613 } |
614 | |
442 | 615 /* Now blit the bitmap itself, or one of its slices. */ |
440 | 616 old = SelectObject (hcompdc, |
428 | 617 IMAGE_INSTANCE_MSWINDOWS_BITMAP_SLICE |
618 (p, IMAGE_INSTANCE_PIXMAP_SLICE (p))); | |
619 | |
442 | 620 StretchBlt (hdc, |
621 db->xpos, db->ypos, | |
622 dga->width, dga->height, | |
623 hcompdc, | |
624 MulDiv (dga->xoffset, real_x, surface_x), | |
625 MulDiv (dga->yoffset, real_y, surface_y), | |
626 MulDiv (dga->width, real_x, surface_x), | |
627 MulDiv (dga->height, real_y, surface_y), | |
628 IMAGE_INSTANCE_MSWINDOWS_MASK (p) ? SRCINVERT : SRCCOPY); | |
428 | 629 |
440 | 630 SelectObject (hcompdc, old); |
428 | 631 } |
632 | |
5138
6d13ad8ed3b2
implement absolute background-placement for Windows, sort of
Ben Wing <ben@xemacs.org>
parents:
5080
diff
changeset
|
633 /* 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
|
634 |
6d13ad8ed3b2
implement absolute background-placement for Windows, sort of
Ben Wing <ben@xemacs.org>
parents:
5080
diff
changeset
|
635 static int |
6d13ad8ed3b2
implement absolute background-placement for Windows, sort of
Ben Wing <ben@xemacs.org>
parents:
5080
diff
changeset
|
636 posmod (int x, int y) |
6d13ad8ed3b2
implement absolute background-placement for Windows, sort of
Ben Wing <ben@xemacs.org>
parents:
5080
diff
changeset
|
637 { |
6d13ad8ed3b2
implement absolute background-placement for Windows, sort of
Ben Wing <ben@xemacs.org>
parents:
5080
diff
changeset
|
638 int retval = x % y; |
6d13ad8ed3b2
implement absolute background-placement for Windows, sort of
Ben Wing <ben@xemacs.org>
parents:
5080
diff
changeset
|
639 if (retval < 0) |
6d13ad8ed3b2
implement absolute background-placement for Windows, sort of
Ben Wing <ben@xemacs.org>
parents:
5080
diff
changeset
|
640 retval += y; |
6d13ad8ed3b2
implement absolute background-placement for Windows, sort of
Ben Wing <ben@xemacs.org>
parents:
5080
diff
changeset
|
641 return retval; |
6d13ad8ed3b2
implement absolute background-placement for Windows, sort of
Ben Wing <ben@xemacs.org>
parents:
5080
diff
changeset
|
642 } |
6d13ad8ed3b2
implement absolute background-placement for Windows, sort of
Ben Wing <ben@xemacs.org>
parents:
5080
diff
changeset
|
643 |
428 | 644 /* X gc's have this nice property that setting the bg pixmap will |
645 * output it offset relative to the window. Windows doesn't have this | |
646 * feature so we have to emulate this by outputting multiple pixmaps. | |
647 * This is only used for background pixmaps. Normal pixmaps are | |
648 * outputted once and are scrollable */ | |
649 static void | |
650 mswindows_output_dibitmap_region (struct frame *f, | |
440 | 651 Lisp_Image_Instance *p, |
428 | 652 struct display_box *db, |
5138
6d13ad8ed3b2
implement absolute background-placement for Windows, sort of
Ben Wing <ben@xemacs.org>
parents:
5080
diff
changeset
|
653 struct display_glyph_area *dga, |
6d13ad8ed3b2
implement absolute background-placement for Windows, sort of
Ben Wing <ben@xemacs.org>
parents:
5080
diff
changeset
|
654 int absolute) |
428 | 655 { |
656 struct display_box xdb = { db->xpos, db->ypos, db->width, db->height }; | |
657 struct display_glyph_area xdga | |
658 = { 0, 0, IMAGE_INSTANCE_PIXMAP_WIDTH (p), | |
659 IMAGE_INSTANCE_PIXMAP_HEIGHT (p) }; | |
660 int pxoffset = 0, pyoffset = 0; | |
5138
6d13ad8ed3b2
implement absolute background-placement for Windows, sort of
Ben Wing <ben@xemacs.org>
parents:
5080
diff
changeset
|
661 int absolute_pxoffset = 0, absolute_pyoffset = 0; |
428 | 662 |
663 if (dga) | |
664 { | |
665 xdga.width = dga->width; | |
666 xdga.height = dga->height; | |
667 } | |
668 else if (!redisplay_normalize_glyph_area (&xdb, &xdga)) | |
669 return; | |
670 | |
5138
6d13ad8ed3b2
implement absolute background-placement for Windows, sort of
Ben Wing <ben@xemacs.org>
parents:
5080
diff
changeset
|
671 if (absolute) |
6d13ad8ed3b2
implement absolute background-placement for Windows, sort of
Ben Wing <ben@xemacs.org>
parents:
5080
diff
changeset
|
672 { |
6d13ad8ed3b2
implement absolute background-placement for Windows, sort of
Ben Wing <ben@xemacs.org>
parents:
5080
diff
changeset
|
673 POINT point; |
6d13ad8ed3b2
implement absolute background-placement for Windows, sort of
Ben Wing <ben@xemacs.org>
parents:
5080
diff
changeset
|
674 point.x = 0; |
6d13ad8ed3b2
implement absolute background-placement for Windows, sort of
Ben Wing <ben@xemacs.org>
parents:
5080
diff
changeset
|
675 point.y = 0; |
6d13ad8ed3b2
implement absolute background-placement for Windows, sort of
Ben Wing <ben@xemacs.org>
parents:
5080
diff
changeset
|
676 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
|
677 { |
6d13ad8ed3b2
implement absolute background-placement for Windows, sort of
Ben Wing <ben@xemacs.org>
parents:
5080
diff
changeset
|
678 absolute_pxoffset = point.x; |
6d13ad8ed3b2
implement absolute background-placement for Windows, sort of
Ben Wing <ben@xemacs.org>
parents:
5080
diff
changeset
|
679 absolute_pyoffset = point.y; |
6d13ad8ed3b2
implement absolute background-placement for Windows, sort of
Ben Wing <ben@xemacs.org>
parents:
5080
diff
changeset
|
680 } |
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 |
428 | 683 /* when doing a bg pixmap do a partial pixmap first so that we |
684 blt whole pixmaps thereafter */ | |
685 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
|
686 posmod (db->ypos - absolute_pyoffset, |
6d13ad8ed3b2
implement absolute background-placement for Windows, sort of
Ben Wing <ben@xemacs.org>
parents:
5080
diff
changeset
|
687 IMAGE_INSTANCE_PIXMAP_HEIGHT (p))); |
428 | 688 |
689 while (xdga.height > 0) | |
690 { | |
691 xdga.width = min (min (db->width, IMAGE_INSTANCE_PIXMAP_WIDTH (p)), | |
692 IMAGE_INSTANCE_PIXMAP_WIDTH (p) - | |
5138
6d13ad8ed3b2
implement absolute background-placement for Windows, sort of
Ben Wing <ben@xemacs.org>
parents:
5080
diff
changeset
|
693 posmod (db->xpos - absolute_pxoffset, |
6d13ad8ed3b2
implement absolute background-placement for Windows, sort of
Ben Wing <ben@xemacs.org>
parents:
5080
diff
changeset
|
694 IMAGE_INSTANCE_PIXMAP_WIDTH (p))); |
428 | 695 pxoffset = 0; |
696 while (xdga.width > 0) | |
697 { | |
698 xdb.xpos = db->xpos + pxoffset; | |
699 xdb.ypos = db->ypos + pyoffset; | |
700 /* do we need to offset the pixmap vertically? this is necessary | |
701 for background pixmaps. */ | |
5138
6d13ad8ed3b2
implement absolute background-placement for Windows, sort of
Ben Wing <ben@xemacs.org>
parents:
5080
diff
changeset
|
702 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
|
703 IMAGE_INSTANCE_PIXMAP_WIDTH (p)); |
6d13ad8ed3b2
implement absolute background-placement for Windows, sort of
Ben Wing <ben@xemacs.org>
parents:
5080
diff
changeset
|
704 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
|
705 IMAGE_INSTANCE_PIXMAP_HEIGHT (p)); |
6d13ad8ed3b2
implement absolute background-placement for Windows, sort of
Ben Wing <ben@xemacs.org>
parents:
5080
diff
changeset
|
706 /* [[ 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
|
707 #### -- 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
|
708 no mswindows_output_pixmap_region(). --ben*/ |
428 | 709 mswindows_output_dibitmap (f, p, &xdb, &xdga); |
710 pxoffset += xdga.width; | |
711 xdga.width = min ((db->width - pxoffset), | |
712 IMAGE_INSTANCE_PIXMAP_WIDTH (p)); | |
713 } | |
714 pyoffset += xdga.height; | |
715 xdga.height = min ((db->height - pyoffset), | |
716 IMAGE_INSTANCE_PIXMAP_HEIGHT (p)); | |
717 } | |
718 } | |
719 | |
720 /* Output a pixmap at the desired location. | |
721 DB normalized display_box. | |
722 DGA normalized display_glyph_area. */ | |
723 static void | |
724 mswindows_output_pixmap (struct window *w, Lisp_Object image_instance, | |
2286 | 725 struct display_box *db, |
726 struct display_glyph_area *dga, face_index findex, | |
727 int UNUSED (cursor_start), int UNUSED (cursor_width), | |
728 int UNUSED (cursor_height), int bg_pixmap) | |
428 | 729 { |
730 struct frame *f = XFRAME (w->frame); | |
442 | 731 HDC hdc = get_frame_dc (f, 1); |
428 | 732 |
440 | 733 Lisp_Image_Instance *p = XIMAGE_INSTANCE (image_instance); |
428 | 734 |
735 /* Output the pixmap. Have to do this as many times as is required | |
736 to fill the given area */ | |
440 | 737 mswindows_update_dc (hdc, |
428 | 738 WINDOW_FACE_CACHEL_FOREGROUND (w, findex), |
739 WINDOW_FACE_CACHEL_BACKGROUND (w, findex), Qnil); | |
740 | |
741 if (bg_pixmap) | |
5138
6d13ad8ed3b2
implement absolute background-placement for Windows, sort of
Ben Wing <ben@xemacs.org>
parents:
5080
diff
changeset
|
742 mswindows_output_dibitmap_region |
6d13ad8ed3b2
implement absolute background-placement for Windows, sort of
Ben Wing <ben@xemacs.org>
parents:
5080
diff
changeset
|
743 (f, p, db, dga, |
6d13ad8ed3b2
implement absolute background-placement for Windows, sort of
Ben Wing <ben@xemacs.org>
parents:
5080
diff
changeset
|
744 EQ (WINDOW_FACE_CACHEL_BACKGROUND_PLACEMENT (w, findex), Qabsolute)); |
428 | 745 else |
746 mswindows_output_dibitmap (f, p, db, dga); | |
747 } | |
748 | |
749 #ifdef HAVE_SCROLLBARS | |
750 /* | |
751 * This function paints window's deadbox, a rectangle between window | |
752 * borders and two short edges of both scrollbars. | |
753 * | |
754 * Function checks whether deadbox intersects with the rectangle pointed | |
755 * to by PRC, and paints only the intersection | |
756 */ | |
757 static void | |
1318 | 758 mswindows_redisplay_deadbox (struct window *w, int x, int y, int width, |
759 int height) | |
428 | 760 { |
1318 | 761 RECT rc = { x, y, x + width, y + height }; |
428 | 762 int sbh = window_scrollbar_height (w); |
763 int sbw = window_scrollbar_width (w); | |
764 RECT rect_dead, rect_paint; | |
765 if (sbh == 0 || sbw == 0) | |
766 return; | |
767 | |
768 if (!NILP (w->scrollbar_on_left_p)) | |
769 rect_dead.left = WINDOW_LEFT (w); | |
770 else | |
771 rect_dead.left = WINDOW_TEXT_RIGHT (w); | |
772 rect_dead.right = rect_dead.left + sbw; | |
773 | |
774 if (!NILP (w->scrollbar_on_top_p)) | |
775 rect_dead.top = WINDOW_TOP (w); | |
776 else | |
777 rect_dead.top = WINDOW_TEXT_BOTTOM (w); | |
778 rect_dead.bottom = rect_dead.top + sbh; | |
779 | |
1318 | 780 if (IntersectRect (&rect_paint, &rect_dead, &rc)) |
428 | 781 { |
782 struct frame *f = XFRAME (WINDOW_FRAME (w)); | |
442 | 783 FillRect (get_frame_dc (f, 1), &rect_paint, |
428 | 784 (HBRUSH) (COLOR_BTNFACE+1)); |
785 } | |
786 } | |
787 | |
788 #endif /* HAVE_SCROLLBARS */ | |
789 | |
790 /***************************************************************************** | |
791 mswindows_bevel_area | |
792 | |
793 Draw a 3d border around the specified area on window W. | |
794 ****************************************************************************/ | |
795 static void | |
796 mswindows_bevel_area (struct window *w, face_index findex, int x, int y, | |
797 int width, int height, int thickness, | |
798 int edges, enum edge_style style) | |
799 { | |
800 struct frame *f = XFRAME (w->frame); | |
801 UINT edge; | |
802 UINT border = 0; | |
803 | |
804 if (style == EDGE_ETCHED_IN) | |
805 edge = EDGE_ETCHED; | |
806 else if (style == EDGE_ETCHED_OUT) | |
807 edge = EDGE_BUMP; | |
808 else if (style == EDGE_BEVEL_IN) | |
809 { | |
810 if (thickness == 1) | |
811 edge = BDR_SUNKENINNER; | |
812 else | |
813 edge = EDGE_SUNKEN; | |
814 } | |
815 else /* EDGE_BEVEL_OUT */ | |
816 { | |
817 if (thickness == 1) | |
818 edge = BDR_RAISEDINNER; | |
819 else | |
820 edge = EDGE_RAISED; | |
821 } | |
822 | |
823 if (edges & EDGE_TOP) | |
824 border |= BF_TOP; | |
825 if (edges & EDGE_LEFT) | |
826 border |= BF_LEFT; | |
827 if (edges & EDGE_BOTTOM) | |
828 border |= BF_BOTTOM; | |
829 if (edges & EDGE_RIGHT) | |
830 border |= BF_RIGHT; | |
831 | |
832 { | |
833 RECT rect = { x, y, x + width, y + height }; | |
834 Lisp_Object color = WINDOW_FACE_CACHEL_BACKGROUND (w, findex); | |
442 | 835 HDC hdc = get_frame_dc (f, 1); |
428 | 836 |
440 | 837 mswindows_update_dc (hdc, Qnil, color, Qnil); |
838 DrawEdge (hdc, &rect, edge, border); | |
428 | 839 } |
840 } | |
841 | |
842 | |
843 /***************************************************************************** | |
844 Display methods | |
845 *****************************************************************************/ | |
846 | |
847 /***************************************************************************** | |
848 mswindows_divider_height | |
849 | |
850 Return the height of the horizontal divider. | |
851 ****************************************************************************/ | |
852 static int | |
853 mswindows_divider_height (void) | |
854 { | |
855 return 1; /* XXX Copied from redisplay-X.c. What is this? */ | |
856 } | |
857 | |
858 /***************************************************************************** | |
859 mswindows_eol_cursor_width | |
860 | |
861 Return the width of the end-of-line cursor. | |
862 ****************************************************************************/ | |
863 static int | |
864 mswindows_eol_cursor_width (void) | |
865 { | |
866 return MSWINDOWS_EOL_CURSOR_WIDTH; | |
867 } | |
868 | |
869 /***************************************************************************** | |
442 | 870 mswindows_frame_output_begin |
428 | 871 |
872 Perform any necessary initialization prior to an update. | |
873 ****************************************************************************/ | |
874 static void | |
2286 | 875 mswindows_frame_output_begin (struct frame *UNUSED (f)) |
428 | 876 { |
877 } | |
878 | |
879 /***************************************************************************** | |
442 | 880 mswindows_frame_output_end |
428 | 881 |
882 Perform any necessary flushing of queues when an update has completed. | |
883 ****************************************************************************/ | |
884 static void | |
2286 | 885 mswindows_frame_output_end (struct frame * |
886 #ifdef DEFER_WINDOW_POS | |
887 f | |
888 #else | |
889 UNUSED (f) | |
890 #endif | |
891 ) | |
442 | 892 { |
893 #ifdef DEFER_WINDOW_POS | |
894 HDWP hdwp = FRAME_MSWINDOWS_DATA (f)->hdwp; | |
895 | |
896 if (hdwp != 0) | |
897 { | |
898 EndDeferWindowPos (hdwp); | |
899 FRAME_MSWINDOWS_DATA (f)->hdwp = 0; | |
900 } | |
901 #endif | |
902 GdiFlush(); | |
903 } | |
904 | |
905 /* Printer version is more lightweight. */ | |
906 static void | |
2286 | 907 msprinter_frame_output_end (struct frame *UNUSED (f)) |
428 | 908 { |
909 GdiFlush(); | |
910 } | |
911 | |
912 static int | |
913 mswindows_flash (struct device *d) | |
914 { | |
915 struct frame *f = device_selected_frame (d); | |
442 | 916 HDC hdc = get_frame_dc (f, 1); |
428 | 917 RECT rc; |
918 | |
919 GetClientRect (FRAME_MSWINDOWS_HANDLE (f), &rc); | |
440 | 920 InvertRect (hdc, &rc); |
428 | 921 GdiFlush (); |
922 Sleep (25); | |
440 | 923 InvertRect (hdc, &rc); |
428 | 924 |
925 return 1; | |
926 } | |
927 | |
928 static void | |
2286 | 929 mswindows_ring_bell (struct device *UNUSED (d), int UNUSED (volume), |
930 int UNUSED (pitch), int UNUSED (duration)) | |
428 | 931 { |
932 /* Beep does not work at all, anyways! -kkm */ | |
933 MessageBeep (MB_OK); | |
934 } | |
935 | |
936 /***************************************************************************** | |
937 mswindows_output_display_block | |
938 | |
939 Given a display line, a block number for that start line, output all | |
940 runes between start and end in the specified display block. | |
941 Ripped off with minimal thought from the corresponding X routine. | |
942 ****************************************************************************/ | |
943 static void | |
771 | 944 mswindows_output_display_block (struct window *w, struct display_line *dl, |
945 int block, int start, int end, | |
946 int start_pixpos, int cursor_start, | |
947 int cursor_width, int cursor_height) | |
428 | 948 { |
949 struct frame *f = XFRAME (w->frame); | |
3479 | 950 Ichar_dynarr *buf; |
428 | 951 Lisp_Object window; |
952 | |
953 struct display_block *db = Dynarr_atp (dl->display_blocks, block); | |
954 rune_dynarr *rba = db->runes; | |
955 struct rune *rb; | |
956 | |
957 int elt = start; | |
958 face_index findex; | |
959 int xpos, width; | |
960 Lisp_Object charset = Qunbound; /* Qnil is a valid charset when | |
961 MULE is not defined */ | |
793 | 962 window = wrap_window (w); |
428 | 963 rb = Dynarr_atp (rba, start); |
964 | |
965 if (!rb) | |
966 /* Nothing to do so don't do anything. */ | |
967 return; | |
968 | |
969 findex = rb->findex; | |
970 xpos = rb->xpos; | |
971 width = 0; | |
972 if (rb->type == RUNE_CHAR) | |
867 | 973 charset = ichar_charset (rb->object.chr.ch); |
428 | 974 |
975 if (end < 0) | |
976 end = Dynarr_length (rba); | |
3479 | 977 buf = Dynarr_new (Ichar); |
428 | 978 |
979 while (elt < end) | |
980 { | |
981 rb = Dynarr_atp (rba, elt); | |
982 | |
983 if (rb->findex == findex && rb->type == RUNE_CHAR | |
984 && rb->object.chr.ch != '\n' && rb->cursor_type != CURSOR_ON | |
867 | 985 && EQ (charset, ichar_charset (rb->object.chr.ch))) |
428 | 986 { |
987 Dynarr_add (buf, rb->object.chr.ch); | |
988 width += rb->width; | |
989 elt++; | |
990 } | |
991 else | |
992 { | |
993 if (Dynarr_length (buf)) | |
994 { | |
771 | 995 mswindows_output_string (w, dl, buf, xpos, 0, start_pixpos, |
996 width, findex, 0, 0, 0, 0); | |
428 | 997 xpos = rb->xpos; |
998 width = 0; | |
999 } | |
1000 Dynarr_reset (buf); | |
1001 width = 0; | |
1002 | |
1003 if (rb->type == RUNE_CHAR) | |
1004 { | |
1005 findex = rb->findex; | |
1006 xpos = rb->xpos; | |
867 | 1007 charset = ichar_charset (rb->object.chr.ch); |
428 | 1008 |
1009 if (rb->cursor_type == CURSOR_ON) | |
1010 { | |
1011 if (rb->object.chr.ch == '\n') | |
1012 { | |
1013 mswindows_output_cursor (w, dl, xpos, cursor_width, | |
1014 findex, 0, 0); | |
1015 } | |
1016 else | |
1017 { | |
1018 Dynarr_add (buf, rb->object.chr.ch); | |
1019 mswindows_output_cursor (w, dl, xpos, cursor_width, | |
1020 findex, rb->object.chr.ch, 0); | |
1021 Dynarr_reset (buf); | |
1022 } | |
1023 | |
1024 xpos += rb->width; | |
1025 elt++; | |
1026 } | |
1027 else if (rb->object.chr.ch == '\n') | |
1028 { | |
1029 /* Clear in case a cursor was formerly here. */ | |
1030 redisplay_clear_region (window, findex, xpos, | |
1031 DISPLAY_LINE_YPOS (dl), | |
1032 rb->width, DISPLAY_LINE_HEIGHT (dl)); | |
1033 elt++; | |
1034 } | |
1035 } | |
1036 else if (rb->type == RUNE_BLANK || rb->type == RUNE_HLINE) | |
1037 { | |
1038 if (rb->type == RUNE_BLANK) | |
1039 mswindows_output_blank (w, dl, rb, start_pixpos); | |
1040 else | |
1041 { | |
1042 /* #### Our flagging of when we need to redraw the | |
1043 modeline shadows sucks. Since RUNE_HLINE is only used | |
1044 by the modeline at the moment it is a good bet | |
1045 that if it gets redrawn then we should also | |
1046 redraw the shadows. This won't be true forever. | |
1047 We borrow the shadow_thickness_changed flag for | |
1048 now. */ | |
1049 w->shadow_thickness_changed = 1; | |
1050 mswindows_output_hline (w, dl, rb); | |
1051 } | |
1052 | |
1053 if (rb->cursor_type == CURSOR_ON) | |
1054 mswindows_output_cursor (w, dl, xpos, cursor_width, rb->findex, 0, 0); | |
1055 | |
1056 elt++; | |
1057 if (elt < end) | |
1058 { | |
1059 rb = Dynarr_atp (rba, elt); | |
1060 | |
1061 findex = rb->findex; | |
1062 xpos = rb->xpos; | |
1063 } | |
1064 } | |
1065 else if (rb->type == RUNE_DGLYPH) | |
1066 { | |
1067 Lisp_Object instance; | |
440 | 1068 struct display_box dbox; |
428 | 1069 struct display_glyph_area dga; |
442 | 1070 |
428 | 1071 redisplay_calculate_display_boxes (dl, rb->xpos, rb->object.dglyph.xoffset, |
819 | 1072 rb->object.dglyph.yoffset, |
1073 start_pixpos, rb->width, &dbox, &dga); | |
428 | 1074 |
793 | 1075 window = wrap_window (w); |
428 | 1076 instance = glyph_image_instance (rb->object.dglyph.glyph, |
793 | 1077 window, ERROR_ME_DEBUG_WARN, 1); |
428 | 1078 findex = rb->findex; |
1079 | |
1080 if (IMAGE_INSTANCEP (instance)) | |
442 | 1081 { |
1082 switch (XIMAGE_INSTANCE_TYPE (instance)) | |
428 | 1083 { |
442 | 1084 case IMAGE_MONO_PIXMAP: |
1085 case IMAGE_COLOR_PIXMAP: | |
1086 redisplay_output_pixmap (w, instance, &dbox, &dga, findex, | |
1087 cursor_start, cursor_width, | |
1088 cursor_height, 0); | |
428 | 1089 if (rb->cursor_type == CURSOR_ON) |
1090 mswindows_output_cursor (w, dl, xpos, cursor_width, | |
442 | 1091 findex, 0, 1); |
1092 break; | |
1093 | |
1094 case IMAGE_WIDGET: | |
1095 if (EQ (XIMAGE_INSTANCE_WIDGET_TYPE (instance), | |
1096 Qlayout)) | |
1097 { | |
1098 redisplay_output_layout (window, instance, &dbox, &dga, findex, | |
1099 cursor_start, cursor_width, | |
1100 cursor_height); | |
1101 if (rb->cursor_type == CURSOR_ON) | |
1102 mswindows_output_cursor (w, dl, xpos, cursor_width, | |
1103 findex, 0, 1); | |
1104 break; | |
1105 } | |
1106 case IMAGE_SUBWINDOW: | |
1107 redisplay_output_subwindow (w, instance, &dbox, &dga, findex, | |
1108 cursor_start, cursor_width, | |
1109 cursor_height); | |
1110 if (rb->cursor_type == CURSOR_ON) | |
1111 mswindows_output_cursor (w, dl, xpos, cursor_width, | |
1112 findex, 0, 1); | |
1113 break; | |
1114 | |
1115 case IMAGE_NOTHING: | |
1116 /* nothing is as nothing does */ | |
1117 break; | |
428 | 1118 |
442 | 1119 case IMAGE_TEXT: |
1120 case IMAGE_POINTER: | |
1121 default: | |
2500 | 1122 ABORT (); |
442 | 1123 } |
1124 IMAGE_INSTANCE_OPTIMIZE_OUTPUT | |
1125 (XIMAGE_INSTANCE (instance)) = 0; | |
1126 } | |
428 | 1127 xpos += rb->width; |
1128 elt++; | |
1129 } | |
1130 else | |
2500 | 1131 ABORT (); |
428 | 1132 } |
1133 } | |
1134 | |
1135 if (Dynarr_length (buf)) | |
1136 mswindows_output_string (w, dl, buf, xpos, 0, start_pixpos, width, findex, | |
1137 0, 0, 0, 0); | |
1138 | |
1139 if (dl->modeline | |
1140 && !EQ (Qzero, w->modeline_shadow_thickness) | |
1141 && (f->clear | |
1142 || f->windows_structure_changed | |
1143 || w->shadow_thickness_changed)) | |
1144 bevel_modeline (w, dl); | |
1145 | |
1146 Dynarr_free (buf); | |
1147 } | |
1148 | |
1149 | |
1150 /***************************************************************************** | |
1151 mswindows_output_vertical_divider | |
1152 | |
1153 Draw a vertical divider down the right side of the given window. | |
1154 ****************************************************************************/ | |
1155 static void | |
2286 | 1156 mswindows_output_vertical_divider (struct window *w, int UNUSED (clear_unused)) |
428 | 1157 { |
1158 struct frame *f = XFRAME (w->frame); | |
442 | 1159 HDC hdc = get_frame_dc (f, 1); |
428 | 1160 RECT rect; |
5581
56144c8593a8
Mechanically change INT to FIXNUM in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5515
diff
changeset
|
1161 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
|
1162 int shadow = XFIXNUM (w->vertical_divider_shadow_thickness); |
428 | 1163 int abs_shadow = abs (shadow); |
5581
56144c8593a8
Mechanically change INT to FIXNUM in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5515
diff
changeset
|
1164 int line_width = XFIXNUM (w->vertical_divider_line_width); |
428 | 1165 int div_left = WINDOW_RIGHT (w) - window_divider_width (w); |
442 | 1166 int y1 = WINDOW_TOP (w); |
1167 int y2 = WINDOW_BOTTOM (w); | |
428 | 1168 |
1169 /* Clear left and right spacing areas */ | |
1170 if (spacing) | |
1171 { | |
1172 rect.top = y1; | |
1173 rect.bottom = y2; | |
440 | 1174 mswindows_update_dc (hdc, Qnil, |
428 | 1175 WINDOW_FACE_CACHEL_BACKGROUND (w, DEFAULT_INDEX), Qnil); |
1176 rect.right = WINDOW_RIGHT (w); | |
1177 rect.left = rect.right - spacing; | |
771 | 1178 ExtTextOutW (hdc, 0, 0, ETO_OPAQUE, &rect, NULL, 0, NULL); |
428 | 1179 rect.left = div_left; |
1180 rect.right = div_left + spacing; | |
771 | 1181 ExtTextOutW (hdc, 0, 0, ETO_OPAQUE, &rect, NULL, 0, NULL); |
428 | 1182 } |
1183 | |
1184 /* Clear divider face */ | |
1185 rect.top = y1 + abs_shadow; | |
1186 rect.bottom = y2 - abs_shadow; | |
1187 rect.left = div_left + spacing + abs_shadow; | |
1188 rect.right = rect.left + line_width; | |
1189 if (rect.left < rect.right) | |
1190 { | |
1191 face_index div_face | |
1192 = get_builtin_face_cache_index (w, Vvertical_divider_face); | |
440 | 1193 mswindows_update_dc (hdc, Qnil, |
428 | 1194 WINDOW_FACE_CACHEL_BACKGROUND (w, div_face), Qnil); |
771 | 1195 ExtTextOutW (hdc, 0, 0, ETO_OPAQUE, &rect, NULL, 0, NULL); |
428 | 1196 } |
1197 | |
1198 /* Draw a shadow around the divider */ | |
1199 if (shadow != 0) | |
1200 { | |
1201 /* #### This will be fixed to support arbitrary thickness */ | |
1202 InflateRect (&rect, abs_shadow, abs_shadow); | |
440 | 1203 DrawEdge (hdc, &rect, |
428 | 1204 shadow > 0 ? EDGE_RAISED : EDGE_SUNKEN, BF_RECT); |
1205 } | |
1206 } | |
1207 | |
1208 /**************************************************************************** | |
1209 mswindows_text_width | |
1210 | |
1211 Given a string and a face, return the string's length in pixels when | |
1212 displayed in the font associated with the face. | |
1213 ****************************************************************************/ | |
1214 static int | |
5628
81fee4aee9b6
text_width methods interface cleanup.
Didier Verna <didier@xemacs.org>
parents:
5624
diff
changeset
|
1215 mswindows_text_width (struct frame *f, struct face_cachel *cachel, |
867 | 1216 const Ichar *str, Charcount len) |
428 | 1217 { |
442 | 1218 HDC hdc = get_frame_dc (f, 0); |
428 | 1219 int width_so_far = 0; |
771 | 1220 textual_run *runs; |
428 | 1221 int nruns; |
1222 int i; | |
1223 | |
771 | 1224 nruns = separate_textual_runs (&runs, str, len); |
428 | 1225 |
1226 for (i = 0; i < nruns; i++) | |
771 | 1227 width_so_far += mswindows_text_width_single_run (hdc, cachel, runs + i); |
428 | 1228 |
1229 return width_so_far; | |
1230 } | |
1231 | |
1232 | |
1233 /**************************************************************************** | |
1234 mswindows_clear_region | |
1235 | |
1236 Clear the area in the box defined by the given parameters using the | |
1237 given face. | |
1238 ****************************************************************************/ | |
1239 static void | |
5046 | 1240 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
|
1241 struct frame *f, |
2286 | 1242 face_index UNUSED (findex), int x, int y, |
1243 int width, int height, Lisp_Object fcolor, | |
5080
5502045ec510
The background-placement face property.
Didier Verna <didier@lrde.epita.fr>
parents:
5046
diff
changeset
|
1244 Lisp_Object bcolor, |
5502045ec510
The background-placement face property.
Didier Verna <didier@lrde.epita.fr>
parents:
5046
diff
changeset
|
1245 Lisp_Object background_pixmap, |
5502045ec510
The background-placement face property.
Didier Verna <didier@lrde.epita.fr>
parents:
5046
diff
changeset
|
1246 Lisp_Object background_placement) |
428 | 1247 { |
1248 RECT rect = { x, y, x+width, y+height }; | |
442 | 1249 HDC hdc = get_frame_dc (f, 1); |
428 | 1250 |
1251 if (!NILP (background_pixmap)) | |
1252 { | |
1253 struct display_box db = { x, y, width, height }; | |
440 | 1254 mswindows_update_dc (hdc, |
1255 fcolor, bcolor, background_pixmap); | |
428 | 1256 mswindows_output_dibitmap_region |
5138
6d13ad8ed3b2
implement absolute background-placement for Windows, sort of
Ben Wing <ben@xemacs.org>
parents:
5080
diff
changeset
|
1257 (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
|
1258 EQ (background_placement, Qabsolute)); |
428 | 1259 } |
1260 else | |
1261 { | |
440 | 1262 mswindows_update_dc (hdc, Qnil, fcolor, Qnil); |
771 | 1263 ExtTextOutW (hdc, 0, 0, ETO_OPAQUE, &rect, NULL, 0, NULL); |
428 | 1264 } |
1265 | |
1266 #ifdef HAVE_SCROLLBARS | |
1267 if (WINDOWP (locale)) | |
1318 | 1268 mswindows_redisplay_deadbox (XWINDOW (locale), x, y, width, height); |
428 | 1269 #endif |
1270 } | |
1271 | |
1318 | 1272 /* #### Implement me! */ |
428 | 1273 static void |
2286 | 1274 mswindows_clear_frame (struct frame *UNUSED (f)) |
428 | 1275 { |
1318 | 1276 GdiFlush (); |
428 | 1277 } |
1278 | |
1279 | |
1280 /************************************************************************/ | |
1281 /* initialization */ | |
1282 /************************************************************************/ | |
1283 | |
1284 void | |
1285 console_type_create_redisplay_mswindows (void) | |
1286 { | |
440 | 1287 /* redisplay methods - display*/ |
428 | 1288 CONSOLE_HAS_METHOD (mswindows, text_width); |
1289 CONSOLE_HAS_METHOD (mswindows, output_display_block); | |
1290 CONSOLE_HAS_METHOD (mswindows, divider_height); | |
1291 CONSOLE_HAS_METHOD (mswindows, eol_cursor_width); | |
1292 CONSOLE_HAS_METHOD (mswindows, output_vertical_divider); | |
1293 CONSOLE_HAS_METHOD (mswindows, clear_region); | |
1294 CONSOLE_HAS_METHOD (mswindows, clear_frame); | |
442 | 1295 CONSOLE_HAS_METHOD (mswindows, frame_output_begin); |
1296 CONSOLE_HAS_METHOD (mswindows, frame_output_end); | |
428 | 1297 CONSOLE_HAS_METHOD (mswindows, flash); |
1298 CONSOLE_HAS_METHOD (mswindows, ring_bell); | |
1299 CONSOLE_HAS_METHOD (mswindows, bevel_area); | |
1300 CONSOLE_HAS_METHOD (mswindows, output_string); | |
1301 CONSOLE_HAS_METHOD (mswindows, output_pixmap); | |
1318 | 1302 #ifdef HAVE_SCROLLBARS |
1303 CONSOLE_HAS_METHOD (mswindows, redisplay_deadbox); | |
1304 #endif | |
440 | 1305 |
1306 /* redisplay methods - printer */ | |
442 | 1307 CONSOLE_HAS_METHOD (msprinter, frame_output_end); |
440 | 1308 CONSOLE_INHERITS_METHOD (msprinter, mswindows, text_width); |
1309 CONSOLE_INHERITS_METHOD (msprinter, mswindows, output_display_block); | |
1310 CONSOLE_INHERITS_METHOD (msprinter, mswindows, divider_height); | |
1311 CONSOLE_INHERITS_METHOD (msprinter, mswindows, eol_cursor_width); | |
1312 CONSOLE_INHERITS_METHOD (msprinter, mswindows, output_vertical_divider); | |
1313 CONSOLE_INHERITS_METHOD (msprinter, mswindows, clear_region); | |
1314 CONSOLE_INHERITS_METHOD (msprinter, mswindows, clear_frame); | |
442 | 1315 CONSOLE_INHERITS_METHOD (msprinter, mswindows, frame_output_begin); |
440 | 1316 CONSOLE_INHERITS_METHOD (msprinter, mswindows, bevel_area); |
1317 CONSOLE_INHERITS_METHOD (msprinter, mswindows, output_string); | |
1318 CONSOLE_INHERITS_METHOD (msprinter, mswindows, output_pixmap); | |
428 | 1319 } |