Mercurial > hg > xemacs-beta
annotate src/redisplay-msw.c @ 5724:ede80ef92a74
Make soft links in src for module source files, if built in to the executable.
This ensures that those files are built with the same compiler flags as all
other source files.
See these xemacs-beta messages:
<CAHCOHQn+q=Xuwq+y68dvqi7afAP9f-TdB7=8YiZ8VYO816sjHg@mail.gmail.com>
<f5by5ejqiyk.fsf@calexico.inf.ed.ac.uk>
author | Jerry James <james@xemacs.org> |
---|---|
date | Sat, 02 Mar 2013 14:32:37 -0700 |
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 } |