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