aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJason Rumney2000-01-23 03:23:49 +0000
committerJason Rumney2000-01-23 03:23:49 +0000
commit791f420fea18d7ef5ddfc386509de2c84d4f39c3 (patch)
tree6d45e6651e29d27659f039f677ae47ace669efb4
parentaba6b952acac672d1140f9620d52f32e518be3d6 (diff)
downloademacs-791f420fea18d7ef5ddfc386509de2c84d4f39c3.tar.gz
emacs-791f420fea18d7ef5ddfc386509de2c84d4f39c3.zip
Complete rewrite based on xterm.c.
-rw-r--r--src/w32term.c8570
1 files changed, 6599 insertions, 1971 deletions
diff --git a/src/w32term.c b/src/w32term.c
index cc71e411a0f..915af573f0a 100644
--- a/src/w32term.c
+++ b/src/w32term.c
@@ -1,5 +1,5 @@
1/* Implementation of GUI terminal on the Microsoft W32 API. 1/* Implementation of GUI terminal on the Microsoft W32 API.
2 Copyright (C) 1989, 93,94,95,96,97,98, 1999 Free Software Foundation, Inc. 2 Copyright (C) 1989, 93, 94, 95, 96, 97, 98 Free Software Foundation, Inc.
3 3
4This file is part of GNU Emacs. 4This file is part of GNU Emacs.
5 5
@@ -21,6 +21,7 @@ Boston, MA 02111-1307, USA. */
21#include <config.h> 21#include <config.h>
22#include <signal.h> 22#include <signal.h>
23#include <stdio.h> 23#include <stdio.h>
24#include <stdlib.h>
24#include "lisp.h" 25#include "lisp.h"
25#include "charset.h" 26#include "charset.h"
26#include "fontset.h" 27#include "fontset.h"
@@ -28,6 +29,7 @@ Boston, MA 02111-1307, USA. */
28 29
29#include "w32heap.h" 30#include "w32heap.h"
30#include "w32term.h" 31#include "w32term.h"
32#include "w32bdf.h"
31#include <shellapi.h> 33#include <shellapi.h>
32 34
33#include "systty.h" 35#include "systty.h"
@@ -49,6 +51,7 @@ Boston, MA 02111-1307, USA. */
49#include "window.h" 51#include "window.h"
50#include "keyboard.h" 52#include "keyboard.h"
51#include "intervals.h" 53#include "intervals.h"
54#include "composite.h"
52#include "coding.h" 55#include "coding.h"
53 56
54#undef min 57#undef min
@@ -56,6 +59,109 @@ Boston, MA 02111-1307, USA. */
56#define min(x, y) (((x) < (y)) ? (x) : (y)) 59#define min(x, y) (((x) < (y)) ? (x) : (y))
57#define max(x, y) (((x) > (y)) ? (x) : (y)) 60#define max(x, y) (((x) > (y)) ? (x) : (y))
58 61
62#define abs(x) ((x) < 0 ? -(x) : (x))
63
64#define BETWEEN(X, LOWER, UPPER) ((X) >= (LOWER) && (X) < (UPPER))
65
66
67/* Bitmaps for truncated lines. */
68
69enum bitmap_type
70{
71 NO_BITMAP,
72 LEFT_TRUNCATION_BITMAP,
73 RIGHT_TRUNCATION_BITMAP,
74 OVERLAY_ARROW_BITMAP,
75 CONTINUED_LINE_BITMAP,
76 CONTINUATION_LINE_BITMAP,
77 ZV_LINE_BITMAP
78};
79
80/* Bitmaps are all unsigned short, as Windows requires bitmap data to
81 be Word aligned. For some reason they are horizontally reflected
82 compared to how they appear on X, so changes in xterm.c should be
83 reflected here. */
84
85/* Bitmap drawn to indicate lines not displaying text if
86 `indicate-empty-lines' is non-nil. */
87
88#define zv_width 8
89#define zv_height 8
90static unsigned short zv_bits[] = {
91 0x00, 0x00, 0x78, 0x78, 0x78, 0x78, 0x00, 0x00};
92
93/* An arrow like this: `<-'. */
94
95#define left_width 8
96#define left_height 8
97static unsigned short left_bits[] = {
98 0x18, 0x30, 0x60, 0xfc, 0xfc, 0x60, 0x30, 0x18};
99
100/* Right truncation arrow bitmap `->'. */
101
102#define right_width 8
103#define right_height 8
104static unsigned short right_bits[] = {
105 0x18, 0x0c, 0x06, 0x3f, 0x3f, 0x06, 0x0c, 0x18};
106
107/* Marker for continued lines. */
108
109#define continued_width 8
110#define continued_height 8
111static unsigned short continued_bits[] = {
112 0x3c, 0x3e, 0x03, 0x27, 0x3f, 0x3e, 0x3c, 0x3e};
113
114/* Marker for continuation lines. */
115
116#define continuation_width 8
117#define continuation_height 8
118static unsigned short continuation_bits[] = {
119 0x3c, 0x7c, 0xc0, 0xe4, 0xfc, 0x7c, 0x3c, 0x7c};
120
121/* Overlay arrow bitmap. */
122
123#if 0
124/* A bomb. */
125#define ov_width 8
126#define ov_height 8
127static unsigned short ov_bits[] = {
128 0x0c, 0x10, 0x3c, 0x7e, 0x5e, 0x5e, 0x46, 0x3c};
129#else
130/* A triangular arrow. */
131#define ov_width 8
132#define ov_height 8
133static unsigned short ov_bits[] = {
134 0xc0, 0xf0, 0xf8, 0xfc, 0xfc, 0xf8, 0xf0, 0xc0};
135
136#endif
137
138extern Lisp_Object Qhelp_echo;
139
140
141/* Non-zero means Emacs uses toolkit scroll bars. */
142
143int x_toolkit_scroll_bars_p;
144
145/* If a string, w32_read_socket generates an event to display that string.
146 (The display is done in read_char.) */
147
148static Lisp_Object help_echo;
149
150/* Temporary variable for w32_read_socket. */
151
152static Lisp_Object previous_help_echo;
153
154/* Non-zero means that a HELP_EVENT has been generated since Emacs
155 start. */
156
157static int any_help_event_p;
158
159/* Non-zero means draw block and hollow cursor as wide as the glyph
160 under it. For example, if a block cursor is over a tab, it will be
161 drawn as wide as that tab on the display. */
162
163int x_stretch_cursor_p;
164
59#define CP_DEFAULT 1004 165#define CP_DEFAULT 1004
60 166
61extern unsigned int msh_mousewheel; 167extern unsigned int msh_mousewheel;
@@ -80,26 +186,18 @@ Lisp_Object w32_display_name_list;
80/* Frame being updated by update_frame. This is declared in term.c. 186/* Frame being updated by update_frame. This is declared in term.c.
81 This is set by update_begin and looked at by all the 187 This is set by update_begin and looked at by all the
82 w32 functions. It is zero while not inside an update. 188 w32 functions. It is zero while not inside an update.
83 In that case, the w32 functions assume that `selected_frame' 189 In that case, the w32 functions assume that `SELECTED_FRAME ()'
84 is the frame to apply to. */ 190 is the frame to apply to. */
85extern struct frame *updating_frame; 191extern struct frame *updating_frame;
86 192
87/* This is a frame waiting to be autoraised, within w32_read_socket. */ 193/* This is a frame waiting to be autoraised, within w32_read_socket. */
88struct frame *pending_autoraise_frame; 194struct frame *pending_autoraise_frame;
89 195
90/* During an update, maximum vpos for ins/del line operations to affect. */
91
92static int flexlines;
93
94/* During an update, nonzero if chars output now should be highlighted. */
95
96static int highlight;
97
98/* Nominal cursor position -- where to draw output. 196/* Nominal cursor position -- where to draw output.
99 During an update, these are different from the cursor-box position. */ 197 HPOS and VPOS are window relative glyph matrix coordinates.
198 X and Y are window relative pixel coordinates. */
100 199
101static int curs_x; 200struct cursor_pos output_cursor;
102static int curs_y;
103 201
104/* Flag to enable Unicode output in case users wish to use programs 202/* Flag to enable Unicode output in case users wish to use programs
105 like Twinbridge on '95 rather than installed system level support 203 like Twinbridge on '95 rather than installed system level support
@@ -146,8 +244,9 @@ int last_scroll_bar_drag_pos;
146/* Mouse movement. */ 244/* Mouse movement. */
147 245
148/* Where the mouse was last time we reported a mouse event. */ 246/* Where the mouse was last time we reported a mouse event. */
149static FRAME_PTR last_mouse_frame; 247FRAME_PTR last_mouse_frame;
150static RECT last_mouse_glyph; 248static RECT last_mouse_glyph;
249static Lisp_Object last_mouse_press_frame;
151 250
152Lisp_Object Vw32_num_mouse_buttons; 251Lisp_Object Vw32_num_mouse_buttons;
153 252
@@ -200,50 +299,93 @@ extern int errno;
200/* A mask of extra modifier bits to put into every keyboard char. */ 299/* A mask of extra modifier bits to put into every keyboard char. */
201extern int extra_keyboard_modifiers; 300extern int extra_keyboard_modifiers;
202 301
302/* Enumeration for overriding/changing the face to use for drawing
303 glyphs in x_draw_glyphs. */
304
305enum draw_glyphs_face
306{
307 DRAW_NORMAL_TEXT,
308 DRAW_INVERSE_VIDEO,
309 DRAW_CURSOR,
310 DRAW_MOUSE_FACE,
311 DRAW_IMAGE_RAISED,
312 DRAW_IMAGE_SUNKEN
313};
314
315static void x_update_window_end P_ ((struct window *, int));
316static void frame_to_window_pixel_xy P_ ((struct window *, int *, int *));
317void w32_delete_display P_ ((struct w32_display_info *));
318static int fast_find_position P_ ((struct window *, int, int *, int *,
319 int *, int *));
320static void set_output_cursor P_ ((struct cursor_pos *));
321static struct glyph *x_y_to_hpos_vpos P_ ((struct window *, int, int,
322 int *, int *, int *));
323static void note_mode_line_highlight P_ ((struct window *, int, int));
324static void x_check_font P_ ((struct frame *, XFontStruct *));
325static void note_mouse_highlight P_ ((struct frame *, int, int));
326static void note_tool_bar_highlight P_ ((struct frame *f, int, int));
327static void w32_handle_tool_bar_click P_ ((struct frame *,
328 struct input_event *));
329static void show_mouse_face P_ ((struct w32_display_info *,
330 enum draw_glyphs_face));
331void clear_mouse_face P_ ((struct w32_display_info *));
332
333void x_lower_frame P_ ((struct frame *));
334void x_scroll_bar_clear P_ ((struct frame *));
335void x_wm_set_size_hint P_ ((struct frame *, long, int));
336void x_raise_frame P_ ((struct frame *));
337void x_set_window_size P_ ((struct frame *, int, int, int));
338void x_wm_set_window_state P_ ((struct frame *, int));
339void x_wm_set_icon_pixmap P_ ((struct frame *, int));
340void w32_initialize P_ ((void));
341static void x_font_min_bounds P_ ((XFontStruct *, int *, int *));
342int x_compute_min_glyph_bounds P_ ((struct frame *));
343static void x_draw_phys_cursor_glyph P_ ((struct window *,
344 struct glyph_row *,
345 enum draw_glyphs_face));
346static void x_update_end P_ ((struct frame *));
347static void w32_frame_up_to_date P_ ((struct frame *));
348static void w32_reassert_line_highlight P_ ((int, int));
349static void x_change_line_highlight P_ ((int, int, int, int));
350static void w32_set_terminal_modes P_ ((void));
351static void w32_reset_terminal_modes P_ ((void));
352static void w32_cursor_to P_ ((int, int, int, int));
353static void x_write_glyphs P_ ((struct glyph *, int));
354static void x_clear_end_of_line P_ ((int));
355static void x_clear_frame P_ ((void));
356static void x_clear_cursor P_ ((struct window *));
357static void frame_highlight P_ ((struct frame *));
358static void frame_unhighlight P_ ((struct frame *));
359static void w32_new_focus_frame P_ ((struct w32_display_info *,
360 struct frame *));
361static void w32_frame_rehighlight P_ ((struct frame *));
362static void x_frame_rehighlight P_ ((struct w32_display_info *));
363static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *));
364static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *));
365static int w32_intersect_rectangles P_ ((RECT *, RECT *, RECT *));
366static void expose_frame P_ ((struct frame *, int, int, int, int));
367static void expose_window_tree P_ ((struct window *, RECT *));
368static void expose_window P_ ((struct window *, RECT *));
369static void expose_area P_ ((struct window *, struct glyph_row *,
370 RECT *, enum glyph_row_area));
371static void expose_line P_ ((struct window *, struct glyph_row *,
372 RECT *));
373void x_update_cursor P_ ((struct frame *, int));
374static void x_update_cursor_in_window_tree P_ ((struct window *, int));
375static void x_update_window_cursor P_ ((struct window *, int));
376static void x_erase_phys_cursor P_ ((struct window *));
377void x_display_cursor P_ ((struct window *w, int, int, int, int, int));
378void x_display_and_set_cursor P_ ((struct window *, int, int, int, int, int));
379static void w32_draw_bitmap P_ ((struct window *, HDC hdc, struct glyph_row *,
380 enum bitmap_type));
381static int x_phys_cursor_in_rect_p P_ ((struct window *, RECT *));
382static void x_draw_row_bitmaps P_ ((struct window *, struct glyph_row *));
383static void note_overwritten_text_cursor P_ ((struct window *, int, int));
384static void w32_clip_to_row P_ ((struct window *, struct glyph_row *,
385 HDC, int));
386
203static Lisp_Object Qvendor_specific_keysyms; 387static Lisp_Object Qvendor_specific_keysyms;
204 388
205void w32_delete_display ();
206
207static void redraw_previous_char ();
208static void redraw_following_char ();
209static unsigned int w32_get_modifiers ();
210
211static int fast_find_position ();
212static void note_mouse_highlight ();
213static void clear_mouse_face ();
214static void show_mouse_face ();
215static void do_line_dance ();
216
217/* Forward declarations for term hooks. Consistency with the rest of Emacs
218 requires the use of K&R functions prototypes. However, MSVC does not
219 pick up the function prototypes correctly with K&R function definitions,
220 and so we declare them first to give a little help to MSVC. */
221static void w32_clear_frame ();
222static void w32_clear_end_of_line (int);
223static void w32_ins_del_lines (int, int);
224static void w32_change_line_highlight (int, int, int);
225static void w32_insert_glyphs (GLYPH *, int);
226static void w32_write_glyphs (GLYPH *, int);
227static void w32_delete_glyphs (int);
228static void w32_ring_bell ();
229static void w32_reset_terminal_modes ();
230static void w32_set_terminal_modes ();
231static void w32_update_begin (FRAME_PTR);
232static void w32_update_end (FRAME_PTR);
233static void w32_set_terminal_window (int);
234extern int w32_read_socket (int, struct input_event *, int, int);
235static void w32_frame_up_to_date (FRAME_PTR);
236static void w32_cursor_to (int, int);
237static void w32_reassert_line_highlight (int, int);
238static void w32_mouse_position (FRAME_PTR *, int, Lisp_Object *,
239 enum scroll_bar_part *, Lisp_Object *,
240 Lisp_Object *, unsigned long *);
241static void w32_frame_rehighlight (FRAME_PTR);
242static void w32_frame_raise_lower (FRAME_PTR, int);
243static void w32_set_vertical_scroll_bar (struct window *, int, int, int);
244static void w32_condemn_scroll_bars (FRAME_PTR);
245static void w32_redeem_scroll_bar (struct window *);
246static void w32_judge_scroll_bars (FRAME_PTR);
247 389
248#if 0 390#if 0
249/* This is a function useful for recording debugging information 391/* This is a function useful for recording debugging information
@@ -273,6 +415,55 @@ record_event (locus, type)
273 415
274#endif /* 0 */ 416#endif /* 0 */
275 417
418
419void XChangeGC (void * ignore, XGCValues* gc, unsigned long mask,
420 XGCValues *xgcv)
421{
422 if (mask & GCForeground)
423 gc->foreground = xgcv->foreground;
424 if (mask & GCBackground)
425 gc->background = xgcv->background;
426 if (mask & GCFont)
427 gc->font = xgcv->font;
428}
429
430XGCValues *XCreateGC (void * ignore, Window window, unsigned long mask,
431 XGCValues *xgcv)
432{
433 XGCValues *gc = (XGCValues *) xmalloc (sizeof (XGCValues));
434 bzero (gc, sizeof (XGCValues));
435
436 XChangeGC (ignore, gc, mask, xgcv);
437
438 return gc;
439}
440
441void XGetGCValues (void* ignore, XGCValues *gc,
442 unsigned long mask, XGCValues *xgcv)
443{
444 XChangeGC (ignore, xgcv, mask, gc);
445}
446
447void XTextExtents16 (XFontStruct *font, wchar_t *text, int nchars,
448 int *direction,int *font_ascent,
449 int *font_descent, XCharStruct *cs)
450{
451 /* NTEMACS_TODO: Use GetTextMetrics to do this and inline it below. */
452}
453
454static void
455w32_set_clip_rectangle (HDC hdc, RECT *rect)
456{
457 if (rect)
458 {
459 HRGN clip_region = CreateRectRgnIndirect (rect);
460 SelectClipRgn (hdc, clip_region);
461 DeleteObject (clip_region);
462 }
463 else
464 SelectClipRgn (hdc, NULL);
465}
466
276/* Return the struct w32_display_info. */ 467/* Return the struct w32_display_info. */
277 468
278struct w32_display_info * 469struct w32_display_info *
@@ -281,6 +472,29 @@ w32_display_info_for_display ()
281 return (&one_w32_display_info); 472 return (&one_w32_display_info);
282} 473}
283 474
475
476/* Draw a hollow rectangle at the specified position. */
477void
478w32_draw_rectangle (HDC hdc, XGCValues *gc, int x, int y,
479 int width, int height)
480{
481 HBRUSH hb, oldhb;
482 HPEN hp, oldhp;
483
484 hb = CreateSolidBrush (gc->background);
485 hp = CreatePen (PS_SOLID, 0, gc->foreground);
486 oldhb = SelectObject (hdc, hb);
487 oldhp = SelectObject (hdc, hp);
488
489 Rectangle (hdc, x, y, x + width, y + height);
490
491 SelectObject (hdc, oldhb);
492 SelectObject (hdc, oldhp);
493 DeleteObject (hb);
494 DeleteObject (hp);
495}
496
497/* Draw a filled rectangle at the specified position. */
284void 498void
285w32_fill_rect (f, _hdc, pix, lprect) 499w32_fill_rect (f, _hdc, pix, lprect)
286 FRAME_PTR f; 500 FRAME_PTR f;
@@ -291,7 +505,7 @@ w32_fill_rect (f, _hdc, pix, lprect)
291 HDC hdc; 505 HDC hdc;
292 HBRUSH hb; 506 HBRUSH hb;
293 RECT rect; 507 RECT rect;
294 508
295 if (_hdc) 509 if (_hdc)
296 hdc = _hdc; 510 hdc = _hdc;
297 else 511 else
@@ -319,132 +533,449 @@ w32_clear_window (f)
319} 533}
320 534
321 535
322/* Starting and ending updates. 536/***********************************************************************
323 537 Starting and ending an update
324 These hooks are called by update_frame at the beginning and end 538 ***********************************************************************/
325 of a frame update. We record in `updating_frame' the identity 539
326 of the frame being updated, so that the w32_... functions do not 540/* Start an update of frame F. This function is installed as a hook
327 need to take a frame as argument. Most of the w32_... functions 541 for update_begin, i.e. it is called when update_begin is called.
328 should never be called except during an update, the only exceptions 542 This function is called prior to calls to x_update_window_begin for
329 being w32_cursor_to, w32_write_glyphs and w32_reassert_line_highlight. */ 543 each window being updated. Currently, there is nothing to do here
544 because all interesting stuff is done on a window basis. */
330 545
331static void 546static void
332w32_update_begin (f) 547x_update_begin (f)
333 struct frame *f; 548 struct frame *f;
334{ 549{
335 if (f == 0) 550 /* Nothing to do. We have to do something though, otherwise the
336 abort (); 551 function gets optimized away and the hook is no longer valid. */
552 struct frame *cf = f;
553}
554
555
556/* Start update of window W. Set the global variable updated_window
557 to the window being updated and set output_cursor to the cursor
558 position of W. */
337 559
338 flexlines = f->height; 560static void
339 highlight = 0; 561x_update_window_begin (w)
562 struct window *w;
563{
564 struct frame *f = XFRAME (WINDOW_FRAME (w));
565 struct w32_display_info *display_info = FRAME_W32_DISPLAY_INFO (f);
566
567 updated_window = w;
568 set_output_cursor (&w->cursor);
340 569
341 BLOCK_INPUT; 570 BLOCK_INPUT;
342 571
343 /* Regenerate display palette before drawing if list of requested 572 /* Regenerate display palette before drawing if list of requested
344 colors has changed. */ 573 colors has changed. */
345 if (FRAME_W32_DISPLAY_INFO (f)->regen_palette) 574 if (display_info->regen_palette)
346 { 575 {
347 w32_regenerate_palette (f); 576 w32_regenerate_palette (f);
348 FRAME_W32_DISPLAY_INFO (f)->regen_palette = FALSE; 577 display_info->regen_palette = FALSE;
349 } 578 }
350 579
351 if (f == FRAME_W32_DISPLAY_INFO (f)->mouse_face_mouse_frame) 580 if (f == display_info->mouse_face_mouse_frame)
352 { 581 {
353 /* Don't do highlighting for mouse motion during the update. */ 582 /* Don't do highlighting for mouse motion during the update. */
354 FRAME_W32_DISPLAY_INFO (f)->mouse_face_defer = 1; 583 display_info->mouse_face_defer = 1;
355 584
356 /* If the frame needs to be redrawn, 585 /* If the frame needs to be redrawn,
357 simply forget about any prior mouse highlighting. */ 586 simply forget about any prior mouse highlighting. */
358 if (FRAME_GARBAGED_P (f)) 587 if (FRAME_GARBAGED_P (f))
359 FRAME_W32_DISPLAY_INFO (f)->mouse_face_window = Qnil; 588 display_info->mouse_face_window = Qnil;
360 589
361 if (!NILP (FRAME_W32_DISPLAY_INFO (f)->mouse_face_window)) 590 /* Can we tell that this update does not affect the window
591 where the mouse highlight is? If so, no need to turn off.
592 Likewise, don't do anything if the frame is garbaged;
593 in that case, the frame's current matrix that we would use
594 is all wrong, and we will redisplay that line anyway. */
595 if (!NILP (display_info->mouse_face_window)
596 && w == XWINDOW (display_info->mouse_face_window))
362 { 597 {
363 int firstline, lastline, i; 598 int i;
364 struct window *w = XWINDOW (FRAME_W32_DISPLAY_INFO (f)->mouse_face_window);
365 599
366 /* Find the first, and the last+1, lines affected by redisplay. */ 600 for (i = 0; i < w->desired_matrix->nrows; ++i)
367 for (firstline = 0; firstline < f->height; firstline++) 601 if (MATRIX_ROW_ENABLED_P (w->desired_matrix, i))
368 if (FRAME_DESIRED_GLYPHS (f)->enable[firstline])
369 break; 602 break;
370 603
371 lastline = f->height; 604 if (i < w->desired_matrix->nrows)
372 for (i = f->height - 1; i >= 0; i--) 605 clear_mouse_face (display_info);
373 {
374 if (FRAME_DESIRED_GLYPHS (f)->enable[i])
375 break;
376 else
377 lastline = i;
378 }
379
380 /* Can we tell that this update does not affect the window
381 where the mouse highlight is? If so, no need to turn off.
382 Likewise, don't do anything if the frame is garbaged;
383 in that case, the FRAME_CURRENT_GLYPHS that we would use
384 are all wrong, and we will redisplay that line anyway. */
385 if (! (firstline > (XFASTINT (w->top) + window_internal_height (w))
386 || lastline < XFASTINT (w->top)))
387 clear_mouse_face (FRAME_W32_DISPLAY_INFO (f));
388 } 606 }
389 } 607 }
390 608
391 UNBLOCK_INPUT; 609 UNBLOCK_INPUT;
392} 610}
393 611
612
613/* Draw a vertical window border to the right of window W if W doesn't
614 have vertical scroll bars. */
615
394static void 616static void
395w32_update_end (f) 617x_draw_vertical_border (w)
396 struct frame *f; 618 struct window *w;
397{ 619{
398 BLOCK_INPUT; 620 struct frame *f = XFRAME (WINDOW_FRAME (w));
621
622 /* Redraw borders between horizontally adjacent windows. Don't
623 do it for frames with vertical scroll bars because either the
624 right scroll bar of a window, or the left scroll bar of its
625 neighbor will suffice as a border. */
626 if (!WINDOW_RIGHTMOST_P (w)
627 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
628 {
629 RECT r;
399 630
400 do_line_dance (); 631 window_box_edges (w, -1, &r.left, &r.top, &r.right, &r.bottom);
401 x_display_cursor (f, 1); 632 r.left = r.right + FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f);
633 r.right = r.left + 1;
634 r.bottom -= 1;
402 635
403 if (f == FRAME_W32_DISPLAY_INFO (f)->mouse_face_mouse_frame) 636 w32_fill_rect (f, NULL, FRAME_FOREGROUND_PIXEL (f), r);
404 FRAME_W32_DISPLAY_INFO (f)->mouse_face_defer = 0; 637 }
638}
405 639
406 UNBLOCK_INPUT; 640
641/* End update of window W (which is equal to updated_window). Draw
642 vertical borders between horizontally adjacent windows, and display
643 W's cursor if CURSOR_ON_P is non-zero. W may be a menu bar
644 pseudo-window in case we don't have X toolkit support. Such
645 windows don't have a cursor, so don't display it here. */
646
647static void
648x_update_window_end (w, cursor_on_p)
649 struct window *w;
650 int cursor_on_p;
651{
652 if (!w->pseudo_window_p)
653 {
654 BLOCK_INPUT;
655 if (cursor_on_p)
656 x_display_and_set_cursor (w, 1, output_cursor.hpos,
657 output_cursor.vpos,
658 output_cursor.x, output_cursor.y);
659 x_draw_vertical_border (w);
660 UNBLOCK_INPUT;
661 }
662
663 updated_window = NULL;
664}
665
666static void
667x_update_end (f)
668 struct frame *f;
669{
670 /* Mouse highlight may be displayed again. */
671 FRAME_W32_DISPLAY_INFO (f)->mouse_face_defer = 0;
407} 672}
408 673
409/* This is called after a redisplay on frame F. */ 674/* This function is called from various places in xdisp.c whenever a
675 complete update has been performed. The global variable
676 updated_window is not available here. */
410 677
411static void 678static void
412w32_frame_up_to_date (f) 679w32_frame_up_to_date (f)
413 FRAME_PTR f; 680 struct frame *f;
414{ 681{
415 BLOCK_INPUT; 682 if (FRAME_W32_P (f))
416 if (FRAME_W32_DISPLAY_INFO (f)->mouse_face_deferred_gc
417 || f == FRAME_W32_DISPLAY_INFO (f)->mouse_face_mouse_frame)
418 { 683 {
419 note_mouse_highlight (FRAME_W32_DISPLAY_INFO (f)->mouse_face_mouse_frame, 684 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
420 FRAME_W32_DISPLAY_INFO (f)->mouse_face_mouse_x, 685 if (dpyinfo->mouse_face_deferred_gc
421 FRAME_W32_DISPLAY_INFO (f)->mouse_face_mouse_y); 686 || f == dpyinfo->mouse_face_mouse_frame)
422 FRAME_W32_DISPLAY_INFO (f)->mouse_face_deferred_gc = 0; 687 {
688 BLOCK_INPUT;
689 if (dpyinfo->mouse_face_mouse_frame)
690 note_mouse_highlight (dpyinfo->mouse_face_mouse_frame,
691 dpyinfo->mouse_face_mouse_x,
692 dpyinfo->mouse_face_mouse_y);
693 dpyinfo->mouse_face_deferred_gc = 0;
694 UNBLOCK_INPUT;
695 }
696 }
697}
698
699
700/* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
701 arrow bitmaps, or clear the areas where they would be displayed
702 before DESIRED_ROW is made current. The window being updated is
703 found in updated_window. This function It is called from
704 update_window_line only if it is known that there are differences
705 between bitmaps to be drawn between current row and DESIRED_ROW. */
706
707static void
708x_after_update_window_line (desired_row)
709 struct glyph_row *desired_row;
710{
711 struct window *w = updated_window;
712
713 xassert (w);
714
715 if (!desired_row->mode_line_p && !w->pseudo_window_p)
716 {
717 BLOCK_INPUT;
718 x_draw_row_bitmaps (w, desired_row);
719
720 /* When a window has disappeared, make sure that no rest of
721 full-width rows stays visible in the internal border. */
722 if (windows_or_buffers_changed)
723 {
724 struct frame *f = XFRAME (w->frame);
725 int width = FRAME_INTERNAL_BORDER_WIDTH (f);
726 int height = desired_row->visible_height;
727 int x = (window_box_right (w, -1)
728 + FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f));
729 int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
730
731 w32_clear_area (f, NULL, x, y, width, height);
732 }
733
734 UNBLOCK_INPUT;
423 } 735 }
424 UNBLOCK_INPUT;
425} 736}
737
738
739/* Draw the bitmap WHICH in one of the areas to the left or right of
740 window W. ROW is the glyph row for which to display the bitmap; it
741 determines the vertical position at which the bitmap has to be
742 drawn. */
743
744static void
745w32_draw_bitmap (w, _hdc, row, which)
746 struct window *w;
747 HDC _hdc;
748 struct glyph_row *row;
749 enum bitmap_type which;
750{
751 struct frame *f = XFRAME (WINDOW_FRAME (w));
752 Window window = FRAME_W32_WINDOW (f);
753 HDC hdc = _hdc ? _hdc : get_frame_dc (f);
754 HDC compat_hdc;
755 int x, y, wd, h, dy;
756 unsigned short *bits;
757 HBITMAP pixmap;
758 HBRUSH fg_brush, orig_brush;
759 HANDLE horig_obj;
760 struct face *face;
761
762 /* Must clip because of partially visible lines. */
763 w32_clip_to_row (w, row, hdc, 1);
764
765 switch (which)
766 {
767 case LEFT_TRUNCATION_BITMAP:
768 wd = left_width;
769 h = left_height;
770 bits = left_bits;
771 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
772 - wd
773 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
774 break;
775
776 case OVERLAY_ARROW_BITMAP:
777 wd = ov_width;
778 h = ov_height;
779 bits = ov_bits;
780 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
781 - wd
782 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
783 break;
784
785 case RIGHT_TRUNCATION_BITMAP:
786 wd = right_width;
787 h = right_height;
788 bits = right_bits;
789 x = window_box_right (w, -1);
790 x += (FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f) - wd) / 2;
791 break;
792
793 case CONTINUED_LINE_BITMAP:
794 wd = continued_width;
795 h = continued_height;
796 bits = continued_bits;
797 x = window_box_right (w, -1);
798 x += (FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f) - wd) / 2;
799 break;
800
801 case CONTINUATION_LINE_BITMAP:
802 wd = continuation_width;
803 h = continuation_height;
804 bits = continuation_bits;
805 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
806 - wd
807 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
808 break;
809
810 case ZV_LINE_BITMAP:
811 wd = zv_width;
812 h = zv_height;
813 bits = zv_bits;
814 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
815 - wd
816 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
817 break;
818
819 default:
820 abort ();
821 }
822
823 /* Convert to frame coordinates. Set dy to the offset in the row to
824 start drawing the bitmap. */
825 y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
826 dy = (row->height - h) / 2;
827
828 /* Draw the bitmap. I believe these small pixmaps can be cached
829 by the server. */
830 face = FACE_FROM_ID (f, BITMAP_AREA_FACE_ID);
831 pixmap = CreateBitmap (wd, h, 1, 1, bits);
832
833 compat_hdc = CreateCompatibleDC (hdc);
834 SaveDC (hdc);
835 fg_brush = CreateSolidBrush (FRAME_FOREGROUND_PIXEL (f));
836 orig_brush = SelectObject (hdc, fg_brush);
837 horig_obj = SelectObject (compat_hdc, pixmap);
838 SetTextColor (hdc, FRAME_BACKGROUND_PIXEL (f));
839 SetBkColor (hdc, FRAME_FOREGROUND_PIXEL (f));
840#if 0 /* From w32bdf.c (which is from Meadow). */
841 BitBlt (hdc, x, y + dy, wd, h, compat_hdc, 0, 0, SRCCOPY);
842#else
843 BitBlt (hdc, x, y + dy, wd, h, compat_hdc, 0, 0, 0xB8074A);
844#endif
845 SelectObject (compat_hdc, horig_obj);
846 SelectObject (hdc, orig_brush);
847 DeleteObject (pixmap);
848 DeleteObject (fg_brush);
849 DeleteDC (compat_hdc);
850 RestoreDC (hdc, -1);
851
852 if (!_hdc)
853 release_frame_dc (f, hdc);
854}
855
856
857/* Draw flags bitmaps for glyph row ROW on window W. Call this
858 function with input blocked. */
859
860static void
861x_draw_row_bitmaps (w, row)
862 struct window *w;
863 struct glyph_row *row;
864{
865 struct frame *f = XFRAME (w->frame);
866 enum bitmap_type bitmap;
867 struct face *face;
868 int header_line_height = -1;
869 HDC hdc = get_frame_dc (f);
870
871 xassert (interrupt_input_blocked);
872
873 /* If row is completely invisible, because of vscrolling, we
874 don't have to draw anything. */
875 if (row->visible_height <= 0)
876 return;
877
878 face = FACE_FROM_ID (f, BITMAP_AREA_FACE_ID);
879 PREPARE_FACE_FOR_DISPLAY (f, face);
880
881 /* Decide which bitmap to draw at the left side. */
882 if (row->overlay_arrow_p)
883 bitmap = OVERLAY_ARROW_BITMAP;
884 else if (row->truncated_on_left_p)
885 bitmap = LEFT_TRUNCATION_BITMAP;
886 else if (MATRIX_ROW_CONTINUATION_LINE_P (row))
887 bitmap = CONTINUATION_LINE_BITMAP;
888 else if (row->indicate_empty_line_p)
889 bitmap = ZV_LINE_BITMAP;
890 else
891 bitmap = NO_BITMAP;
892
893 /* Clear flags area if no bitmap to draw or if bitmap doesn't fill
894 the flags area. */
895 if (bitmap == NO_BITMAP
896 || FRAME_FLAGS_BITMAP_WIDTH (f) < FRAME_X_LEFT_FLAGS_AREA_WIDTH (f)
897 || row->height > FRAME_FLAGS_BITMAP_HEIGHT (f))
898 {
899 /* If W has a vertical border to its left, don't draw over it. */
900 int border = ((XFASTINT (w->left) > 0
901 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
902 ? 1 : 0);
903 int left = window_box_left (w, -1);
904
905 if (header_line_height < 0)
906 header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
907
908 w32_fill_area (f, hdc, face->background,
909 left - FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) + border,
910 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
911 row->y)),
912 FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - border,
913 row->visible_height);
914 }
915
916 /* Draw the left bitmap. */
917 if (bitmap != NO_BITMAP)
918 w32_draw_bitmap (w, hdc, row, bitmap);
919
920 /* Decide which bitmap to draw at the right side. */
921 if (row->truncated_on_right_p)
922 bitmap = RIGHT_TRUNCATION_BITMAP;
923 else if (row->continued_p)
924 bitmap = CONTINUED_LINE_BITMAP;
925 else
926 bitmap = NO_BITMAP;
927
928 /* Clear flags area if no bitmap to draw of if bitmap doesn't fill
929 the flags area. */
930 if (bitmap == NO_BITMAP
931 || FRAME_FLAGS_BITMAP_WIDTH (f) < FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f)
932 || row->height > FRAME_FLAGS_BITMAP_HEIGHT (f))
933 {
934 int right = window_box_right (w, -1);
935
936 if (header_line_height < 0)
937 header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
938
939 w32_fill_area (f, hdc, face->background,
940 right,
941 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
942 row->y)),
943 FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f),
944 row->visible_height);
945 }
946
947 /* Draw the right bitmap. */
948 if (bitmap != NO_BITMAP)
949 w32_draw_bitmap (w, hdc, row, bitmap);
950
951 release_frame_dc (f, hdc);
952}
953
426 954
427/* External interface to control of standout mode. 955
428 Call this when about to modify line at position VPOS 956/***********************************************************************
429 and not change whether it is highlighted. */ 957 Line Highlighting
958 ***********************************************************************/
959
960/* External interface to control of standout mode. Not used for W32
961 frames. Aborts when called. */
430 962
431static void 963static void
432w32_reassert_line_highlight (new, vpos) 964w32_reassert_line_highlight (new, vpos)
433 int new, vpos; 965 int new, vpos;
434{ 966{
435 highlight = new; 967 abort ();
436} 968}
437 969
438/* Call this when about to modify line at position VPOS 970/* Call this when about to modify line at position VPOS and change
439 and change whether it is highlighted. */ 971 whether it is highlighted. Not used for W32 frames. Aborts when
972 called. */
440 973
441static void 974static void
442w32_change_line_highlight (new_highlight, vpos, first_unused_hpos) 975x_change_line_highlight (new_highlight, vpos, y, first_unused_hpos)
443 int new_highlight, vpos, first_unused_hpos; 976 int new_highlight, vpos, y, first_unused_hpos;
444{ 977{
445 highlight = new_highlight; 978 abort ();
446 w32_cursor_to (vpos, 0);
447 w32_clear_end_of_line (updating_frame->width);
448} 979}
449 980
450/* This is used when starting Emacs and when restarting after suspend. 981/* This is used when starting Emacs and when restarting after suspend.
@@ -464,27 +995,1249 @@ static void
464w32_reset_terminal_modes (void) 995w32_reset_terminal_modes (void)
465{ 996{
466} 997}
998
467 999
468/* Set the nominal cursor position of the frame. 1000/***********************************************************************
469 This is where display update commands will take effect. 1001 Output Cursor
470 This does not affect the place where the cursor-box is displayed. */ 1002 ***********************************************************************/
471 1003
1004/* Set the global variable output_cursor to CURSOR. All cursor
1005 positions are relative to updated_window. */
472static void 1006static void
473w32_cursor_to (row, col) 1007set_output_cursor (cursor)
474 register int row, col; 1008 struct cursor_pos *cursor;
475{ 1009{
476 int orow = row; 1010 output_cursor.hpos = cursor->hpos;
1011 output_cursor.vpos = cursor->vpos;
1012 output_cursor.x = cursor->x;
1013 output_cursor.y = cursor->y;
1014}
1015
1016
1017/* Set a nominal cursor position.
1018
1019 HPOS and VPOS are column/row positions in a window glyph matrix. X
1020 and Y are window text area relative pixel positions.
1021
1022 If this is done during an update, updated_window will contain the
1023 window that is being updated and the position is the future output
1024 cursor position for that window. If updated_window is null, use
1025 selected_window and display the cursor at the given position. */
1026
1027static void
1028w32_cursor_to (vpos, hpos, y, x)
1029 int vpos, hpos, y, x;
1030{
1031 struct window *w;
1032
1033 /* If updated_window is not set, work on selected_window. */
1034 if (updated_window)
1035 w = updated_window;
1036 else
1037 w = XWINDOW (selected_window);
477 1038
478 curs_x = col; 1039 /* Set the output cursor. */
479 curs_y = row; 1040 output_cursor.hpos = hpos;
1041 output_cursor.vpos = vpos;
1042 output_cursor.x = x;
1043 output_cursor.y = y;
480 1044
481 if (updating_frame == 0) 1045 /* If not called as part of an update, really display the cursor.
1046 This will also set the cursor position of W. */
1047 if (updated_window == NULL)
482 { 1048 {
483 BLOCK_INPUT; 1049 BLOCK_INPUT;
484 x_display_cursor (selected_frame, 1); 1050 x_display_cursor (w, 1, hpos, vpos, x, y);
485 UNBLOCK_INPUT; 1051 UNBLOCK_INPUT;
486 } 1052 }
487} 1053}
1054
1055
1056/***********************************************************************
1057 Display Iterator
1058 ***********************************************************************/
1059
1060/* Function prototypes of this page. */
1061
1062static struct face *x_get_glyph_face_and_encoding P_ ((struct frame *,
1063 struct glyph *,
1064 wchar_t *));
1065static struct face *x_get_char_face_and_encoding P_ ((struct frame *, int,
1066 int, wchar_t *, int));
1067static XCharStruct *w32_per_char_metric P_ ((HDC hdc, XFontStruct *,
1068 wchar_t *, int unicode_p));
1069static void x_encode_char P_ ((int, wchar_t *, struct font_info *));
1070static void x_append_glyph P_ ((struct it *));
1071static void x_append_composite_glyph P_ ((struct it *));
1072static void x_append_stretch_glyph P_ ((struct it *it, Lisp_Object,
1073 int, int, double));
1074static void x_produce_glyphs P_ ((struct it *));
1075static void x_produce_image_glyph P_ ((struct it *it));
1076
1077
1078/* Dealing with bits of wchar_t as if they were an XChar2B. */
1079#define BUILD_WCHAR_T(byte1, byte2) \
1080 ((wchar_t)((((byte1) & 0x00ff) << 8) | ((byte2) & 0x00ff)))
1081
1082
1083#define BYTE1(ch) \
1084 (((ch) & 0xff00) >> 8)
1085
1086#define BYTE2(ch) \
1087 ((ch) & 0x00ff)
1088
1089
1090/* Get metrics of character CHAR2B in FONT. Value is always non-null.
1091 If CHAR2B is not contained in FONT, the font's default character
1092 metric is returned. If unicode_p is non-zero, use unicode functions,
1093 otherwise use ANSI functions. */
1094
1095static INLINE XCharStruct *
1096w32_per_char_metric (hdc, font, char2b, unicode_p)
1097 HDC hdc;
1098 XFontStruct *font;
1099 wchar_t *char2b;
1100 int unicode_p;
1101{
1102 /* The result metric information. */
1103 XCharStruct *pcm;
1104 ABC char_widths;
1105 int char_total_width;
1106 BOOL retval;
1107
1108 xassert (font && char2b);
1109
1110 pcm = (XCharStruct *) xmalloc (sizeof (XCharStruct));
1111
1112 if (font->hfont)
1113 SelectObject (hdc, font->hfont);
1114
1115 if (unicode_p)
1116 retval = GetCharABCWidthsW (hdc, *char2b, *char2b, &char_widths);
1117 else
1118 retval = GetCharABCWidthsA (hdc, *char2b, *char2b, &char_widths);
1119
1120 if (retval)
1121 {
1122 pcm->width = char_widths.abcA + char_widths.abcB + char_widths.abcC;
1123 pcm->lbearing = char_widths.abcA;
1124 pcm->rbearing = pcm->width - char_widths.abcC;
1125 }
1126 else
1127 {
1128 if (unicode_p)
1129 retval = GetCharWidth32W (hdc, *char2b, *char2b, &char_total_width);
1130 else
1131 retval = GetCharWidth32A (hdc, *char2b, *char2b, &char_total_width);
1132
1133 if (retval)
1134 {
1135 pcm->width = char_total_width;
1136 pcm->rbearing = char_total_width;
1137 pcm->lbearing = 0;
1138 }
1139 else
1140 {
1141 pcm->width = FONT_MAX_WIDTH (font);
1142 pcm->rbearing = FONT_MAX_WIDTH (font);
1143 pcm->lbearing = 0;
1144 }
1145 }
1146
1147 pcm->ascent = FONT_BASE (font);
1148 pcm->descent = FONT_DESCENT (font);
1149
1150 return pcm;
1151}
1152
1153
1154/* Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
1155 the two-byte form of C. Encoding is returned in *CHAR2B. */
1156
1157static INLINE void
1158x_encode_char (c, char2b, font_info)
1159 int c;
1160 wchar_t *char2b;
1161 struct font_info *font_info;
1162{
1163 int charset = CHAR_CHARSET (c);
1164 int codepage;
1165 XFontStruct *font = font_info->font;
1166
1167 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
1168 This may be either a program in a special encoder language or a
1169 fixed encoding. */
1170 if (font_info->font_encoder)
1171 {
1172 /* It's a program. */
1173 struct ccl_program *ccl = font_info->font_encoder;
1174
1175 if (CHARSET_DIMENSION (charset) == 1)
1176 {
1177 ccl->reg[0] = charset;
1178 ccl->reg[1] = BYTE2 (*char2b);
1179 }
1180 else
1181 {
1182 ccl->reg[0] = charset;
1183 ccl->reg[1] = BYTE1 (*char2b);
1184 ccl->reg[2] = BYTE2 (*char2b);
1185 }
1186
1187 ccl_driver (ccl, NULL, NULL, 0, 0, NULL);
1188
1189 /* We assume that MSBs are appropriately set/reset by CCL
1190 program. */
1191 /* NTEMACS_TODO : Use GetFontLanguageInfo to determine if
1192 font is double byte. */
1193#if 0
1194 if (FONT_MAX_BYTE1 (font) == 0) /* 1-byte font */
1195#endif
1196 *char2b = BUILD_WCHAR_T (0, ccl->reg[1]);
1197#if 0
1198 else
1199 *char2b = BUILD_WCHAR_T (ccl->reg[1], ccl->reg[2]);
1200#endif
1201 }
1202 else if (font_info->encoding[charset])
1203 {
1204 /* Fixed encoding scheme. See fontset.h for the meaning of the
1205 encoding numbers. */
1206 int enc = font_info->encoding[charset];
1207
1208 if ((enc == 1 || enc == 2)
1209 && CHARSET_DIMENSION (charset) == 2)
1210 *char2b = BUILD_WCHAR_T (BYTE1 (*char2b) | 0x80, BYTE2 (*char2b));
1211
1212 if (enc == 1 || enc == 3
1213 || (enc == 4 && CHARSET_DIMENSION (charset) == 1))
1214 *char2b = BUILD_WCHAR_T (BYTE1 (*char2b), BYTE2 (*char2b) | 0x80);
1215 else if (enc == 4)
1216 {
1217 int sjis1, sjis2;
1218
1219 ENCODE_SJIS (BYTE1 (*char2b), BYTE2 (*char2b),
1220 sjis1, sjis2);
1221 *char2b = BUILD_WCHAR_T (sjis1, sjis2);
1222 }
1223 }
1224 codepage = w32_codepage_for_font (font_info->name);
1225
1226 /* If charset is not ASCII or Latin-1, may need to move it into
1227 Unicode space. */
1228 if ( font && !font->bdf && w32_use_unicode_for_codepage (codepage)
1229 && charset != CHARSET_ASCII && charset != charset_latin_iso8859_1)
1230 {
1231 char temp[3];
1232 temp[0] = BYTE1 (*char2b);
1233 temp[1] = BYTE2 (*char2b);
1234 temp[2] = '\0';
1235 if (temp[0])
1236 MultiByteToWideChar (codepage, 0, temp, 2, char2b, 1);
1237 else
1238 MultiByteToWideChar (codepage, 0, temp+1, 1, char2b, 1);
1239 }
1240}
1241
1242
1243/* Get face and two-byte form of character C in face FACE_ID on frame
1244 F. The encoding of C is returned in *CHAR2B. MULTIBYTE_P non-zero
1245 means we want to display multibyte text. Value is a pointer to a
1246 realized face that is ready for display. */
1247
1248static INLINE struct face *
1249x_get_char_face_and_encoding (f, c, face_id, char2b, multibyte_p)
1250 struct frame *f;
1251 int c, face_id;
1252 wchar_t *char2b;
1253 int multibyte_p;
1254{
1255 struct face *face = FACE_FROM_ID (f, face_id);
1256
1257 if (!multibyte_p)
1258 {
1259 /* Unibyte case. We don't have to encode, but we have to make
1260 sure to use a face suitable for unibyte. */
1261 *char2b = BUILD_WCHAR_T (0, c);
1262
1263 if (!FACE_SUITABLE_FOR_CHARSET_P (face, -1))
1264 {
1265 face_id = FACE_FOR_CHARSET (f, face_id, -1);
1266 face = FACE_FROM_ID (f, face_id);
1267 }
1268 }
1269 else if (c < 128 && face_id < BASIC_FACE_ID_SENTINEL)
1270 {
1271 /* Case of ASCII in a face known to fit ASCII. */
1272 *char2b = BUILD_WCHAR_T (0, c);
1273 }
1274 else
1275 {
1276 int c1, c2, charset;
1277
1278 /* Split characters into bytes. If c2 is -1 afterwards, C is
1279 really a one-byte character so that byte1 is zero. */
1280 SPLIT_CHAR (c, charset, c1, c2);
1281 if (c2 > 0)
1282 *char2b = BUILD_WCHAR_T (c1, c2);
1283 else
1284 *char2b = BUILD_WCHAR_T (0, c1);
1285
1286 /* Get the face for displaying C. If `face' is not suitable for
1287 charset, get the one that fits. (This can happen for the
1288 translations of a composition where the glyph
1289 specifies a face for the first component, but the other
1290 components have a different charset.) */
1291 if (!FACE_SUITABLE_FOR_CHARSET_P (face, charset))
1292 {
1293 face_id = FACE_FOR_CHARSET (f, face_id, charset);
1294 face = FACE_FROM_ID (f, face_id);
1295 }
1296
1297 /* Maybe encode the character in *CHAR2B. */
1298 if (charset != CHARSET_ASCII)
1299 {
1300 struct font_info *font_info
1301 = FONT_INFO_FROM_ID (f, face->font_info_id);
1302 if (font_info)
1303 {
1304 x_encode_char (c, char2b, font_info);
1305 if (charset == charset_latin_iso8859_1)
1306 *char2b = BUILD_WCHAR_T (BYTE1 (*char2b),
1307 BYTE2 (*char2b) | 0x80);
1308 }
1309 }
1310 }
1311
1312 /* Make sure X resources of the face are allocated. */
1313 xassert (face != NULL);
1314 PREPARE_FACE_FOR_DISPLAY (f, face);
1315
1316 return face;
1317}
1318
1319
1320/* Get face and two-byte form of character glyph GLYPH on frame F.
1321 The encoding of GLYPH->u.ch is returned in *CHAR2B. Value is
1322 a pointer to a realized face that is ready for display. */
1323
1324static INLINE struct face *
1325x_get_glyph_face_and_encoding (f, glyph, char2b)
1326 struct frame *f;
1327 struct glyph *glyph;
1328 wchar_t *char2b;
1329{
1330 struct face *face;
1331
1332 xassert (glyph->type == CHAR_GLYPH);
1333 face = FACE_FROM_ID (f, glyph->face_id);
1334
1335 if (!glyph->multibyte_p)
1336 {
1337 /* Unibyte case. We don't have to encode, but we have to make
1338 sure to use a face suitable for unibyte. */
1339 *char2b = BUILD_WCHAR_T (0, glyph->u.ch);
1340 }
1341 else if (glyph->u.ch < 128
1342 && glyph->face_id < BASIC_FACE_ID_SENTINEL)
1343 {
1344 /* Case of ASCII in a face known to fit ASCII. */
1345 *char2b = BUILD_WCHAR_T (0, glyph->u.ch);
1346 }
1347 else
1348 {
1349 int c1, c2, charset;
1350
1351 /* Split characters into bytes. If c2 is -1 afterwards, C is
1352 really a one-byte character so that byte1 is zero. */
1353 SPLIT_CHAR (glyph->u.ch, charset, c1, c2);
1354 if (c2 > 0)
1355 *char2b = BUILD_WCHAR_T (c1, c2);
1356 else
1357 *char2b = BUILD_WCHAR_T (0, c1);
1358
1359 /* Maybe encode the character in *CHAR2B. */
1360 if (charset != CHARSET_ASCII)
1361 {
1362 struct font_info *font_info
1363 = FONT_INFO_FROM_ID (f, face->font_info_id);
1364 if (font_info)
1365 {
1366 x_encode_char (glyph->u.ch, char2b, font_info);
1367 if (charset == charset_latin_iso8859_1)
1368 *char2b = BUILD_WCHAR_T (BYTE1 (*char2b),
1369 BYTE2 (*char2b) | 0x80);
1370 }
1371 }
1372 }
1373
1374 /* Make sure X resources of the face are allocated. */
1375 xassert (face != NULL);
1376 PREPARE_FACE_FOR_DISPLAY (f, face);
1377 return face;
1378}
1379
1380
1381/* Store one glyph for IT->char_to_display in IT->glyph_row.
1382 Called from x_produce_glyphs when IT->glyph_row is non-null. */
1383
1384static INLINE void
1385x_append_glyph (it)
1386 struct it *it;
1387{
1388 struct glyph *glyph;
1389 enum glyph_row_area area = it->area;
1390
1391 xassert (it->glyph_row);
1392 xassert (it->char_to_display != '\n' && it->char_to_display != '\t');
1393
1394 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1395 if (glyph < it->glyph_row->glyphs[area + 1])
1396 {
1397 /* Play it safe. If sub-structures of the glyph are not all the
1398 same size, it otherwise be that some bits stay set. This
1399 would prevent a comparison with GLYPH_EQUAL_P. */
1400 glyph->u.val = 0;
1401
1402 glyph->type = CHAR_GLYPH;
1403 glyph->pixel_width = it->pixel_width;
1404 glyph->u.ch = it->char_to_display;
1405 glyph->face_id = it->face_id;
1406 glyph->charpos = CHARPOS (it->position);
1407 glyph->object = it->object;
1408 glyph->left_box_line_p = it->start_of_box_run_p;
1409 glyph->right_box_line_p = it->end_of_box_run_p;
1410 glyph->voffset = it->voffset;
1411 glyph->multibyte_p = it->multibyte_p;
1412 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
1413 || it->phys_descent > it->descent);
1414 ++it->glyph_row->used[area];
1415 }
1416}
1417
1418/* Store one glyph for the composition IT->cmp_id in IT->glyph_row.
1419 Called from x_produce_glyphs when IT->glyph_row is non-null. */
1420
1421static INLINE void
1422x_append_composite_glyph (it)
1423 struct it *it;
1424{
1425 struct glyph *glyph;
1426 enum glyph_row_area area = it->area;
1427
1428 xassert (it->glyph_row);
1429
1430 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1431 if (glyph < it->glyph_row->glyphs[area + 1])
1432 {
1433 /* Play it safe. If sub-structures of the glyph are not all the
1434 same size, it otherwise be that some bits stay set. This
1435 would prevent a comparison with GLYPH_EQUAL_P. */
1436 glyph->u.val = 0;
1437
1438 glyph->type = COMPOSITE_GLYPH;
1439 glyph->pixel_width = it->pixel_width;
1440 glyph->u.cmp_id = it->cmp_id;
1441 glyph->face_id = it->face_id;
1442 glyph->charpos = CHARPOS (it->position);
1443 glyph->object = it->object;
1444 glyph->left_box_line_p = it->start_of_box_run_p;
1445 glyph->right_box_line_p = it->end_of_box_run_p;
1446 glyph->voffset = it->voffset;
1447 glyph->multibyte_p = it->multibyte_p;
1448 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
1449 || it->phys_descent > it->descent);
1450 ++it->glyph_row->used[area];
1451 }
1452}
1453
1454
1455/* Change IT->ascent and IT->height according to the setting of
1456 IT->voffset. */
1457
1458static INLINE void
1459take_vertical_position_into_account (it)
1460 struct it *it;
1461{
1462 if (it->voffset)
1463 {
1464 if (it->voffset < 0)
1465 /* Increase the ascent so that we can display the text higher
1466 in the line. */
1467 it->ascent += abs (it->voffset);
1468 else
1469 /* Increase the descent so that we can display the text lower
1470 in the line. */
1471 it->descent += it->voffset;
1472 }
1473}
1474
1475
1476/* Produce glyphs/get display metrics for the image IT is loaded with.
1477 See the description of struct display_iterator in dispextern.h for
1478 an overview of struct display_iterator. */
1479
1480static void
1481x_produce_image_glyph (it)
1482 struct it *it;
1483{
1484 struct image *img;
1485 struct face *face;
1486
1487 xassert (it->what == IT_IMAGE);
1488
1489 face = FACE_FROM_ID (it->f, it->face_id);
1490 img = IMAGE_FROM_ID (it->f, it->image_id);
1491 xassert (img);
1492
1493 /* Make sure X resources of the face and image are loaded. */
1494 PREPARE_FACE_FOR_DISPLAY (it->f, face);
1495 prepare_image_for_display (it->f, img);
1496
1497 it->ascent = it->phys_ascent = IMAGE_ASCENT (img);
1498 it->descent = it->phys_descent = img->height + 2 * img->margin - it->ascent;
1499 it->pixel_width = img->width + 2 * img->margin;
1500
1501 it->nglyphs = 1;
1502
1503 if (face->box != FACE_NO_BOX)
1504 {
1505 it->ascent += face->box_line_width;
1506 it->descent += face->box_line_width;
1507
1508 if (it->start_of_box_run_p)
1509 it->pixel_width += face->box_line_width;
1510 if (it->end_of_box_run_p)
1511 it->pixel_width += face->box_line_width;
1512 }
1513
1514 take_vertical_position_into_account (it);
1515
1516 if (it->glyph_row)
1517 {
1518 struct glyph *glyph;
1519 enum glyph_row_area area = it->area;
1520
1521 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1522 if (glyph < it->glyph_row->glyphs[area + 1])
1523 {
1524 glyph->type = IMAGE_GLYPH;
1525 glyph->u.img_id = img->id;
1526 glyph->face_id = it->face_id;
1527 glyph->pixel_width = it->pixel_width;
1528 glyph->charpos = CHARPOS (it->position);
1529 glyph->object = it->object;
1530 glyph->left_box_line_p = it->start_of_box_run_p;
1531 glyph->right_box_line_p = it->end_of_box_run_p;
1532 glyph->voffset = it->voffset;
1533 glyph->multibyte_p = it->multibyte_p;
1534 ++it->glyph_row->used[area];
1535 }
1536 }
1537}
1538
1539
1540/* Append a stretch glyph to IT->glyph_row. OBJECT is the source
1541 of the glyph, WIDTH and HEIGHT are the width and height of the
1542 stretch. ASCENT is the percentage/100 of HEIGHT to use for the
1543 ascent of the glyph (0 <= ASCENT <= 1). */
1544
1545static void
1546x_append_stretch_glyph (it, object, width, height, ascent)
1547 struct it *it;
1548 Lisp_Object object;
1549 int width, height;
1550 double ascent;
1551{
1552 struct glyph *glyph;
1553 enum glyph_row_area area = it->area;
1554
1555 xassert (ascent >= 0 && ascent <= 1);
1556
1557 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1558 if (glyph < it->glyph_row->glyphs[area + 1])
1559 {
1560 glyph->type = STRETCH_GLYPH;
1561 glyph->u.stretch.ascent = height * ascent;
1562 glyph->u.stretch.height = height;
1563 glyph->face_id = it->face_id;
1564 glyph->pixel_width = width;
1565 glyph->charpos = CHARPOS (it->position);
1566 glyph->object = object;
1567 glyph->left_box_line_p = it->start_of_box_run_p;
1568 glyph->right_box_line_p = it->end_of_box_run_p;
1569 glyph->voffset = it->voffset;
1570 glyph->multibyte_p = it->multibyte_p;
1571 ++it->glyph_row->used[area];
1572 }
1573}
1574
1575
1576/* Produce a stretch glyph for iterator IT. IT->object is the value
1577 of the glyph property displayed. The value must be a list
1578 `(space KEYWORD VALUE ...)' with the following KEYWORD/VALUE pairs
1579 being recognized:
1580
1581 1. `:width WIDTH' specifies that the space should be WIDTH *
1582 canonical char width wide. WIDTH may be an integer or floating
1583 point number.
1584
1585 2. `:relative-width FACTOR' specifies that the width of the stretch
1586 should be computed from the width of the first character having the
1587 `glyph' property, and should be FACTOR times that width.
1588
1589 3. `:align-to HPOS' specifies that the space should be wide enough
1590 to reach HPOS, a value in canonical character units.
1591
1592 Exactly one of the above pairs must be present.
1593
1594 4. `:height HEIGHT' specifies that the height of the stretch produced
1595 should be HEIGHT, measured in canonical character units.
1596
1597 5. `:relative-height FACTOR' specifies that the height of the the
1598 stretch should be FACTOR times the height of the characters having
1599 the glyph property.
1600
1601 Either none or exactly one of 4 or 5 must be present.
1602
1603 6. `:ascent ASCENT' specifies that ASCENT percent of the height
1604 of the stretch should be used for the ascent of the stretch.
1605 ASCENT must be in the range 0 <= ASCENT <= 100. */
1606
1607#define NUMVAL(X) \
1608 ((INTEGERP (X) || FLOATP (X)) \
1609 ? XFLOATINT (X) \
1610 : - 1)
1611
1612
1613static void
1614x_produce_stretch_glyph (it)
1615 struct it *it;
1616{
1617 /* (space :width WIDTH :height HEIGHT. */
1618 extern Lisp_Object QCwidth, QCheight, QCascent, Qspace;
1619 extern Lisp_Object QCrelative_width, QCrelative_height;
1620 extern Lisp_Object QCalign_to;
1621 Lisp_Object prop, plist;
1622 double width = 0, height = 0, ascent = 0;
1623 struct face *face = FACE_FROM_ID (it->f, it->face_id);
1624 XFontStruct *font = face->font ? face->font : FRAME_FONT (it->f);
1625
1626 PREPARE_FACE_FOR_DISPLAY (it->f, face);
1627
1628 /* List should start with `space'. */
1629 xassert (CONSP (it->object) && EQ (XCAR (it->object), Qspace));
1630 plist = XCDR (it->object);
1631
1632 /* Compute the width of the stretch. */
1633 if (prop = Fplist_get (plist, QCwidth),
1634 NUMVAL (prop) > 0)
1635 /* Absolute width `:width WIDTH' specified and valid. */
1636 width = NUMVAL (prop) * CANON_X_UNIT (it->f);
1637 else if (prop = Fplist_get (plist, QCrelative_width),
1638 NUMVAL (prop) > 0)
1639 {
1640 /* Relative width `:relative-width FACTOR' specified and valid.
1641 Compute the width of the characters having the `glyph'
1642 property. */
1643 struct it it2;
1644 unsigned char *p = BYTE_POS_ADDR (IT_BYTEPOS (*it));
1645
1646 it2 = *it;
1647 if (it->multibyte_p)
1648 {
1649 int maxlen = ((IT_BYTEPOS (*it) >= GPT ? ZV : GPT)
1650 - IT_BYTEPOS (*it));
1651 it2.c = STRING_CHAR_AND_LENGTH (p, maxlen, it2.len);
1652 }
1653 else
1654 it2.c = *p, it2.len = 1;
1655
1656 it2.glyph_row = NULL;
1657 it2.what = IT_CHARACTER;
1658 x_produce_glyphs (&it2);
1659 width = NUMVAL (prop) * it2.pixel_width;
1660 }
1661 else if (prop = Fplist_get (plist, QCalign_to),
1662 NUMVAL (prop) > 0)
1663 width = NUMVAL (prop) * CANON_X_UNIT (it->f) - it->current_x;
1664 else
1665 /* Nothing specified -> width defaults to canonical char width. */
1666 width = CANON_X_UNIT (it->f);
1667
1668 /* Compute height. */
1669 if (prop = Fplist_get (plist, QCheight),
1670 NUMVAL (prop) > 0)
1671 height = NUMVAL (prop) * CANON_Y_UNIT (it->f);
1672 else if (prop = Fplist_get (plist, QCrelative_height),
1673 NUMVAL (prop) > 0)
1674 height = FONT_HEIGHT (font) * NUMVAL (prop);
1675 else
1676 height = FONT_HEIGHT (font);
1677
1678 /* Compute percentage of height used for ascent. If
1679 `:ascent ASCENT' is present and valid, use that. Otherwise,
1680 derive the ascent from the font in use. */
1681 if (prop = Fplist_get (plist, QCascent),
1682 NUMVAL (prop) > 0 && NUMVAL (prop) <= 100)
1683 ascent = NUMVAL (prop) / 100.0;
1684 else
1685 ascent = (double) FONT_BASE (font) / FONT_HEIGHT (font);
1686
1687 if (width <= 0)
1688 width = 1;
1689 if (height <= 0)
1690 height = 1;
1691
1692 if (it->glyph_row)
1693 {
1694 Lisp_Object object = it->stack[it->sp - 1].string;
1695 if (!STRINGP (object))
1696 object = it->w->buffer;
1697 x_append_stretch_glyph (it, object, width, height, ascent);
1698 }
1699
1700 it->pixel_width = width;
1701 it->ascent = it->phys_ascent = height * ascent;
1702 it->descent = it->phys_descent = height - it->ascent;
1703 it->nglyphs = 1;
1704
1705 if (face->box != FACE_NO_BOX)
1706 {
1707 it->ascent += face->box_line_width;
1708 it->descent += face->box_line_width;
1709
1710 if (it->start_of_box_run_p)
1711 it->pixel_width += face->box_line_width;
1712 if (it->end_of_box_run_p)
1713 it->pixel_width += face->box_line_width;
1714 }
1715
1716 take_vertical_position_into_account (it);
1717}
1718
1719/* Return proper value to be used as baseline offset of font that has
1720 ASCENT and DESCENT to draw characters by the font at the vertical
1721 center of the line of frame F.
1722
1723 Here, out task is to find the value of BOFF in the following figure;
1724
1725 -------------------------+-----------+-
1726 -+-+---------+-+ | |
1727 | | | | | |
1728 | | | | F_ASCENT F_HEIGHT
1729 | | | ASCENT | |
1730 HEIGHT | | | | |
1731 | | |-|-+------+-----------|------- baseline
1732 | | | | BOFF | |
1733 | |---------|-+-+ | |
1734 | | | DESCENT | |
1735 -+-+---------+-+ F_DESCENT |
1736 -------------------------+-----------+-
1737
1738 -BOFF + DESCENT + (F_HEIGHT - HEIGHT) / 2 = F_DESCENT
1739 BOFF = DESCENT + (F_HEIGHT - HEIGHT) / 2 - F_DESCENT
1740 DESCENT = FONT->descent
1741 HEIGHT = FONT_HEIGHT (FONT)
1742 F_DESCENT = (F->output_data.x->font->descent
1743 - F->output_data.x->baseline_offset)
1744 F_HEIGHT = FRAME_LINE_HEIGHT (F)
1745*/
1746
1747#define VCENTER_BASELINE_OFFSET(FONT, F) \
1748 (FONT_DESCENT (FONT) \
1749 + (FRAME_LINE_HEIGHT ((F)) - FONT_HEIGHT ((FONT))) / 2 \
1750 - (FONT_DESCENT (FRAME_FONT (F)) - FRAME_BASELINE_OFFSET (F)))
1751
1752/* Produce glyphs/get display metrics for the display element IT is
1753 loaded with. See the description of struct display_iterator in
1754 dispextern.h for an overview of struct display_iterator. */
1755
1756static void
1757x_produce_glyphs (it)
1758 struct it *it;
1759{
1760 if (it->what == IT_CHARACTER)
1761 {
1762 wchar_t char2b;
1763 XFontStruct *font;
1764 struct face *face;
1765 XCharStruct *pcm;
1766 int font_not_found_p;
1767 struct font_info *font_info;
1768 int boff; /* baseline offset */
1769 HDC hdc;
1770
1771 hdc = get_frame_dc (it->f);
1772
1773 /* Maybe translate single-byte characters to multibyte. */
1774 it->char_to_display = it->c;
1775 if (unibyte_display_via_language_environment
1776 && SINGLE_BYTE_CHAR_P (it->c)
1777 && (it->c >= 0240
1778 || (it->c >= 0200
1779 && !NILP (Vnonascii_translation_table))))
1780 {
1781 it->char_to_display = unibyte_char_to_multibyte (it->c);
1782 it->charset = CHAR_CHARSET (it->char_to_display);
1783 }
1784
1785 /* Get face and font to use. Encode IT->char_to_display. */
1786 face = x_get_char_face_and_encoding (it->f, it->char_to_display,
1787 it->face_id, &char2b,
1788 it->multibyte_p);
1789 font = face->font;
1790
1791 /* When no suitable font found, use the default font. */
1792 font_not_found_p = font == NULL;
1793 if (font_not_found_p)
1794 {
1795 font = FRAME_FONT (it->f);
1796 boff = it->f->output_data.w32->baseline_offset;
1797 font_info = NULL;
1798 }
1799 else
1800 {
1801 font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
1802 boff = font_info->baseline_offset;
1803 if (font_info->vertical_centering)
1804 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
1805 }
1806
1807 if (font->hfont)
1808 SelectObject (hdc, font->hfont);
1809
1810 if (it->char_to_display >= ' '
1811 && (!it->multibyte_p || it->char_to_display < 128))
1812 {
1813 /* Either unibyte or ASCII. */
1814 int stretched_p;
1815
1816 it->nglyphs = 1;
1817
1818 pcm = w32_per_char_metric (hdc, font, &char2b, 0);
1819 it->ascent = FONT_BASE (font) + boff;
1820 it->descent = FONT_DESCENT (font) - boff;
1821 it->phys_ascent = pcm->ascent + boff;
1822 it->phys_descent = pcm->descent - boff;
1823 it->pixel_width = pcm->width;
1824
1825 /* If this is a space inside a region of text with
1826 `space-width' property, change its width. */
1827 stretched_p = it->char_to_display == ' ' && !NILP (it->space_width);
1828 if (stretched_p)
1829 it->pixel_width *= XFLOATINT (it->space_width);
1830
1831 /* If face has a box, add the box thickness to the character
1832 height. If character has a box line to the left and/or
1833 right, add the box line width to the character's width. */
1834 if (face->box != FACE_NO_BOX)
1835 {
1836 int thick = face->box_line_width;
1837
1838 it->ascent += thick;
1839 it->descent += thick;
1840
1841 if (it->start_of_box_run_p)
1842 it->pixel_width += thick;
1843 if (it->end_of_box_run_p)
1844 it->pixel_width += thick;
1845 }
1846
1847 /* If face has an overline, add the height of the overline
1848 (1 pixel) and a 1 pixel margin to the character height. */
1849 if (face->overline_p)
1850 it->ascent += 2;
1851
1852 take_vertical_position_into_account (it);
1853
1854 /* If we have to actually produce glyphs, do it. */
1855 if (it->glyph_row)
1856 {
1857 if (stretched_p)
1858 {
1859 /* Translate a space with a `space-width' property
1860 into a stretch glyph. */
1861 double ascent = (double) FONT_BASE (font)
1862 / FONT_HEIGHT (font);
1863 x_append_stretch_glyph (it, it->object, it->pixel_width,
1864 it->ascent + it->descent, ascent);
1865 }
1866 else
1867 x_append_glyph (it);
1868
1869 /* If characters with lbearing or rbearing are displayed
1870 in this line, record that fact in a flag of the
1871 glyph row. This is used to optimize X output code. */
1872 if (pcm->lbearing < 0
1873 || pcm->rbearing > pcm->width)
1874 it->glyph_row->contains_overlapping_glyphs_p = 1;
1875 }
1876 }
1877 else if (it->char_to_display == '\n')
1878 {
1879 /* A newline has no width but we need the height of the line. */
1880 it->pixel_width = 0;
1881 it->nglyphs = 0;
1882 it->ascent = it->phys_ascent = FONT_BASE (font) + boff;
1883 it->descent = it->phys_descent = FONT_DESCENT (font) - boff;
1884
1885 if (face->box != FACE_NO_BOX)
1886 {
1887 int thick = face->box_line_width;
1888 it->ascent += thick;
1889 it->descent += thick;
1890 }
1891 }
1892 else if (it->char_to_display == '\t')
1893 {
1894 int tab_width = it->tab_width * CANON_X_UNIT (it->f);
1895 int x = (it->current_x
1896 - it->prompt_width
1897 + it->continuation_lines_width);
1898 int next_tab_x = ((1 + x + tab_width - 1) / tab_width) * tab_width;
1899
1900 it->pixel_width = next_tab_x - x;
1901 it->nglyphs = 1;
1902 it->ascent = it->phys_ascent = FONT_BASE (font) + boff;
1903 it->descent = it->phys_descent = FONT_DESCENT (font) - boff;
1904
1905 if (it->glyph_row)
1906 {
1907 double ascent = (double) it->ascent / (it->ascent + it->descent);
1908 x_append_stretch_glyph (it, it->object, it->pixel_width,
1909 it->ascent + it->descent, ascent);
1910 }
1911 }
1912 else
1913 {
1914 /* A multi-byte character. Assume that the display width of the
1915 character is the width of the character multiplied by the
1916 width of the font. */
1917
1918 /* If we found a font, this font should give us the right
1919 metrics. If we didn't find a font, use the frame's
1920 default font and calculate the width of the character
1921 from the charset width; this is what old redisplay code
1922 did. */
1923 pcm = w32_per_char_metric (hdc, font, &char2b, 1);
1924 it->pixel_width = pcm->width;
1925 if (font_not_found_p)
1926 it->pixel_width *= CHARSET_WIDTH (it->charset);
1927 it->nglyphs = 1;
1928 it->ascent = FONT_BASE (font) + boff;
1929 it->descent = FONT_DESCENT (font) - boff;
1930 it->phys_ascent = pcm->ascent + boff;
1931 it->phys_descent = pcm->descent - boff;
1932 if (it->glyph_row
1933 && (pcm->lbearing < 0
1934 || pcm->rbearing > pcm->width))
1935 it->glyph_row->contains_overlapping_glyphs_p = 1;
1936
1937 if (face->box != FACE_NO_BOX)
1938 {
1939 int thick = face->box_line_width;
1940 it->ascent += thick;
1941 it->descent += thick;
1942
1943 if (it->start_of_box_run_p)
1944 it->pixel_width += thick;
1945 if (it->end_of_box_run_p)
1946 it->pixel_width += thick;
1947 }
1948
1949 /* If face has an overline, add the height of the overline
1950 (1 pixel) and a 1 pixel margin to the character height. */
1951 if (face->overline_p)
1952 it->ascent += 2;
1953
1954 take_vertical_position_into_account (it);
1955
1956 if (it->glyph_row)
1957 x_append_glyph (it);
1958 }
1959 release_frame_dc (it->f, hdc);
1960 }
1961 else if (it->what == IT_COMPOSITION)
1962 {
1963#if 0 /* NTEMACS_TODO: Composite glyphs. */
1964 /* Note: A composition is represented as one glyph in the
1965 glyph matrix. There are no padding glyphs. */
1966 XChar2b char2b;
1967 XFontStruct *font;
1968 struct face *face;
1969 XCharStruct *pcm;
1970 int font_not_found_p;
1971 struct font_info *font_info;
1972 int boff; /* baseline offset */
1973 struct composition *cmp = composition_table[it->cmp_id];
1974
1975 /* Maybe translate single-byte characters to multibyte. */
1976 it->char_to_display = it->c;
1977 if (unibyte_display_via_language_environment
1978 && SINGLE_BYTE_CHAR_P (it->c)
1979 && (it->c >= 0240
1980 || (it->c >= 0200
1981 && !NILP (Vnonascii_translation_table))))
1982 {
1983 it->char_to_display = unibyte_char_to_multibyte (it->c);
1984 it->charset = CHAR_CHARSET (it->char_to_display);
1985 }
1986
1987 /* Get face and font to use. Encode IT->char_to_display. */
1988 face = x_get_char_face_and_encoding (it->f, it->char_to_display,
1989 it->face_id, &char2b,
1990 it->multibyte_p);
1991 font = face->font;
1992
1993 /* When no suitable font found, use the default font. */
1994 font_not_found_p = font == NULL;
1995 if (font_not_found_p)
1996 {
1997 font = FRAME_FONT (it->f);
1998 boff = it->f->output_data.x->baseline_offset;
1999 font_info = NULL;
2000 }
2001 else
2002 {
2003 font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
2004 boff = font_info->baseline_offset;
2005 if (font_info->vertical_centering)
2006 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
2007 }
2008
2009 /* There are no padding glyphs, so there is only one glyph to
2010 produce for the composition. Important is that pixel_width,
2011 ascent and descent are the values of what is drawn by
2012 draw_glyphs (i.e. the values of the overall glyphs composed). */
2013 it->nglyphs = 1;
2014
2015 /* If we have not yet calculated pixel size data of glyphs of
2016 the composition for the current face font, calculate them
2017 now. Theoretically, we have to check all fonts for the
2018 glyphs, but that requires much time and memory space. So,
2019 here we check only the font of the first glyph. This leads
2020 to incorrect display very rarely, and C-l (recenter) can
2021 correct the display anyway. */
2022 if (cmp->font != (void *) font)
2023 {
2024 /* Ascent and descent of the font of the first character of
2025 this composition (adjusted by baseline offset). Ascent
2026 and descent of overall glyphs should not be less than
2027 them respectively. */
2028 int font_ascent = font->ascent + boff;
2029 int font_descent = font->descent - boff;
2030 /* Bounding box of the overall glyphs. */
2031 int leftmost, rightmost, lowest, highest;
2032 int i;
2033
2034 cmp->font = (void *) font;
2035
2036 /* Initialize the bounding box. */
2037 pcm = x_per_char_metric (font, &char2b);
2038 leftmost = 0;
2039 rightmost = pcm->width;
2040 lowest = - pcm->descent + boff;
2041 highest = pcm->ascent + boff;
2042 if (font_info
2043 && font_info->default_ascent
2044 && CHAR_TABLE_P (Vuse_default_ascent)
2045 && !NILP (Faref (Vuse_default_ascent,
2046 make_number (it->char_to_display))))
2047 highest = font_info->default_ascent + boff;
2048
2049 /* Draw the first glyph at the normal position. It may be
2050 shifted to right later if some other glyphs are drawn at
2051 the left. */
2052 cmp->offsets[0] = 0;
2053 cmp->offsets[1] = boff;
2054
2055 /* Set cmp->offsets for the remaining glyphs. */
2056 for (i = 1; i < cmp->glyph_len; i++)
2057 {
2058 int left, right, btm, top;
2059 int ch = COMPOSITION_GLYPH (cmp, i);
2060
2061 face = x_get_char_face_and_encoding (it->f, ch,
2062 it->face_id, &char2b,
2063 it->multibyte_p);
2064 font = face->font;
2065 if (font == NULL)
2066 {
2067 font = FRAME_FONT (it->f);
2068 boff = it->f->output_data.x->baseline_offset;
2069 font_info = NULL;
2070 }
2071 else
2072 {
2073 font_info
2074 = FONT_INFO_FROM_ID (it->f, face->font_info_id);
2075 boff = font_info->baseline_offset;
2076 if (font_info->vertical_centering)
2077 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
2078 }
2079
2080 pcm = x_per_char_metric (font, &char2b);
2081
2082 if (cmp->method != COMPOSITION_WITH_RULE_ALTCHARS)
2083 {
2084 /* Relative composition with or without
2085 alternate chars. */
2086 left = (leftmost + rightmost - pcm->width) / 2;
2087 btm = - pcm->descent + boff;
2088 if (font_info && font_info->relative_compose
2089 && (! CHAR_TABLE_P (Vignore_relative_composition)
2090 || NILP (Faref (Vignore_relative_composition,
2091 make_number (ch)))))
2092 {
2093
2094 if (- pcm->descent
2095 >= font_info->relative_compose)
2096 /* One extra pixel between two glyphs. */
2097 btm = highest + 1;
2098 else if (pcm->ascent <= 0)
2099 /* One extra pixel between two glyphs. */
2100 btm = lowest - 1 - pcm->ascent - pcm->descent;
2101 }
2102 }
2103 else
2104 {
2105 /* A composition rule is specified by an integer
2106 value that encodes global and new reference
2107 points (GREF and NREF). GREF and NREF are
2108 specified by numbers as below:
2109
2110 0---1---2 -- ascent
2111 | |
2112 | |
2113 | |
2114 9--10--11 -- center
2115 | |
2116 ---3---4---5--- baseline
2117 | |
2118 6---7---8 -- descent
2119 */
2120 int rule = COMPOSITION_RULE (cmp, i);
2121 int gref, nref, grefx, grefy, nrefx, nrefy;
2122
2123 COMPOSITION_DECODE_RULE (rule, gref, nref);
2124 grefx = gref % 3, nrefx = nref % 3;
2125 grefy = gref / 3, nrefy = nref / 3;
2126
2127 left = (leftmost
2128 + grefx * (rightmost - leftmost) / 2
2129 - nrefx * pcm->width / 2);
2130 btm = ((grefy == 0 ? highest
2131 : grefy == 1 ? 0
2132 : grefy == 2 ? lowest
2133 : (highest + lowest) / 2)
2134 - (nrefy == 0 ? pcm->ascent + pcm->descent
2135 : nrefy == 1 ? pcm->descent - boff
2136 : nrefy == 2 ? 0
2137 : (pcm->ascent + pcm->descent) / 2));
2138 }
2139
2140 cmp->offsets[i * 2] = left;
2141 cmp->offsets[i * 2 + 1] = btm + pcm->descent;
2142
2143 /* Update the bounding box of the overall glyphs. */
2144 right = left + pcm->width;
2145 top = btm + pcm->descent + pcm->ascent;
2146 if (left < leftmost)
2147 leftmost = left;
2148 if (right > rightmost)
2149 rightmost = right;
2150 if (top > highest)
2151 highest = top;
2152 if (btm < lowest)
2153 lowest = btm;
2154 }
2155
2156 /* If there are glyphs whose x-offsets are negative,
2157 shift all glyphs to the right and make all x-offsets
2158 non-negative. */
2159 if (leftmost < 0)
2160 {
2161 for (i = 0; i < cmp->glyph_len; i++)
2162 cmp->offsets[i * 2] -= leftmost;
2163 rightmost -= leftmost;
2164 }
2165
2166 cmp->pixel_width = rightmost;
2167 cmp->ascent = highest;
2168 cmp->descent = - lowest;
2169 if (cmp->ascent < font_ascent)
2170 cmp->ascent = font_ascent;
2171 if (cmp->descent < font_descent)
2172 cmp->descent = font_descent;
2173 }
2174
2175 it->pixel_width = cmp->pixel_width;
2176 it->ascent = it->phys_ascent = cmp->ascent;
2177 it->descent = it->phys_descent = cmp->descent;
2178
2179 if (face->box != FACE_NO_BOX)
2180 {
2181 int thick = face->box_line_width;
2182 it->ascent += thick;
2183 it->descent += thick;
2184
2185 if (it->start_of_box_run_p)
2186 it->pixel_width += thick;
2187 if (it->end_of_box_run_p)
2188 it->pixel_width += thick;
2189 }
2190
2191 /* If face has an overline, add the height of the overline
2192 (1 pixel) and a 1 pixel margin to the character height. */
2193 if (face->overline_p)
2194 it->ascent += 2;
2195
2196 take_vertical_position_into_account (it);
2197
2198 if (it->glyph_row)
2199 x_append_composite_glyph (it);
2200#endif
2201 }
2202 else if (it->what == IT_IMAGE)
2203 x_produce_image_glyph (it);
2204 else if (it->what == IT_STRETCH)
2205 x_produce_stretch_glyph (it);
2206
2207 /* Accumulate dimensions. */
2208 xassert (it->ascent >= 0 && it->descent > 0);
2209 if (it->area == TEXT_AREA)
2210 it->current_x += it->pixel_width;
2211
2212 it->max_ascent = max (it->max_ascent, it->ascent);
2213 it->max_descent = max (it->max_descent, it->descent);
2214 it->max_phys_ascent = max (it->max_phys_ascent, it->phys_ascent);
2215 it->max_phys_descent = max (it->max_phys_descent, it->phys_descent);
2216}
2217
2218
2219/* Estimate the pixel height of the mode or top line on frame F.
2220 FACE_ID specifies what line's height to estimate. */
2221
2222int
2223x_estimate_mode_line_height (f, face_id)
2224 struct frame *f;
2225 enum face_id face_id;
2226{
2227 int height = 1;
2228
2229 /* This function is called so early when Emacs starts that the face
2230 cache and mode line face are not yet initialized. */
2231 if (FRAME_FACE_CACHE (f))
2232 {
2233 struct face *face = FACE_FROM_ID (f, face_id);
2234 if (face)
2235 height = FONT_HEIGHT (face->font) + 2 * face->box_line_width;
2236 }
2237
2238 return height;
2239}
2240
488 2241
489/* Get the Windows codepage corresponding to the specified font. The 2242/* Get the Windows codepage corresponding to the specified font. The
490 charset info in the font name is used to look up 2243 charset info in the font name is used to look up
@@ -526,879 +2279,2644 @@ w32_codepage_for_font (char *fontname)
526 2279
527BOOL 2280BOOL
528w32_use_unicode_for_codepage (codepage) 2281w32_use_unicode_for_codepage (codepage)
2282 int codepage;
529{ 2283{
530 /* If the current codepage is supported, use Unicode for output. */ 2284 /* If the current codepage is supported, use Unicode for output. */
531 return (w32_enable_unicode_output 2285 return (w32_enable_unicode_output
532 && codepage != CP_DEFAULT && IsValidCodePage (codepage)); 2286 && codepage != CP_DEFAULT && IsValidCodePage (codepage));
533} 2287}
534 2288
535/* Dealing with bits of wchar_t as if they were an XChar2B. */ 2289
536#define BUILD_WCHAR_T(byte1, byte2) \ 2290/***********************************************************************
537 ((wchar_t)(((byte1 & 0x00ff) << 8) | (byte2 & 0x00ff))) 2291 Glyph display
2292 ***********************************************************************/
538 2293
2294/* A sequence of glyphs to be drawn in the same face.
539 2295
540#define BYTE1(ch) \ 2296 This data structure is not really completely X specific, so it
541 ((ch & 0xff00) >> 8) 2297 could possibly, at least partially, be useful for other systems. It
2298 is currently not part of the external redisplay interface because
2299 it's not clear what other systems will need. */
542 2300
543#define BYTE2(ch) \ 2301struct glyph_string
544 (ch & 0x00ff) 2302{
545 2303 /* X-origin of the string. */
546#define W32_TEXTOUT(start_offset,nchars) \ 2304 int x;
547{ \ 2305
548 int charset_dim = CHARSET_DIMENSION(charset); \ 2306 /* Y-origin and y-position of the base line of this string. */
549 if (font->bdf) \ 2307 int y, ybase;
550 w32_BDF_TextOut (font->bdf, hdc, left + xoffset, \ 2308
551 top + yoffset, \ 2309 /* The width of the string, not including a face extension. */
552 x_1byte_buffer + start_offset, \ 2310 int width;
553 charset_dim, nchars, 0); \ 2311
554 else if (print_via_unicode) \ 2312 /* The width of the string, including a face extension. */
555 ExtTextOutW (hdc, left + xoffset, top + yoffset, \ 2313 int background_width;
556 fuOptions, clip_region, \ 2314
557 x_2byte_buffer + start_offset, nchars, NULL); \ 2315 /* The height of this string. This is the height of the line this
558 else \ 2316 string is drawn in, and can be different from the height of the
559 ExtTextOut (hdc, left + xoffset, top + yoffset, \ 2317 font the string is drawn in. */
560 fuOptions, clip_region, \ 2318 int height;
561 x_1byte_buffer + start_offset, \ 2319
562 nchars * charset_dim, NULL); \ 2320 /* Number of pixels this string overwrites in front of its x-origin.
563 start_offset += nchars * (print_via_unicode ? 1 : charset_dim ); \ 2321 This number is zero if the string has an lbearing >= 0; it is
564 xoffset += nchars * glyph_width; \ 2322 -lbearing, if the string has an lbearing < 0. */
2323 int left_overhang;
2324
2325 /* Number of pixels this string overwrites past its right-most
2326 nominal x-position, i.e. x + width. Zero if the string's
2327 rbearing is <= its nominal width, rbearing - width otherwise. */
2328 int right_overhang;
2329
2330 /* The frame on which the glyph string is drawn. */
2331 struct frame *f;
2332
2333 /* The window on which the glyph string is drawn. */
2334 struct window *w;
2335
2336 /* X display and window for convenience. */
2337 Window window;
2338
2339 /* The glyph row for which this string was built. It determines the
2340 y-origin and height of the string. */
2341 struct glyph_row *row;
2342
2343 /* The area within row. */
2344 enum glyph_row_area area;
2345
2346 /* Characters to be drawn, and number of characters. */
2347 wchar_t *char2b;
2348 int nchars;
2349
2350 /* Character set of this glyph string. */
2351 int charset;
2352
2353 /* A face-override for drawing cursors, mouse face and similar. */
2354 enum draw_glyphs_face hl;
2355
2356 /* Face in which this string is to be drawn. */
2357 struct face *face;
2358
2359 /* Font in which this string is to be drawn. */
2360 XFontStruct *font;
2361
2362 /* Font info for this string. */
2363 struct font_info *font_info;
2364
2365 /* Non-null means this string describes (part of) a composition.
2366 All characters from char2b are drawn composed. */
2367 struct composition *cmp;
2368
2369 /* Index of this glyph string's first character in the glyph
2370 definition of CMP. If this is zero, this glyph string describes
2371 the first character of a composition. */
2372 int gidx;
2373
2374 /* 1 means this glyph strings face has to be drawn to the right end
2375 of the window's drawing area. */
2376 unsigned extends_to_end_of_line_p : 1;
2377
2378 /* 1 means the background of this string has been drawn. */
2379 unsigned background_filled_p : 1;
2380
2381 /* 1 means glyph string must be drawn with 16-bit functions. */
2382 unsigned two_byte_p : 1;
2383
2384 /* 1 means that the original font determined for drawing this glyph
2385 string could not be loaded. The member `font' has been set to
2386 the frame's default font in this case. */
2387 unsigned font_not_found_p : 1;
2388
2389 /* 1 means that the face in which this glyph string is drawn has a
2390 stipple pattern. */
2391 unsigned stippled_p : 1;
2392
2393 /* 1 means only the foreground of this glyph string must be drawn,
2394 and we should use the physical height of the line this glyph
2395 string appears in as clip rect. */
2396 unsigned for_overlaps_p : 1;
2397
2398 /* The GC to use for drawing this glyph string. */
2399 XGCValues *gc;
2400
2401 HDC hdc;
2402
2403 /* A pointer to the first glyph in the string. This glyph
2404 corresponds to char2b[0]. Needed to draw rectangles if
2405 font_not_found_p is 1. */
2406 struct glyph *first_glyph;
2407
2408 /* Image, if any. */
2409 struct image *img;
2410
2411 struct glyph_string *next, *prev;
2412};
2413
2414
2415/* Encapsulate the different ways of printing text under W32. */
2416
2417void W32_TEXTOUT(s, x, y,chars,nchars)
2418 struct glyph_string * s;
2419 int x, y;
2420 wchar_t * chars;
2421 int nchars;
2422{
2423 int charset_dim = CHARSET_DIMENSION (s->charset);
2424
2425 if (s->gc->font->bdf)
2426 w32_BDF_TextOut (s->gc->font->bdf, s->hdc,
2427 x, y, (char *) chars, charset_dim, nchars, 0);
2428 else if (s->two_byte_p)
2429 ExtTextOutW (s->hdc, x, y, 0, NULL, chars, nchars, NULL);
2430 else
2431 ExtTextOut (s->hdc, x, y, 0, NULL, (char *) chars,
2432 nchars * charset_dim, NULL);
565} 2433}
566
567/* Display a sequence of N glyphs found at GP.
568 WINDOW is the window to output to. LEFT and TOP are starting coords.
569 HL is 1 if this text is highlighted, 2 if the cursor is on it,
570 3 if should appear in its mouse-face.
571 JUST_FOREGROUND if 1 means draw only the foreground;
572 don't alter the background.
573
574 FONT is the default font to use (for glyphs whose font-code is 0).
575
576 Since the display generation code is responsible for calling
577 compute_char_face and compute_glyph_face on everything it puts in
578 the display structure, we can assume that the face code on each
579 glyph is a valid index into FRAME_COMPUTED_FACES (f), and the one
580 to which we can actually apply intern_face.
581 Call this function with input blocked. */
582 2434
583static int 2435#if 0
584dumpglyphs (f, left, top, gp, n, hl, just_foreground, cmpcharp)
585 struct frame *f;
586 int left, top;
587 register GLYPH *gp; /* Points to first GLYPH. */
588 register int n; /* Number of glyphs to display. */
589 int hl;
590 int just_foreground;
591 struct cmpchar_info *cmpcharp;
592{
593 wchar_t *x_2byte_buffer
594 = (wchar_t *) alloca (FRAME_WINDOW_WIDTH (f) * sizeof (*x_2byte_buffer));
595 register wchar_t *cp; /* Steps through x_2byte_buffer[]. */
596
597 /* Allocate double the window width, as this buffer may contain MBCS
598 characters under w32. Unsigned to let GetCharABCWidths work. */
599 unsigned char *x_1byte_buffer
600 = (unsigned char *) alloca (2 * FRAME_WINDOW_WIDTH (f)
601 * sizeof (*x_1byte_buffer));
602 register unsigned char *bp; /* Steps through x_1byte_buffer[]. */
603 register int tlen = GLYPH_TABLE_LENGTH;
604 register Lisp_Object *tbase = GLYPH_TABLE_BASE;
605 Window window = FRAME_W32_WINDOW (f);
606 HDC hdc = get_frame_dc (f);
607 int orig_left = left;
608 int gidx = 0;
609 int i;
610 2436
611 while (n > 0) 2437static void
2438x_dump_glyph_string (s)
2439 struct glyph_string *s;
2440{
2441 fprintf (stderr, "glyph string\n");
2442 fprintf (stderr, " x, y, w, h = %d, %d, %d, %d\n",
2443 s->x, s->y, s->width, s->height);
2444 fprintf (stderr, " ybase = %d\n", s->ybase);
2445 fprintf (stderr, " hl = %d\n", s->hl);
2446 fprintf (stderr, " left overhang = %d, right = %d\n",
2447 s->left_overhang, s->right_overhang);
2448 fprintf (stderr, " nchars = %d\n", s->nchars);
2449 fprintf (stderr, " extends to end of line = %d\n",
2450 s->extends_to_end_of_line_p);
2451 fprintf (stderr, " font height = %d\n", FONT_HEIGHT (s->font));
2452 fprintf (stderr, " bg width = %d\n", s->background_width);
2453}
2454
2455#endif /* GLYPH_DEBUG */
2456
2457
2458
2459static void x_append_glyph_string_lists P_ ((struct glyph_string **,
2460 struct glyph_string **,
2461 struct glyph_string *,
2462 struct glyph_string *));
2463static void x_prepend_glyph_string_lists P_ ((struct glyph_string **,
2464 struct glyph_string **,
2465 struct glyph_string *,
2466 struct glyph_string *));
2467static void x_append_glyph_string P_ ((struct glyph_string **,
2468 struct glyph_string **,
2469 struct glyph_string *));
2470static int x_left_overwritten P_ ((struct glyph_string *));
2471static int x_left_overwriting P_ ((struct glyph_string *));
2472static int x_right_overwritten P_ ((struct glyph_string *));
2473static int x_right_overwriting P_ ((struct glyph_string *));
2474static int x_fill_glyph_string P_ ((struct glyph_string *, int, int,
2475 int, int));
2476static void w32_init_glyph_string P_ ((struct glyph_string *, HDC hdc,
2477 wchar_t *, struct window *,
2478 struct glyph_row *,
2479 enum glyph_row_area, int,
2480 enum draw_glyphs_face));
2481static int x_draw_glyphs P_ ((struct window *, int , struct glyph_row *,
2482 enum glyph_row_area, int, int,
2483 enum draw_glyphs_face, int *, int *, int));
2484static void x_set_glyph_string_clipping P_ ((struct glyph_string *));
2485static void x_set_glyph_string_gc P_ ((struct glyph_string *));
2486static void x_draw_glyph_string_background P_ ((struct glyph_string *,
2487 int));
2488static void x_draw_glyph_string_foreground P_ ((struct glyph_string *));
2489static void x_draw_composite_glyph_string_foreground P_ ((struct glyph_string *));
2490static void x_draw_glyph_string_underline P_ ((struct glyph_string *));
2491static void x_draw_glyph_string_underline P_ ((struct glyph_string *));
2492static void x_draw_glyph_string_box P_ ((struct glyph_string *));
2493static void x_draw_glyph_string P_ ((struct glyph_string *));
2494static void x_compute_glyph_string_overhangs P_ ((struct glyph_string *));
2495static void x_set_cursor_gc P_ ((struct glyph_string *));
2496static void x_set_mode_line_face_gc P_ ((struct glyph_string *));
2497static void x_set_mouse_face_gc P_ ((struct glyph_string *));
2498static void w32_get_glyph_overhangs P_ ((HDC hdc, struct glyph *,
2499 struct frame *,
2500 int *, int *, int));
2501static void x_compute_overhangs_and_x P_ ((struct glyph_string *, int, int));
2502static int w32_alloc_lighter_color (struct frame *, COLORREF *, double, int);
2503static void w32_setup_relief_color P_ ((struct frame *, struct relief *,
2504 double, int, COLORREF));
2505static void x_setup_relief_colors P_ ((struct glyph_string *));
2506static void x_draw_image_glyph_string P_ ((struct glyph_string *));
2507static void x_draw_image_relief P_ ((struct glyph_string *));
2508static void x_draw_image_foreground P_ ((struct glyph_string *));
2509static void w32_draw_image_foreground_1 P_ ((struct glyph_string *, HBITMAP));
2510static void x_fill_image_glyph_string P_ ((struct glyph_string *));
2511static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int,
2512 int, int, int));
2513static void w32_draw_relief_rect P_ ((struct frame *, int, int, int, int,
2514 int, int, int, int, RECT *));
2515static void w32_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,
2516 int, int, int, RECT *));
2517static void x_fix_overlapping_area P_ ((struct window *, struct glyph_row *,
2518 enum glyph_row_area));
2519
2520
2521/* Append the list of glyph strings with head H and tail T to the list
2522 with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the result. */
2523
2524static INLINE void
2525x_append_glyph_string_lists (head, tail, h, t)
2526 struct glyph_string **head, **tail;
2527 struct glyph_string *h, *t;
2528{
2529 if (h)
612 { 2530 {
613 /* Get the face-code of the next GLYPH. */ 2531 if (*head)
614 int cf, len, n_chars; 2532 (*tail)->next = h;
615 GLYPH g = *gp; 2533 else
616 int ch, charset; 2534 *head = h;
617 Lisp_Object first_ch; 2535 h->prev = *tail;
618 /* HIGHEST and LOWEST are used while drawing a composite 2536 *tail = t;
619 character. The meanings are described later. */ 2537 }
620 int highest, lowest; 2538}
621 2539
622 GLYPH_FOLLOW_ALIASES (tbase, tlen, g); 2540
623 cf = (cmpcharp ? cmpcharp->face_work : FAST_GLYPH_FACE (g)); 2541/* Prepend the list of glyph strings with head H and tail T to the
624 ch = FAST_GLYPH_CHAR (g); 2542 list with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the
625 if (unibyte_display_via_language_environment 2543 result. */
626 && SINGLE_BYTE_CHAR_P (ch) 2544
627 && ch >= 160) 2545static INLINE void
628 ch = unibyte_char_to_multibyte (ch); 2546x_prepend_glyph_string_lists (head, tail, h, t)
629 if (gidx == 0) XSETFASTINT (first_ch, ch); 2547 struct glyph_string **head, **tail;
630 charset = CHAR_CHARSET (ch); 2548 struct glyph_string *h, *t;
631 if (charset == CHARSET_COMPOSITION) 2549{
2550 if (h)
2551 {
2552 if (*head)
2553 (*head)->prev = t;
2554 else
2555 *tail = t;
2556 t->next = *head;
2557 *head = h;
2558 }
2559}
2560
2561
2562/* Append glyph string S to the list with head *HEAD and tail *TAIL.
2563 Set *HEAD and *TAIL to the resulting list. */
2564
2565static INLINE void
2566x_append_glyph_string (head, tail, s)
2567 struct glyph_string **head, **tail;
2568 struct glyph_string *s;
2569{
2570 s->next = s->prev = NULL;
2571 x_append_glyph_string_lists (head, tail, s, s);
2572}
2573
2574
2575/* Set S->gc to a suitable GC for drawing glyph string S in cursor
2576 face. */
2577
2578static void
2579x_set_cursor_gc (s)
2580 struct glyph_string *s;
2581{
2582 if (s->font == FRAME_FONT (s->f)
2583 && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
2584 && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
2585 && !s->cmp)
2586 s->gc = s->f->output_data.w32->cursor_gc;
2587 else
2588 {
2589 /* Cursor on non-default face: must merge. */
2590 XGCValues xgcv;
2591 unsigned long mask;
2592
2593 xgcv.background = s->f->output_data.w32->cursor_pixel;
2594 xgcv.foreground = s->face->background;
2595
2596 /* If the glyph would be invisible, try a different foreground. */
2597 if (xgcv.foreground == xgcv.background)
2598 xgcv.foreground = s->face->foreground;
2599 if (xgcv.foreground == xgcv.background)
2600 xgcv.foreground = s->f->output_data.w32->cursor_foreground_pixel;
2601 if (xgcv.foreground == xgcv.background)
2602 xgcv.foreground = s->face->foreground;
2603
2604 /* Make sure the cursor is distinct from text in this face. */
2605 if (xgcv.background == s->face->background
2606 && xgcv.foreground == s->face->foreground)
632 { 2607 {
633 /* We must draw components of the composite character on the 2608 xgcv.background = s->face->foreground;
634 same column. */ 2609 xgcv.foreground = s->face->background;
635 cmpcharp = cmpchar_table[COMPOSITE_CHAR_ID (ch)];
636
637 /* Set the face in the slot for work. */
638 cmpcharp->face_work = cf;
639
640 /* We don't need the return value ... */
641 dumpglyphs (f, left, top, cmpcharp->glyph, cmpcharp->glyph_len,
642 hl, just_foreground, cmpcharp);
643 /* ... because the width of just drawn text can be
644 calculated as follows. */
645 left += FONT_WIDTH (FRAME_FONT (f)) * cmpcharp->width;
646
647 ++gp, --n;
648 while (gp && (*gp & GLYPH_MASK_PADDING)) ++gp, --n;
649 cmpcharp = NULL;
650 continue;
651 } 2610 }
652 2611
653 /* Find the run of consecutive glyphs which can be drawn with 2612 IF_DEBUG (x_check_font (s->f, s->font));
654 the same DC (i.e. the same charset and the same face-code). 2613 xgcv.font = s->font;
655 Extract their character codes into X_2BYTE_BUFFER. 2614 mask = GCForeground | GCBackground | GCFont;
656 If CMPCHARP is not NULL, face-code is not checked because we 2615
657 use only the face specified in `cmpcharp->face_work'. */ 2616 if (FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc)
658 cp = x_2byte_buffer; 2617 XChangeGC (NULL, FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc,
659 while (n > 0) 2618 mask, &xgcv);
2619 else
2620 FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc
2621 = XCreateGC (NULL, s->window, mask, &xgcv);
2622
2623 s->gc = FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc;
2624 }
2625}
2626
2627
2628/* Set up S->gc of glyph string S for drawing text in mouse face. */
2629
2630static void
2631x_set_mouse_face_gc (s)
2632 struct glyph_string *s;
2633{
2634 int face_id;
2635
2636 /* What face has to be used for the mouse face? */
2637 face_id = FRAME_W32_DISPLAY_INFO (s->f)->mouse_face_face_id;
2638 face_id = FACE_FOR_CHARSET (s->f, face_id, s->charset);
2639 s->face = FACE_FROM_ID (s->f, face_id);
2640 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
2641
2642 /* If font in this face is same as S->font, use it. */
2643 if (s->font == s->face->font)
2644 s->gc = s->face->gc;
2645 else
2646 {
2647 /* Otherwise construct scratch_cursor_gc with values from FACE
2648 but font FONT. */
2649 XGCValues xgcv;
2650 unsigned long mask;
2651
2652 xgcv.background = s->face->background;
2653 xgcv.foreground = s->face->foreground;
2654 IF_DEBUG (x_check_font (s->f, s->font));
2655 xgcv.font = s->font;
2656 mask = GCForeground | GCBackground | GCFont;
2657
2658 if (FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc)
2659 XChangeGC (NULL, FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc,
2660 mask, &xgcv);
2661 else
2662 FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc
2663 = XCreateGC (NULL, s->window, mask, &xgcv);
2664
2665 s->gc = FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc;
2666 }
2667
2668 xassert (s->gc != 0);
2669}
2670
2671
2672/* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
2673 Faces to use in the mode line have already been computed when the
2674 matrix was built, so there isn't much to do, here. */
2675
2676static INLINE void
2677x_set_mode_line_face_gc (s)
2678 struct glyph_string *s;
2679{
2680 s->gc = s->face->gc;
2681 xassert (s->gc != 0);
2682}
2683
2684
2685/* Set S->gc of glyph string S for drawing that glyph string. Set
2686 S->stippled_p to a non-zero value if the face of S has a stipple
2687 pattern. */
2688
2689static INLINE void
2690x_set_glyph_string_gc (s)
2691 struct glyph_string *s;
2692{
2693 if (s->hl == DRAW_NORMAL_TEXT)
2694 {
2695 s->gc = s->face->gc;
2696 s->stippled_p = s->face->stipple != 0;
2697 }
2698 else if (s->hl == DRAW_INVERSE_VIDEO)
2699 {
2700 x_set_mode_line_face_gc (s);
2701 s->stippled_p = s->face->stipple != 0;
2702 }
2703 else if (s->hl == DRAW_CURSOR)
2704 {
2705 x_set_cursor_gc (s);
2706 s->stippled_p = 0;
2707 }
2708 else if (s->hl == DRAW_MOUSE_FACE)
2709 {
2710 x_set_mouse_face_gc (s);
2711 s->stippled_p = s->face->stipple != 0;
2712 }
2713 else if (s->hl == DRAW_IMAGE_RAISED
2714 || s->hl == DRAW_IMAGE_SUNKEN)
2715 {
2716 s->gc = s->face->gc;
2717 s->stippled_p = s->face->stipple != 0;
2718 }
2719 else
2720 {
2721 s->gc = s->face->gc;
2722 s->stippled_p = s->face->stipple != 0;
2723 }
2724
2725 /* GC must have been set. */
2726 xassert (s->gc != 0);
2727}
2728
2729
2730/* Return in *R the clipping rectangle for glyph string S. */
2731
2732static void
2733w32_get_glyph_string_clip_rect (s, r)
2734 struct glyph_string *s;
2735 RECT *r;
2736{
2737 int r_height, r_width;
2738
2739 if (s->row->full_width_p)
2740 {
2741 /* Draw full-width. X coordinates are relative to S->w->left. */
2742 int canon_x = CANON_X_UNIT (s->f);
2743
2744 r->left = WINDOW_LEFT_MARGIN (s->w) * canon_x;
2745 r_width = XFASTINT (s->w->width) * canon_x;
2746
2747 if (FRAME_HAS_VERTICAL_SCROLL_BARS (s->f))
660 { 2748 {
661 int this_charset, c1, c2; 2749 int width = FRAME_SCROLL_BAR_WIDTH (s->f) * canon_x;
662 2750 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (s->f))
663 g = *gp; 2751 r->left -= width;
664 GLYPH_FOLLOW_ALIASES (tbase, tlen, g); 2752 }
665 ch = FAST_GLYPH_CHAR (g); 2753
666 if (unibyte_display_via_language_environment 2754 r->left += FRAME_INTERNAL_BORDER_WIDTH (s->f);
667 && SINGLE_BYTE_CHAR_P (ch)
668 && ch >= 160)
669 ch = unibyte_char_to_multibyte (ch);
670 SPLIT_CHAR (ch, this_charset, c1, c2);
671 if (this_charset != charset
672 || (cmpcharp == NULL && FAST_GLYPH_FACE (g) != cf))
673 break;
674 2755
675 if (c2 > 0) 2756 /* Unless displaying a mode or menu bar line, which are always
676 *cp = BUILD_WCHAR_T (c1, c2); 2757 fully visible, clip to the visible part of the row. */
677 else 2758 if (s->w->pseudo_window_p)
678 *cp = BUILD_WCHAR_T (0, c1); 2759 r_height = s->row->visible_height;
679 ++cp; 2760 else
680 ++gp, --n; 2761 r_height = s->height;
681 while (gp && (*gp & GLYPH_MASK_PADDING)) 2762 }
682 ++gp, --n; 2763 else
2764 {
2765 /* This is a text line that may be partially visible. */
2766 r->left = WINDOW_AREA_TO_FRAME_PIXEL_X (s->w, s->area, 0);
2767 r_width = window_box_width (s->w, s->area);
2768 r_height = s->row->visible_height;
2769 }
2770
2771 /* Don't use S->y for clipping because it doesn't take partially
2772 visible lines into account. For example, it can be negative for
2773 partially visible lines at the top of a window. */
2774 if (!s->row->full_width_p
2775 && MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (s->w, s->row))
2776 r->top = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
2777 else
2778 r->top = max (0, s->row->y);
2779
2780 /* If drawing a tool-bar window, draw it over the internal border
2781 at the top of the window. */
2782 if (s->w == XWINDOW (s->f->tool_bar_window))
2783 r->top -= s->f->output_data.w32->internal_border_width;
2784
2785 /* If S draws overlapping rows, it's sufficient to use the top and
2786 bottom of the window for clipping because this glyph string
2787 intentionally draws over other lines. */
2788 if (s->for_overlaps_p)
2789 {
2790 r->top = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
2791 r_height = window_text_bottom_y (s->w) - r->top;
2792 }
2793
2794 r->top = WINDOW_TO_FRAME_PIXEL_Y (s->w, r->top);
2795
2796 r->bottom = r->top + r_height;
2797 r->right = r->left + r_width;
2798}
2799
2800
2801/* Set clipping for output of glyph string S. S may be part of a mode
2802 line or menu if we don't have X toolkit support. */
2803
2804static INLINE void
2805x_set_glyph_string_clipping (s)
2806 struct glyph_string *s;
2807{
2808 RECT r;
2809 w32_get_glyph_string_clip_rect (s, &r);
2810 w32_set_clip_rectangle (s->hdc, &r);
2811}
2812
2813
2814/* Compute left and right overhang of glyph string S. If S is a glyph
2815 string for a composition, assume overhangs don't exist. */
2816
2817static INLINE void
2818x_compute_glyph_string_overhangs (s)
2819 struct glyph_string *s;
2820{
2821 if (s->cmp == NULL
2822 && s->first_glyph->type == CHAR_GLYPH)
2823 {
2824 XCharStruct cs;
2825 int direction, font_ascent, font_descent;
2826 XTextExtents16 (s->font, s->char2b, s->nchars, &direction,
2827 &font_ascent, &font_descent, &cs);
2828 s->right_overhang = cs.rbearing > cs.width ? cs.rbearing - cs.width : 0;
2829 s->left_overhang = cs.lbearing < 0 ? -cs.lbearing : 0;
2830 }
2831}
2832
2833
2834/* Compute overhangs and x-positions for glyph string S and its
2835 predecessors, or successors. X is the starting x-position for S.
2836 BACKWARD_P non-zero means process predecessors. */
2837
2838static void
2839x_compute_overhangs_and_x (s, x, backward_p)
2840 struct glyph_string *s;
2841 int x;
2842 int backward_p;
2843{
2844 if (backward_p)
2845 {
2846 while (s)
2847 {
2848 x_compute_glyph_string_overhangs (s);
2849 x -= s->width;
2850 s->x = x;
2851 s = s->prev;
2852 }
2853 }
2854 else
2855 {
2856 while (s)
2857 {
2858 x_compute_glyph_string_overhangs (s);
2859 s->x = x;
2860 x += s->width;
2861 s = s->next;
2862 }
2863 }
2864}
2865
2866
2867/* Set *LEFT and *RIGHT to the left and right overhang of GLYPH on
2868 frame F. Overhangs of glyphs other than type CHAR_GLYPH are
2869 assumed to be zero. */
2870
2871static void
2872w32_get_glyph_overhangs (_hdc, glyph, f, left, right, unicode_p)
2873 HDC _hdc;
2874 struct glyph *glyph;
2875 struct frame *f;
2876 int *left, *right, unicode_p;
2877{
2878 int c;
2879 HDC hdc = _hdc ? _hdc : get_frame_dc (f);
2880
2881 *left = *right = 0;
2882
2883 if (glyph->type == CHAR_GLYPH)
2884 {
2885 XFontStruct *font;
2886 struct face *face;
2887 struct font_info *font_info;
2888 wchar_t char2b;
2889
2890 face = x_get_glyph_face_and_encoding (f, glyph, &char2b);
2891 font = face->font;
2892 font_info = FONT_INFO_FROM_ID (f, face->font_info_id);
2893 if (font)
2894 {
2895 XCharStruct *pcm = w32_per_char_metric (hdc, font, &char2b,
2896 unicode_p);
2897
2898 if (pcm->rbearing > pcm->width)
2899 *right = pcm->rbearing - pcm->width;
2900 if (pcm->lbearing < 0)
2901 *left = -pcm->lbearing;
2902 }
2903 }
2904 if (!_hdc)
2905 release_frame_dc (f, hdc);
2906}
2907
2908
2909static void
2910x_get_glyph_overhangs (glyph, f, left, right)
2911 struct glyph *glyph;
2912 struct frame *f;
2913 int *left, *right;
2914{
2915 HDC hdc = get_frame_dc (f);
2916 w32_get_glyph_overhangs (hdc, glyph, f, left, right, glyph->multibyte_p);
2917 release_frame_dc (f, hdc);
2918}
2919
2920
2921/* Return the index of the first glyph preceding glyph string S that
2922 is overwritten by S because of S's left overhang. Value is -1
2923 if no glyphs are overwritten. */
2924
2925static int
2926x_left_overwritten (s)
2927 struct glyph_string *s;
2928{
2929 int k;
2930
2931 if (s->left_overhang)
2932 {
2933 int x = 0, i;
2934 struct glyph *glyphs = s->row->glyphs[s->area];
2935 int first = s->first_glyph - glyphs;
2936
2937 for (i = first - 1; i >= 0 && x > -s->left_overhang; --i)
2938 x -= glyphs[i].pixel_width;
2939
2940 k = i + 1;
2941 }
2942 else
2943 k = -1;
2944
2945 return k;
2946}
2947
2948
2949/* Return the index of the first glyph preceding glyph string S that
2950 is overwriting S because of its right overhang. Value is -1 if no
2951 glyph in front of S overwrites S. */
2952
2953static int
2954x_left_overwriting (s)
2955 struct glyph_string *s;
2956{
2957 int i, k, x;
2958 struct glyph *glyphs = s->row->glyphs[s->area];
2959 int first = s->first_glyph - glyphs;
2960
2961 k = -1;
2962 x = 0;
2963 for (i = first - 1; i >= 0; --i)
2964 {
2965 int left, right;
2966 w32_get_glyph_overhangs (s->hdc, glyphs + i, s->f, &left,
2967 &right, s->two_byte_p);
2968 if (x + right > 0)
2969 k = i;
2970 x -= glyphs[i].pixel_width;
2971 }
2972
2973 return k;
2974}
2975
2976
2977/* Return the index of the last glyph following glyph string S that is
2978 not overwritten by S because of S's right overhang. Value is -1 if
2979 no such glyph is found. */
2980
2981static int
2982x_right_overwritten (s)
2983 struct glyph_string *s;
2984{
2985 int k = -1;
2986
2987 if (s->right_overhang)
2988 {
2989 int x = 0, i;
2990 struct glyph *glyphs = s->row->glyphs[s->area];
2991 int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
2992 int end = s->row->used[s->area];
2993
2994 for (i = first; i < end && s->right_overhang > x; ++i)
2995 x += glyphs[i].pixel_width;
2996
2997 k = i;
2998 }
2999
3000 return k;
3001}
3002
3003
3004/* Return the index of the last glyph following glyph string S that
3005 overwrites S because of its left overhang. Value is negative
3006 if no such glyph is found. */
3007
3008static int
3009x_right_overwriting (s)
3010 struct glyph_string *s;
3011{
3012 int i, k, x;
3013 int end = s->row->used[s->area];
3014 struct glyph *glyphs = s->row->glyphs[s->area];
3015 int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
3016
3017 k = -1;
3018 x = 0;
3019 for (i = first; i < end; ++i)
3020 {
3021 int left, right;
3022 w32_get_glyph_overhangs (s->hdc, glyphs + i, s->f, &left,
3023 &right, s->two_byte_p);
3024 if (x - left < 0)
3025 k = i;
3026 x += glyphs[i].pixel_width;
3027 }
3028
3029 return k;
3030}
3031
3032
3033/* Fill rectangle X, Y, W, H with background color of glyph string S. */
3034
3035static INLINE void
3036x_clear_glyph_string_rect (s, x, y, w, h)
3037 struct glyph_string *s;
3038 int x, y, w, h;
3039{
3040 int real_x = x;
3041 int real_y = y;
3042 int real_w = w;
3043 int real_h = h;
3044#if 0
3045 /* Take clipping into account. */
3046 if (s->gc->clip_mask == Rect)
3047 {
3048 real_x = max (real_x, s->gc->clip_rectangle.left);
3049 real_y = max (real_y, s->gc->clip_rectangle.top);
3050 real_w = min (real_w, s->gc->clip_rectangle.right
3051 - s->gc->clip_rectangle.left);
3052 real_h = min (real_h, s->gc->clip_rectangle.bottom
3053 - s->gc->clip_rectangle.top);
3054 }
3055#endif
3056 w32_fill_area (s->f, s->hdc, s->gc->background, real_x, real_y,
3057 real_w, real_h);
3058}
3059
3060
3061/* Draw the background of glyph_string S. If S->background_filled_p
3062 is non-zero don't draw it. FORCE_P non-zero means draw the
3063 background even if it wouldn't be drawn normally. This is used
3064 when a string preceding S draws into the background of S, or S
3065 contains the first component of a composition. */
3066
3067static void
3068x_draw_glyph_string_background (s, force_p)
3069 struct glyph_string *s;
3070 int force_p;
3071{
3072 /* Nothing to do if background has already been drawn or if it
3073 shouldn't be drawn in the first place. */
3074 if (!s->background_filled_p)
3075 {
3076#if 0 /* NTEMACS_TODO: stipple */
3077 if (s->stippled_p)
3078 {
3079 /* Fill background with a stipple pattern. */
3080 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
3081 XFillRectangle (s->display, s->window, s->gc, s->x,
3082 s->y + s->face->box_line_width,
3083 s->background_width,
3084 s->height - 2 * s->face->box_line_width);
3085 XSetFillStyle (s->display, s->gc, FillSolid);
3086 s->background_filled_p = 1;
683 } 3087 }
3088 else
3089#endif
3090 if (FONT_HEIGHT (s->font) < s->height - 2 * s->face->box_line_width
3091 || s->font_not_found_p
3092 || s->extends_to_end_of_line_p
3093 || force_p)
3094 {
3095 x_clear_glyph_string_rect (s, s->x, s->y + s->face->box_line_width,
3096 s->background_width,
3097 s->height - 2 * s->face->box_line_width);
3098 s->background_filled_p = 1;
3099 }
3100 }
3101}
3102
3103
3104/* Draw the foreground of glyph string S. */
3105
3106static void
3107x_draw_glyph_string_foreground (s)
3108 struct glyph_string *s;
3109{
3110 int i, x;
3111
3112 /* If first glyph of S has a left box line, start drawing the text
3113 of S to the right of that box line. */
3114 if (s->face->box != FACE_NO_BOX
3115 && s->first_glyph->left_box_line_p)
3116 x = s->x + s->face->box_line_width;
3117 else
3118 x = s->x;
3119
3120 if (s->for_overlaps_p || (s->background_filled_p && s->hl != DRAW_CURSOR))
3121 SetBkMode (s->hdc, TRANSPARENT);
3122 else
3123 SetBkMode (s->hdc, OPAQUE);
3124
3125 SetTextColor (s->hdc, s->gc->foreground);
3126 SetBkColor (s->hdc, s->gc->background);
3127 SetTextAlign (s->hdc, TA_BASELINE | TA_LEFT);
3128
3129 if (s->font && s->font->hfont)
3130 SelectObject (s->hdc, s->font->hfont);
3131
3132 /* Draw characters of S as rectangles if S's font could not be
3133 loaded. */
3134 if (s->font_not_found_p)
3135 {
3136 for (i = 0; i < s->nchars; ++i)
3137 {
3138 struct glyph *g = s->first_glyph + i;
3139
3140 w32_draw_rectangle (s->hdc, s->gc, x, s->y, g->pixel_width - 1,
3141 s->height - 1);
3142 x += g->pixel_width;
3143 }
3144 }
3145 else
3146 {
3147 char *char1b = (char *) s->char2b;
3148 int boff = s->font_info->baseline_offset;
3149
3150 if (s->font_info->vertical_centering)
3151 boff = VCENTER_BASELINE_OFFSET (s->font, s->f) - boff;
3152
3153 /* If we can use 8-bit functions, condense S->char2b. */
3154 if (!s->two_byte_p)
3155 for (i = 0; i < s->nchars; ++i)
3156 char1b[i] = BYTE2 (s->char2b[i]);
3157
3158 /* Draw text with TextOut and friends. */
3159 W32_TEXTOUT (s, x, s->ybase - boff, s->char2b, s->nchars);
3160 }
3161}
3162
3163/* Draw the foreground of composite glyph string S. */
3164
3165static void
3166x_draw_composite_glyph_string_foreground (s)
3167 struct glyph_string *s;
3168{
3169 int i, x;
684 3170
685 /* LEN gets the length of the run. */ 3171 /* If first glyph of S has a left box line, start drawing the text
686 len = cp - x_2byte_buffer; 3172 of S to the right of that box line. */
687 /* Now output this run of chars, with the font and pixel values 3173 if (s->face->box != FACE_NO_BOX
688 determined by the face code CF. */ 3174 && s->first_glyph->left_box_line_p)
3175 x = s->x + s->face->box_line_width;
3176 else
3177 x = s->x;
3178
3179 /* S is a glyph string for a composition. S->gidx is the index of
3180 the first character drawn for glyphs of this composition.
3181 S->gidx == 0 means we are drawing the very first character of
3182 this composition. */
3183
3184 SetTextColor (s->hdc, s->gc->foreground);
3185 SetBkColor (s->hdc, s->gc->background);
3186 SetBkMode (s->hdc, TRANSPARENT);
3187 SetTextAlign (s->hdc, TA_BASELINE | TA_LEFT);
3188
3189 /* Draw a rectangle for the composition if the font for the very
3190 first character of the composition could not be loaded. */
3191 if (s->font_not_found_p)
3192 {
3193 if (s->gidx == 0)
3194 w32_draw_rectangle (s->hdc, s->gc, x, s->y, s->width - 1,
3195 s->height - 1);
3196 }
3197 else
3198 {
3199 for (i = 0; i < s->nchars; i++, ++s->gidx)
3200 W32_TEXTOUT (s, x + s->cmp->offsets[s->gidx * 2],
3201 s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
3202 s->char2b + i, 1);
3203 }
3204}
3205
3206/* Allocate a color which is lighter or darker than *COLOR by FACTOR
3207 or DELTA. Try a color with RGB values multiplied by FACTOR first.
3208 If this produces the same color as COLOR, try a color where all RGB
3209 values have DELTA added. Return the allocated color in *COLOR.
3210 DISPLAY is the X display, CMAP is the colormap to operate on.
3211 Value is non-zero if successful. */
3212
3213static int
3214w32_alloc_lighter_color (f, color, factor, delta)
3215 struct frame *f;
3216 COLORREF *color;
3217 double factor;
3218 int delta;
3219{
3220 COLORREF new;
3221
3222 /* Change RGB values by specified FACTOR. Avoid overflow! */
3223 xassert (factor >= 0);
3224 new = PALETTERGB (min (0xff, factor * GetRValue (*color)),
3225 min (0xff, factor * GetGValue (*color)),
3226 min (0xff, factor * GetBValue (*color)));
3227 if (new == *color)
3228 new = PALETTERGB (max (0, min (0xff, delta + GetRValue (*color))),
3229 max (0, min (0xff, delta + GetGValue (*color))),
3230 max (0, min (0xff, delta + GetBValue (*color))));
3231
3232 if (new == *color)
3233 return 0;
3234
3235 *color = new;
3236
3237 return 1;
3238}
3239
3240
3241/* Set up the foreground color for drawing relief lines of glyph
3242 string S. RELIEF is a pointer to a struct relief containing the GC
3243 with which lines will be drawn. Use a color that is FACTOR or
3244 DELTA lighter or darker than the relief's background which is found
3245 in S->f->output_data.x->relief_background. If such a color cannot
3246 be allocated, use DEFAULT_PIXEL, instead. */
3247
3248static void
3249w32_setup_relief_color (f, relief, factor, delta, default_pixel)
3250 struct frame *f;
3251 struct relief *relief;
3252 double factor;
3253 int delta;
3254 COLORREF default_pixel;
3255{
3256 XGCValues xgcv;
3257 struct w32_output *di = f->output_data.w32;
3258 unsigned long mask = GCForeground;
3259 COLORREF pixel;
3260 COLORREF background = di->relief_background;
3261 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
3262
3263 /* Allocate new color. */
3264 xgcv.foreground = default_pixel;
3265 pixel = background;
3266 if (w32_alloc_lighter_color (f, &pixel, factor, delta))
3267 {
3268 relief->allocated_p = 1;
3269 xgcv.foreground = relief->pixel = pixel;
3270 }
3271
3272 if (relief->gc == 0)
3273 {
3274#if 0 /* NTEMACS_TODO: stipple */
3275 xgcv.stipple = dpyinfo->gray;
3276 mask |= GCStipple;
3277#endif
3278 relief->gc = XCreateGC (NULL, FRAME_W32_WINDOW (f), mask, &xgcv);
3279 }
3280 else
3281 XChangeGC (NULL, relief->gc, mask, &xgcv);
3282}
3283
3284
3285/* Set up colors for the relief lines around glyph string S. */
3286
3287static void
3288x_setup_relief_colors (s)
3289 struct glyph_string *s;
3290{
3291 struct w32_output *di = s->f->output_data.w32;
3292 COLORREF color;
3293
3294 if (s->face->use_box_color_for_shadows_p)
3295 color = s->face->box_color;
3296 else
3297 color = s->gc->background;
3298
3299 if (di->white_relief.gc == 0
3300 || color != di->relief_background)
3301 {
3302 di->relief_background = color;
3303 w32_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
3304 WHITE_PIX_DEFAULT (s->f));
3305 w32_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
3306 BLACK_PIX_DEFAULT (s->f));
3307 }
3308}
3309
3310
3311/* Draw a relief on frame F inside the rectangle given by LEFT_X,
3312 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
3313 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
3314 relief. LEFT_P non-zero means draw a relief on the left side of
3315 the rectangle. RIGHT_P non-zero means draw a relief on the right
3316 side of the rectangle. CLIP_RECT is the clipping rectangle to use
3317 when drawing. */
3318
3319static void
3320w32_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
3321 raised_p, left_p, right_p, clip_rect)
3322 struct frame *f;
3323 int left_x, top_y, right_x, bottom_y, left_p, right_p, raised_p;
3324 RECT *clip_rect;
3325{
3326 int i;
3327 XGCValues gc;
3328 HDC hdc = get_frame_dc (f);
3329
3330 if (raised_p)
3331 gc.foreground = PALETTERGB (255, 255, 255);
3332 else
3333 gc.foreground = PALETTERGB (0, 0, 0);
3334
3335 w32_set_clip_rectangle (hdc, clip_rect);
3336
3337 /* Top. */
3338 for (i = 0; i < width; ++i)
3339 {
3340 w32_fill_area (f, hdc, gc.foreground,
3341 left_x + i * left_p, top_y + i,
3342 (right_x + 1 - i * right_p) - (left_x + i * left_p), 1);
3343 }
3344
3345 /* Left. */
3346 if (left_p)
3347 for (i = 0; i < width; ++i)
689 { 3348 {
690 struct face *face = FRAME_DEFAULT_FACE (f); 3349 w32_fill_area (f, hdc, gc.foreground,
691 XFontStruct *font = NULL; 3350 left_x + i, top_y + i, 1,
692 int fontset; 3351 (bottom_y - i) - (top_y + i));
693 struct font_info *fontp; 3352 }
694 int font_id;
695 COLORREF fg;
696 COLORREF bg;
697 int stippled = 0;
698 int line_height = FRAME_LINE_HEIGHT (f);
699 /* Pixel width of each glyph in this run. */
700 int glyph_width
701 = (FONT_WIDTH (FRAME_FONT (f))
702 * (cmpcharp ? cmpcharp->width : CHARSET_WIDTH (charset)));
703 /* Overall pixel width of this run. */
704 int run_width
705 = (FONT_WIDTH (FRAME_FONT (f))
706 * (cmpcharp ? cmpcharp->width : len * CHARSET_WIDTH (charset)));
707 /* A flag to tell if we have already filled background. We
708 fill background in advance in the following cases:
709 1) A face has stipple.
710 2) A height of font is shorter than LINE_HEIGHT.
711 3) Drawing a composite character.
712 4) Font has non-zero _MULE_BASELINE_OFFSET property.
713 5) Font is a bdf font.
714 6) Font is italic (italic fonts falsely report their height).
715 After filling background, we draw glyphs by XDrawString16. */
716 int background_filled;
717 /* Baseline position of a character, offset from TOP. */
718 int baseline;
719 /* The property value of `_MULE_RELATIVE_COMPOSE' and
720 `_MULE_DEFAULT_ASCENT'. */
721 int relative_compose = 0, default_ascent = 0;
722 /* 1 if we find no font or a font of inappropriate size. */
723 int require_clipping;
724 RECT clip_rectangle;
725 LPRECT clip_region = NULL;
726 UINT fuOptions = 0;
727
728 int codepage = CP_DEFAULT;
729 BOOL print_via_unicode = FALSE;
730
731 /* HL = 3 means use a mouse face previously chosen. */
732 if (hl == 3)
733 cf = FRAME_W32_DISPLAY_INFO (f)->mouse_face_face_id;
734
735 /* First look at the face of the text itself. */
736 if (cf != 0)
737 {
738 /* It's possible for the display table to specify
739 a face code that is out of range. Use 0 in that case. */
740 if (cf < 0 || cf >= FRAME_N_COMPUTED_FACES (f)
741 || FRAME_COMPUTED_FACES (f) [cf] == 0)
742 cf = 0;
743
744 if (cf == 1)
745 face = FRAME_MODE_LINE_FACE (f);
746 else
747 face = intern_face (f, FRAME_COMPUTED_FACES (f) [cf]);
748 if (FACE_STIPPLE (face))
749 stippled = 1;
750 }
751 3353
752 /* Then comes the distinction between modeline and normal text. */ 3354 w32_set_clip_rectangle (hdc, NULL);
753 else if (hl == 0) 3355
754 ; 3356 if (raised_p)
755 else if (hl == 1) 3357 gc.foreground = PALETTERGB (0, 0, 0);
756 { 3358 else
757 face = FRAME_MODE_LINE_FACE (f); 3359 gc.foreground = PALETTERGB (255, 255, 255);
758 if (FACE_STIPPLE (face))
759 stippled = 1;
760 }
761 3360
762 /* Setting appropriate font and codepage for this charset. */ 3361 w32_set_clip_rectangle (hdc, clip_rect);
763 if (charset != CHARSET_ASCII) 3362
764 { 3363 /* Bottom. */
765 fontset = FACE_FONTSET (face); 3364 for (i = 0; i < width; ++i)
3365 {
3366 w32_fill_area (f, hdc, gc.foreground,
3367 left_x + i * left_p, bottom_y - i,
3368 (right_x + 1 - i * right_p) - left_x + i * left_p, 1);
3369 }
766 3370
767 if ((fontset < 0 && (fontset = FRAME_FONTSET (f)) < 0) 3371 /* Right. */
768 || !(fontp = FS_LOAD_FONT (f, FRAME_W32_FONT_TABLE (f), 3372 if (right_p)
769 charset, NULL, fontset))) 3373 for (i = 0; i < width; ++i)
770 goto font_not_found; 3374 {
3375 w32_fill_area (f, hdc, gc.foreground,
3376 right_x - i, top_y + i + 1, 1,
3377 (bottom_y - i) - (top_y + i + 1));
3378 }
771 3379
772 font = (XFontStruct *) (fontp->font); 3380 w32_set_clip_rectangle (hdc, NULL);
773 codepage = w32_codepage_for_font (fontp->name); 3381
3382 release_frame_dc (f, hdc);
3383}
774 3384
775 if ( font && !font->bdf )
776 print_via_unicode = w32_use_unicode_for_codepage (codepage);
777 3385
778 baseline = FONT_BASE (font) + fontp->baseline_offset; 3386/* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
3387 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
3388 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
3389 left side of the rectangle. RIGHT_P non-zero means draw a line
3390 on the right side of the rectangle. CLIP_RECT is the clipping
3391 rectangle to use when drawing. */
779 3392
780 if (cmpcharp && cmpcharp->cmp_rule == NULL) 3393static void
781 { 3394w32_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
782 relative_compose = fontp->relative_compose; 3395 left_p, right_p, clip_rect)
783 default_ascent = fontp->default_ascent; 3396 struct glyph_string *s;
784 } 3397 int left_x, top_y, right_x, bottom_y, width, left_p, right_p;
3398 RECT *clip_rect;
3399{
3400 HDC hdc = get_frame_dc (s->f);
785 3401
786 /* We have to change code points in the following cases. */ 3402 w32_set_clip_rectangle (hdc, clip_rect);
787 if (fontp->font_encoder) 3403
788 { 3404 /* Top. */
789 /* This font requires CCL program to calculate code 3405 w32_fill_area (s->f, hdc, s->face->box_color,
790 point of characters. */ 3406 left_x, top_y, right_x - left_x, width);
791 struct ccl_program *ccl = fontp->font_encoder;
792 3407
793 if (CHARSET_DIMENSION (charset) == 1) 3408 /* Left. */
794 for (cp = x_2byte_buffer; cp < x_2byte_buffer + len; cp++) 3409 if (left_p)
795 { 3410 {
796 ccl->reg[0] = charset; 3411 w32_fill_area (s->f, hdc, s->face->box_color,
797 ccl->reg[1] = BYTE2 (*cp); 3412 left_x, top_y, width, bottom_y - top_y);
798 ccl_driver (ccl, NULL, NULL, 0, 0, NULL); 3413 }
799 /* We assume that MSBs are appropriately 3414
800 set/reset by CCL program. */ 3415 /* Bottom. */
801#if 0 /* this probably works under NT, but not under 95. */ 3416 w32_fill_area (s->f, hdc, s->face->box_color,
802 if (font->tm.tmLastChar < 256) /* 1-byte font */ 3417 left_x, bottom_y - width, right_x - left_x, width);
803 *cp = BUILD_WCHAR_T (0, ccl->reg[1]); 3418
804 else 3419 /* Right. */
805 *cp = BUILD_WCHAR_T (ccl->reg[1], ccl->reg[2]); 3420 if (right_p)
806#else /* Assume single dimensional charsets stay so. */ 3421 {
807 *cp = BUILD_WCHAR_T (0, ccl->reg[1]); 3422 w32_fill_area (s->f, hdc, s->face->box_color,
3423 right_x - width, top_y, width, bottom_y - top_y);
3424 }
3425
3426 w32_set_clip_rectangle (hdc, NULL);
3427 release_frame_dc (s->f, hdc);
3428}
3429
3430
3431/* Draw a box around glyph string S. */
3432
3433static void
3434x_draw_glyph_string_box (s)
3435 struct glyph_string *s;
3436{
3437 int width, left_x, right_x, top_y, bottom_y, last_x, raised_p;
3438 int left_p, right_p;
3439 struct glyph *last_glyph;
3440 RECT clip_rect;
3441
3442 last_x = window_box_right (s->w, s->area);
3443 if (s->row->full_width_p
3444 && !s->w->pseudo_window_p)
3445 {
3446 last_x += FRAME_X_RIGHT_FLAGS_AREA_WIDTH (s->f);
3447 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (s->f))
3448 last_x += FRAME_SCROLL_BAR_WIDTH (s->f) * CANON_X_UNIT (s->f);
3449 }
3450
3451 /* The glyph that may have a right box line. */
3452 last_glyph = (s->cmp || s->img
3453 ? s->first_glyph
3454 : s->first_glyph + s->nchars - 1);
3455
3456 width = s->face->box_line_width;
3457 raised_p = s->face->box == FACE_RAISED_BOX;
3458 left_x = s->x;
3459 right_x = ((s->row->full_width_p
3460 ? last_x - 1
3461 : min (last_x, s->x + s->background_width) - 1));
3462 top_y = s->y;
3463 bottom_y = top_y + s->height - 1;
3464
3465 left_p = (s->first_glyph->left_box_line_p
3466 || (s->hl == DRAW_MOUSE_FACE
3467 && (s->prev == NULL
3468 || s->prev->hl != s->hl)));
3469 right_p = (last_glyph->right_box_line_p
3470 || (s->hl == DRAW_MOUSE_FACE
3471 && (s->next == NULL
3472 || s->next->hl != s->hl)));
3473
3474 w32_get_glyph_string_clip_rect (s, &clip_rect);
3475
3476 if (s->face->box == FACE_SIMPLE_BOX)
3477 w32_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
3478 left_p, right_p, &clip_rect);
3479 else
3480 {
3481 x_setup_relief_colors (s);
3482 w32_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
3483 width, raised_p, left_p, right_p, &clip_rect);
3484 }
3485}
3486
3487
3488/* Draw foreground of image glyph string S. */
3489
3490static void
3491x_draw_image_foreground (s)
3492 struct glyph_string *s;
3493{
3494 int x;
3495 int y = s->ybase - IMAGE_ASCENT (s->img);
3496
3497 /* If first glyph of S has a left box line, start drawing it to the
3498 right of that line. */
3499 if (s->face->box != FACE_NO_BOX
3500 && s->first_glyph->left_box_line_p)
3501 x = s->x + s->face->box_line_width;
3502 else
3503 x = s->x;
3504
3505 /* If there is a margin around the image, adjust x- and y-position
3506 by that margin. */
3507 if (s->img->margin)
3508 {
3509 x += s->img->margin;
3510 y += s->img->margin;
3511 }
3512
3513 SaveDC (s->hdc);
3514
3515 if (s->img->pixmap)
3516 {
3517#if 0 /* NTEMACS_TODO: image mask */
3518 if (s->img->mask)
3519 {
3520 /* We can't set both a clip mask and use XSetClipRectangles
3521 because the latter also sets a clip mask. We also can't
3522 trust on the shape extension to be available
3523 (XShapeCombineRegion). So, compute the rectangle to draw
3524 manually. */
3525 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
3526 | GCFunction);
3527 XGCValues xgcv;
3528 XRectangle clip_rect, image_rect, r;
3529
3530 xgcv.clip_mask = s->img->mask;
3531 xgcv.clip_x_origin = x;
3532 xgcv.clip_y_origin = y;
3533 xgcv.function = GXcopy;
3534 XChangeGC (s->display, s->gc, mask, &xgcv);
3535
3536 w32_get_glyph_string_clip_rect (s, &clip_rect);
3537 image_rect.x = x;
3538 image_rect.y = y;
3539 image_rect.width = s->img->width;
3540 image_rect.height = s->img->height;
3541 if (w32_intersect_rectangles (&clip_rect, &image_rect, &r))
3542 XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
3543 r.x - x, r.y - y, r.width, r.height, r.x, r.y);
3544 }
3545 else
808#endif 3546#endif
809 } 3547 {
810 else 3548 HDC compat_hdc = CreateCompatibleDC (s->hdc);
811 for (cp = x_2byte_buffer; cp < x_2byte_buffer + len; cp++) 3549 HBRUSH fg_brush = CreateSolidBrush (s->gc->foreground);
812 { 3550 HBRUSH orig_brush = SelectObject (s->hdc, fg_brush);
813 ccl->reg[0] = charset; 3551 HGDIOBJ orig_obj = SelectObject (compat_hdc, s->img->pixmap);
814 ccl->reg[1] = BYTE1 (*cp) , ccl->reg[2] = BYTE2 (*cp); 3552
815 ccl_driver (ccl, NULL, NULL, 0, 0, NULL); 3553 SetTextColor (s->hdc, s->gc->foreground);
816 /* We assume that MSBs are appropriately 3554 SetBkColor (s->hdc, s->gc->background);
817 set/reset by CCL program. */ 3555#if 0 /* From w32bdf.c (which is from Meadow). */
818#if 0 /* this probably works under NT, but not under 95. */ 3556 BitBlt (s->hdc, x, y, s->img->width, s->img->height,
819 if (font->tm.tmLastChar < 256) /* 1-byte font */ 3557 compat_hdc, 0, 0, SRCCOPY);
820 *cp = BUILD_WCHAR_T (0, ccl->reg[1]); 3558#else
821 else 3559 BitBlt (s->hdc, x, y, s->img->width, s->img->height,
822 *cp = BUILD_WCHAR_T (ccl->reg[1],ccl->reg[2]); 3560 compat_hdc, 0, 0, 0xB8074A);
823#else /* Assume multidimensional charsets stay so. */
824 *cp = BUILD_WCHAR_T (ccl->reg[1],ccl->reg[2]);
825#endif 3561#endif
826 } 3562 SelectObject (s->hdc, orig_brush);
827 } 3563 DeleteObject (fg_brush);
828 else if (fontp->encoding[charset]) 3564 SelectObject (compat_hdc, orig_obj);
829 { 3565 DeleteDC (compat_hdc);
830 int enc = fontp->encoding[charset]; 3566
831 3567 /* When the image has a mask, we can expect that at
832 if ((enc == 1 || enc == 2) && CHARSET_DIMENSION (charset) == 2) 3568 least part of a mouse highlight or a block cursor will
833 for (cp = x_2byte_buffer; cp < x_2byte_buffer + len; cp++) 3569 be visible. If the image doesn't have a mask, make
834 *cp = BUILD_WCHAR_T (BYTE1 (*cp) | 0x80, BYTE2 (*cp)); 3570 a block cursor visible by drawing a rectangle around
835 if (enc == 1 || enc == 3) 3571 the image. I believe it's looking better if we do
836 for (cp = x_2byte_buffer; cp < x_2byte_buffer + len; cp++) 3572 nothing here for mouse-face. */
837 *cp = BUILD_WCHAR_T (BYTE1 (*cp), BYTE2 (*cp) | 0x80); 3573 if (s->hl == DRAW_CURSOR)
838 /* Special encoding for SJIS Kanji. */ 3574 w32_draw_rectangle (s->hdc, s->gc, x, y, s->img->width - 1,
839 if (enc == 4) 3575 s->img->height - 1);
840 { 3576 }
841 if (CHARSET_DIMENSION (charset) == 2) 3577 }
842 { 3578 else
843 int sjis1, sjis2; 3579 w32_draw_rectangle (s->hdc, s->gc, x, y, s->img->width -1,
844 for (cp = x_2byte_buffer; 3580 s->img->height - 1);
845 cp < x_2byte_buffer + len; cp++)
846 {
847 ENCODE_SJIS (BYTE1 (*cp), BYTE2 (*cp),
848 sjis1, sjis2);
849 *cp = BUILD_WCHAR_T (sjis1, sjis2);
850 }
851 }
852 else
853 for (cp = x_2byte_buffer;
854 cp < x_2byte_buffer + len; cp++)
855 *cp = BUILD_WCHAR_T (BYTE1 (*cp),
856 BYTE2 (*cp) | 0x80);
857 }
858 }
859 }
860 else
861 {
862 font_not_found:
863 if (charset == CHARSET_ASCII || charset == charset_latin_iso8859_1)
864 {
865 font = FACE_FONT (face);
866 if (!font || font == (XFontStruct *) FACE_DEFAULT)
867 font = FRAME_FONT (f);
868 baseline = FONT_BASE (FRAME_FONT (f));
869 if (charset == charset_latin_iso8859_1)
870 {
871 if (!font->bdf && font->tm.tmLastChar < 0x80)
872 /* This font can't display Latin1 characters. */
873 font = NULL;
874 else
875 {
876 for (cp = x_2byte_buffer;
877 cp < x_2byte_buffer + len; cp++)
878 *cp = BUILD_WCHAR_T (BYTE1 (*cp),
879 BYTE2 (*cp) | 0x80);
880 }
881 }
882 }
883 }
884 3581
885 fg = face->foreground; 3582 RestoreDC (s->hdc ,-1);
886 bg = face->background; 3583}
887 3584
888 /* Now override that if the cursor's on this character. */
889 if (hl == 2)
890 {
891 /* The cursor overrides stippling. */
892 stippled = 0;
893 3585
894 if (font == FRAME_FONT (f)
895 && face->background == FRAME_BACKGROUND_PIXEL (f)
896 && face->foreground == FRAME_FOREGROUND_PIXEL (f)
897 && !cmpcharp)
898 {
899 bg = f->output_data.w32->cursor_pixel;
900 fg = face->background;
901 }
902 /* Cursor on non-default face: must merge. */
903 else
904 {
905 bg = f->output_data.w32->cursor_pixel;
906 fg = face->background;
907 /* If the glyph would be invisible,
908 try a different foreground. */
909 if (fg == bg)
910 fg = face->foreground;
911 if (fg == bg)
912 fg = f->output_data.w32->cursor_foreground_pixel;
913 if (fg == bg)
914 fg = face->foreground;
915 /* Make sure the cursor is distinct from text in this face. */
916 if (bg == face->background
917 && fg == face->foreground)
918 {
919 bg = face->foreground;
920 fg = face->background;
921 }
922 }
923 }
924 3586
925 if (font) 3587/* Draw a relief around the image glyph string S. */
926 require_clipping = (!NILP (Vclip_large_size_font)
927 && ((font->bdf
928 ? (font->bdf->ury > baseline
929 || font->bdf->lly > line_height - baseline)
930 : (font->tm.tmAscent > baseline
931 || font->tm.tmDescent > line_height - baseline))
932 || (!cmpcharp && FONT_MAX_WIDTH (font) > glyph_width)));
933
934 if (font && (just_foreground || (cmpcharp && gidx > 0)))
935 background_filled = 1;
936
937 /* Stippling not supported under w32. */
938
939 else if (!font
940 || font->bdf
941 || FONT_HEIGHT (font) < line_height
942 || FONT_WIDTH (font) < glyph_width
943 || FONT_MAX_WIDTH (font) != FONT_WIDTH (font)
944 || font->tm.tmItalic
945 || cmpcharp)
946 {
947 /* Fill in the background for the current run. */
948 w32_fill_area (f, hdc, bg,
949 left,
950 top,
951 run_width,
952 line_height);
953 background_filled = 1;
954 if (cmpcharp)
955 /* To assure not to fill background while drawing
956 remaining components. */
957 just_foreground = 1;
958 }
959 else
960 background_filled = 0;
961
962 SetBkMode (hdc, background_filled ? TRANSPARENT : OPAQUE);
963 SetTextColor (hdc, fg);
964 SetBkColor (hdc, bg);
965 SetTextAlign (hdc, TA_BASELINE | TA_LEFT);
966
967 /* On NT, where conversion to Unicode has to happen sometime
968 when using the normal ExtTextOut facility, we might as well
969 take advantage of x_2byte_buffer which is already allocated,
970 to avoid the allocation overhead for implicit conversion. */
971
972 if (!print_via_unicode
973 && codepage == CP_DEFAULT
974 && w32_enable_unicode_output
975 && os_subtype == OS_NT
976 && font && !font->bdf)
977 {
978 print_via_unicode = TRUE;
979 }
980 3588
981 /* Note that we can special-case the conversion to Unicode when 3589static void
982 the charset is CHARSET_ASCII (an important case) or Latin-1, 3590x_draw_image_relief (s)
983 because x_2byte_buffer in fact already contains the unicode 3591 struct glyph_string *s;
984 characters. So avoid setting up x_1byte_buffer in that case. */ 3592{
985 if (!print_via_unicode 3593 int x0, y0, x1, y1, thick, raised_p;
986 || (charset != CHARSET_ASCII && charset != charset_latin_iso8859_1)) 3594 RECT r;
987 { 3595 int x;
988 /* Convert x_2byte_buffer into a buffer of single byte 3596 int y = s->ybase - IMAGE_ASCENT (s->img);
989 characters - possibly containing MBCS runs. */ 3597
990 bp = x_1byte_buffer; 3598 /* If first glyph of S has a left box line, start drawing it to the
991 for (i = 0; i < len; i++) 3599 right of that line. */
992 { 3600 if (s->face->box != FACE_NO_BOX
993 if (BYTE1 (*(x_2byte_buffer + i))) 3601 && s->first_glyph->left_box_line_p)
994 *bp++ = BYTE1 (*(x_2byte_buffer + i)); 3602 x = s->x + s->face->box_line_width;
995 *bp++ = BYTE2 (*(x_2byte_buffer + i)); 3603 else
996 } 3604 x = s->x;
997 n_chars = bp - x_1byte_buffer; 3605
998 } 3606 /* If there is a margin around the image, adjust x- and y-position
999 else 3607 by that margin. */
1000 n_chars = len; 3608 if (s->img->margin)
3609 {
3610 x += s->img->margin;
3611 y += s->img->margin;
3612 }
3613
3614 if (s->hl == DRAW_IMAGE_SUNKEN
3615 || s->hl == DRAW_IMAGE_RAISED)
3616 {
3617 thick = tool_bar_button_relief > 0 ? tool_bar_button_relief : 3;
3618 raised_p = s->hl == DRAW_IMAGE_RAISED;
3619 }
3620 else
3621 {
3622 thick = abs (s->img->relief);
3623 raised_p = s->img->relief > 0;
3624 }
3625
3626 x0 = x - thick;
3627 y0 = y - thick;
3628 x1 = x + s->img->width + thick - 1;
3629 y1 = y + s->img->height + thick - 1;
3630
3631 x_setup_relief_colors (s);
3632 w32_get_glyph_string_clip_rect (s, &r);
3633 w32_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p, 1, 1, &r);
3634}
1001 3635
1002 if (print_via_unicode
1003 && charset != CHARSET_ASCII && charset != charset_latin_iso8859_1)
1004 {
1005 i = MultiByteToWideChar
1006 (codepage, 0, x_1byte_buffer, n_chars,
1007 x_2byte_buffer, FRAME_WINDOW_WIDTH (f));
1008 3636
1009 /* Make sure we don't display nothing if conversion fails. */ 3637/* Draw the foreground of image glyph string S to PIXMAP. */
1010 if (i == 0)
1011 print_via_unicode = FALSE;
1012 else
1013 n_chars = i;
1014 }
1015 3638
1016 if (font) 3639static void
1017 { 3640w32_draw_image_foreground_1 (s, pixmap)
1018 if (font->hfont) 3641 struct glyph_string *s;
1019 SelectObject (hdc, font->hfont); 3642 HBITMAP pixmap;
3643{
3644 HDC hdc = CreateCompatibleDC (s->hdc);
3645 HGDIOBJ orig_hdc_obj = SelectObject (hdc, pixmap);
3646 int x;
3647 int y = s->ybase - s->y - IMAGE_ASCENT (s->img);
3648
3649 /* If first glyph of S has a left box line, start drawing it to the
3650 right of that line. */
3651 if (s->face->box != FACE_NO_BOX
3652 && s->first_glyph->left_box_line_p)
3653 x = s->face->box_line_width;
3654 else
3655 x = 0;
1020 3656
1021 if (!cmpcharp) 3657 /* If there is a margin around the image, adjust x- and y-position
1022 { 3658 by that margin. */
1023 int xoffset = 0, yoffset = baseline; 3659 if (s->img->margin)
1024 if (require_clipping || FONT_WIDTH (font) != glyph_width 3660 {
1025 || FONT_MAX_WIDTH (font) != FONT_WIDTH (font)) 3661 x += s->img->margin;
1026 { 3662 y += s->img->margin;
1027 /* The incrementing of i in this loop is done 3663 }
1028 inside the W32_CHAROUT macro. */
1029 for (i = 0; i < n_chars; )
1030 {
1031 if (require_clipping)
1032 {
1033 /* Set up a clipping rectangle for ExtTextOut */
1034 fuOptions |= ETO_CLIPPED;
1035 clip_rectangle.left = left + i * glyph_width;
1036 clip_rectangle.right
1037 = left + (i + 1) * glyph_width;
1038 clip_rectangle.top = top;
1039 clip_rectangle.bottom = top + line_height;
1040 clip_region = &clip_rectangle;
1041 }
1042 W32_TEXTOUT (i, 1);
1043 }
1044 }
1045 else
1046 {
1047 i = 0;
1048 W32_TEXTOUT (i, n_chars);
1049 }
1050 }
1051 else
1052 {
1053 /* Handle composite characters. */
1054 RECT clip_rectangle;
1055 LPRECT clip_region = NULL;
1056 UINT fuOptions = 0;
1057 ABC char_placement;
1058 int char_width = 0;
1059
1060 if (require_clipping)
1061 {
1062 /* Set up a clipping rectangle for ExtTextOut */
1063 fuOptions |= ETO_CLIPPED;
1064 clip_rectangle.left = left;
1065 clip_rectangle.right = left + glyph_width;
1066 clip_rectangle.top = top;
1067 clip_rectangle.bottom = top + line_height;
1068 clip_region = &clip_rectangle;
1069 }
1070 if ((cmpcharp->cmp_rule || relative_compose)
1071 && gidx == 0)
1072 {
1073 /* This is the first character. Initialize variables.
1074 HIGHEST is the highest position of glyphs ever
1075 written, LOWEST the lowest position. */
1076 int xoffset = 0;
1077 int yoffset = baseline;
1078 int start = 0;
1079
1080 if (default_ascent
1081 && CHAR_TABLE_P (Vuse_default_ascent)
1082 && !NILP (Faref (Vuse_default_ascent, first_ch)))
1083 {
1084 highest = default_ascent;
1085 lowest = 0;
1086 }
1087 /* TODO: per char metrics for Truetype and BDF
1088 fonts. */
1089 {
1090 highest = FONT_BASE (font) + 1;
1091 lowest = - (FONT_HEIGHT (font) - FONT_BASE (font));
1092 }
1093 3664
1094 if (cmpcharp->cmp_rule) 3665 if (s->img->pixmap)
1095 xoffset = (int)(cmpcharp->col_offset[0] 3666 {
1096 * FONT_WIDTH (FRAME_FONT (f))); 3667#if 0 /* NTEMACS_TODO: image mask */
1097 3668 if (s->img->mask)
1098 i = 1; 3669 {
1099 3670 /* We can't set both a clip mask and use XSetClipRectangles
1100 /* Truetype fonts often contain underhangs to 3671 because the latter also sets a clip mask. We also can't
1101 handle composition characters. This works 3672 trust on the shape extension to be available
1102 against our attempts to position the characters 3673 (XShapeCombineRegion). So, compute the rectangle to draw
1103 manually, so we need to compensate for this. 3674 manually. */
1104 */ 3675 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
1105 if (print_via_unicode ? 3676 | GCFunction);
1106 GetCharABCWidthsW (hdc, *x_2byte_buffer, 3677 XGCValues xgcv;
1107 *x_2byte_buffer, 3678
1108 &char_placement) 3679 xgcv.clip_mask = s->img->mask;
1109 : GetCharABCWidths (hdc, *x_1byte_buffer, 3680 xgcv.clip_x_origin = x;
1110 *x_1byte_buffer, 3681 xgcv.clip_y_origin = y;
1111 &char_placement)) 3682 xgcv.function = GXcopy;
1112 { 3683 XChangeGC (s->display, s->gc, mask, &xgcv);
1113 char_width = char_placement.abcA 3684
1114 + char_placement.abcB + char_placement.abcC; 3685 XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
1115 xoffset += FONT_WIDTH (font) - char_width; 3686 0, 0, s->img->width, s->img->height, x, y);
1116 } 3687 XSetClipMask (s->display, s->gc, None);
1117 /* Don't let characters go beyond the glyph 3688 }
1118 boundary whatever their over/underhangs. */ 3689 else
1119 if (xoffset > glyph_width - char_width) 3690#endif
1120 xoffset = glyph_width - char_width; 3691 {
1121 3692 HDC compat_hdc = CreateCompatibleDC (hdc);
1122 if (xoffset < 0) 3693 HBRUSH fg_brush = CreateSolidBrush (s->gc->foreground);
1123 xoffset = 0; 3694 HBRUSH orig_brush = SelectObject (hdc, fg_brush);
1124 3695 HGDIOBJ orig_obj = SelectObject (compat_hdc, s->img->pixmap);
1125 /* Draw the first character at the normal 3696
1126 position. */ 3697 SetTextColor (hdc, s->gc->foreground);
1127 W32_TEXTOUT (start, 1); 3698 SetBkColor (hdc, s->gc->background);
1128 gidx++; 3699#if 0 /* From w32bdf.c (which is from Meadow). */
1129 } 3700 BitBlt (hdc, x, y, s->img->width, s->img->height,
1130 else 3701 compat_hdc, 0, 0, SRCCOPY);
1131 i = 0; 3702#else
3703 BitBlt (hdc, x, y, s->img->width, s->img->height,
3704 compat_hdc, 0, 0, 0xB8074A);
3705#endif
3706 SelectObject (hdc, orig_brush);
3707 DeleteObject (fg_brush);
3708 SelectObject (compat_hdc, orig_obj);
3709 DeleteDC (compat_hdc);
3710
3711 /* When the image has a mask, we can expect that at
3712 least part of a mouse highlight or a block cursor will
3713 be visible. If the image doesn't have a mask, make
3714 a block cursor visible by drawing a rectangle around
3715 the image. I believe it's looking better if we do
3716 nothing here for mouse-face. */
3717 if (s->hl == DRAW_CURSOR)
3718 w32_draw_rectangle (hdc, s->gc, x, y, s->img->width - 1,
3719 s->img->height - 1);
3720 }
3721 }
3722 else
3723 w32_draw_rectangle (hdc, s->gc, x, y, s->img->width - 1,
3724 s->img->height - 1);
1132 3725
1133 for (; i < n_chars; gidx++) 3726 SelectObject (hdc, orig_hdc_obj);
1134 { 3727 DeleteDC (hdc);
1135 int xoffset = 0, yoffset = FONT_BASE (font); 3728}
1136 3729
1137 if (relative_compose)
1138 {
1139 /* No per char metrics on w32. */
1140 if (NILP (Vignore_relative_composition)
1141 || NILP (Faref (Vignore_relative_composition,
1142 make_number (cmpcharp->glyph[gidx]))))
1143 {
1144 if (- (FONT_HEIGHT (font) - FONT_BASE (font))
1145 >= relative_compose)
1146 {
1147 /* Draw above the current glyphs. */
1148 yoffset = highest + FONT_HEIGHT (font);
1149 highest += FONT_HEIGHT (font);
1150 }
1151 else if (FONT_BASE (font) <= 0)
1152 {
1153 /* Draw beneath the current glyphs. */
1154 yoffset = lowest;
1155 lowest -= FONT_HEIGHT (font);
1156 }
1157 }
1158 else
1159 {
1160 /* Draw the glyph at normal position. If
1161 it sticks out of HIGHEST or LOWEST,
1162 update them appropriately. */
1163 if (FONT_BASE (font) > highest)
1164 highest = FONT_BASE (font);
1165 else if (- (FONT_HEIGHT (font) - FONT_BASE (font))
1166 < lowest)
1167 lowest = - (FONT_HEIGHT (font) -
1168 FONT_BASE (font));
1169 }
1170 }
1171 else if (cmpcharp->cmp_rule)
1172 {
1173 int gref = (cmpcharp->cmp_rule[gidx] - 0xA0) / 9;
1174 int nref = (cmpcharp->cmp_rule[gidx] - 0xA0) % 9;
1175 int bottom, top;
1176
1177 /* Re-encode GREF and NREF so that they specify
1178 only Y-axis information:
1179 0:top, 1:base, 2:bottom, 3:center */
1180 gref = gref / 3 + (gref == 4) * 2;
1181 nref = nref / 3 + (nref == 4) * 2;
1182
1183 /* No per char metrics on w32. */
1184 bottom = ((gref == 0 ? highest : gref == 1 ? 0
1185 : gref == 2 ? lowest
1186 : (highest + lowest) / 2)
1187 - (nref == 0 ? FONT_HEIGHT (font)
1188 : nref == 1 ? (FONT_HEIGHT (font) -
1189 FONT_BASE (font))
1190 : nref == 2 ? 0
1191 : (FONT_HEIGHT (font) / 2)));
1192 top = bottom + FONT_HEIGHT (font);
1193
1194 if (top > highest)
1195 highest = top;
1196 if (bottom < lowest)
1197 lowest = bottom;
1198 yoffset = bottom + FONT_HEIGHT (font);
1199 xoffset = (int)(cmpcharp->col_offset[gidx]
1200 * FONT_WIDTH (FRAME_FONT(f)));
1201 }
1202 3730
1203 /* Truetype fonts often contain underhangs to 3731/* Draw part of the background of glyph string S. X, Y, W, and H
1204 handle composition characters. This works 3732 give the rectangle to draw. */
1205 against our attempts to position the characters
1206 manually, so we need to compensate for this.
1207 */
1208 if (print_via_unicode ?
1209 GetCharABCWidthsW (hdc, *(x_2byte_buffer + i),
1210 *(x_2byte_buffer + i),
1211 &char_placement)
1212 : GetCharABCWidths (hdc, *(x_1byte_buffer + i),
1213 *(x_1byte_buffer + i),
1214 &char_placement))
1215 {
1216 char_width = char_placement.abcA
1217 + char_placement.abcB + char_placement.abcC;
1218 xoffset += FONT_WIDTH (font) - char_width;
1219 }
1220 /* Don't let characters go beyond the glyph
1221 boundary whatever their over/underhangs. */
1222 if (xoffset > glyph_width - char_width)
1223 xoffset = glyph_width - char_width;
1224 3733
1225 if (xoffset < 0) 3734static void
1226 xoffset = 0; 3735x_draw_glyph_string_bg_rect (s, x, y, w, h)
3736 struct glyph_string *s;
3737 int x, y, w, h;
3738{
3739#if 0 /* NTEMACS_TODO: stipple */
3740 if (s->stippled_p)
3741 {
3742 /* Fill background with a stipple pattern. */
3743 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
3744 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
3745 XSetFillStyle (s->display, s->gc, FillSolid);
3746 }
3747 else
3748#endif
3749 x_clear_glyph_string_rect (s, x, y, w, h);
3750}
1227 3751
1228 W32_TEXTOUT (i, 1);
1229 }
1230 }
1231 }
1232 if (!font)
1233 {
1234 /* Show rectangles to indicate that we found no font. */
1235 int limit = cmpcharp ? 1 : len;
1236 HBRUSH hb, oldhb;
1237 HPEN hp, oldhp;
1238 hb = CreateSolidBrush (bg);
1239 hp = CreatePen (PS_SOLID, 0, fg);
1240 oldhb = SelectObject(hdc, hb);
1241 oldhp = SelectObject(hdc, hp);
1242
1243 for (i = 0; i < limit; i++)
1244 Rectangle (hdc, left + glyph_width * i, top,
1245 left + glyph_width * (i + 1),
1246 top + line_height);
1247
1248 SelectObject(hdc, oldhb);
1249 SelectObject(hdc, oldhp);
1250 DeleteObject (hb);
1251 DeleteObject (hp);
1252 }
1253 else if (require_clipping && !NILP (Vhighlight_wrong_size_font))
1254 {
1255 /* Indicate that we found a font of inappropriate size. */
1256 int limit = cmpcharp ? 1 : len;
1257 3752
1258 for (i = 0; i < limit; i++) 3753/* Draw image glyph string S.
1259 { 3754
1260 w32_fill_area (f, hdc, fg, left + glyph_width * i, 3755 s->y
1261 top + line_height - 1, glyph_width, 1); 3756 s->x +-------------------------
1262 w32_fill_area (f, hdc, fg, left + glyph_width * i, 3757 | s->face->box
1263 top + line_height - 3, 1, 2); 3758 |
1264 } 3759 | +-------------------------
1265 } 3760 | | s->img->margin
3761 | |
3762 | | +-------------------
3763 | | | the image
1266 3764
3765 */
3766
3767static void
3768x_draw_image_glyph_string (s)
3769 struct glyph_string *s;
3770{
3771 int x, y;
3772 int box_line_width = s->face->box_line_width;
3773 int margin = s->img->margin;
3774 int height;
3775 HBITMAP pixmap = 0;
3776
3777 height = s->height - 2 * box_line_width;
3778
3779 /* Fill background with face under the image. Do it only if row is
3780 taller than image or if image has a clip mask to reduce
3781 flickering. */
3782 s->stippled_p = s->face->stipple != 0;
3783 if (height > s->img->height
3784 || margin
3785#if 0 /* NTEMACS_TODO: image mask */
3786 || s->img->mask
3787#endif
3788 || s->img->pixmap == 0
3789 || s->width != s->background_width)
3790 {
3791 if (box_line_width && s->first_glyph->left_box_line_p)
3792 x = s->x + box_line_width;
3793 else
3794 x = s->x;
3795
3796 y = s->y + box_line_width;
3797#if 0 /* NTEMACS_TODO: image mask */
3798 if (s->img->mask)
1267 { 3799 {
1268 /* Setting underline position based on the metric of the 3800 /* Create a pixmap as large as the glyph string Fill it with
1269 current font results in shaky underline if it strides 3801 the background color. Copy the image to it, using its
1270 over different fonts. So, we set the position based only 3802 mask. Copy the temporary pixmap to the display. */
1271 on the default font of this frame. */ 3803 Screen *screen = FRAME_X_SCREEN (s->f);
1272 int underline_position = 1; 3804 int depth = DefaultDepthOfScreen (screen);
1273 3805
1274 if (FONT_HEIGHT (FRAME_FONT (f)) - FONT_BASE(FRAME_FONT (f)) 3806 /* Create a pixmap as large as the glyph string. */
1275 <= underline_position) 3807 pixmap = XCreatePixmap (s->display, s->window,
1276 underline_position = (FONT_HEIGHT (FRAME_FONT (f)) - 3808 s->background_width,
1277 FONT_BASE(FRAME_FONT (f))) - 1; 3809 s->height, depth);
1278 3810
1279 if (face->underline) 3811 /* Don't clip in the following because we're working on the
1280 w32_fill_area (f, hdc, fg, left, 3812 pixmap. */
1281 top + FONT_BASE (FRAME_FONT (f)) 3813 XSetClipMask (s->display, s->gc, None);
1282 + underline_position, 3814
1283 run_width, 1); 3815 /* Fill the pixmap with the background color/stipple. */
3816 if (s->stippled_p)
3817 {
3818 /* Fill background with a stipple pattern. */
3819 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
3820 XFillRectangle (s->display, pixmap, s->gc,
3821 0, 0, s->background_width, s->height);
3822 XSetFillStyle (s->display, s->gc, FillSolid);
3823 }
3824 else
3825 {
3826 XGCValues xgcv;
3827 XGetGCValues (s->display, s->gc, GCForeground | GCBackground,
3828 &xgcv);
3829 XSetForeground (s->display, s->gc, xgcv.background);
3830 XFillRectangle (s->display, pixmap, s->gc,
3831 0, 0, s->background_width, s->height);
3832 XSetForeground (s->display, s->gc, xgcv.foreground);
3833 }
1284 } 3834 }
3835 else
3836#endif
3837 /* Implementation idea: Is it possible to construct a mask?
3838 We could look at the color at the margins of the image, and
3839 say that this color is probably the background color of the
3840 image. */
3841 x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
3842
3843 s->background_filled_p = 1;
3844 }
1285 3845
1286 if (!cmpcharp) 3846 /* Draw the foreground. */
1287 left += run_width; 3847 if (pixmap != 0)
3848 {
3849 w32_draw_image_foreground_1 (s, pixmap);
3850 x_set_glyph_string_clipping (s);
3851 {
3852 HDC compat_hdc = CreateCompatibleDC (s->hdc);
3853 HBRUSH fg_brush = CreateSolidBrush (s->gc->foreground);
3854 HBRUSH orig_brush = SelectObject (s->hdc, fg_brush);
3855 HGDIOBJ orig_obj = SelectObject (compat_hdc, pixmap);
3856
3857 SetTextColor (s->hdc, s->gc->foreground);
3858 SetBkColor (s->hdc, s->gc->background);
3859#if 0 /* From w32bdf.c (which is from Meadow). */
3860 BitBlt (s->hdc, s->x, s->y, s->background_width, s->height,
3861 compat_hdc, 0, 0, SRCCOPY);
3862#else
3863 BitBlt (s->hdc, s->x, s->y, s->background_width, s->height,
3864 compat_hdc, 0, 0, 0xB8074A);
3865#endif
3866 SelectObject (s->hdc, orig_brush);
3867 DeleteObject (fg_brush);
3868 SelectObject (compat_hdc, orig_obj);
3869 DeleteDC (compat_hdc);
1288 } 3870 }
3871 DeleteObject (pixmap);
3872 pixmap = 0;
1289 } 3873 }
1290 release_frame_dc (f, hdc); 3874 else
3875 x_draw_image_foreground (s);
1291 3876
1292 return (left - orig_left); 3877 /* If we must draw a relief around the image, do it. */
3878 if (s->img->relief
3879 || s->hl == DRAW_IMAGE_RAISED
3880 || s->hl == DRAW_IMAGE_SUNKEN)
3881 x_draw_image_relief (s);
1293} 3882}
1294 3883
1295
1296/* Output some text at the nominal frame cursor position.
1297 Advance the cursor over the text.
1298 Output LEN glyphs at START.
1299 3884
1300 `highlight', set up by w32_reassert_line_highlight or w32_change_line_highlight, 3885/* Draw stretch glyph string S. */
1301 controls the pixel values used for foreground and background. */
1302 3886
1303static void 3887static void
1304w32_write_glyphs (start, len) 3888x_draw_stretch_glyph_string (s)
1305 register GLYPH *start; 3889 struct glyph_string *s;
1306 int len;
1307{ 3890{
1308 register int temp_length; 3891 xassert (s->first_glyph->type == STRETCH_GLYPH);
1309 struct frame *f; 3892 s->stippled_p = s->face->stipple != 0;
3893
3894 if (s->hl == DRAW_CURSOR
3895 && !x_stretch_cursor_p)
3896 {
3897 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
3898 as wide as the stretch glyph. */
3899 int width = min (CANON_X_UNIT (s->f), s->background_width);
3900
3901 /* Draw cursor. */
3902 x_draw_glyph_string_bg_rect (s, s->x, s->y, width, s->height);
3903
3904 /* Clear rest using the GC of the original non-cursor face. */
3905 if (width < s->background_width)
3906 {
3907 XGCValues *gc = s->face->gc;
3908 int x = s->x + width, y = s->y;
3909 int w = s->background_width - width, h = s->height;
3910 RECT r;
3911 HDC hdc = s->hdc;
3912 w32_get_glyph_string_clip_rect (s, &r);
3913 w32_set_clip_rectangle (hdc, &r);
3914
3915#if 0 /* NTEMACS_TODO: stipple */
3916 if (s->face->stipple)
3917 {
3918 /* Fill background with a stipple pattern. */
3919 XSetFillStyle (s->display, gc, FillOpaqueStippled);
3920 XFillRectangle (s->display, s->window, gc, x, y, w, h);
3921 XSetFillStyle (s->display, gc, FillSolid);
3922 }
3923 else
3924#endif
3925 {
3926 w32_fill_area (s->f, s->hdc, gc->background, x, y, w, h);
3927 }
3928 }
3929 }
3930 else
3931 x_draw_glyph_string_bg_rect (s, s->x, s->y, s->background_width,
3932 s->height);
3933
3934 s->background_filled_p = 1;
3935}
1310 3936
1311 BLOCK_INPUT;
1312 3937
1313 do_line_dance (); 3938/* Draw glyph string S. */
1314 f = updating_frame; 3939
1315 if (f == 0) 3940static void
3941x_draw_glyph_string (s)
3942 struct glyph_string *s;
3943{
3944 /* If S draws into the background of its successor, draw the
3945 background of the successor first so that S can draw into it.
3946 This makes S->next use XDrawString instead of XDrawImageString. */
3947 if (s->next && s->right_overhang && !s->for_overlaps_p)
1316 { 3948 {
1317 f = selected_frame; 3949 xassert (s->next->img == NULL);
1318 /* If not within an update, 3950 x_set_glyph_string_gc (s->next);
1319 output at the frame's visible cursor. */ 3951 x_set_glyph_string_clipping (s->next);
1320 curs_x = f->cursor_x; 3952 x_draw_glyph_string_background (s->next, 1);
1321 curs_y = f->cursor_y;
1322 } 3953 }
1323 3954
1324 dumpglyphs (f, 3955 /* Set up S->gc, set clipping and draw S. */
1325 CHAR_TO_PIXEL_COL (f, curs_x), 3956 x_set_glyph_string_gc (s);
1326 CHAR_TO_PIXEL_ROW (f, curs_y), 3957 x_set_glyph_string_clipping (s);
1327 start, len, highlight, 0, NULL); 3958
3959 switch (s->first_glyph->type)
3960 {
3961 case IMAGE_GLYPH:
3962 x_draw_image_glyph_string (s);
3963 break;
3964
3965 case STRETCH_GLYPH:
3966 x_draw_stretch_glyph_string (s);
3967 break;
3968
3969 case CHAR_GLYPH:
3970 if (s->for_overlaps_p)
3971 s->background_filled_p = 1;
3972 else
3973 x_draw_glyph_string_background (s, 0);
3974 x_draw_glyph_string_foreground (s);
3975 break;
3976
3977 case COMPOSITE_GLYPH:
3978 if (s->for_overlaps_p || s->gidx > 0)
3979 s->background_filled_p = 1;
3980 else
3981 x_draw_glyph_string_background (s, 1);
3982 x_draw_composite_glyph_string_foreground (s);
3983 break;
3984
3985 default:
3986 abort ();
3987 }
3988
3989 if (!s->for_overlaps_p)
3990 {
3991 /* Draw underline. */
3992 if (s->face->underline_p && (!s->font->bdf && !s->font->tm.tmUnderlined))
3993 {
3994 unsigned long h = 1;
3995 unsigned long dy = s->height - h;
3996
3997 if (s->face->underline_defaulted_p)
3998 {
3999 w32_fill_area (s->f, s->hdc, s->gc->foreground, s->x,
4000 s->y + dy, s->width, 1);
4001 }
4002 else
4003 {
4004 w32_fill_area (s->f, s->hdc, s->face->underline_color, s->x,
4005 s->y + dy, s->width, 1);
4006 }
4007 }
4008
4009 /* Draw overline. */
4010 if (s->face->overline_p)
4011 {
4012 unsigned long dy = 0, h = 1;
4013
4014 if (s->face->overline_color_defaulted_p)
4015 {
4016 w32_fill_area (s->f, s->hdc, s->gc->foreground, s->x,
4017 s->y + dy, s->width, h);
4018 }
4019 else
4020 {
4021 w32_fill_area (s->f, s->hdc, s->face->underline_color, s->x,
4022 s->y + dy, s->width, h);
4023 }
4024 }
4025
4026 /* Draw strike-through. */
4027 if (s->face->strike_through_p && (!s->font->bdf &&!s->font->tm.tmStruckOut))
4028 {
4029 unsigned long h = 1;
4030 unsigned long dy = (s->height - h) / 2;
4031
4032 if (s->face->strike_through_color_defaulted_p)
4033 {
4034 w32_fill_area (s->f, s->hdc, s->gc->foreground, s->x, s->y + dy,
4035 s->width, h);
4036 }
4037 else
4038 {
4039 w32_fill_area (s->f, s->hdc, s->face->underline_color, s->x,
4040 s->y + dy, s->width, h);
4041 }
4042 }
4043
4044 /* Draw relief. */
4045 if (s->face->box != FACE_NO_BOX)
4046 x_draw_glyph_string_box (s);
4047 }
4048
4049 /* Reset clipping. */
4050 w32_set_clip_rectangle (s->hdc, NULL);
4051}
4052
4053
4054static int x_fill_composite_glyph_string P_ ((struct glyph_string *,
4055 struct face **, int));
4056
4057
4058/* Load glyph string S with a composition components specified by S->cmp.
4059 FACES is an array of faces for all components of this composition.
4060 S->gidx is the index of the first component for S.
4061 OVERLAPS_P non-zero means S should draw the foreground only, and
4062 use its lines physical height for clipping.
4063
4064 Value is the index of a component not in S. */
4065
4066static int
4067x_fill_composite_glyph_string (s, faces, overlaps_p)
4068 struct glyph_string *s;
4069 struct face **faces;
4070 int overlaps_p;
4071{
4072 int i;
4073
4074 xassert (s);
4075
4076 s->for_overlaps_p = overlaps_p;
4077
4078 s->face = faces[s->gidx];
4079 s->font = s->face->font;
4080 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
4081
4082 /* For all glyphs of this composition, starting at the offset
4083 S->gidx, until we reach the end of the definition or encounter a
4084 glyph that requires the different face, add it to S. */
4085 ++s->nchars;
4086 for (i = s->gidx + 1; i < s->cmp->glyph_len && faces[i] == s->face; ++i)
4087 ++s->nchars;
4088
4089 /* All glyph strings for the same composition has the same width,
4090 i.e. the width set for the first component of the composition. */
1328 4091
1329 /* If we drew on top of the cursor, note that it is turned off. */ 4092 s->width = s->first_glyph->pixel_width;
1330 if (curs_y == f->phys_cursor_y
1331 && curs_x <= f->phys_cursor_x
1332 && curs_x + len > f->phys_cursor_x)
1333 f->phys_cursor_on = 0;
1334 4093
1335 if (updating_frame == 0) 4094 /* If the specified font could not be loaded, use the frame's
4095 default font, but record the fact that we couldn't load it in
4096 the glyph string so that we can draw rectangles for the
4097 characters of the glyph string. */
4098 if (s->font == NULL)
1336 { 4099 {
1337 f->cursor_x += len; 4100 s->font_not_found_p = 1;
1338 x_display_cursor (f, 1); 4101 s->font = FRAME_FONT (s->f);
1339 f->cursor_x -= len;
1340 } 4102 }
4103
4104 /* Adjust base line for subscript/superscript text. */
4105 s->ybase += s->first_glyph->voffset;
4106
4107 xassert (s->face && s->face->gc);
4108
4109 /* This glyph string must always be drawn with 16-bit functions. */
4110 s->two_byte_p = 1;
4111
4112 return s->gidx + s->nchars;
4113}
4114
4115
4116/* Load glyph string S with a sequence of characters.
4117 FACE_ID is the face id of the string. START is the index of the
4118 first glyph to consider, END is the index of the last + 1.
4119 OVERLAPS_P non-zero means S should draw the foreground only, and
4120 use its lines physical height for clipping.
4121
4122 Value is the index of the first glyph not in S. */
4123
4124static int
4125x_fill_glyph_string (s, face_id, start, end, overlaps_p)
4126 struct glyph_string *s;
4127 int face_id;
4128 int start, end, overlaps_p;
4129{
4130 struct glyph *glyph, *last;
4131 int voffset;
4132
4133 xassert (s->f == XFRAME (s->w->frame));
4134 xassert (s->nchars == 0);
4135 xassert (start >= 0 && end > start);
4136
4137 s->for_overlaps_p = overlaps_p;
4138
4139 glyph = s->row->glyphs[s->area] + start;
4140 last = s->row->glyphs[s->area] + end;
4141 voffset = glyph->voffset;
4142
4143 while (glyph < last
4144 && glyph->type == CHAR_GLYPH
4145 && glyph->voffset == voffset
4146 /* Same face id implies same charset, nowadays. */
4147 && glyph->face_id == face_id)
4148 {
4149 s->face = x_get_glyph_face_and_encoding (s->f, glyph,
4150 s->char2b + s->nchars);
4151 if (BYTE2(s->char2b[s->nchars]) != 0)
4152 s->two_byte_p = 1;
4153
4154 ++s->nchars;
4155 xassert (s->nchars <= end - start);
4156 s->width += glyph->pixel_width;
4157 ++glyph;
4158 }
4159
4160 s->font = s->face->font;
4161 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
4162
4163 /* If the specified font could not be loaded, use the frame's font,
4164 but record the fact that we couldn't load it in
4165 S->font_not_found_p so that we can draw rectangles for the
4166 characters of the glyph string. */
4167 if (s->font == NULL)
4168 {
4169 s->font_not_found_p = 1;
4170 s->font = FRAME_FONT (s->f);
4171 }
4172
4173 /* Adjust base line for subscript/superscript text. */
4174 s->ybase += voffset;
4175
4176 xassert (s->face && s->face->gc);
4177 return glyph - s->row->glyphs[s->area];
4178}
4179
4180
4181/* Fill glyph string S from image glyph S->first_glyph. */
4182
4183static void
4184x_fill_image_glyph_string (s)
4185 struct glyph_string *s;
4186{
4187 xassert (s->first_glyph->type == IMAGE_GLYPH);
4188 s->img = IMAGE_FROM_ID (s->f, s->first_glyph->u.img_id);
4189 xassert (s->img);
4190 s->face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
4191 s->font = s->face->font;
4192 s->width = s->first_glyph->pixel_width;
4193
4194 /* Adjust base line for subscript/superscript text. */
4195 s->ybase += s->first_glyph->voffset;
4196}
4197
4198
4199/* Fill glyph string S from stretch glyph S->first_glyph. */
4200
4201static void
4202x_fill_stretch_glyph_string (s)
4203 struct glyph_string *s;
4204{
4205 xassert (s->first_glyph->type == STRETCH_GLYPH);
4206 s->face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
4207 s->font = s->face->font;
4208 s->width = s->first_glyph->pixel_width;
4209
4210 /* Adjust base line for subscript/superscript text. */
4211 s->ybase += s->first_glyph->voffset;
4212}
4213
4214
4215/* Initialize glyph string S. CHAR2B is a suitably allocated vector
4216 of XChar2b structures for S; it can't be allocated in
4217 x_init_glyph_string because it must be allocated via `alloca'. W
4218 is the window on which S is drawn. ROW and AREA are the glyph row
4219 and area within the row from which S is constructed. START is the
4220 index of the first glyph structure covered by S. HL is a
4221 face-override for drawing S. */
4222
4223static void
4224w32_init_glyph_string (s, hdc, char2b, w, row, area, start, hl)
4225 struct glyph_string *s;
4226 HDC hdc;
4227 wchar_t *char2b;
4228 struct window *w;
4229 struct glyph_row *row;
4230 enum glyph_row_area area;
4231 int start;
4232 enum draw_glyphs_face hl;
4233{
4234 bzero (s, sizeof *s);
4235 s->w = w;
4236 s->f = XFRAME (w->frame);
4237 s->hdc = hdc;
4238 s->window = FRAME_W32_WINDOW (s->f);
4239 s->char2b = char2b;
4240 s->hl = hl;
4241 s->row = row;
4242 s->area = area;
4243 s->first_glyph = row->glyphs[area] + start;
4244 s->height = row->height;
4245 s->y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
4246
4247 /* Display the internal border below the tool-bar window. */
4248 if (s->w == XWINDOW (s->f->tool_bar_window))
4249 s->y -= s->f->output_data.w32->internal_border_width;
4250
4251 s->ybase = s->y + row->ascent;
4252}
4253
4254
4255/* Set background width of glyph string S. START is the index of the
4256 first glyph following S. LAST_X is the right-most x-position + 1
4257 in the drawing area. */
4258
4259static INLINE void
4260x_set_glyph_string_background_width (s, start, last_x)
4261 struct glyph_string *s;
4262 int start;
4263 int last_x;
4264{
4265 /* If the face of this glyph string has to be drawn to the end of
4266 the drawing area, set S->extends_to_end_of_line_p. */
4267 struct face *default_face = FACE_FROM_ID (s->f, DEFAULT_FACE_ID);
4268
4269 if (start == s->row->used[s->area]
4270 && s->hl == DRAW_NORMAL_TEXT
4271 && ((s->area == TEXT_AREA && s->row->fill_line_p)
4272 || s->face->background != default_face->background
4273 || s->face->stipple != default_face->stipple))
4274 s->extends_to_end_of_line_p = 1;
4275
4276 /* If S extends its face to the end of the line, set its
4277 background_width to the distance to the right edge of the drawing
4278 area. */
4279 if (s->extends_to_end_of_line_p)
4280 s->background_width = last_x - s->x + 1;
1341 else 4281 else
1342 curs_x += len; 4282 s->background_width = s->width;
4283}
1343 4284
1344 UNBLOCK_INPUT; 4285
4286/* Add a glyph string for a stretch glyph to the list of strings
4287 between HEAD and TAIL. START is the index of the stretch glyph in
4288 row area AREA of glyph row ROW. END is the index of the last glyph
4289 in that glyph row area. X is the current output position assigned
4290 to the new glyph string constructed. HL overrides that face of the
4291 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
4292 is the right-most x-position of the drawing area. */
4293
4294#define BUILD_STRETCH_GLYPH_STRING(hdc, W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
4295 do \
4296 { \
4297 s = (struct glyph_string *) alloca (sizeof *s); \
4298 w32_init_glyph_string (s, hdc, NULL, W, ROW, AREA, START, HL); \
4299 x_fill_stretch_glyph_string (s); \
4300 x_append_glyph_string (&HEAD, &TAIL, s); \
4301 ++START; \
4302 s->x = (X); \
4303 } \
4304 while (0)
4305
4306
4307/* Add a glyph string for an image glyph to the list of strings
4308 between HEAD and TAIL. START is the index of the image glyph in
4309 row area AREA of glyph row ROW. END is the index of the last glyph
4310 in that glyph row area. X is the current output position assigned
4311 to the new glyph string constructed. HL overrides that face of the
4312 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
4313 is the right-most x-position of the drawing area. */
4314
4315#define BUILD_IMAGE_GLYPH_STRING(hdc, W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
4316 do \
4317 { \
4318 s = (struct glyph_string *) alloca (sizeof *s); \
4319 w32_init_glyph_string (s, hdc, NULL, W, ROW, AREA, START, HL); \
4320 x_fill_image_glyph_string (s); \
4321 x_append_glyph_string (&HEAD, &TAIL, s); \
4322 ++START; \
4323 s->x = (X); \
4324 } \
4325 while (0)
4326
4327
4328/* Add a glyph string for a sequence of character glyphs to the list
4329 of strings between HEAD and TAIL. START is the index of the first
4330 glyph in row area AREA of glyph row ROW that is part of the new
4331 glyph string. END is the index of the last glyph in that glyph row
4332 area. X is the current output position assigned to the new glyph
4333 string constructed. HL overrides that face of the glyph; e.g. it
4334 is DRAW_CURSOR if a cursor has to be drawn. LAST_X is the
4335 right-most x-position of the drawing area. */
4336
4337#define BUILD_CHAR_GLYPH_STRINGS(hdc, W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
4338 do \
4339 { \
4340 int c, charset, face_id; \
4341 wchar_t *char2b; \
4342 \
4343 c = (ROW)->glyphs[AREA][START].u.ch; \
4344 charset = CHAR_CHARSET (c); \
4345 face_id = (ROW)->glyphs[AREA][START].face_id; \
4346 s = (struct glyph_string *) alloca (sizeof *s); \
4347 char2b = (wchar_t *) alloca ((END - START) * sizeof *char2b); \
4348 w32_init_glyph_string (s, hdc, char2b, W, ROW, AREA, START, HL); \
4349 x_append_glyph_string (&HEAD, &TAIL, s); \
4350 s->charset = charset; \
4351 s->x = (X); \
4352 START = x_fill_glyph_string (s, face_id, START, END, \
4353 OVERLAPS_P); \
4354 } \
4355 while (0)
4356
4357
4358/* Add a glyph string for a composite sequence to the list of strings
4359 between HEAD and TAIL. START is the index of the first glyph in
4360 row area AREA of glyph row ROW that is part of the new glyph
4361 string. END is the index of the last glyph in that glyph row area.
4362 X is the current output position assigned to the new glyph string
4363 constructed. HL overrides that face of the glyph; e.g. it is
4364 DRAW_CURSOR if a cursor has to be drawn. LAST_X is the right-most
4365 x-position of the drawing area. */
4366
4367#define BUILD_COMPOSITE_GLYPH_STRING(hdc, W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
4368 do { \
4369 int cmp_id = (ROW)->glyphs[AREA][START].u.cmp_id; \
4370 int face_id = (ROW)->glyphs[AREA][START].face_id; \
4371 struct composition *cmp = composition_table[cmp_id]; \
4372 int glyph_len = cmp->glyph_len; \
4373 wchar_t *char2b; \
4374 struct face **faces; \
4375 struct glyph_string *first_s = NULL; \
4376 int n; \
4377 \
4378 char2b = (wchar_t *) alloca ((sizeof *char2b) * glyph_len); \
4379 faces = (struct face **) alloca ((sizeof *faces) * glyph_len); \
4380 /* At first, fill in `char2b' and `faces'. */ \
4381 for (n = 0; n < glyph_len; n++) \
4382 { \
4383 int c = COMPOSITION_GLYPH (cmp, n); \
4384 faces[n] = x_get_char_face_and_encoding (XFRAME (w->frame), c, \
4385 face_id, char2b + n, 1); \
4386 } \
4387 \
4388 /* Make glyph_strings for each glyph sequence that is drawable by \
4389 the same face, and append them to HEAD/TAIL. */ \
4390 for (n = 0; n < cmp->glyph_len;) \
4391 { \
4392 s = (struct glyph_string *) alloca (sizeof *s); \
4393 w32_init_glyph_string (s, hdc, char2b + n, W, ROW, AREA, START, HL); \
4394 x_append_glyph_string (&(HEAD), &(TAIL), s); \
4395 s->cmp = cmp; \
4396 s->gidx = n; \
4397 s->charset = 0; \
4398 s->x = (X); \
4399 \
4400 if (n == 0) \
4401 first_s = s; \
4402 \
4403 n = x_fill_composite_glyph_string (s, faces, OVERLAPS_P); \
4404 } \
4405 \
4406 ++START; \
4407 s = first_s; \
4408 } while (0)
4409
4410/* Build a list of glyph strings between HEAD and TAIL for the glyphs
4411 of AREA of glyph row ROW on window W between indices START and END.
4412 HL overrides the face for drawing glyph strings, e.g. it is
4413 DRAW_CURSOR to draw a cursor. X and LAST_X are start and end
4414 x-positions of the drawing area.
4415
4416 This is an ugly monster macro construct because we must use alloca
4417 to allocate glyph strings (because x_draw_glyphs can be called
4418 asynchronously). */
4419
4420#define BUILD_GLYPH_STRINGS(hdc, W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
4421 do \
4422 { \
4423 HEAD = TAIL = NULL; \
4424 while (START < END) \
4425 { \
4426 struct glyph *first_glyph = (ROW)->glyphs[AREA] + START; \
4427 switch (first_glyph->type) \
4428 { \
4429 case CHAR_GLYPH: \
4430 BUILD_CHAR_GLYPH_STRINGS (hdc, W, ROW, AREA, START, END, \
4431 HEAD, TAIL, HL, X, LAST_X, \
4432 OVERLAPS_P); \
4433 break; \
4434 \
4435 case COMPOSITE_GLYPH: \
4436 BUILD_COMPOSITE_GLYPH_STRING (hdc, W, ROW, AREA, START, \
4437 END, HEAD, TAIL, HL, X, \
4438 LAST_X, OVERLAPS_P); \
4439 break; \
4440 \
4441 case STRETCH_GLYPH: \
4442 BUILD_STRETCH_GLYPH_STRING (hdc, W, ROW, AREA, START, END,\
4443 HEAD, TAIL, HL, X, LAST_X); \
4444 break; \
4445 \
4446 case IMAGE_GLYPH: \
4447 BUILD_IMAGE_GLYPH_STRING (hdc, W, ROW, AREA, START, END, \
4448 HEAD, TAIL, HL, X, LAST_X); \
4449 break; \
4450 \
4451 default: \
4452 abort (); \
4453 } \
4454 \
4455 x_set_glyph_string_background_width (s, START, LAST_X); \
4456 (X) += s->width; \
4457 } \
4458 } \
4459 while (0)
4460
4461
4462/* Draw glyphs between START and END in AREA of ROW on window W,
4463 starting at x-position X. X is relative to AREA in W. HL is a
4464 face-override with the following meaning:
4465
4466 DRAW_NORMAL_TEXT draw normally
4467 DRAW_CURSOR draw in cursor face
4468 DRAW_MOUSE_FACE draw in mouse face.
4469 DRAW_INVERSE_VIDEO draw in mode line face
4470 DRAW_IMAGE_SUNKEN draw an image with a sunken relief around it
4471 DRAW_IMAGE_RAISED draw an image with a raised relief around it
4472
4473 If REAL_START is non-null, return in *REAL_START the real starting
4474 position for display. This can be different from START in case
4475 overlapping glyphs must be displayed. If REAL_END is non-null,
4476 return in *REAL_END the real end position for display. This can be
4477 different from END in case overlapping glyphs must be displayed.
4478
4479 If OVERLAPS_P is non-zero, draw only the foreground of characters
4480 and clip to the physical height of ROW.
4481
4482 Value is the x-position reached, relative to AREA of W. */
4483
4484static int
4485x_draw_glyphs (w, x, row, area, start, end, hl, real_start, real_end,
4486 overlaps_p)
4487 struct window *w;
4488 int x;
4489 struct glyph_row *row;
4490 enum glyph_row_area area;
4491 int start, end;
4492 enum draw_glyphs_face hl;
4493 int *real_start, *real_end;
4494 int overlaps_p;
4495{
4496 struct glyph_string *head, *tail;
4497 struct glyph_string *s;
4498 int last_x, area_width;
4499 int x_reached;
4500 int i, j;
4501 HDC hdc = get_frame_dc (XFRAME (WINDOW_FRAME (w)));
4502
4503 /* Let's rather be paranoid than getting a SEGV. */
4504 start = max (0, start);
4505 end = min (end, row->used[area]);
4506 if (real_start)
4507 *real_start = start;
4508 if (real_end)
4509 *real_end = end;
4510
4511 /* Translate X to frame coordinates. Set last_x to the right
4512 end of the drawing area. */
4513 if (row->full_width_p)
4514 {
4515 struct frame *f = XFRAME (WINDOW_FRAME (w));
4516
4517 /* X is relative to the left edge of W, without scroll bars
4518 or flag areas. */
4519 /* int width = FRAME_FLAGS_AREA_WIDTH (f); */
4520 int window_left_x = WINDOW_LEFT_MARGIN (w) * CANON_X_UNIT (f);
4521
4522 x += window_left_x;
4523 area_width = XFASTINT (w->width) * CANON_X_UNIT (f);
4524 last_x = window_left_x + area_width;
4525
4526 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
4527 {
4528 int width = FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
4529 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
4530 last_x += width;
4531 else
4532 x -= width;
4533 }
4534
4535 x += FRAME_INTERNAL_BORDER_WIDTH (f);
4536 last_x -= FRAME_INTERNAL_BORDER_WIDTH (f);
4537 }
4538 else
4539 {
4540 x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, x);
4541 area_width = window_box_width (w, area);
4542 last_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, area_width);
4543 }
4544
4545 /* Build a doubly-linked list of glyph_string structures between
4546 head and tail from what we have to draw. Note that the macro
4547 BUILD_GLYPH_STRINGS will modify its start parameter. That's
4548 the reason we use a separate variable `i'. */
4549 i = start;
4550 BUILD_GLYPH_STRINGS (hdc, w, row, area, i, end, head, tail, hl, x, last_x,
4551 overlaps_p);
4552
4553 if (tail)
4554 x_reached = tail->x + tail->background_width;
4555 else
4556 x_reached = x;
4557
4558 /* If there are any glyphs with lbearing < 0 or rbearing > width in
4559 the row, redraw some glyphs in front or following the glyph
4560 strings built above. */
4561 if (!overlaps_p && row->contains_overlapping_glyphs_p)
4562 {
4563 int dummy_x = 0;
4564 struct glyph_string *h, *t;
4565
4566 /* Compute overhangs for all glyph strings. */
4567 for (s = head; s; s = s->next)
4568 x_compute_glyph_string_overhangs (s);
4569
4570 /* Prepend glyph strings for glyphs in front of the first glyph
4571 string that are overwritten because of the first glyph
4572 string's left overhang. The background of all strings
4573 prepended must be drawn because the first glyph string
4574 draws over it. */
4575 i = x_left_overwritten (head);
4576 if (i >= 0)
4577 {
4578 j = i;
4579 BUILD_GLYPH_STRINGS (hdc, w, row, area, j, start, h, t,
4580 DRAW_NORMAL_TEXT, dummy_x, last_x,
4581 overlaps_p);
4582 start = i;
4583 if (real_start)
4584 *real_start = start;
4585 x_compute_overhangs_and_x (t, head->x, 1);
4586 x_prepend_glyph_string_lists (&head, &tail, h, t);
4587 }
4588
4589 /* Prepend glyph strings for glyphs in front of the first glyph
4590 string that overwrite that glyph string because of their
4591 right overhang. For these strings, only the foreground must
4592 be drawn, because it draws over the glyph string at `head'.
4593 The background must not be drawn because this would overwrite
4594 right overhangs of preceding glyphs for which no glyph
4595 strings exist. */
4596 i = x_left_overwriting (head);
4597 if (i >= 0)
4598 {
4599 BUILD_GLYPH_STRINGS (hdc, w, row, area, i, start, h, t,
4600 DRAW_NORMAL_TEXT, dummy_x, last_x,
4601 overlaps_p);
4602
4603 for (s = h; s; s = s->next)
4604 s->background_filled_p = 1;
4605 if (real_start)
4606 *real_start = i;
4607 x_compute_overhangs_and_x (t, head->x, 1);
4608 x_prepend_glyph_string_lists (&head, &tail, h, t);
4609 }
4610
4611 /* Append glyphs strings for glyphs following the last glyph
4612 string tail that are overwritten by tail. The background of
4613 these strings has to be drawn because tail's foreground draws
4614 over it. */
4615 i = x_right_overwritten (tail);
4616 if (i >= 0)
4617 {
4618 BUILD_GLYPH_STRINGS (hdc, w, row, area, end, i, h, t,
4619 DRAW_NORMAL_TEXT, x, last_x,
4620 overlaps_p);
4621
4622 x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
4623 x_append_glyph_string_lists (&head, &tail, h, t);
4624 if (real_end)
4625 *real_end = i;
4626 }
4627
4628 /* Append glyph strings for glyphs following the last glyph
4629 string tail that overwrite tail. The foreground of such
4630 glyphs has to be drawn because it writes into the background
4631 of tail. The background must not be drawn because it could
4632 paint over the foreground of following glyphs. */
4633 i = x_right_overwriting (tail);
4634 if (i >= 0)
4635 {
4636 BUILD_GLYPH_STRINGS (hdc, w, row, area, end, i, h, t,
4637 DRAW_NORMAL_TEXT, x, last_x,
4638 overlaps_p);
4639
4640 for (s = h; s; s = s->next)
4641 s->background_filled_p = 1;
4642 x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
4643 x_append_glyph_string_lists (&head, &tail, h, t);
4644 if (real_end)
4645 *real_end = i;
4646 }
4647 }
4648
4649 /* Draw all strings. */
4650 for (s = head; s; s = s->next)
4651 x_draw_glyph_string (s);
4652
4653 /* Value is the x-position up to which drawn, relative to AREA of W.
4654 This doesn't include parts drawn because of overhangs. */
4655 x_reached = FRAME_TO_WINDOW_PIXEL_X (w, x_reached);
4656 if (!row->full_width_p)
4657 {
4658 if (area > LEFT_MARGIN_AREA)
4659 x_reached -= window_box_width (w, LEFT_MARGIN_AREA);
4660 if (area > TEXT_AREA)
4661 x_reached -= window_box_width (w, TEXT_AREA);
4662 }
4663
4664 release_frame_dc (XFRAME (WINDOW_FRAME (w)), hdc);
4665
4666 return x_reached;
1345} 4667}
1346 4668
1347/* Clear to the end of the line. 4669
1348 Erase the current text line from the nominal cursor position (inclusive) 4670/* Fix the display of area AREA of overlapping row ROW in window W. */
1349 to column FIRST_UNUSED (exclusive). The idea is that everything
1350 from FIRST_UNUSED onward is already erased. */
1351 4671
1352static void 4672static void
1353w32_clear_end_of_line (first_unused) 4673x_fix_overlapping_area (w, row, area)
1354 register int first_unused; 4674 struct window *w;
4675 struct glyph_row *row;
4676 enum glyph_row_area area;
1355{ 4677{
1356 struct frame *f = updating_frame; 4678 int i, x;
4679
4680 BLOCK_INPUT;
4681
4682 if (area == LEFT_MARGIN_AREA)
4683 x = 0;
4684 else if (area == TEXT_AREA)
4685 x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
4686 else
4687 x = (window_box_width (w, LEFT_MARGIN_AREA)
4688 + window_box_width (w, TEXT_AREA));
1357 4689
1358 if (f == 0) 4690 for (i = 0; i < row->used[area];)
1359 abort (); 4691 {
4692 if (row->glyphs[area][i].overlaps_vertically_p)
4693 {
4694 int start = i, start_x = x;
4695
4696 do
4697 {
4698 x += row->glyphs[area][i].pixel_width;
4699 ++i;
4700 }
4701 while (i < row->used[area]
4702 && row->glyphs[area][i].overlaps_vertically_p);
4703
4704 x_draw_glyphs (w, start_x, row, area, start, i,
4705 (row->inverse_p
4706 ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT),
4707 NULL, NULL, 1);
4708 }
4709 else
4710 {
4711 x += row->glyphs[area][i].pixel_width;
4712 ++i;
4713 }
4714 }
4715
4716 UNBLOCK_INPUT;
4717}
1360 4718
1361 if (curs_y < 0 || curs_y >= f->height)
1362 return;
1363 if (first_unused <= 0)
1364 return;
1365 4719
1366 if (first_unused >= f->width) 4720/* Output LEN glyphs starting at START at the nominal cursor position.
1367 first_unused = f->width; 4721 Advance the nominal cursor over the text. The global variable
4722 updated_window contains the window being updated, updated_row is
4723 the glyph row being updated, and updated_area is the area of that
4724 row being updated. */
1368 4725
1369 first_unused += FRAME_LEFT_SCROLL_BAR_WIDTH (f); 4726static void
4727x_write_glyphs (start, len)
4728 struct glyph *start;
4729 int len;
4730{
4731 int x, hpos, real_start, real_end;
1370 4732
4733 xassert (updated_window && updated_row);
1371 BLOCK_INPUT; 4734 BLOCK_INPUT;
4735
4736 /* Write glyphs. */
1372 4737
1373 do_line_dance (); 4738 hpos = start - updated_row->glyphs[updated_area];
4739 x = x_draw_glyphs (updated_window, output_cursor.x,
4740 updated_row, updated_area,
4741 hpos, hpos + len,
4742 (updated_row->inverse_p
4743 ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT),
4744 &real_start, &real_end, 0);
1374 4745
1375 /* Notice if the cursor will be cleared by this operation. */ 4746 /* If we drew over the cursor, note that it is not visible any more. */
1376 if (curs_y == f->phys_cursor_y 4747 note_overwritten_text_cursor (updated_window, real_start,
1377 && curs_x <= f->phys_cursor_x 4748 real_end - real_start);
1378 && f->phys_cursor_x < first_unused) 4749
1379 f->phys_cursor_on = 0; 4750 UNBLOCK_INPUT;
4751
4752 /* Advance the output cursor. */
4753 output_cursor.hpos += len;
4754 output_cursor.x = x;
4755}
4756
4757
4758/* Insert LEN glyphs from START at the nominal cursor position. */
4759
4760static void
4761x_insert_glyphs (start, len)
4762 struct glyph *start;
4763 register int len;
4764{
4765 struct frame *f;
4766 struct window *w;
4767 int line_height, shift_by_width, shifted_region_width;
4768 struct glyph_row *row;
4769 struct glyph *glyph;
4770 int frame_x, frame_y, hpos, real_start, real_end;
4771 HDC hdc;
1380 4772
1381 w32_clear_area (f, NULL, 4773 xassert (updated_window && updated_row);
1382 CHAR_TO_PIXEL_COL (f, curs_x), 4774 BLOCK_INPUT;
1383 CHAR_TO_PIXEL_ROW (f, curs_y), 4775 w = updated_window;
1384 FONT_WIDTH (f->output_data.w32->font) * (first_unused - curs_x), 4776 f = XFRAME (WINDOW_FRAME (w));
1385 f->output_data.w32->line_height); 4777 hdc = get_frame_dc (f);
4778
4779 /* Get the height of the line we are in. */
4780 row = updated_row;
4781 line_height = row->height;
4782
4783 /* Get the width of the glyphs to insert. */
4784 shift_by_width = 0;
4785 for (glyph = start; glyph < start + len; ++glyph)
4786 shift_by_width += glyph->pixel_width;
4787
4788 /* Get the width of the region to shift right. */
4789 shifted_region_width = (window_box_width (w, updated_area)
4790 - output_cursor.x
4791 - shift_by_width);
4792
4793 /* Shift right. */
4794 frame_x = WINDOW_TO_FRAME_PIXEL_X (w, output_cursor.x);
4795 frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, output_cursor.y);
4796 BitBlt (hdc, frame_x + shift_by_width, frame_y,
4797 shifted_region_width, line_height,
4798 hdc, frame_x, frame_y, SRCCOPY);
4799
4800 /* Write the glyphs. */
4801 hpos = start - row->glyphs[updated_area];
4802 x_draw_glyphs (w, output_cursor.x, row, updated_area, hpos, hpos + len,
4803 DRAW_NORMAL_TEXT, &real_start, &real_end, 0);
4804 note_overwritten_text_cursor (w, real_start, real_end - real_start);
4805
4806 /* Advance the output cursor. */
4807 output_cursor.hpos += len;
4808 output_cursor.x += shift_by_width;
4809 release_frame_dc (f, hdc);
1386 4810
1387 UNBLOCK_INPUT; 4811 UNBLOCK_INPUT;
1388} 4812}
1389 4813
4814
4815/* Delete N glyphs at the nominal cursor position. Not implemented
4816 for X frames. */
4817
4818static void
4819x_delete_glyphs (n)
4820 register int n;
4821{
4822 abort ();
4823}
4824
4825
4826/* Erase the current text line from the nominal cursor position
4827 (inclusive) to pixel column TO_X (exclusive). The idea is that
4828 everything from TO_X onward is already erased.
4829
4830 TO_X is a pixel position relative to updated_area of
4831 updated_window. TO_X == -1 means clear to the end of this area. */
4832
4833static void
4834x_clear_end_of_line (to_x)
4835 int to_x;
4836{
4837 struct frame *f;
4838 struct window *w = updated_window;
4839 int max_x, min_y, max_y;
4840 int from_x, from_y, to_y;
4841
4842 xassert (updated_window && updated_row);
4843 f = XFRAME (w->frame);
4844
4845 if (updated_row->full_width_p)
4846 {
4847 max_x = XFASTINT (w->width) * CANON_X_UNIT (f);
4848 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f)
4849 && !w->pseudo_window_p)
4850 max_x += FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
4851 }
4852 else
4853 max_x = window_box_width (w, updated_area);
4854 max_y = window_text_bottom_y (w);
4855
4856 /* TO_X == 0 means don't do anything. TO_X < 0 means clear to end
4857 of window. For TO_X > 0, truncate to end of drawing area. */
4858 if (to_x == 0)
4859 return;
4860 else if (to_x < 0)
4861 to_x = max_x;
4862 else
4863 to_x = min (to_x, max_x);
4864
4865 to_y = min (max_y, output_cursor.y + updated_row->height);
4866
4867 /* Notice if the cursor will be cleared by this operation. */
4868 if (!updated_row->full_width_p)
4869 note_overwritten_text_cursor (w, output_cursor.hpos, -1);
4870
4871 from_x = output_cursor.x;
4872
4873 /* Translate to frame coordinates. */
4874 if (updated_row->full_width_p)
4875 {
4876 from_x = WINDOW_TO_FRAME_PIXEL_X (w, from_x);
4877 to_x = WINDOW_TO_FRAME_PIXEL_X (w, to_x);
4878 }
4879 else
4880 {
4881 from_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, from_x);
4882 to_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, to_x);
4883 }
4884
4885 min_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
4886 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, max (min_y, output_cursor.y));
4887 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, to_y);
4888
4889 /* Prevent inadvertently clearing to end of the X window. */
4890 if (to_x > from_x && to_y > from_y)
4891 {
4892 BLOCK_INPUT;
4893 w32_clear_area (f, NULL, from_x, from_y, to_x - from_x, to_y - from_y);
4894 UNBLOCK_INPUT;
4895 }
4896}
4897
4898
4899/* Clear entire frame. If updating_frame is non-null, clear that
4900 frame. Otherwise clear the selected frame. */
4901
1390static void 4902static void
1391w32_clear_frame () 4903x_clear_frame ()
1392{ 4904{
1393 struct frame *f = updating_frame; 4905 struct frame *f;
1394 4906
1395 if (f == 0) 4907 if (updating_frame)
1396 f = selected_frame; 4908 f = updating_frame;
4909 else
4910 f = SELECTED_FRAME ();
1397 4911
1398 f->phys_cursor_on = 0; /* Cursor not visible. */ 4912 /* Clearing the frame will erase any cursor, so mark them all as no
1399 curs_x = 0; /* Nominal cursor position is top left. */ 4913 longer visible. */
1400 curs_y = 0; 4914 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
4915 output_cursor.hpos = output_cursor.vpos = 0;
4916 output_cursor.x = -1;
1401 4917
4918 /* We don't set the output cursor here because there will always
4919 follow an explicit cursor_to. */
1402 BLOCK_INPUT; 4920 BLOCK_INPUT;
1403 4921
1404 w32_clear_window (f); 4922 w32_clear_window (f);
@@ -1409,6 +4927,7 @@ w32_clear_frame ()
1409 4927
1410 UNBLOCK_INPUT; 4928 UNBLOCK_INPUT;
1411} 4929}
4930
1412 4931
1413/* Make audible bell. */ 4932/* Make audible bell. */
1414 4933
@@ -1420,7 +4939,7 @@ w32_ring_bell (void)
1420 if (visible_bell) 4939 if (visible_bell)
1421 { 4940 {
1422 int i; 4941 int i;
1423 HWND hwnd = FRAME_W32_WINDOW (selected_frame); 4942 HWND hwnd = FRAME_W32_WINDOW (SELECTED_FRAME ());
1424 4943
1425 for (i = 0; i < 5; i++) 4944 for (i = 0; i < 5; i++)
1426 { 4945 {
@@ -1434,289 +4953,467 @@ w32_ring_bell (void)
1434 4953
1435 UNBLOCK_INPUT; 4954 UNBLOCK_INPUT;
1436} 4955}
4956
1437 4957
1438/* Insert and delete character. 4958/* Specify how many text lines, from the top of the window,
1439 These are not supposed to be used because we are supposed to turn 4959 should be affected by insert-lines and delete-lines operations.
1440 off the feature of using them. */ 4960 This, and those operations, are used only within an update
4961 that is bounded by calls to x_update_begin and x_update_end. */
1441 4962
1442static void 4963static void
1443w32_insert_glyphs (start, len) 4964w32_set_terminal_window (n)
1444 register GLYPH *start; 4965 register int n;
1445 register int len;
1446{ 4966{
1447 abort (); 4967 /* This function intentionally left blank. */
1448} 4968}
4969
4970
4971
4972/***********************************************************************
4973 Line Dance
4974 ***********************************************************************/
4975
4976/* Perform an insert-lines or delete-lines operation, inserting N
4977 lines or deleting -N lines at vertical position VPOS. */
1449 4978
1450static void 4979static void
1451w32_delete_glyphs (n) 4980x_ins_del_lines (vpos, n)
1452 register int n; 4981 int vpos, n;
1453{ 4982{
1454 abort (); 4983 abort ();
1455} 4984}
1456 4985
1457/* Specify how many text lines, from the top of the window, 4986
1458 should be affected by insert-lines and delete-lines operations. 4987/* Scroll part of the display as described by RUN. */
1459 This, and those operations, are used only within an update
1460 that is bounded by calls to w32_update_begin and w32_update_end. */
1461 4988
1462static void 4989static void
1463w32_set_terminal_window (n) 4990x_scroll_run (w, run)
1464 register int n; 4991 struct window *w;
4992 struct run *run;
1465{ 4993{
1466 if (updating_frame == 0) 4994 struct frame *f = XFRAME (w->frame);
1467 abort (); 4995 int x, y, width, height, from_y, to_y, bottom_y;
4996 HDC hdc = get_frame_dc (f);
1468 4997
1469 if ((n <= 0) || (n > updating_frame->height)) 4998 /* Get frame-relative bounding box of the text display area of W,
1470 flexlines = updating_frame->height; 4999 without mode lines. Include in this box the flags areas to the
1471 else 5000 left and right of W. */
1472 flexlines = n; 5001 window_box (w, -1, &x, &y, &width, &height);
1473} 5002 width += FRAME_X_FLAGS_AREA_WIDTH (f);
1474 5003 x -= FRAME_X_LEFT_FLAGS_AREA_WIDTH (f);
1475/* These variables need not be per frame 5004
1476 because redisplay is done on a frame-by-frame basis 5005 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
1477 and the line dance for one frame is finished before 5006 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
1478 anything is done for another frame. */ 5007 bottom_y = y + height;
1479 5008
1480/* Array of line numbers from cached insert/delete operations. 5009 if (to_y < from_y)
1481 line_dance[i] is the old position of the line that we want 5010 {
1482 to move to line i, or -1 if we want a blank line there. */ 5011 /* Scrolling up. Make sure we don't copy part of the mode
1483static int *line_dance; 5012 line at the bottom. */
5013 if (from_y + run->height > bottom_y)
5014 height = bottom_y - from_y;
5015 else
5016 height = run->height;
5017 }
5018 else
5019 {
5020 /* Scolling down. Make sure we don't copy over the mode line.
5021 at the bottom. */
5022 if (to_y + run->height > bottom_y)
5023 height = bottom_y - to_y;
5024 else
5025 height = run->height;
5026 }
1484 5027
1485/* Allocated length of that array. */ 5028 BLOCK_INPUT;
1486static int line_dance_len; 5029
5030 /* Cursor off. Will be switched on again in x_update_window_end. */
5031 updated_window = w;
5032 x_clear_cursor (w);
1487 5033
1488/* Flag indicating whether we've done any work. */ 5034 BitBlt (hdc, x, to_y, width, height, hdc, x, from_y, SRCCOPY);
1489static int line_dance_in_progress; 5035
5036 UNBLOCK_INPUT;
5037 release_frame_dc (f, hdc);
5038}
1490 5039
1491/* Perform an insert-lines or delete-lines operation, 5040
1492 inserting N lines or deleting -N lines at vertical position VPOS. */ 5041/***********************************************************************
5042 Exposure Events
5043 ***********************************************************************/
5044
5045/* Redisplay an exposed area of frame F. X and Y are the upper-left
5046 corner of the exposed rectangle. W and H are width and height of
5047 the exposed area. All are pixel values. W or H zero means redraw
5048 the entire frame. */
1493 5049
1494static void 5050static void
1495w32_ins_del_lines (vpos, n) 5051expose_frame (f, x, y, w, h)
1496 int vpos, n; 5052 struct frame *f;
5053 int x, y, w, h;
1497{ 5054{
1498 register int fence, i; 5055 RECT r;
1499 5056
1500 if (vpos >= flexlines) 5057 TRACE ((stderr, "expose_frame "));
1501 return;
1502 5058
1503 if (!line_dance_in_progress) 5059 /* No need to redraw if frame will be redrawn soon. */
5060 if (FRAME_GARBAGED_P (f))
1504 { 5061 {
1505 int ht = updating_frame->height; 5062 TRACE ((stderr, " garbaged\n"));
1506 if (ht > line_dance_len) 5063 return;
1507 { 5064 }
1508 line_dance = (int *)xrealloc (line_dance, ht * sizeof (int)); 5065
1509 line_dance_len = ht; 5066 /* If basic faces haven't been realized yet, there is no point in
1510 } 5067 trying to redraw anything. This can happen when we get an expose
1511 for (i = 0; i < ht; ++i) line_dance[i] = i; 5068 event while Emacs is starting, e.g. by moving another window. */
1512 line_dance_in_progress = 1; 5069 if (FRAME_FACE_CACHE (f) == NULL
5070 || FRAME_FACE_CACHE (f)->used < BASIC_FACE_ID_SENTINEL)
5071 {
5072 TRACE ((stderr, " no faces\n"));
5073 return;
1513 } 5074 }
1514 if (n >= 0) 5075
5076 if (w == 0 || h == 0)
1515 { 5077 {
1516 if (n > flexlines - vpos) 5078 r.left = r.top = 0;
1517 n = flexlines - vpos; 5079 r.right = CANON_X_UNIT (f) * f->width;
1518 fence = vpos + n; 5080 r.bottom = CANON_Y_UNIT (f) * f->height;
1519 for (i = flexlines; --i >= fence;)
1520 line_dance[i] = line_dance[i-n];
1521 for (i = fence; --i >= vpos;)
1522 line_dance[i] = -1;
1523 } 5081 }
1524 else 5082 else
1525 { 5083 {
1526 n = -n; 5084 r.left = x;
1527 if (n > flexlines - vpos) 5085 r.top = y;
1528 n = flexlines - vpos; 5086 r.right = x + w;
1529 fence = flexlines - n; 5087 r.bottom = y + h;
1530 for (i = vpos; i < fence; ++i) 5088 }
1531 line_dance[i] = line_dance[i + n]; 5089
1532 for (i = fence; i < flexlines; ++i) 5090 TRACE ((stderr, "(%d, %d, %d, %d)\n", r.left, r.top, r.right, r.bottom));
1533 line_dance[i] = -1; 5091 expose_window_tree (XWINDOW (f->root_window), &r);
5092
5093 if (WINDOWP (f->tool_bar_window))
5094 {
5095 struct window *w = XWINDOW (f->tool_bar_window);
5096 RECT window_rect;
5097 RECT intersection_rect;
5098 int window_x, window_y, window_width, window_height;
5099
5100 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
5101 window_rect.left = window_x;
5102 window_rect.top = window_y;
5103 window_rect.right = window_x + window_width;
5104 window_rect.bottom = window_y + window_height;
5105
5106 if (w32_intersect_rectangles (&r, &window_rect, &intersection_rect))
5107 expose_window (w, &intersection_rect);
1534 } 5108 }
1535} 5109}
1536 5110
1537/* Here's where we actually move the pixels around. 5111
1538 Must be called with input blocked. */ 5112/* Redraw (parts) of all windows in the window tree rooted at W that
5113 intersect R. R contains frame pixel coordinates. */
5114
1539static void 5115static void
1540do_line_dance () 5116expose_window_tree (w, r)
5117 struct window *w;
5118 RECT *r;
1541{ 5119{
1542 register int i, j, distance; 5120 while (w)
1543 register struct frame *f; 5121 {
1544 int ht; 5122 if (!NILP (w->hchild))
1545 int intborder; 5123 expose_window_tree (XWINDOW (w->hchild), r);
1546 HDC hdc; 5124 else if (!NILP (w->vchild))
5125 expose_window_tree (XWINDOW (w->vchild), r);
5126 else
5127 {
5128 RECT window_rect;
5129 RECT intersection_rect;
5130 struct frame *f = XFRAME (w->frame);
5131 int window_x, window_y, window_width, window_height;
5132
5133 /* Frame-relative pixel rectangle of W. */
5134 window_box (w, -1, &window_x, &window_y, &window_width,
5135 &window_height);
5136 window_rect.left
5137 = (window_x
5138 - FRAME_X_LEFT_FLAGS_AREA_WIDTH (f)
5139 - FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_Y_UNIT (f));
5140 window_rect.top = window_y;
5141 window_rect.right = window_rect.left
5142 + (window_width
5143 + FRAME_X_FLAGS_AREA_WIDTH (f)
5144 + FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f));
5145 window_rect.bottom = window_rect.top
5146 + window_height + CURRENT_MODE_LINE_HEIGHT (w);
5147
5148 if (w32_intersect_rectangles (r, &window_rect, &intersection_rect))
5149 expose_window (w, &intersection_rect);
5150 }
1547 5151
1548 /* Must check this flag first. If it's not set, then not only is the 5152 w = NILP (w->next) ? 0 : XWINDOW (w->next);
1549 array uninitialized, but we might not even have a frame. */ 5153 }
1550 if (!line_dance_in_progress) 5154}
1551 return;
1552 5155
1553 f = updating_frame;
1554 if (f == 0)
1555 abort ();
1556 5156
1557 ht = f->height; 5157/* Redraw the part of glyph row area AREA of glyph row ROW on window W
1558 intborder = CHAR_TO_PIXEL_COL (f, FRAME_LEFT_SCROLL_BAR_WIDTH (f)); 5158 which intersects rectangle R. R is in window-relative coordinates. */
1559 5159
1560 x_display_cursor (updating_frame, 0); 5160static void
5161expose_area (w, row, r, area)
5162 struct window *w;
5163 struct glyph_row *row;
5164 RECT *r;
5165 enum glyph_row_area area;
5166{
5167 int x;
5168 struct glyph *first = row->glyphs[area];
5169 struct glyph *end = row->glyphs[area] + row->used[area];
5170 struct glyph *last;
5171 int first_x;
5172
5173 /* Set x to the window-relative start position for drawing glyphs of
5174 AREA. The first glyph of the text area can be partially visible.
5175 The first glyphs of other areas cannot. */
5176 if (area == LEFT_MARGIN_AREA)
5177 x = 0;
5178 else if (area == TEXT_AREA)
5179 x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
5180 else
5181 x = (window_box_width (w, LEFT_MARGIN_AREA)
5182 + window_box_width (w, TEXT_AREA));
5183
5184 if (area == TEXT_AREA && row->fill_line_p)
5185 /* If row extends face to end of line write the whole line. */
5186 x_draw_glyphs (w, x, row, area,
5187 0, row->used[area],
5188 row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT,
5189 NULL, NULL, 0);
5190 else
5191 {
5192 /* Find the first glyph that must be redrawn. */
5193 while (first < end
5194 && x + first->pixel_width < r->left)
5195 {
5196 x += first->pixel_width;
5197 ++first;
5198 }
5199
5200 /* Find the last one. */
5201 last = first;
5202 first_x = x;
5203 while (last < end
5204 && x < r->right)
5205 {
5206 x += last->pixel_width;
5207 ++last;
5208 }
5209
5210 /* Repaint. */
5211 if (last > first)
5212 x_draw_glyphs (w, first_x, row, area,
5213 first - row->glyphs[area],
5214 last - row->glyphs[area],
5215 row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT,
5216 NULL, NULL, 0);
5217 }
5218}
1561 5219
1562 hdc = get_frame_dc (f);
1563 5220
1564 for (i = 0; i < ht; ++i) 5221/* Redraw the parts of the glyph row ROW on window W intersecting
1565 if (line_dance[i] != -1 && (distance = line_dance[i]-i) > 0) 5222 rectangle R. R is in window-relative coordinates. */
1566 {
1567 for (j = i; (j < ht && line_dance[j] != -1
1568 && line_dance[j]-j == distance); ++j);
1569 /* Copy [i,j) upward from [i+distance, j+distance) */
1570 BitBlt (hdc,
1571 intborder, CHAR_TO_PIXEL_ROW (f, i+distance),
1572 FRAME_WINDOW_WIDTH (f) * FONT_WIDTH (FRAME_FONT (f)),
1573 (j-i) * FRAME_LINE_HEIGHT (f),
1574 hdc,
1575 intborder, CHAR_TO_PIXEL_ROW (f, i),
1576 SRCCOPY);
1577 i = j-1;
1578 }
1579 5223
1580 for (i = ht; --i >=0; ) 5224static void
1581 if (line_dance[i] != -1 && (distance = line_dance[i]-i) < 0) 5225expose_line (w, row, r)
1582 { 5226 struct window *w;
1583 for (j = i; (--j >= 0 && line_dance[j] != -1 5227 struct glyph_row *row;
1584 && line_dance[j]-j == distance);); 5228 RECT *r;
1585 /* Copy (j, i] downward from (j+distance, i+distance] */ 5229{
1586 BitBlt (hdc, 5230 xassert (row->enabled_p);
1587 intborder, CHAR_TO_PIXEL_ROW (f, j+1+distance), 5231
1588 FRAME_WINDOW_WIDTH (f) * FONT_WIDTH (FRAME_FONT (f)), 5232 if (row->mode_line_p || w->pseudo_window_p)
1589 (i-j) * FRAME_LINE_HEIGHT (f), 5233 x_draw_glyphs (w, 0, row, TEXT_AREA, 0, row->used[TEXT_AREA],
1590 hdc, 5234 row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT,
1591 intborder, CHAR_TO_PIXEL_ROW (f, j+1), 5235 NULL, NULL, 0);
1592 SRCCOPY); 5236 else
1593 i = j+1; 5237 {
1594 } 5238 if (row->used[LEFT_MARGIN_AREA])
5239 expose_area (w, row, r, LEFT_MARGIN_AREA);
5240 if (row->used[TEXT_AREA])
5241 expose_area (w, row, r, TEXT_AREA);
5242 if (row->used[RIGHT_MARGIN_AREA])
5243 expose_area (w, row, r, RIGHT_MARGIN_AREA);
5244 x_draw_row_bitmaps (w, row);
5245 }
5246}
1595 5247
1596 for (i = 0; i < ht; ++i)
1597 if (line_dance[i] == -1)
1598 {
1599 for (j = i; j < ht && line_dance[j] == -1; ++j);
1600 /* Clear [i,j) */
1601 w32_clear_area (f, hdc,
1602 intborder,
1603 CHAR_TO_PIXEL_ROW (f, i),
1604 FRAME_WINDOW_WIDTH (f) * FONT_WIDTH (FRAME_FONT (f)),
1605 (j-i) * FRAME_LINE_HEIGHT (f));
1606 i = j-1;
1607 }
1608 line_dance_in_progress = 0;
1609 5248
1610 release_frame_dc (f, hdc); 5249/* Return non-zero if W's cursor intersects rectangle R. */
5250
5251static int
5252x_phys_cursor_in_rect_p (w, r)
5253 struct window *w;
5254 RECT *r;
5255{
5256 RECT cr, result;
5257 struct glyph *cursor_glyph;
5258
5259 cursor_glyph = get_phys_cursor_glyph (w);
5260 if (cursor_glyph)
5261 {
5262 cr.left = w->phys_cursor.x;
5263 cr.top = w->phys_cursor.y;
5264 cr.right = cr.left + cursor_glyph->pixel_width;
5265 cr.bottom = cr.top + w->phys_cursor_height;
5266 return w32_intersect_rectangles (&cr, r, &result);
5267 }
5268 else
5269 return 0;
1611} 5270}
1612
1613/* Support routines for exposure events. */
1614static void clear_cursor ();
1615 5271
1616/* Output into a rectangle of a window (for frame F)
1617 the characters in f->phys_lines that overlap that rectangle.
1618 TOP and LEFT are the position of the upper left corner of the rectangle.
1619 ROWS and COLS are the size of the rectangle.
1620 Call this function with input blocked. */
1621 5272
1622void 5273/* Redraw a rectangle of window W. R is a rectangle in window
1623dumprectangle (f, left, top, cols, rows) 5274 relative coordinates. Call this function with input blocked. */
1624 struct frame *f;
1625 register int left, top, cols, rows;
1626{
1627 register struct frame_glyphs *active_frame = FRAME_CURRENT_GLYPHS (f);
1628 int cursor_cleared = 0;
1629 int bottom, right;
1630 register int y;
1631 5275
1632 if (FRAME_GARBAGED_P (f)) 5276static void
5277expose_window (w, r)
5278 struct window *w;
5279 RECT *r;
5280{
5281 struct glyph_row *row;
5282 int y;
5283 int yb = window_text_bottom_y (w);
5284 int cursor_cleared_p;
5285
5286 /* If window is not yet fully initialized, do nothing. This can
5287 happen when toolkit scroll bars are used and a window is split.
5288 Reconfiguring the scroll bar will generate an expose for a newly
5289 created window. */
5290 if (w->current_matrix == NULL)
1633 return; 5291 return;
1634 5292
1635 /* Express rectangle as four edges, instead of position-and-size. */ 5293 TRACE ((stderr, "expose_window (%d, %d, %d, %d)\n",
1636 bottom = top + rows; 5294 r->left, r->top, r->right, r->bottom));
1637 right = left + cols; 5295
1638 5296 /* Convert to window coordinates. */
1639 /* Convert rectangle edges in pixels to edges in chars. 5297 r->left = FRAME_TO_WINDOW_PIXEL_X (w, r->left);
1640 Round down for left and top, up for right and bottom. */ 5298 r->top = FRAME_TO_WINDOW_PIXEL_Y (w, r->top);
1641 top = PIXEL_TO_CHAR_ROW (f, top); 5299 r->right = FRAME_TO_WINDOW_PIXEL_X (w, r->right);
1642 left = PIXEL_TO_CHAR_COL (f, left); 5300 r->bottom = FRAME_TO_WINDOW_PIXEL_Y (w, r->bottom);
1643 bottom += (f->output_data.w32->line_height - 1);
1644 right += (FONT_WIDTH (f->output_data.w32->font) - 1);
1645 bottom = PIXEL_TO_CHAR_ROW (f, bottom);
1646 right = PIXEL_TO_CHAR_COL (f, right);
1647
1648 /* Clip the rectangle to what can be visible. */
1649 if (left < FRAME_LEFT_SCROLL_BAR_WIDTH (f))
1650 left = FRAME_LEFT_SCROLL_BAR_WIDTH (f);
1651 if (top < 0)
1652 top = 0;
1653 if (right > f->width + FRAME_LEFT_SCROLL_BAR_WIDTH (f))
1654 right = f->width + FRAME_LEFT_SCROLL_BAR_WIDTH (f);
1655 if (bottom > f->height)
1656 bottom = f->height;
1657
1658 /* Get size in chars of the rectangle. */
1659 cols = right - left;
1660 rows = bottom - top;
1661
1662 /* If rectangle has zero area, return. */
1663 if (rows <= 0) return;
1664 if (cols <= 0) return;
1665
1666 /* Turn off the cursor if it is in the rectangle.
1667 We will turn it back on afterward. */
1668 if ((f->phys_cursor_x >= left) && (f->phys_cursor_x < right)
1669 && (f->phys_cursor_y >= top) && (f->phys_cursor_y < bottom))
1670 {
1671 clear_cursor (f);
1672 cursor_cleared = 1;
1673 }
1674 5301
5302 /* Turn off the cursor. */
5303 if (!w->pseudo_window_p
5304 && x_phys_cursor_in_rect_p (w, r))
5305 {
5306 x_clear_cursor (w);
5307 cursor_cleared_p = 1;
5308 }
5309 else
5310 cursor_cleared_p = 0;
5311
5312 /* Find the first row intersecting the rectangle R. */
5313 row = w->current_matrix->rows;
5314 y = 0;
5315 while (row->enabled_p
5316 && y < yb
5317 && y + row->height < r->top)
5318 {
5319 y += row->height;
5320 ++row;
5321 }
5322
1675 /* Display the text in the rectangle, one text line at a time. */ 5323 /* Display the text in the rectangle, one text line at a time. */
5324 while (row->enabled_p
5325 && y < yb
5326 && y < r->bottom)
5327 {
5328 expose_line (w, row, r);
5329 y += row->height;
5330 ++row;
5331 }
5332
5333 /* Display the mode line if there is one. */
5334 if (WINDOW_WANTS_MODELINE_P (w)
5335 && (row = MATRIX_MODE_LINE_ROW (w->current_matrix),
5336 row->enabled_p)
5337 && row->y < r->bottom)
5338 expose_line (w, row, r);
5339
5340 if (!w->pseudo_window_p)
5341 {
5342 /* Draw border between windows. */
5343 x_draw_vertical_border (w);
5344
5345 /* Turn the cursor on again. */
5346 if (cursor_cleared_p)
5347 x_update_window_cursor (w, 1);
5348 }
5349}
5350
5351
5352/* Determine the intersection of two rectangles R1 and R2. Return
5353 the intersection in *RESULT. Value is non-zero if RESULT is not
5354 empty. */
1676 5355
1677 for (y = top; y < bottom; y++) 5356static int
5357w32_intersect_rectangles (r1, r2, result)
5358 RECT *r1, *r2, *result;
5359{
5360 RECT *left, *right;
5361 RECT *upper, *lower;
5362 int intersection_p = 0;
5363
5364 /* Arrange so that left is the left-most rectangle. */
5365 if (r1->left < r2->left)
5366 left = r1, right = r2;
5367 else
5368 left = r2, right = r1;
5369
5370 /* X0 of the intersection is right.x0, if this is inside R1,
5371 otherwise there is no intersection. */
5372 if (right->left <= left->right)
1678 { 5373 {
1679 GLYPH *line = &active_frame->glyphs[y][left]; 5374 result->left = right->left;
5375
5376 /* The right end of the intersection is the minimum of the
5377 the right ends of left and right. */
5378 result->right = min (left->right, right->right);
1680 5379
1681 if (! active_frame->enable[y] || left > active_frame->used[y]) 5380 /* Same game for Y. */
1682 continue; 5381 if (r1->top < r2->top)
5382 upper = r1, lower = r2;
5383 else
5384 upper = r2, lower = r1;
1683 5385
1684 while (*line & GLYPH_MASK_PADDING) 5386 /* The upper end of the intersection is lower.y0, if this is inside
5387 of upper. Otherwise, there is no intersection. */
5388 if (lower->top <= upper->bottom)
1685 { 5389 {
1686 /* We must display the whole glyph of a wide-column 5390 result->top = lower->top;
1687 character. */ 5391
1688 left--; 5392 /* The lower end of the intersection is the minimum of the lower
1689 line--; 5393 ends of upper and lower. */
1690 cols++; 5394 result->bottom = min (lower->bottom, upper->bottom);
5395 intersection_p = 1;
1691 } 5396 }
1692 dumpglyphs (f,
1693 CHAR_TO_PIXEL_COL (f, left),
1694 CHAR_TO_PIXEL_ROW (f, y),
1695 line, min (cols, active_frame->used[y] - left),
1696 active_frame->highlight[y], 0, NULL);
1697 } 5397 }
1698 5398
1699 /* Turn the cursor on if we turned it off. */ 5399 return intersection_p;
1700
1701 if (cursor_cleared)
1702 x_display_cursor (f, 1);
1703} 5400}
5401
1704 5402
1705static void 5403static void
1706frame_highlight (f) 5404frame_highlight (f)
1707 struct frame *f; 5405 struct frame *f;
1708{ 5406{
1709 x_display_cursor (f, 1); 5407 x_update_cursor (f, 1);
1710} 5408}
1711 5409
1712static void 5410static void
1713frame_unhighlight (f) 5411frame_unhighlight (f)
1714 struct frame *f; 5412 struct frame *f;
1715{ 5413{
1716 x_display_cursor (f, 1); 5414 x_update_cursor (f, 1);
1717} 5415}
1718 5416
1719static void x_frame_rehighlight ();
1720 5417
1721/* The focus has changed. Update the frames as necessary to reflect 5418/* The focus has changed. Update the frames as necessary to reflect
1722 the new situation. Note that we can't change the selected frame 5419 the new situation. Note that we can't change the selected frame
@@ -1730,7 +5427,6 @@ x_new_focus_frame (dpyinfo, frame)
1730 struct frame *frame; 5427 struct frame *frame;
1731{ 5428{
1732 struct frame *old_focus = dpyinfo->w32_focus_frame; 5429 struct frame *old_focus = dpyinfo->w32_focus_frame;
1733 int events_enqueued = 0;
1734 5430
1735 if (frame != dpyinfo->w32_focus_frame) 5431 if (frame != dpyinfo->w32_focus_frame)
1736 { 5432 {
@@ -1879,22 +5575,48 @@ pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds, noclip)
1879 *y = pix_y; 5575 *y = pix_y;
1880} 5576}
1881 5577
1882void 5578
1883glyph_to_pixel_coords (f, x, y, pix_x, pix_y) 5579/* Given HPOS/VPOS in the current matrix of W, return corresponding
1884 FRAME_PTR f; 5580 frame-relative pixel positions in *FRAME_X and *FRAME_Y. If we
1885 register int x, y; 5581 can't tell the positions because W's display is not up to date,
1886 register int *pix_x, *pix_y; 5582 return 0. */
5583
5584int
5585glyph_to_pixel_coords (w, hpos, vpos, frame_x, frame_y)
5586 struct window *w;
5587 int hpos, vpos;
5588 int *frame_x, *frame_y;
1887{ 5589{
1888 /* Support tty mode: if Vwindow_system is nil, behave correctly. */ 5590 int success_p;
1889 if (NILP (Vwindow_system)) 5591
5592 xassert (hpos >= 0 && hpos < w->current_matrix->matrix_w);
5593 xassert (vpos >= 0 && vpos < w->current_matrix->matrix_h);
5594
5595 if (display_completed)
1890 { 5596 {
1891 *pix_x = x; 5597 struct glyph_row *row = MATRIX_ROW (w->current_matrix, vpos);
1892 *pix_y = y; 5598 struct glyph *glyph = row->glyphs[TEXT_AREA];
1893 return; 5599 struct glyph *end = glyph + min (hpos, row->used[TEXT_AREA]);
5600
5601 *frame_y = row->y;
5602 *frame_x = row->x;
5603 while (glyph < end)
5604 {
5605 *frame_x += glyph->pixel_width;
5606 ++glyph;
5607 }
5608
5609 success_p = 1;
5610 }
5611 else
5612 {
5613 *frame_y = *frame_x = 0;
5614 success_p = 0;
1894 } 5615 }
1895 5616
1896 *pix_x = CHAR_TO_PIXEL_COL (f, x); 5617 *frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, *frame_y);
1897 *pix_y = CHAR_TO_PIXEL_ROW (f, y); 5618 *frame_x = WINDOW_TO_FRAME_PIXEL_X (w, *frame_x);
5619 return success_p;
1898} 5620}
1899 5621
1900BOOL 5622BOOL
@@ -2068,18 +5790,22 @@ construct_drag_n_drop (result, msg, f)
2068 the mainstream emacs code by setting mouse_moved. If not, ask for 5790 the mainstream emacs code by setting mouse_moved. If not, ask for
2069 another motion event, so we can check again the next time it moves. */ 5791 another motion event, so we can check again the next time it moves. */
2070 5792
5793static MSG last_mouse_motion_event;
5794static Lisp_Object last_mouse_motion_frame;
5795
2071static void 5796static void
2072note_mouse_movement (frame, msg) 5797note_mouse_movement (frame, msg)
2073 FRAME_PTR frame; 5798 FRAME_PTR frame;
2074 MSG *msg; 5799 MSG *msg;
2075{ 5800{
2076 last_mouse_movement_time = msg->time; 5801 last_mouse_movement_time = msg->time;
5802 memcpy (&last_mouse_motion_event, msg, sizeof (last_mouse_motion_event));
5803 XSETFRAME (last_mouse_motion_frame, frame);
2077 5804
2078 if (msg->hwnd != FRAME_W32_WINDOW (frame)) 5805 if (msg->hwnd != FRAME_W32_WINDOW (frame))
2079 { 5806 {
2080 frame->mouse_moved = 1; 5807 frame->mouse_moved = 1;
2081 last_mouse_scroll_bar = Qnil; 5808 last_mouse_scroll_bar = Qnil;
2082
2083 note_mouse_highlight (frame, -1, -1); 5809 note_mouse_highlight (frame, -1, -1);
2084 } 5810 }
2085 5811
@@ -2097,7 +5823,188 @@ note_mouse_movement (frame, msg)
2097} 5823}
2098 5824
2099/* This is used for debugging, to turn off note_mouse_highlight. */ 5825/* This is used for debugging, to turn off note_mouse_highlight. */
2100static int disable_mouse_highlight; 5826int disable_mouse_highlight;
5827
5828
5829
5830/************************************************************************
5831 Mouse Face
5832 ************************************************************************/
5833
5834/* Find the glyph under window-relative coordinates X/Y in window W.
5835 Consider only glyphs from buffer text, i.e. no glyphs from overlay
5836 strings. Return in *HPOS and *VPOS the row and column number of
5837 the glyph found. Return in *AREA the glyph area containing X.
5838 Value is a pointer to the glyph found or null if X/Y is not on
5839 text, or we can't tell because W's current matrix is not up to
5840 date. */
5841
5842static struct glyph *
5843x_y_to_hpos_vpos (w, x, y, hpos, vpos, area)
5844 struct window *w;
5845 int x, y;
5846 int *hpos, *vpos, *area;
5847{
5848 struct glyph *glyph, *end;
5849 struct glyph_row *row;
5850 int x0, i, left_area_width;
5851
5852 /* Find row containing Y. Give up if some row is not enabled. */
5853 for (i = 0; i < w->current_matrix->nrows; ++i)
5854 {
5855 row = MATRIX_ROW (w->current_matrix, i);
5856 if (!row->enabled_p)
5857 return NULL;
5858 if (y >= row->y && y < MATRIX_ROW_BOTTOM_Y (row))
5859 break;
5860 }
5861
5862 *vpos = i;
5863 *hpos = 0;
5864
5865 /* Give up if Y is not in the window. */
5866 if (i == w->current_matrix->nrows)
5867 return NULL;
5868
5869 /* Get the glyph area containing X. */
5870 if (w->pseudo_window_p)
5871 {
5872 *area = TEXT_AREA;
5873 x0 = 0;
5874 }
5875 else
5876 {
5877 left_area_width = window_box_width (w, LEFT_MARGIN_AREA);
5878 if (x < left_area_width)
5879 {
5880 *area = LEFT_MARGIN_AREA;
5881 x0 = 0;
5882 }
5883 else if (x < left_area_width + window_box_width (w, TEXT_AREA))
5884 {
5885 *area = TEXT_AREA;
5886 x0 = row->x + left_area_width;
5887 }
5888 else
5889 {
5890 *area = RIGHT_MARGIN_AREA;
5891 x0 = left_area_width + window_box_width (w, TEXT_AREA);
5892 }
5893 }
5894
5895 /* Find glyph containing X. */
5896 glyph = row->glyphs[*area];
5897 end = glyph + row->used[*area];
5898 while (glyph < end)
5899 {
5900 if (x < x0 + glyph->pixel_width)
5901 {
5902 if (w->pseudo_window_p)
5903 break;
5904 else if (BUFFERP (glyph->object))
5905 break;
5906 }
5907
5908 x0 += glyph->pixel_width;
5909 ++glyph;
5910 }
5911
5912 if (glyph == end)
5913 return NULL;
5914
5915 *hpos = glyph - row->glyphs[*area];
5916 return glyph;
5917}
5918
5919
5920/* Convert frame-relative x/y to coordinates relative to window W.
5921 Takes pseudo-windows into account. */
5922
5923static void
5924frame_to_window_pixel_xy (w, x, y)
5925 struct window *w;
5926 int *x, *y;
5927{
5928 if (w->pseudo_window_p)
5929 {
5930 /* A pseudo-window is always full-width, and starts at the
5931 left edge of the frame, plus a frame border. */
5932 struct frame *f = XFRAME (w->frame);
5933 *x -= FRAME_INTERNAL_BORDER_WIDTH_SAFE (f);
5934 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
5935 }
5936 else
5937 {
5938 *x = FRAME_TO_WINDOW_PIXEL_X (w, *x);
5939 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
5940 }
5941}
5942
5943
5944/* Take proper action when mouse has moved to the mode or top line of
5945 window W, x-position X. MODE_LINE_P non-zero means mouse is on the
5946 mode line. X is relative to the start of the text display area of
5947 W, so the width of bitmap areas and scroll bars must be subtracted
5948 to get a position relative to the start of the mode line. */
5949
5950static void
5951note_mode_line_highlight (w, x, mode_line_p)
5952 struct window *w;
5953 int x, mode_line_p;
5954{
5955 struct frame *f = XFRAME (w->frame);
5956 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
5957 Cursor cursor = dpyinfo->vertical_scroll_bar_cursor;
5958 struct glyph_row *row;
5959
5960 if (mode_line_p)
5961 row = MATRIX_MODE_LINE_ROW (w->current_matrix);
5962 else
5963 row = MATRIX_HEADER_LINE_ROW (w->current_matrix);
5964
5965 if (row->enabled_p)
5966 {
5967 struct glyph *glyph, *end;
5968 Lisp_Object help, map;
5969 int x0;
5970
5971 /* Find the glyph under X. */
5972 glyph = row->glyphs[TEXT_AREA];
5973 end = glyph + row->used[TEXT_AREA];
5974 x0 = - (FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f)
5975 + FRAME_X_LEFT_FLAGS_AREA_WIDTH (f));
5976 while (glyph < end
5977 && x >= x0 + glyph->pixel_width)
5978 {
5979 x0 += glyph->pixel_width;
5980 ++glyph;
5981 }
5982
5983 if (glyph < end
5984 && STRINGP (glyph->object)
5985 && XSTRING (glyph->object)->intervals
5986 && glyph->charpos >= 0
5987 && glyph->charpos < XSTRING (glyph->object)->size)
5988 {
5989 /* If we're on a string with `help-echo' text property,
5990 arrange for the help to be displayed. This is done by
5991 setting the global variable help_echo to the help string. */
5992 help = Fget_text_property (make_number (glyph->charpos),
5993 Qhelp_echo, glyph->object);
5994 if (STRINGP (help))
5995 help_echo = help;
5996
5997 /* Change the mouse pointer according to what is under X/Y. */
5998 map = Fget_text_property (make_number (glyph->charpos),
5999 Qlocal_map, glyph->object);
6000 if (!NILP (Fkeymapp (map)))
6001 cursor = f->output_data.w32->nontext_cursor;
6002 }
6003 }
6004#if 0 /* NTEMACS_TODO: mouse cursor */
6005 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);
6006#endif
6007}
2101 6008
2102/* Take proper action when the mouse has moved to position X, Y on frame F 6009/* Take proper action when the mouse has moved to position X, Y on frame F
2103 as regards highlighting characters that have mouse-face properties. 6010 as regards highlighting characters that have mouse-face properties.
@@ -2109,336 +6016,692 @@ note_mouse_highlight (f, x, y)
2109 FRAME_PTR f; 6016 FRAME_PTR f;
2110 int x, y; 6017 int x, y;
2111{ 6018{
2112 int row, column, portion; 6019 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
2113 RECT new_glyph; 6020 int portion;
2114 Lisp_Object window; 6021 Lisp_Object window;
2115 struct window *w; 6022 struct window *w;
2116 6023
6024 /* When a menu is active, don't highlight because this looks odd. */
6025 if (popup_activated ())
6026 return;
6027
2117 if (disable_mouse_highlight) 6028 if (disable_mouse_highlight)
2118 return; 6029 return;
2119 6030
2120 FRAME_W32_DISPLAY_INFO (f)->mouse_face_mouse_x = x; 6031 dpyinfo->mouse_face_mouse_x = x;
2121 FRAME_W32_DISPLAY_INFO (f)->mouse_face_mouse_y = y; 6032 dpyinfo->mouse_face_mouse_y = y;
2122 FRAME_W32_DISPLAY_INFO (f)->mouse_face_mouse_frame = f; 6033 dpyinfo->mouse_face_mouse_frame = f;
2123 6034
2124 if (FRAME_W32_DISPLAY_INFO (f)->mouse_face_defer) 6035 if (dpyinfo->mouse_face_defer)
2125 return; 6036 return;
2126 6037
2127 if (gc_in_progress) 6038 if (gc_in_progress)
2128 { 6039 {
2129 FRAME_W32_DISPLAY_INFO (f)->mouse_face_deferred_gc = 1; 6040 dpyinfo->mouse_face_deferred_gc = 1;
2130 return; 6041 return;
2131 } 6042 }
2132 6043
2133 /* Find out which glyph the mouse is on. */
2134 pixel_to_glyph_coords (f, x, y, &column, &row,
2135 &new_glyph, FRAME_W32_DISPLAY_INFO (f)->grabbed);
2136
2137 /* Which window is that in? */ 6044 /* Which window is that in? */
2138 window = window_from_coordinates (f, column, row, &portion); 6045 window = window_from_coordinates (f, x, y, &portion, 1);
2139 w = XWINDOW (window);
2140 6046
2141 /* If we were displaying active text in another window, clear that. */ 6047 /* If we were displaying active text in another window, clear that. */
2142 if (! EQ (window, FRAME_W32_DISPLAY_INFO (f)->mouse_face_window)) 6048 if (! EQ (window, dpyinfo->mouse_face_window))
2143 clear_mouse_face (FRAME_W32_DISPLAY_INFO (f)); 6049 clear_mouse_face (dpyinfo);
6050
6051 /* Not on a window -> return. */
6052 if (!WINDOWP (window))
6053 return;
6054
6055 /* Convert to window-relative pixel coordinates. */
6056 w = XWINDOW (window);
6057 frame_to_window_pixel_xy (w, &x, &y);
6058
6059 /* Handle tool-bar window differently since it doesn't display a
6060 buffer. */
6061 if (EQ (window, f->tool_bar_window))
6062 {
6063 note_tool_bar_highlight (f, x, y);
6064 return;
6065 }
6066
6067 if (portion == 1 || portion == 3)
6068 {
6069 /* Mouse is on the mode or top line. */
6070 note_mode_line_highlight (w, x, portion == 1);
6071 return;
6072 }
6073#if 0 /* NTEMACS_TODO: mouse cursor */
6074 else
6075 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
6076 f->output_data.x->text_cursor);
6077#endif
2144 6078
2145 /* Are we in a window whose display is up to date? 6079 /* Are we in a window whose display is up to date?
2146 And verify the buffer's text has not changed. */ 6080 And verify the buffer's text has not changed. */
2147 if (WINDOWP (window) && portion == 0 && row >= 0 && column >= 0 6081 if (/* Within the text portion of the window. */
2148 && row < FRAME_HEIGHT (f) && column < FRAME_WIDTH (f) 6082 portion == 0
2149 && EQ (w->window_end_valid, w->buffer) 6083 && EQ (w->window_end_valid, w->buffer)
2150 && w->last_modified == BUF_MODIFF (XBUFFER (w->buffer)) 6084 && w->last_modified == BUF_MODIFF (XBUFFER (w->buffer))
2151 && w->last_overlay_modified == BUF_OVERLAY_MODIFF (XBUFFER (w->buffer))) 6085 && w->last_overlay_modified == BUF_OVERLAY_MODIFF (XBUFFER (w->buffer)))
2152 { 6086 {
2153 int *ptr = FRAME_CURRENT_GLYPHS (f)->charstarts[row]; 6087 int hpos, vpos, pos, i, area;
2154 int i, pos; 6088 struct glyph *glyph;
2155 6089
2156 /* Find which buffer position the mouse corresponds to. */ 6090 /* Find the glyph under X/Y. */
2157 for (i = column; i >= 0; i--) 6091 glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, &area);
2158 if (ptr[i] > 0)
2159 break;
2160 pos = ptr[i];
2161 /* Is it outside the displayed active region (if any)? */
2162 if (pos <= 0)
2163 clear_mouse_face (FRAME_W32_DISPLAY_INFO (f));
2164 else if (! (EQ (window, FRAME_W32_DISPLAY_INFO (f)->mouse_face_window)
2165 && row >= FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_row
2166 && row <= FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_row
2167 && (row > FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_row
2168 || column >= FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_col)
2169 && (row < FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_row
2170 || column < FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_col
2171 || FRAME_W32_DISPLAY_INFO (f)->mouse_face_past_end)))
2172 {
2173 Lisp_Object mouse_face, overlay, position;
2174 Lisp_Object *overlay_vec;
2175 int len, noverlays, ignor1;
2176 struct buffer *obuf;
2177 int obegv, ozv;
2178
2179 /* If we get an out-of-range value, return now; avoid an error. */
2180 if (pos > BUF_Z (XBUFFER (w->buffer)))
2181 return;
2182
2183 /* Make the window's buffer temporarily current for
2184 overlays_at and compute_char_face. */
2185 obuf = current_buffer;
2186 current_buffer = XBUFFER (w->buffer);
2187 obegv = BEGV;
2188 ozv = ZV;
2189 BEGV = BEG;
2190 ZV = Z;
2191
2192 /* Yes. Clear the display of the old active region, if any. */
2193 clear_mouse_face (FRAME_W32_DISPLAY_INFO (f));
2194
2195 /* Is this char mouse-active? */
2196 XSETINT (position, pos);
2197
2198 len = 10;
2199 overlay_vec = (Lisp_Object *) xmalloc (len * sizeof (Lisp_Object));
2200
2201 /* Put all the overlays we want in a vector in overlay_vec.
2202 Store the length in len. */
2203 noverlays = overlays_at (XINT (pos), 1, &overlay_vec, &len,
2204 NULL, NULL);
2205 noverlays = sort_overlays (overlay_vec, noverlays, w);
2206
2207 /* Find the highest priority overlay that has a mouse-face prop. */
2208 overlay = Qnil;
2209 for (i = 0; i < noverlays; i++)
2210 {
2211 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
2212 if (!NILP (mouse_face))
2213 {
2214 overlay = overlay_vec[i];
2215 break;
2216 }
2217 }
2218 free (overlay_vec);
2219 /* If no overlay applies, get a text property. */
2220 if (NILP (overlay))
2221 mouse_face = Fget_text_property (position, Qmouse_face, w->buffer);
2222 6092
2223 /* Handle the overlay case. */ 6093 /* Clear mouse face if X/Y not over text. */
2224 if (! NILP (overlay)) 6094 if (glyph == NULL
2225 { 6095 || area != TEXT_AREA
2226 /* Find the range of text around this char that 6096 || !MATRIX_ROW (w->current_matrix, vpos)->displays_text_p)
2227 should be active. */ 6097 {
2228 Lisp_Object before, after; 6098 clear_mouse_face (dpyinfo);
2229 int ignore; 6099 return;
2230
2231 before = Foverlay_start (overlay);
2232 after = Foverlay_end (overlay);
2233 /* Record this as the current active region. */
2234 fast_find_position (window, before,
2235 &FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_col,
2236 &FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_row);
2237 FRAME_W32_DISPLAY_INFO (f)->mouse_face_past_end
2238 = !fast_find_position (window, after,
2239 &FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_col,
2240 &FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_row);
2241 FRAME_W32_DISPLAY_INFO (f)->mouse_face_window = window;
2242 FRAME_W32_DISPLAY_INFO (f)->mouse_face_face_id
2243 = compute_char_face (f, w, pos, 0, 0,
2244 &ignore, pos + 1, 1);
2245
2246 /* Display it as active. */
2247 show_mouse_face (FRAME_W32_DISPLAY_INFO (f), 1);
2248 }
2249 /* Handle the text property case. */
2250 else if (! NILP (mouse_face))
2251 {
2252 /* Find the range of text around this char that
2253 should be active. */
2254 Lisp_Object before, after, beginning, end;
2255 int ignore;
2256
2257 beginning = Fmarker_position (w->start);
2258 XSETINT (end, (BUF_Z (XBUFFER (w->buffer))
2259 - XFASTINT (w->window_end_pos)));
2260 before
2261 = Fprevious_single_property_change (make_number (pos + 1),
2262 Qmouse_face,
2263 w->buffer, beginning);
2264 after
2265 = Fnext_single_property_change (position, Qmouse_face,
2266 w->buffer, end);
2267 /* Record this as the current active region. */
2268 fast_find_position (window, before,
2269 &FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_col,
2270 &FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_row);
2271 FRAME_W32_DISPLAY_INFO (f)->mouse_face_past_end
2272 = !fast_find_position (window, after,
2273 &FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_col,
2274 &FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_row);
2275 FRAME_W32_DISPLAY_INFO (f)->mouse_face_window = window;
2276 FRAME_W32_DISPLAY_INFO (f)->mouse_face_face_id
2277 = compute_char_face (f, w, pos, 0, 0,
2278 &ignore, pos + 1, 1);
2279
2280 /* Display it as active. */
2281 show_mouse_face (FRAME_W32_DISPLAY_INFO (f), 1);
2282 }
2283 BEGV = obegv;
2284 ZV = ozv;
2285 current_buffer = obuf;
2286 } 6100 }
6101
6102 pos = glyph->charpos;
6103 xassert (w->pseudo_window_p || BUFFERP (glyph->object));
6104
6105 /* Check for mouse-face and help-echo. */
6106 {
6107 Lisp_Object mouse_face, overlay, position;
6108 Lisp_Object *overlay_vec;
6109 int len, noverlays;
6110 struct buffer *obuf;
6111 int obegv, ozv;
6112
6113 /* If we get an out-of-range value, return now; avoid an error. */
6114 if (pos > BUF_Z (XBUFFER (w->buffer)))
6115 return;
6116
6117 /* Make the window's buffer temporarily current for
6118 overlays_at and compute_char_face. */
6119 obuf = current_buffer;
6120 current_buffer = XBUFFER (w->buffer);
6121 obegv = BEGV;
6122 ozv = ZV;
6123 BEGV = BEG;
6124 ZV = Z;
6125
6126 /* Is this char mouse-active or does it have help-echo? */
6127 XSETINT (position, pos);
6128
6129 /* Put all the overlays we want in a vector in overlay_vec.
6130 Store the length in len. If there are more than 10, make
6131 enough space for all, and try again. */
6132 len = 10;
6133 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
6134 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL);
6135 if (noverlays > len)
6136 {
6137 len = noverlays;
6138 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
6139 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL);
6140 }
6141
6142 noverlays = sort_overlays (overlay_vec, noverlays, w);
6143
6144 /* Check mouse-face highlighting. */
6145 if (! (EQ (window, dpyinfo->mouse_face_window)
6146 && vpos >= dpyinfo->mouse_face_beg_row
6147 && vpos <= dpyinfo->mouse_face_end_row
6148 && (vpos > dpyinfo->mouse_face_beg_row
6149 || hpos >= dpyinfo->mouse_face_beg_col)
6150 && (vpos < dpyinfo->mouse_face_end_row
6151 || hpos < dpyinfo->mouse_face_end_col
6152 || dpyinfo->mouse_face_past_end)))
6153 {
6154 /* Clear the display of the old active region, if any. */
6155 clear_mouse_face (dpyinfo);
6156
6157 /* Find the highest priority overlay that has a mouse-face prop. */
6158 overlay = Qnil;
6159 for (i = 0; i < noverlays; i++)
6160 {
6161 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
6162 if (!NILP (mouse_face))
6163 {
6164 overlay = overlay_vec[i];
6165 break;
6166 }
6167 }
6168
6169 /* If no overlay applies, get a text property. */
6170 if (NILP (overlay))
6171 mouse_face = Fget_text_property (position, Qmouse_face, w->buffer);
6172
6173 /* Handle the overlay case. */
6174 if (! NILP (overlay))
6175 {
6176 /* Find the range of text around this char that
6177 should be active. */
6178 Lisp_Object before, after;
6179 int ignore;
6180
6181 before = Foverlay_start (overlay);
6182 after = Foverlay_end (overlay);
6183 /* Record this as the current active region. */
6184 fast_find_position (w, XFASTINT (before),
6185 &dpyinfo->mouse_face_beg_col,
6186 &dpyinfo->mouse_face_beg_row,
6187 &dpyinfo->mouse_face_beg_x,
6188 &dpyinfo->mouse_face_beg_y);
6189 dpyinfo->mouse_face_past_end
6190 = !fast_find_position (w, XFASTINT (after),
6191 &dpyinfo->mouse_face_end_col,
6192 &dpyinfo->mouse_face_end_row,
6193 &dpyinfo->mouse_face_end_x,
6194 &dpyinfo->mouse_face_end_y);
6195 dpyinfo->mouse_face_window = window;
6196 dpyinfo->mouse_face_face_id
6197 = face_at_buffer_position (w, pos, 0, 0,
6198 &ignore, pos + 1, 1);
6199
6200 /* Display it as active. */
6201 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
6202 }
6203 /* Handle the text property case. */
6204 else if (! NILP (mouse_face))
6205 {
6206 /* Find the range of text around this char that
6207 should be active. */
6208 Lisp_Object before, after, beginning, end;
6209 int ignore;
6210
6211 beginning = Fmarker_position (w->start);
6212 XSETINT (end, (BUF_Z (XBUFFER (w->buffer))
6213 - XFASTINT (w->window_end_pos)));
6214 before
6215 = Fprevious_single_property_change (make_number (pos + 1),
6216 Qmouse_face,
6217 w->buffer, beginning);
6218 after
6219 = Fnext_single_property_change (position, Qmouse_face,
6220 w->buffer, end);
6221 /* Record this as the current active region. */
6222 fast_find_position (w, XFASTINT (before),
6223 &dpyinfo->mouse_face_beg_col,
6224 &dpyinfo->mouse_face_beg_row,
6225 &dpyinfo->mouse_face_beg_x,
6226 &dpyinfo->mouse_face_beg_y);
6227 dpyinfo->mouse_face_past_end
6228 = !fast_find_position (w, XFASTINT (after),
6229 &dpyinfo->mouse_face_end_col,
6230 &dpyinfo->mouse_face_end_row,
6231 &dpyinfo->mouse_face_end_x,
6232 &dpyinfo->mouse_face_end_y);
6233 dpyinfo->mouse_face_window = window;
6234 dpyinfo->mouse_face_face_id
6235 = face_at_buffer_position (w, pos, 0, 0,
6236 &ignore, pos + 1, 1);
6237
6238 /* Display it as active. */
6239 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
6240 }
6241 }
6242
6243 /* Look for a `help-echo' property. */
6244 {
6245 Lisp_Object help;
6246
6247 /* Check overlays first. */
6248 help = Qnil;
6249 for (i = 0; i < noverlays && !STRINGP (help); ++i)
6250 help = Foverlay_get (overlay_vec[i], Qhelp_echo);
6251
6252 /* Try text properties. */
6253 if (!STRINGP (help)
6254 && ((STRINGP (glyph->object)
6255 && glyph->charpos >= 0
6256 && glyph->charpos < XSTRING (glyph->object)->size)
6257 || (BUFFERP (glyph->object)
6258 && glyph->charpos >= BEGV
6259 && glyph->charpos < ZV)))
6260 help = Fget_text_property (make_number (glyph->charpos),
6261 Qhelp_echo, glyph->object);
6262
6263 if (STRINGP (help))
6264 help_echo = help;
6265 }
6266
6267 BEGV = obegv;
6268 ZV = ozv;
6269 current_buffer = obuf;
6270 }
2287 } 6271 }
2288} 6272}
6273
2289 6274
2290/* Find the row and column of position POS in window WINDOW. 6275static void
2291 Store them in *COLUMNP and *ROWP. 6276redo_mouse_highlight ()
2292 This assumes display in WINDOW is up to date. 6277{
2293 If POS is above start of WINDOW, return coords 6278 if (!NILP (last_mouse_motion_frame)
2294 of start of first screen line. 6279 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame)))
2295 If POS is after end of WINDOW, return coords of end of last screen line. 6280 note_mouse_highlight (XFRAME (last_mouse_motion_frame),
6281 LOWORD (last_mouse_motion_event.lParam),
6282 HIWORD (last_mouse_motion_event.lParam));
6283}
2296 6284
2297 Value is 1 if POS is in range, 0 if it was off screen. */ 6285
6286
6287/***********************************************************************
6288 Tool-bars
6289 ***********************************************************************/
6290
6291static int x_tool_bar_item P_ ((struct frame *, int, int,
6292 struct glyph **, int *, int *, int *));
6293
6294/* Tool-bar item index of the item on which a mouse button was pressed
6295 or -1. */
6296
6297static int last_tool_bar_item;
6298
6299
6300/* Get information about the tool-bar item at position X/Y on frame F.
6301 Return in *GLYPH a pointer to the glyph of the tool-bar item in
6302 the current matrix of the tool-bar window of F, or NULL if not
6303 on a tool-bar item. Return in *PROP_IDX the index of the tool-bar
6304 item in F->current_tool_bar_items. Value is
6305
6306 -1 if X/Y is not on a tool-bar item
6307 0 if X/Y is on the same item that was highlighted before.
6308 1 otherwise. */
2298 6309
2299static int 6310static int
2300fast_find_position (window, pos, columnp, rowp) 6311x_tool_bar_item (f, x, y, glyph, hpos, vpos, prop_idx)
2301 Lisp_Object window; 6312 struct frame *f;
2302 int pos; 6313 int x, y;
2303 int *columnp, *rowp; 6314 struct glyph **glyph;
6315 int *hpos, *vpos, *prop_idx;
6316{
6317 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
6318 struct window *w = XWINDOW (f->tool_bar_window);
6319 int area;
6320
6321 /* Find the glyph under X/Y. */
6322 *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, &area);
6323 if (*glyph == NULL)
6324 return -1;
6325
6326 /* Get the start of this tool-bar item's properties in
6327 f->current_tool_bar_items. */
6328 if (!tool_bar_item_info (f, *glyph, prop_idx))
6329 return -1;
6330
6331 /* Is mouse on the highlighted item? */
6332 if (EQ (f->tool_bar_window, dpyinfo->mouse_face_window)
6333 && *vpos >= dpyinfo->mouse_face_beg_row
6334 && *vpos <= dpyinfo->mouse_face_end_row
6335 && (*vpos > dpyinfo->mouse_face_beg_row
6336 || *hpos >= dpyinfo->mouse_face_beg_col)
6337 && (*vpos < dpyinfo->mouse_face_end_row
6338 || *hpos < dpyinfo->mouse_face_end_col
6339 || dpyinfo->mouse_face_past_end))
6340 return 0;
6341
6342 return 1;
6343}
6344
6345
6346/* Handle mouse button event on the tool_bar of frame F, at
6347 frame-relative coordinates X/Y. EVENT_TYPE is either ButtionPress
6348 or ButtonRelase. */
6349
6350static void
6351w32_handle_tool_bar_click (f, button_event)
6352 struct frame *f;
6353 struct input_event *button_event;
6354{
6355 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
6356 struct window *w = XWINDOW (f->tool_bar_window);
6357 int hpos, vpos, prop_idx;
6358 struct glyph *glyph;
6359 Lisp_Object enabled_p;
6360 int x = XFASTINT (button_event->x);
6361 int y = XFASTINT (button_event->y);
6362
6363 /* If not on the highlighted tool-bar item, return. */
6364 frame_to_window_pixel_xy (w, &x, &y);
6365 if (x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx) != 0)
6366 return;
6367
6368 /* If item is disabled, do nothing. */
6369 enabled_p = (XVECTOR (f->current_tool_bar_items)
6370 ->contents[prop_idx + TOOL_BAR_ITEM_ENABLED_P]);
6371 if (NILP (enabled_p))
6372 return;
6373
6374 if (button_event->kind == mouse_click)
6375 {
6376 /* Show item in pressed state. */
6377 show_mouse_face (dpyinfo, DRAW_IMAGE_SUNKEN);
6378 dpyinfo->mouse_face_image_state = DRAW_IMAGE_SUNKEN;
6379 last_tool_bar_item = prop_idx;
6380 }
6381 else
6382 {
6383 Lisp_Object key, frame;
6384 struct input_event event;
6385
6386 /* Show item in released state. */
6387 show_mouse_face (dpyinfo, DRAW_IMAGE_RAISED);
6388 dpyinfo->mouse_face_image_state = DRAW_IMAGE_RAISED;
6389
6390 key = (XVECTOR (f->current_tool_bar_items)
6391 ->contents[prop_idx + TOOL_BAR_ITEM_KEY]);
6392
6393 XSETFRAME (frame, f);
6394 event.kind = TOOL_BAR_EVENT;
6395 event.frame_or_window = Fcons (frame, Fcons (Qtool_bar, Qnil));
6396 kbd_buffer_store_event (&event);
6397
6398 event.kind = TOOL_BAR_EVENT;
6399 event.frame_or_window = Fcons (frame, key);
6400 event.modifiers = button_event->modifiers;
6401 kbd_buffer_store_event (&event);
6402 last_tool_bar_item = -1;
6403 }
6404}
6405
6406
6407/* Possibly highlight a tool_bar item on frame F when mouse moves to
6408 tool-bar window-relative coordinates X/Y. Called from
6409 note_mouse_highlight. */
6410
6411static void
6412note_tool_bar_highlight (f, x, y)
6413 struct frame *f;
6414 int x, y;
2304{ 6415{
6416 Lisp_Object window = f->tool_bar_window;
2305 struct window *w = XWINDOW (window); 6417 struct window *w = XWINDOW (window);
2306 FRAME_PTR f = XFRAME (WINDOW_FRAME (w)); 6418 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
6419 int hpos, vpos;
6420 struct glyph *glyph;
6421 struct glyph_row *row;
2307 int i; 6422 int i;
2308 int row = 0; 6423 Lisp_Object enabled_p;
2309 int left = WINDOW_LEFT_MARGIN (w); 6424 int prop_idx;
2310 int top = w->top; 6425 enum draw_glyphs_face draw = DRAW_IMAGE_RAISED;
2311 int height = XFASTINT (w->height) - ! MINI_WINDOW_P (w); 6426 int mouse_down_p, rc;
2312 int width = window_internal_width (w); 6427
2313 int *charstarts; 6428 /* Function note_mouse_highlight is called with negative x(y
2314 int lastcol; 6429 values when mouse moves outside of the frame. */
2315 int maybe_next_line = 0; 6430 if (x <= 0 || y <= 0)
6431 {
6432 clear_mouse_face (dpyinfo);
6433 return;
6434 }
2316 6435
2317 /* Find the right row. */ 6436 rc = x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx);
2318 for (i = 0; 6437 if (rc < 0)
2319 i < height; 6438 {
2320 i++) 6439 /* Not on tool-bar item. */
6440 clear_mouse_face (dpyinfo);
6441 return;
6442 }
6443 else if (rc == 0)
6444 /* On same tool-bar item as before. */
6445 goto set_help_echo;
6446
6447 clear_mouse_face (dpyinfo);
6448
6449 /* Mouse is down, but on different tool-bar item? */
6450 mouse_down_p = (dpyinfo->grabbed
6451 && f == last_mouse_frame
6452 && FRAME_LIVE_P (f));
6453 if (mouse_down_p
6454 && last_tool_bar_item != prop_idx)
6455 return;
6456
6457 dpyinfo->mouse_face_image_state = DRAW_NORMAL_TEXT;
6458 draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
6459
6460 /* If tool-bar item is not enabled, don't highlight it. */
6461 enabled_p = (XVECTOR (f->current_tool_bar_items)
6462 ->contents[prop_idx + TOOL_BAR_ITEM_ENABLED_P]);
6463 if (!NILP (enabled_p))
6464 {
6465 /* Compute the x-position of the glyph. In front and past the
6466 image is a space. We include this is the highlighted area. */
6467 row = MATRIX_ROW (w->current_matrix, vpos);
6468 for (i = x = 0; i < hpos; ++i)
6469 x += row->glyphs[TEXT_AREA][i].pixel_width;
6470
6471 /* Record this as the current active region. */
6472 dpyinfo->mouse_face_beg_col = hpos;
6473 dpyinfo->mouse_face_beg_row = vpos;
6474 dpyinfo->mouse_face_beg_x = x;
6475 dpyinfo->mouse_face_beg_y = row->y;
6476 dpyinfo->mouse_face_past_end = 0;
6477
6478 dpyinfo->mouse_face_end_col = hpos + 1;
6479 dpyinfo->mouse_face_end_row = vpos;
6480 dpyinfo->mouse_face_end_x = x + glyph->pixel_width;
6481 dpyinfo->mouse_face_end_y = row->y;
6482 dpyinfo->mouse_face_window = window;
6483 dpyinfo->mouse_face_face_id = TOOL_BAR_FACE_ID;
6484
6485 /* Display it as active. */
6486 show_mouse_face (dpyinfo, draw);
6487 dpyinfo->mouse_face_image_state = draw;
6488 }
6489
6490 set_help_echo:
6491
6492 /* Set help_echo to a help string.to display for this tool-bar item.
6493 w32_read_socket does the rest. */
6494 help_echo = (XVECTOR (f->current_tool_bar_items)
6495 ->contents[prop_idx + TOOL_BAR_ITEM_HELP]);
6496 if (!STRINGP (help_echo))
6497 help_echo = (XVECTOR (f->current_tool_bar_items)
6498 ->contents[prop_idx + TOOL_BAR_ITEM_CAPTION]);
6499}
6500
6501
6502/* Find the glyph matrix position of buffer position POS in window W.
6503 *HPOS, *VPOS, *X, and *Y are set to the positions found. W's
6504 current glyphs must be up to date. If POS is above window start
6505 return (0, 0, 0, 0). If POS is after end of W, return end of
6506 last line in W. */
6507
6508static int
6509fast_find_position (w, pos, hpos, vpos, x, y)
6510 struct window *w;
6511 int pos;
6512 int *hpos, *vpos, *x, *y;
6513{
6514 int i;
6515 int lastcol;
6516 int maybe_next_line_p = 0;
6517 int line_start_position;
6518 int yb = window_text_bottom_y (w);
6519 struct glyph_row *row = MATRIX_ROW (w->current_matrix, 0);
6520 struct glyph_row *best_row = row;
6521 int row_vpos = 0, best_row_vpos = 0;
6522 int current_x;
6523
6524 while (row->y < yb)
2321 { 6525 {
2322 int linestart = FRAME_CURRENT_GLYPHS (f)->charstarts[top + i][left]; 6526 if (row->used[TEXT_AREA])
2323 if (linestart > pos) 6527 line_start_position = row->glyphs[TEXT_AREA]->charpos;
6528 else
6529 line_start_position = 0;
6530
6531 if (line_start_position > pos)
2324 break; 6532 break;
2325 /* If the position sought is the end of the buffer, 6533 /* If the position sought is the end of the buffer,
2326 don't include the blank lines at the bottom of the window. */ 6534 don't include the blank lines at the bottom of the window. */
2327 if (linestart == pos && pos == BUF_ZV (XBUFFER (w->buffer))) 6535 else if (line_start_position == pos
6536 && pos == BUF_ZV (XBUFFER (w->buffer)))
2328 { 6537 {
2329 maybe_next_line = 1; 6538 maybe_next_line_p = 1;
2330 break; 6539 break;
2331 } 6540 }
2332 if (linestart > 0) 6541 else if (line_start_position > 0)
2333 row = i; 6542 {
6543 best_row = row;
6544 best_row_vpos = row_vpos;
6545 }
6546
6547 ++row;
6548 ++row_vpos;
2334 } 6549 }
2335 6550
2336 /* Find the right column with in it. */ 6551 /* Find the right column within BEST_ROW. */
2337 charstarts = FRAME_CURRENT_GLYPHS (f)->charstarts[top + row]; 6552 lastcol = 0;
2338 lastcol = left; 6553 current_x = best_row->x;
2339 for (i = 0; i < width; i++) 6554 for (i = 0; i < best_row->used[TEXT_AREA]; i++)
2340 { 6555 {
2341 if (charstarts[left + i] == pos) 6556 struct glyph *glyph = best_row->glyphs[TEXT_AREA] + i;
6557 int charpos;
6558
6559 charpos = glyph->charpos;
6560 if (charpos == pos)
2342 { 6561 {
2343 *rowp = row + top; 6562 *hpos = i;
2344 *columnp = i + left; 6563 *vpos = best_row_vpos;
6564 *x = current_x;
6565 *y = best_row->y;
2345 return 1; 6566 return 1;
2346 } 6567 }
2347 else if (charstarts[left + i] > pos) 6568 else if (charpos > pos)
2348 break; 6569 break;
2349 else if (charstarts[left + i] > 0) 6570 else if (charpos > 0)
2350 lastcol = left + i; 6571 lastcol = i;
6572
6573 current_x += glyph->pixel_width;
2351 } 6574 }
2352 6575
2353 /* If we're looking for the end of the buffer, 6576 /* If we're looking for the end of the buffer,
2354 and we didn't find it in the line we scanned, 6577 and we didn't find it in the line we scanned,
2355 use the start of the following line. */ 6578 use the start of the following line. */
2356 if (maybe_next_line) 6579 if (maybe_next_line_p)
2357 { 6580 {
2358 row++; 6581 ++best_row;
2359 i = 0; 6582 ++best_row_vpos;
6583 lastcol = 0;
6584 current_x = best_row->x;
2360 } 6585 }
2361 6586
2362 *rowp = row + top; 6587 *vpos = best_row_vpos;
2363 *columnp = lastcol; 6588 *hpos = lastcol + 1;
6589 *x = current_x;
6590 *y = best_row->y;
2364 return 0; 6591 return 0;
2365} 6592}
2366 6593
6594
2367/* Display the active region described by mouse_face_* 6595/* Display the active region described by mouse_face_*
2368 in its mouse-face if HL > 0, in its normal face if HL = 0. */ 6596 in its mouse-face if HL > 0, in its normal face if HL = 0. */
2369 6597
2370static void 6598static void
2371show_mouse_face (dpyinfo, hl) 6599show_mouse_face (dpyinfo, draw)
2372 struct w32_display_info *dpyinfo; 6600 struct w32_display_info *dpyinfo;
2373 int hl; 6601 enum draw_glyphs_face draw;
2374{ 6602{
2375 struct window *w = XWINDOW (dpyinfo->mouse_face_window); 6603 struct window *w = XWINDOW (dpyinfo->mouse_face_window);
2376 int width = window_internal_width (w); 6604 struct frame *f = XFRAME (WINDOW_FRAME (w));
2377 FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
2378 int i; 6605 int i;
2379 int cursor_off = 0; 6606 int cursor_off_p = 0;
2380 int old_curs_x = curs_x; 6607 struct cursor_pos saved_cursor;
2381 int old_curs_y = curs_y; 6608
2382 6609 saved_cursor = output_cursor;
2383 /* Set these variables temporarily 6610
2384 so that if we have to turn the cursor off and on again 6611 /* If window is in the process of being destroyed, don't bother
2385 we will put it back at the same place. */ 6612 to do anything. */
2386 curs_x = f->phys_cursor_x; 6613 if (w->current_matrix == NULL)
2387 curs_y = f->phys_cursor_y; 6614 goto set_x_cursor;
2388 6615
2389 for (i = FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_row; 6616 /* Recognize when we are called to operate on rows that don't exist
2390 i <= FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_row; i++) 6617 anymore. This can happen when a window is split. */
2391 { 6618 if (dpyinfo->mouse_face_end_row >= w->current_matrix->nrows)
2392 int column = (i == FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_row 6619 goto set_x_cursor;
2393 ? FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_col 6620
2394 : WINDOW_LEFT_MARGIN (w)); 6621 set_output_cursor (&w->phys_cursor);
2395 int endcolumn = (i == FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_row 6622
2396 ? FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_col 6623 /* Note that mouse_face_beg_row etc. are window relative. */
2397 : WINDOW_LEFT_MARGIN (w) + width); 6624 for (i = dpyinfo->mouse_face_beg_row;
2398 endcolumn = min (endcolumn, FRAME_CURRENT_GLYPHS (f)->used[i]); 6625 i <= dpyinfo->mouse_face_end_row;
2399 6626 i++)
2400 /* If the cursor's in the text we are about to rewrite, 6627 {
2401 turn the cursor off. */ 6628 int start_hpos, end_hpos, start_x;
2402 if (i == curs_y 6629 struct glyph_row *row = MATRIX_ROW (w->current_matrix, i);
2403 && curs_x >= column - 1 6630
2404 && curs_x <= endcolumn) 6631 /* Don't do anything if row doesn't have valid contents. */
6632 if (!row->enabled_p)
6633 continue;
6634
6635 /* For all but the first row, the highlight starts at column 0. */
6636 if (i == dpyinfo->mouse_face_beg_row)
6637 {
6638 start_hpos = dpyinfo->mouse_face_beg_col;
6639 start_x = dpyinfo->mouse_face_beg_x;
6640 }
6641 else
2405 { 6642 {
2406 x_display_cursor (f, 0); 6643 start_hpos = 0;
2407 cursor_off = 1; 6644 start_x = 0;
2408 } 6645 }
2409 6646
2410 dumpglyphs (f, 6647 if (i == dpyinfo->mouse_face_end_row)
2411 CHAR_TO_PIXEL_COL (f, column), 6648 end_hpos = dpyinfo->mouse_face_end_col;
2412 CHAR_TO_PIXEL_ROW (f, i), 6649 else
2413 FRAME_CURRENT_GLYPHS (f)->glyphs[i] + column, 6650 end_hpos = row->used[TEXT_AREA];
2414 endcolumn - column, 6651
2415 /* Highlight with mouse face if hl > 0. */ 6652 /* If the cursor's in the text we are about to rewrite, turn the
2416 hl > 0 ? 3 : 0, 0, NULL); 6653 cursor off. */
6654 if (!w->pseudo_window_p
6655 && i == output_cursor.vpos
6656 && output_cursor.hpos >= start_hpos - 1
6657 && output_cursor.hpos <= end_hpos)
6658 {
6659 x_update_window_cursor (w, 0);
6660 cursor_off_p = 1;
6661 }
6662
6663 if (end_hpos > start_hpos)
6664 x_draw_glyphs (w, start_x, row, TEXT_AREA,
6665 start_hpos, end_hpos, draw, NULL, NULL, 0);
2417 } 6666 }
2418 6667
2419 /* If we turned the cursor off, turn it back on. */ 6668 /* If we turned the cursor off, turn it back on. */
2420 if (cursor_off) 6669 if (cursor_off_p)
2421 x_display_cursor (f, 1); 6670 x_display_cursor (w, 1,
2422 6671 output_cursor.hpos, output_cursor.vpos,
2423 curs_x = old_curs_x; 6672 output_cursor.x, output_cursor.y);
2424 curs_y = old_curs_y; 6673
2425 6674 output_cursor = saved_cursor;
2426 /* Change the mouse cursor according to the value of HL. */ 6675
2427 if (hl > 0) 6676 set_x_cursor:
2428 SetCursor (f->output_data.w32->cross_cursor); 6677#if 0 /* NTEMACS_TODO: mouse cursor */
6678 /* Change the mouse cursor. */
6679 if (draw == DRAW_NORMAL_TEXT)
6680 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
6681 f->output_data.x->text_cursor);
6682 else if (draw == DRAW_MOUSE_FACE)
6683 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
6684 f->output_data.x->cross_cursor);
2429 else 6685 else
2430 SetCursor (f->output_data.w32->text_cursor); 6686 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
6687 f->output_data.x->nontext_cursor);
6688#endif
6689 ;
2431} 6690}
2432 6691
6692
2433/* Clear out the mouse-highlighted active region. 6693/* Clear out the mouse-highlighted active region.
2434 Redraw it unhighlighted first. */ 6694 Redraw it unhighlighted first. */
2435 6695
2436static void 6696void
2437clear_mouse_face (dpyinfo) 6697clear_mouse_face (dpyinfo)
2438 struct w32_display_info *dpyinfo; 6698 struct w32_display_info *dpyinfo;
2439{ 6699{
6700 if (tip_frame)
6701 return;
6702
2440 if (! NILP (dpyinfo->mouse_face_window)) 6703 if (! NILP (dpyinfo->mouse_face_window))
2441 show_mouse_face (dpyinfo, 0); 6704 show_mouse_face (dpyinfo, DRAW_NORMAL_TEXT);
2442 6705
2443 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1; 6706 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
2444 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1; 6707 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
@@ -2547,20 +6810,48 @@ w32_mouse_position (fp, insist, bar_window, part, x, y, time)
2547 } 6810 }
2548 6811
2549 if (f1 == 0 && insist > 0) 6812 if (f1 == 0 && insist > 0)
2550 f1 = selected_frame; 6813 f1 = SELECTED_FRAME ();
2551 6814
2552 if (f1) 6815 if (f1)
2553 { 6816 {
6817 /* Ok, we found a frame. Store all the values.
6818 last_mouse_glyph is a rectangle used to reduce the
6819 generation of mouse events. To not miss any motion
6820 events, we must divide the frame into rectangles of the
6821 size of the smallest character that could be displayed
6822 on it, i.e. into the same rectangles that matrices on
6823 the frame are divided into. */
6824
6825#if OLD_REDISPLAY_CODE
2554 int ignore1, ignore2; 6826 int ignore1, ignore2;
2555 6827
2556 ScreenToClient (FRAME_W32_WINDOW (f1), &pt); 6828 ScreenToClient (FRAME_W32_WINDOW (f1), &pt);
2557 6829
2558 /* Ok, we found a frame. Store all the values. */
2559
2560 pixel_to_glyph_coords (f1, pt.x, pt.y, &ignore1, &ignore2, 6830 pixel_to_glyph_coords (f1, pt.x, pt.y, &ignore1, &ignore2,
2561 &last_mouse_glyph, 6831 &last_mouse_glyph,
2562 FRAME_W32_DISPLAY_INFO (f1)->grabbed 6832 FRAME_W32_DISPLAY_INFO (f1)->grabbed
2563 || insist); 6833 || insist);
6834#else
6835 ScreenToClient (FRAME_W32_WINDOW (f1), &pt);
6836 {
6837 int width = FRAME_SMALLEST_CHAR_WIDTH (f1);
6838 int height = FRAME_SMALLEST_FONT_HEIGHT (f1);
6839 int x = pt.x;
6840 int y = pt.y;
6841
6842 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to
6843 round down even for negative values. */
6844 if (x < 0)
6845 x -= width - 1;
6846 if (y < 0)
6847 y -= height - 1;
6848
6849 last_mouse_glyph.left = (x + width - 1) / width * width;
6850 last_mouse_glyph.top = (y + height - 1) / height * height;
6851 last_mouse_glyph.right = last_mouse_glyph.left + width;
6852 last_mouse_glyph.bottom = last_mouse_glyph.top + height;
6853 }
6854#endif
2564 6855
2565 *bar_window = Qnil; 6856 *bar_window = Qnil;
2566 *part = 0; 6857 *part = 0;
@@ -2574,6 +6865,7 @@ w32_mouse_position (fp, insist, bar_window, part, x, y, time)
2574 6865
2575 UNBLOCK_INPUT; 6866 UNBLOCK_INPUT;
2576} 6867}
6868
2577 6869
2578/* Scroll bar support. */ 6870/* Scroll bar support. */
2579 6871
@@ -2584,7 +6876,7 @@ struct scroll_bar *
2584x_window_to_scroll_bar (window_id) 6876x_window_to_scroll_bar (window_id)
2585 Window window_id; 6877 Window window_id;
2586{ 6878{
2587 Lisp_Object tail, frame; 6879 Lisp_Object tail;
2588 6880
2589 for (tail = Vframe_list; 6881 for (tail = Vframe_list;
2590 XGCTYPE (tail) == Lisp_Cons; 6882 XGCTYPE (tail) == Lisp_Cons;
@@ -2614,6 +6906,71 @@ x_window_to_scroll_bar (window_id)
2614 return 0; 6906 return 0;
2615} 6907}
2616 6908
6909
6910
6911/* Set the thumb size and position of scroll bar BAR. We are currently
6912 displaying PORTION out of a whole WHOLE, and our position POSITION. */
6913
6914static void
6915w32_set_scroll_bar_thumb (bar, portion, position, whole)
6916 struct scroll_bar *bar;
6917 int portion, position, whole;
6918{
6919 Window w = SCROLL_BAR_W32_WINDOW (bar);
6920 int range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
6921 int sb_page, sb_pos;
6922 BOOL draggingp = !NILP (bar->dragging) ? TRUE : FALSE;
6923
6924 if (whole)
6925 {
6926 /* Position scroll bar at rock bottom if the bottom of the
6927 buffer is visible. This avoids shinking the thumb away
6928 to nothing if it is held at the bottom of the buffer. */
6929 if (position + portion >= whole)
6930 {
6931 sb_page = range * (whole - position) / whole
6932 + VERTICAL_SCROLL_BAR_MIN_HANDLE;
6933 sb_pos = range;
6934 }
6935
6936 sb_page = portion * range / whole + VERTICAL_SCROLL_BAR_MIN_HANDLE;
6937 sb_pos = position * range / whole;
6938 }
6939 else
6940 {
6941 sb_page = range;
6942 sb_pos = 0;
6943 }
6944
6945 BLOCK_INPUT;
6946
6947 if (pfnSetScrollInfo)
6948 {
6949 SCROLLINFO si;
6950
6951 si.cbSize = sizeof (si);
6952 /* Only update page size if currently dragging, to reduce
6953 flicker effects. */
6954 if (draggingp)
6955 si.fMask = SIF_PAGE;
6956 else
6957 si.fMask = SIF_PAGE | SIF_POS;
6958 si.nPage = sb_page;
6959 si.nPos = sb_pos;
6960
6961 pfnSetScrollInfo (w, SB_CTL, &si, !draggingp);
6962 }
6963 else
6964 SetScrollPos (w, SB_CTL, sb_pos, !draggingp);
6965
6966 UNBLOCK_INPUT;
6967}
6968
6969
6970/************************************************************************
6971 Scroll bars, general
6972 ************************************************************************/
6973
2617HWND 6974HWND
2618my_create_scrollbar (f, bar) 6975my_create_scrollbar (f, bar)
2619 struct frame * f; 6976 struct frame * f;
@@ -2680,21 +7037,24 @@ my_destroy_window (f, hwnd)
2680 (WPARAM) hwnd, 0); 7037 (WPARAM) hwnd, 0);
2681} 7038}
2682 7039
2683/* Open a new window to serve as a scroll bar, and return the 7040/* Create a scroll bar and return the scroll bar vector for it. W is
2684 scroll bar vector for it. */ 7041 the Emacs window on which to create the scroll bar. TOP, LEFT,
7042 WIDTH and HEIGHT are.the pixel coordinates and dimensions of the
7043 scroll bar. */
7044
2685static struct scroll_bar * 7045static struct scroll_bar *
2686x_scroll_bar_create (window, top, left, width, height) 7046x_scroll_bar_create (w, top, left, width, height)
2687 struct window *window; 7047 struct window *w;
2688 int top, left, width, height; 7048 int top, left, width, height;
2689{ 7049{
2690 FRAME_PTR f = XFRAME (WINDOW_FRAME (window)); 7050 struct frame *f = XFRAME (WINDOW_FRAME (w));
7051 HWND hwnd;
2691 struct scroll_bar *bar 7052 struct scroll_bar *bar
2692 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil)); 7053 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
2693 HWND hwnd;
2694 7054
2695 BLOCK_INPUT; 7055 BLOCK_INPUT;
2696 7056
2697 XSETWINDOW (bar->window, window); 7057 XSETWINDOW (bar->window, w);
2698 XSETINT (bar->top, top); 7058 XSETINT (bar->top, top);
2699 XSETINT (bar->left, left); 7059 XSETINT (bar->left, left);
2700 XSETINT (bar->width, width); 7060 XSETINT (bar->width, width);
@@ -2714,8 +7074,8 @@ x_scroll_bar_create (window, top, left, width, height)
2714 si.cbSize = sizeof (si); 7074 si.cbSize = sizeof (si);
2715 si.fMask = SIF_ALL; 7075 si.fMask = SIF_ALL;
2716 si.nMin = 0; 7076 si.nMin = 0;
2717 si.nMax = VERTICAL_SCROLL_BAR_TOP_RANGE (height) 7077 si.nMax = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height)
2718 + VERTICAL_SCROLL_BAR_MIN_HANDLE; 7078 + VERTICAL_SCROLL_BAR_MIN_HANDLE;
2719 si.nPage = si.nMax; 7079 si.nPage = si.nMax;
2720 si.nPos = 0; 7080 si.nPos = 0;
2721 7081
@@ -2723,7 +7083,8 @@ x_scroll_bar_create (window, top, left, width, height)
2723 } 7083 }
2724 else 7084 else
2725 { 7085 {
2726 SetScrollRange (hwnd, SB_CTL, 0, VERTICAL_SCROLL_BAR_TOP_RANGE (height), FALSE); 7086 SetScrollRange (hwnd, SB_CTL, 0,
7087 VERTICAL_SCROLL_BAR_TOP_RANGE (f, height), FALSE);
2727 SetScrollPos (hwnd, SB_CTL, 0, FALSE); 7088 SetScrollPos (hwnd, SB_CTL, 0, FALSE);
2728 } 7089 }
2729 7090
@@ -2741,136 +7102,10 @@ x_scroll_bar_create (window, top, left, width, height)
2741 return bar; 7102 return bar;
2742} 7103}
2743 7104
2744/* Draw BAR's handle in the proper position.
2745 If the handle is already drawn from START to END, don't bother
2746 redrawing it, unless REBUILD is non-zero; in that case, always
2747 redraw it. (REBUILD is handy for drawing the handle after expose
2748 events.)
2749
2750 Normally, we want to constrain the start and end of the handle to
2751 fit inside its rectangle, but if the user is dragging the scroll bar
2752 handle, we want to let them drag it down all the way, so that the
2753 bar's top is as far down as it goes; otherwise, there's no way to
2754 move to the very end of the buffer. */
2755static void
2756x_scroll_bar_set_handle (bar, start, end, rebuild)
2757 struct scroll_bar *bar;
2758 int start, end;
2759 int rebuild;
2760{
2761 int dragging = ! NILP (bar->dragging);
2762 Window w = SCROLL_BAR_W32_WINDOW (bar);
2763 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
2764
2765 /* If the display is already accurate, do nothing. */
2766 if (! rebuild
2767 && start == XINT (bar->start)
2768 && end == XINT (bar->end))
2769 return;
2770
2771 BLOCK_INPUT;
2772
2773 {
2774 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar->height));
2775
2776 /* Make sure the values are reasonable, and try to preserve
2777 the distance between start and end. */
2778 {
2779 int length = end - start;
2780
2781 if (start < 0)
2782 start = 0;
2783 else if (start > top_range)
2784 start = top_range;
2785 end = start + length;
2786
2787 if (end < start)
2788 end = start;
2789 else if (end > top_range && ! dragging)
2790 end = top_range;
2791 }
2792 }
2793
2794 /* Store the adjusted setting in the scroll bar. */
2795 XSETINT (bar->start, start);
2796 XSETINT (bar->end, end);
2797
2798 /* If being dragged, let scroll bar update itself. */
2799 if (!dragging)
2800 {
2801 if (pfnSetScrollInfo)
2802 {
2803 SCROLLINFO si;
2804
2805 si.cbSize = sizeof (si);
2806 si.fMask = SIF_PAGE | SIF_POS;
2807 si.nPage = end - start + VERTICAL_SCROLL_BAR_MIN_HANDLE;
2808 si.nPos = start;
2809
2810 pfnSetScrollInfo (w, SB_CTL, &si, TRUE);
2811 }
2812 else
2813 SetScrollPos (w, SB_CTL, start, TRUE);
2814 }
2815
2816 UNBLOCK_INPUT;
2817}
2818
2819/* Move a scroll bar around on the screen, to accommodate changing
2820 window configurations. */
2821static void
2822x_scroll_bar_move (bar, top, left, width, height)
2823 struct scroll_bar *bar;
2824 int top, left, width, height;
2825{
2826 Window w = SCROLL_BAR_W32_WINDOW (bar);
2827 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
2828
2829 /* If already correctly positioned, do nothing. */
2830 if ( XINT (bar->left) == left
2831 && XINT (bar->top) == top
2832 && XINT (bar->width) == width
2833 && XINT (bar->height) == height )
2834 {
2835 /* Redraw after clear_frame. */
2836 if (!my_show_window (f, w, SW_NORMAL))
2837 InvalidateRect (w, NULL, FALSE);
2838 return;
2839 }
2840
2841 BLOCK_INPUT;
2842
2843 /* Make sure scroll bar is "visible" before moving, to ensure the
2844 area of the parent window now exposed will be refreshed. */
2845 my_show_window (f, w, SW_HIDE);
2846 MoveWindow (w, left, top, width, height, TRUE);
2847 if (pfnSetScrollInfo)
2848 {
2849 SCROLLINFO si;
2850
2851 si.cbSize = sizeof (si);
2852 si.fMask = SIF_RANGE;
2853 si.nMin = 0;
2854 si.nMax = VERTICAL_SCROLL_BAR_TOP_RANGE (height)
2855 + VERTICAL_SCROLL_BAR_MIN_HANDLE;
2856
2857 pfnSetScrollInfo (w, SB_CTL, &si, FALSE);
2858 }
2859 else
2860 SetScrollRange (w, SB_CTL, 0, VERTICAL_SCROLL_BAR_TOP_RANGE (height), FALSE);
2861 my_show_window (f, w, SW_NORMAL);
2862// InvalidateRect (w, NULL, FALSE);
2863
2864 XSETINT (bar->left, left);
2865 XSETINT (bar->top, top);
2866 XSETINT (bar->width, width);
2867 XSETINT (bar->height, height);
2868 7105
2869 UNBLOCK_INPUT; 7106/* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
2870} 7107 nil. */
2871 7108
2872/* Destroy the window for BAR, and set its Emacs window's scroll bar
2873 to nil. */
2874static void 7109static void
2875x_scroll_bar_remove (bar) 7110x_scroll_bar_remove (bar)
2876 struct scroll_bar *bar; 7111 struct scroll_bar *bar;
@@ -2893,54 +7128,115 @@ x_scroll_bar_remove (bar)
2893 characters, starting at POSITION. If WINDOW has no scroll bar, 7128 characters, starting at POSITION. If WINDOW has no scroll bar,
2894 create one. */ 7129 create one. */
2895static void 7130static void
2896w32_set_vertical_scroll_bar (window, portion, whole, position) 7131w32_set_vertical_scroll_bar (w, portion, whole, position)
2897 struct window *window; 7132 struct window *w;
2898 int portion, whole, position; 7133 int portion, whole, position;
2899{ 7134{
2900 FRAME_PTR f = XFRAME (WINDOW_FRAME (window)); 7135 struct frame *f = XFRAME (w->frame);
2901 int top = XINT (window->top);
2902 int left = WINDOW_VERTICAL_SCROLL_BAR_COLUMN (window);
2903 int height = WINDOW_VERTICAL_SCROLL_BAR_HEIGHT (window);
2904
2905 /* Where should this scroll bar be, pixelwise? */
2906 int pixel_top = CHAR_TO_PIXEL_ROW (f, top);
2907 int pixel_left = CHAR_TO_PIXEL_COL (f, left);
2908 int pixel_width
2909 = (FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0
2910 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f)
2911 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.w32->font)));
2912 int pixel_height = VERTICAL_SCROLL_BAR_PIXEL_HEIGHT (f, height);
2913
2914 struct scroll_bar *bar; 7136 struct scroll_bar *bar;
7137 int top, left, sb_left, width, sb_width, height;
7138 int window_x, window_y, window_width, window_height;
7139
7140 /* Get window dimensions. */
7141 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
7142 top = window_y;
7143 width = FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f);
7144 height = window_height;
7145
7146 /* Compute the left edge of the scroll bar area. */
7147 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
7148 left = XINT (w->left) + XINT (w->width) - FRAME_SCROLL_BAR_COLS (f);
7149 else
7150 left = XFASTINT (w->left);
7151 left *= CANON_X_UNIT (f);
7152 left += FRAME_INTERNAL_BORDER_WIDTH (f);
7153
7154 /* Compute the width of the scroll bar which might be less than
7155 the width of the area reserved for the scroll bar. */
7156 if (FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0)
7157 sb_width = FRAME_SCROLL_BAR_PIXEL_WIDTH (f);
7158 else
7159 sb_width = width;
2915 7160
2916 /* Does the scroll bar exist yet? */ 7161 /* Compute the left edge of the scroll bar. */
2917 if (NILP (window->vertical_scroll_bar)) 7162 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
2918 bar = x_scroll_bar_create (window, 7163 sb_left = left + width - sb_width - (width - sb_width) / 2;
2919 pixel_top, pixel_left,
2920 pixel_width, pixel_height);
2921 else 7164 else
7165 sb_left = left + (width - sb_width) / 2;
7166
7167 /* Does the scroll bar exist yet? */
7168 if (NILP (w->vertical_scroll_bar))
2922 { 7169 {
2923 /* It may just need to be moved and resized. */ 7170 BLOCK_INPUT;
2924 bar = XSCROLL_BAR (window->vertical_scroll_bar); 7171 w32_clear_area (f, NULL, left, top, width, height);
2925 x_scroll_bar_move (bar, pixel_top, pixel_left, pixel_width, pixel_height); 7172 UNBLOCK_INPUT;
7173 bar = x_scroll_bar_create (w, top, sb_left, sb_width, height);
2926 } 7174 }
7175 else
7176 {
7177 /* It may just need to be moved and resized. */
7178 HWND hwnd;
7179
7180 bar = XSCROLL_BAR (w->vertical_scroll_bar);
7181 hwnd = SCROLL_BAR_W32_WINDOW (bar);
7182
7183 /* If already correctly positioned, do nothing. */
7184 if ( XINT (bar->left) == sb_left
7185 && XINT (bar->top) == top
7186 && XINT (bar->width) == sb_width
7187 && XINT (bar->height) == height )
7188 {
7189 /* Redraw after clear_frame. */
7190 if (!my_show_window (f, hwnd, SW_NORMAL))
7191 InvalidateRect (hwnd, NULL, FALSE);
7192 }
7193 else
7194 {
7195 BLOCK_INPUT;
7196
7197 /* Since Windows scroll bars are smaller than the space reserved
7198 for them on the frame, we have to clear "under" them. */
7199 w32_clear_area (f, NULL,
7200 left,
7201 top,
7202 width,
7203 height);
7204
7205 /* Make sure scroll bar is "visible" before moving, to ensure the
7206 area of the parent window now exposed will be refreshed. */
7207 my_show_window (f, hwnd, SW_HIDE);
7208 MoveWindow (hwnd, sb_left, top,
7209 sb_width, height, TRUE);
7210 if (pfnSetScrollInfo)
7211 {
7212 SCROLLINFO si;
2927 7213
2928 /* Set the scroll bar's current state. */ 7214 si.cbSize = sizeof (si);
2929 { 7215 si.fMask = SIF_RANGE;
2930 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (pixel_height); 7216 si.nMin = 0;
2931 7217 si.nMax = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height)
2932 if (whole == 0) 7218 + VERTICAL_SCROLL_BAR_MIN_HANDLE;
2933 x_scroll_bar_set_handle (bar, 0, top_range, 0);
2934 else
2935 {
2936 int start = (int) (((double) position * top_range) / whole);
2937 int end = (int) (((double) (position + portion) * top_range) / whole);
2938 7219
2939 x_scroll_bar_set_handle (bar, start, end, 0); 7220 pfnSetScrollInfo (w, SB_CTL, &si, FALSE);
2940 } 7221 }
2941 } 7222 else
7223 SetScrollRange (w, SB_CTL, 0,
7224 VERTICAL_SCROLL_BAR_TOP_RANGE (f, height), FALSE);
7225 my_show_window (f, hwnd, SW_NORMAL);
7226 // InvalidateRect (w, NULL, FALSE);
7227
7228 /* Remember new settings. */
7229 XSETINT (bar->left, sb_left);
7230 XSETINT (bar->top, top);
7231 XSETINT (bar->width, sb_width);
7232 XSETINT (bar->height, height);
7233
7234 UNBLOCK_INPUT;
7235 }
7236 }
7237 w32_set_scroll_bar_thumb (bar, portion, position, whole);
2942 7238
2943 XSETVECTOR (window->vertical_scroll_bar, bar); 7239 XSETVECTOR (w->vertical_scroll_bar, bar);
2944} 7240}
2945 7241
2946 7242
@@ -2971,17 +7267,6 @@ w32_condemn_scroll_bars (frame)
2971 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar; 7267 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
2972 FRAME_CONDEMNED_SCROLL_BARS (frame) = bar; 7268 FRAME_CONDEMNED_SCROLL_BARS (frame) = bar;
2973 } 7269 }
2974#ifdef PIGSFLY
2975 /* The condemned list should be empty at this point; if it's not,
2976 then the rest of Emacs isn't using the condemn/redeem/judge
2977 protocol correctly. */
2978 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
2979 abort ();
2980
2981 /* Move them all to the "condemned" list. */
2982 FRAME_CONDEMNED_SCROLL_BARS (frame) = FRAME_SCROLL_BARS (frame);
2983 FRAME_SCROLL_BARS (frame) = Qnil;
2984#endif
2985} 7270}
2986 7271
2987/* Unmark WINDOW's scroll bar for deletion in this judgement cycle. 7272/* Unmark WINDOW's scroll bar for deletion in this judgement cycle.
@@ -3029,47 +7314,6 @@ w32_redeem_scroll_bar (window)
3029 if (! NILP (bar->next)) 7314 if (! NILP (bar->next))
3030 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar); 7315 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
3031 } 7316 }
3032#ifdef PIGSFLY
3033 struct scroll_bar *bar;
3034
3035 /* We can't redeem this window's scroll bar if it doesn't have one. */
3036 if (NILP (window->vertical_scroll_bar))
3037 abort ();
3038
3039 bar = XSCROLL_BAR (window->vertical_scroll_bar);
3040
3041 /* Unlink it from the condemned list. */
3042 {
3043 FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
3044
3045 if (NILP (bar->prev))
3046 {
3047 /* If the prev pointer is nil, it must be the first in one of
3048 the lists. */
3049 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
3050 /* It's not condemned. Everything's fine. */
3051 return;
3052 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
3053 window->vertical_scroll_bar))
3054 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
3055 else
3056 /* If its prev pointer is nil, it must be at the front of
3057 one or the other! */
3058 abort ();
3059 }
3060 else
3061 XSCROLL_BAR (bar->prev)->next = bar->next;
3062
3063 if (! NILP (bar->next))
3064 XSCROLL_BAR (bar->next)->prev = bar->prev;
3065
3066 bar->next = FRAME_SCROLL_BARS (f);
3067 bar->prev = Qnil;
3068 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
3069 if (! NILP (bar->next))
3070 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
3071 }
3072#endif
3073} 7317}
3074 7318
3075/* Remove all scroll bars on FRAME that haven't been saved since the 7319/* Remove all scroll bars on FRAME that haven't been saved since the
@@ -3098,28 +7342,6 @@ w32_judge_scroll_bars (f)
3098 7342
3099 /* Now there should be no references to the condemned scroll bars, 7343 /* Now there should be no references to the condemned scroll bars,
3100 and they should get garbage-collected. */ 7344 and they should get garbage-collected. */
3101#ifdef PIGSFLY
3102 Lisp_Object bar, next;
3103
3104 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
3105
3106 /* Clear out the condemned list now so we won't try to process any
3107 more events on the hapless scroll bars. */
3108 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
3109
3110 for (; ! NILP (bar); bar = next)
3111 {
3112 struct scroll_bar *b = XSCROLL_BAR (bar);
3113
3114 x_scroll_bar_remove (b);
3115
3116 next = b->next;
3117 b->next = b->prev = Qnil;
3118 }
3119
3120 /* Now there should be no references to the condemned scroll bars,
3121 and they should get garbage-collected. */
3122#endif
3123} 7345}
3124 7346
3125/* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind 7347/* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
@@ -3145,7 +7367,7 @@ x_scroll_bar_handle_click (bar, msg, emacs_event)
3145 emacs_event->timestamp = msg->msg.time; 7367 emacs_event->timestamp = msg->msg.time;
3146 7368
3147 { 7369 {
3148 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar->height)); 7370 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
3149 int y; 7371 int y;
3150 int dragging = !NILP (bar->dragging); 7372 int dragging = !NILP (bar->dragging);
3151 7373
@@ -3188,8 +7410,8 @@ x_scroll_bar_handle_click (bar, msg, emacs_event)
3188 break; 7410 break;
3189 case SB_THUMBTRACK: 7411 case SB_THUMBTRACK:
3190 case SB_THUMBPOSITION: 7412 case SB_THUMBPOSITION:
3191 if (VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar->height)) <= 0xffff) 7413 if (VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height)) <= 0xffff)
3192 y = HIWORD (msg->msg.wParam); 7414 y = HIWORD (msg->msg.wParam);
3193 bar->dragging = Qt; 7415 bar->dragging = Qt;
3194 emacs_event->part = scroll_bar_handle; 7416 emacs_event->part = scroll_bar_handle;
3195 7417
@@ -3200,27 +7422,6 @@ x_scroll_bar_handle_click (bar, msg, emacs_event)
3200 7422
3201 si.cbSize = sizeof (si); 7423 si.cbSize = sizeof (si);
3202 si.fMask = SIF_POS; 7424 si.fMask = SIF_POS;
3203
3204#if 0
3205 /* Shrink handle if necessary to allow full range for position. */
3206 {
3207 int start = XINT (bar->start);
3208 int end = XINT (bar->end);
3209 int len = end - start;
3210
3211 /* If new end is nearly hitting bottom, we must shrink
3212 handle. How much we shrink it depends on the relative
3213 sizes of len and top_range. */
3214 if (y + len > top_range - 2)
3215 {
3216 len -= min (top_range / 10, (len / 3) + 2);
3217 if (len < 0)
3218 len = 0;
3219 }
3220 si.nPage = len + VERTICAL_SCROLL_BAR_MIN_HANDLE;
3221 si.fMask |= SIF_PAGE;
3222 }
3223#endif
3224 si.nPos = y; 7425 si.nPos = y;
3225 /* Remember apparent position (we actually lag behind the real 7426 /* Remember apparent position (we actually lag behind the real
3226 position, so don't set that directly. */ 7427 position, so don't set that directly. */
@@ -3245,9 +7446,8 @@ x_scroll_bar_handle_click (bar, msg, emacs_event)
3245 7446
3246 si.cbSize = sizeof (si); 7447 si.cbSize = sizeof (si);
3247 si.fMask = SIF_PAGE | SIF_POS; 7448 si.fMask = SIF_PAGE | SIF_POS;
3248 si.nPage = end - start + VERTICAL_SCROLL_BAR_MIN_HANDLE; 7449 si.nPage = end - start + VERTICAL_SCROLL_BAR_MIN_HANDLE;
3249 si.nPos = last_scroll_bar_drag_pos; 7450 si.nPos = last_scroll_bar_drag_pos;
3250
3251 pfnSetScrollInfo (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, &si, TRUE); 7451 pfnSetScrollInfo (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, &si, TRUE);
3252 } 7452 }
3253 else 7453 else
@@ -3280,7 +7480,7 @@ x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
3280 Window w = SCROLL_BAR_W32_WINDOW (bar); 7480 Window w = SCROLL_BAR_W32_WINDOW (bar);
3281 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window))); 7481 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
3282 int pos; 7482 int pos;
3283 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar->height)); 7483 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
3284 7484
3285 BLOCK_INPUT; 7485 BLOCK_INPUT;
3286 7486
@@ -3306,7 +7506,7 @@ x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
3306 case SB_THUMBPOSITION: 7506 case SB_THUMBPOSITION:
3307 case SB_THUMBTRACK: 7507 case SB_THUMBTRACK:
3308 *part = scroll_bar_handle; 7508 *part = scroll_bar_handle;
3309 if (VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar->height)) <= 0xffff) 7509 if (VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height)) <= 0xffff)
3310 pos = HIWORD (last_mouse_scroll_bar_pos); 7510 pos = HIWORD (last_mouse_scroll_bar_pos);
3311 break; 7511 break;
3312 case SB_LINEDOWN: 7512 case SB_LINEDOWN:
@@ -3333,9 +7533,9 @@ x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
3333 background colors, and the scroll bars may need to be redrawn. 7533 background colors, and the scroll bars may need to be redrawn.
3334 Clear out the scroll bars, and ask for expose events, so we can 7534 Clear out the scroll bars, and ask for expose events, so we can
3335 redraw them. */ 7535 redraw them. */
3336 7536void
3337x_scroll_bar_clear (f) 7537x_scroll_bar_clear (f)
3338 FRAME_PTR f; 7538 struct frame *f;
3339{ 7539{
3340 Lisp_Object bar; 7540 Lisp_Object bar;
3341 7541
@@ -3418,7 +7618,6 @@ w32_read_socket (sd, bufp, numchars, expected)
3418 int check_visibility = 0; 7618 int check_visibility = 0;
3419 W32Msg msg; 7619 W32Msg msg;
3420 struct frame *f; 7620 struct frame *f;
3421 Lisp_Object part;
3422 struct w32_display_info *dpyinfo = &one_w32_display_info; 7621 struct w32_display_info *dpyinfo = &one_w32_display_info;
3423 7622
3424 if (interrupt_input_blocked) 7623 if (interrupt_input_blocked)
@@ -3436,6 +7635,8 @@ w32_read_socket (sd, bufp, numchars, expected)
3436 if (numchars <= 0) 7635 if (numchars <= 0)
3437 abort (); /* Don't think this happens. */ 7636 abort (); /* Don't think this happens. */
3438 7637
7638 /* NTEMACS_TODO: tooltips, tool-bars, ghostscript integration, mouse
7639 cursors. */
3439 while (get_next_msg (&msg, FALSE)) 7640 while (get_next_msg (&msg, FALSE))
3440 { 7641 {
3441 switch (msg.msg.message) 7642 switch (msg.msg.message)
@@ -3482,11 +7683,11 @@ w32_read_socket (sd, bufp, numchars, expected)
3482 { 7683 {
3483 /* Erase background again for safety. */ 7684 /* Erase background again for safety. */
3484 w32_clear_rect (f, NULL, &msg.rect); 7685 w32_clear_rect (f, NULL, &msg.rect);
3485 dumprectangle (f, 7686 expose_frame (f,
3486 msg.rect.left, 7687 msg.rect.left,
3487 msg.rect.top, 7688 msg.rect.top,
3488 msg.rect.right - msg.rect.left, 7689 msg.rect.right - msg.rect.left,
3489 msg.rect.bottom - msg.rect.top); 7690 msg.rect.bottom - msg.rect.top);
3490 } 7691 }
3491 } 7692 }
3492 break; 7693 break;
@@ -3527,6 +7728,9 @@ w32_read_socket (sd, bufp, numchars, expected)
3527 bufp++; 7728 bufp++;
3528 numchars--; 7729 numchars--;
3529 count++; 7730 count++;
7731 if (display_busy_cursor_p)
7732 if (bufp->code != VK_RETURN || minibuf_level == 0)
7733 inhibit_busy_cursor = 2;
3530 } 7734 }
3531 break; 7735 break;
3532 7736
@@ -3547,10 +7751,16 @@ w32_read_socket (sd, bufp, numchars, expected)
3547 bufp++; 7751 bufp++;
3548 numchars--; 7752 numchars--;
3549 count++; 7753 count++;
7754 if (display_busy_cursor_p)
7755 if (bufp->code != VK_RETURN || minibuf_level == 0)
7756 inhibit_busy_cursor = 2;
3550 } 7757 }
3551 break; 7758 break;
3552 7759
3553 case WM_MOUSEMOVE: 7760 case WM_MOUSEMOVE:
7761 previous_help_echo = help_echo;
7762 help_echo = Qnil;
7763
3554 if (dpyinfo->grabbed && last_mouse_frame 7764 if (dpyinfo->grabbed && last_mouse_frame
3555 && FRAME_LIVE_P (last_mouse_frame)) 7765 && FRAME_LIVE_P (last_mouse_frame))
3556 f = last_mouse_frame; 7766 f = last_mouse_frame;
@@ -3560,9 +7770,30 @@ w32_read_socket (sd, bufp, numchars, expected)
3560 if (f) 7770 if (f)
3561 note_mouse_movement (f, &msg.msg); 7771 note_mouse_movement (f, &msg.msg);
3562 else 7772 else
3563 clear_mouse_face (FRAME_W32_DISPLAY_INFO (f)); 7773 {
3564 7774 /* If we move outside the frame, then we're
3565 break; 7775 certainly no longer on any text in the frame. */
7776 clear_mouse_face (FRAME_W32_DISPLAY_INFO (f));
7777 }
7778
7779 /* If the contents of the global variable help_echo
7780 has changed, generate a HELP_EVENT. */
7781 if (STRINGP (help_echo)
7782 || STRINGP (previous_help_echo))
7783 {
7784 Lisp_Object frame;
7785
7786 if (f)
7787 XSETFRAME (frame, f);
7788 else
7789 frame = Qnil;
7790
7791 any_help_event_p = 1;
7792 bufp->kind = HELP_EVENT;
7793 bufp->frame_or_window = Fcons (frame, help_echo);
7794 ++bufp, ++count, --numchars;
7795 }
7796 break;
3566 7797
3567 case WM_LBUTTONDOWN: 7798 case WM_LBUTTONDOWN:
3568 case WM_LBUTTONUP: 7799 case WM_LBUTTONUP:
@@ -3571,8 +7802,14 @@ w32_read_socket (sd, bufp, numchars, expected)
3571 case WM_RBUTTONDOWN: 7802 case WM_RBUTTONDOWN:
3572 case WM_RBUTTONUP: 7803 case WM_RBUTTONUP:
3573 { 7804 {
7805 /* If we decide we want to generate an event to be seen
7806 by the rest of Emacs, we put it here. */
7807 struct input_event emacs_event;
7808 int tool_bar_p = 0;
3574 int button; 7809 int button;
3575 int up; 7810 int up;
7811
7812 emacs_event.kind = no_event;
3576 7813
3577 if (dpyinfo->grabbed && last_mouse_frame 7814 if (dpyinfo->grabbed && last_mouse_frame
3578 && FRAME_LIVE_P (last_mouse_frame)) 7815 && FRAME_LIVE_P (last_mouse_frame))
@@ -3582,14 +7819,37 @@ w32_read_socket (sd, bufp, numchars, expected)
3582 7819
3583 if (f) 7820 if (f)
3584 { 7821 {
3585 if ((!dpyinfo->w32_focus_frame || f == dpyinfo->w32_focus_frame) 7822 construct_mouse_click (&emacs_event, &msg, f);
3586 && (numchars >= 1)) 7823
3587 { 7824 /* Is this in the tool-bar? */
3588 construct_mouse_click (bufp, &msg, f); 7825 if (WINDOWP (f->tool_bar_window)
3589 bufp++; 7826 && XFASTINT (XWINDOW (f->tool_bar_window)->height))
3590 count++; 7827 {
3591 numchars--; 7828 Lisp_Object window;
3592 } 7829 int p, x, y;
7830
7831 /* Set x and y. */
7832 window = window_from_coordinates (f,
7833 emacs_event.x,
7834 emacs_event.y,
7835 &p, 1);
7836 if (EQ (window, f->tool_bar_window))
7837 {
7838 w32_handle_tool_bar_click (f, &emacs_event);
7839 tool_bar_p = 1;
7840 }
7841 }
7842
7843 if (!tool_bar_p)
7844 if (!dpyinfo->w32_focus_frame
7845 || f == dpyinfo->w32_focus_frame
7846 && (numchars >= 1))
7847 {
7848 construct_mouse_click (bufp, &msg, f);
7849 bufp++;
7850 count++;
7851 numchars--;
7852 }
3593 } 7853 }
3594 7854
3595 parse_button (msg.msg.message, &button, &up); 7855 parse_button (msg.msg.message, &button, &up);
@@ -3602,6 +7862,17 @@ w32_read_socket (sd, bufp, numchars, expected)
3602 { 7862 {
3603 dpyinfo->grabbed |= (1 << button); 7863 dpyinfo->grabbed |= (1 << button);
3604 last_mouse_frame = f; 7864 last_mouse_frame = f;
7865 /* Ignore any mouse motion that happened
7866 before this event; any subsequent mouse-movement
7867 Emacs events should reflect only motion after
7868 the ButtonPress. */
7869 if (f != 0)
7870 f->mouse_moved = 0;
7871
7872 if (!tool_bar_p)
7873 last_tool_bar_item = -1;
7874 if (display_busy_cursor_p)
7875 inhibit_busy_cursor = 2;
3605 } 7876 }
3606 break; 7877 break;
3607 } 7878 }
@@ -3778,9 +8049,7 @@ w32_read_socket (sd, bufp, numchars, expected)
3778 || width != f->output_data.w32->pixel_width 8049 || width != f->output_data.w32->pixel_width
3779 || height != f->output_data.w32->pixel_height) 8050 || height != f->output_data.w32->pixel_height)
3780 { 8051 {
3781 /* I had set this to 0, 0 - I am not sure why?? */ 8052 change_frame_size (f, rows, columns, 0, 1, 0);
3782
3783 change_frame_size (f, rows, columns, 0, 1);
3784 SET_FRAME_GARBAGED (f); 8053 SET_FRAME_GARBAGED (f);
3785 cancel_mouse_face (f); 8054 cancel_mouse_face (f);
3786 f->output_data.w32->pixel_width = width; 8055 f->output_data.w32->pixel_width = width;
@@ -3793,20 +8062,51 @@ w32_read_socket (sd, bufp, numchars, expected)
3793 break; 8062 break;
3794 8063
3795 case WM_SETFOCUS: 8064 case WM_SETFOCUS:
8065 f = x_any_window_to_frame (dpyinfo, msg.msg.hwnd);
8066
8067 dpyinfo->w32_focus_event_frame = f;
8068
8069 if (f)
8070 x_new_focus_frame (dpyinfo, f);
8071
8072
8073 dpyinfo->grabbed = 0;
8074 check_visibility = 1;
8075 break;
8076
3796 case WM_KILLFOCUS: 8077 case WM_KILLFOCUS:
3797 f = x_window_to_frame (dpyinfo, msg.msg.hwnd); 8078 /* NTEMACS_TODO: some of this belongs in MOUSE_LEAVE */
3798 8079 f = x_top_window_to_frame (dpyinfo, msg.msg.hwnd);
3799 if (msg.msg.message == WM_SETFOCUS)
3800 {
3801 x_new_focus_frame (dpyinfo, f);
3802 }
3803 else if (f == dpyinfo->w32_focus_frame)
3804 {
3805 x_new_focus_frame (dpyinfo, 0);
3806 8080
3807 if (f == dpyinfo->mouse_face_mouse_frame) 8081 if (f)
3808 clear_mouse_face (dpyinfo); 8082 {
3809 } 8083 Lisp_Object frame;
8084
8085 if (f == dpyinfo->w32_focus_event_frame)
8086 dpyinfo->w32_focus_event_frame = 0;
8087
8088 if (f == dpyinfo->w32_focus_frame)
8089 x_new_focus_frame (dpyinfo, 0);
8090
8091 if (f == dpyinfo->mouse_face_mouse_frame)
8092 {
8093 /* If we move outside the frame, then we're
8094 certainly no longer on any text in the frame. */
8095 clear_mouse_face (dpyinfo);
8096 dpyinfo->mouse_face_mouse_frame = 0;
8097 }
8098 /* Generate a nil HELP_EVENT to cancel a help-echo.
8099 Do it only if there's something to cancel.
8100 Otherwise, the startup message is cleared when
8101 the mouse leaves the frame. */
8102 if (any_help_event_p)
8103 {
8104 XSETFRAME (frame, f);
8105 bufp->kind = HELP_EVENT;
8106 bufp->frame_or_window = Fcons (frame, Qnil);
8107 ++bufp, ++count, --numchars;
8108 }
8109 }
3810 8110
3811 dpyinfo->grabbed = 0; 8111 dpyinfo->grabbed = 0;
3812 check_visibility = 1; 8112 check_visibility = 1;
@@ -3967,252 +8267,482 @@ w32_read_socket (sd, bufp, numchars, expected)
3967 UNBLOCK_INPUT; 8267 UNBLOCK_INPUT;
3968 return count; 8268 return count;
3969} 8269}
8270
3970 8271
3971/* Drawing the cursor. */ 8272/***********************************************************************
8273 Text Cursor
8274 ***********************************************************************/
3972 8275
8276/* Note if the text cursor of window W has been overwritten by a
8277 drawing operation that outputs N glyphs starting at HPOS in the
8278 line given by output_cursor.vpos. N < 0 means all the rest of the
8279 line after HPOS has been written. */
3973 8280
3974/* Draw a hollow box cursor. Don't change the inside of the box. */ 8281static void
8282note_overwritten_text_cursor (w, hpos, n)
8283 struct window *w;
8284 int hpos, n;
8285{
8286 if (updated_area == TEXT_AREA
8287 && output_cursor.vpos == w->phys_cursor.vpos
8288 && hpos <= w->phys_cursor.hpos
8289 && (n < 0
8290 || hpos + n > w->phys_cursor.hpos))
8291 w->phys_cursor_on_p = 0;
8292}
8293
8294
8295/* Set clipping for output in glyph row ROW. W is the window in which
8296 we operate. GC is the graphics context to set clipping in.
8297 WHOLE_LINE_P non-zero means include the areas used for truncation
8298 mark display and alike in the clipping rectangle.
8299
8300 ROW may be a text row or, e.g., a mode line. Text rows must be
8301 clipped to the interior of the window dedicated to text display,
8302 mode lines must be clipped to the whole window. */
3975 8303
3976static void 8304static void
3977x_draw_box (f) 8305w32_clip_to_row (w, row, hdc, whole_line_p)
3978 struct frame *f; 8306 struct window *w;
8307 struct glyph_row *row;
8308 HDC hdc;
8309 int whole_line_p;
3979{ 8310{
3980 RECT rect; 8311 struct frame *f = XFRAME (WINDOW_FRAME (w));
3981 HBRUSH hb; 8312 RECT clip_rect;
3982 HDC hdc; 8313 int window_x, window_y, window_width, window_height;
3983
3984 hdc = get_frame_dc (f);
3985
3986 hb = CreateSolidBrush (f->output_data.w32->cursor_pixel);
3987
3988 rect.left = CHAR_TO_PIXEL_COL (f, curs_x);
3989 rect.top = CHAR_TO_PIXEL_ROW (f, curs_y);
3990 rect.right = rect.left + FONT_WIDTH (f->output_data.w32->font);
3991 rect.bottom = rect.top + f->output_data.w32->line_height;
3992 8314
3993 FrameRect (hdc, &rect, hb); 8315 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
3994 DeleteObject (hb);
3995 8316
3996 release_frame_dc (f, hdc); 8317 clip_rect.left = WINDOW_TO_FRAME_PIXEL_X (w, 0);
8318 clip_rect.top = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
8319 clip_rect.top = max (clip_rect.top, window_y);
8320 clip_rect.right = clip_rect.left + window_width;
8321 clip_rect.bottom = clip_rect.top + row->visible_height;
8322
8323 /* If clipping to the whole line, including trunc marks, extend
8324 the rectangle to the left and right. */
8325 if (whole_line_p)
8326 {
8327 clip_rect.left -= FRAME_X_LEFT_FLAGS_AREA_WIDTH (f);
8328 clip_rect.right += FRAME_X_FLAGS_AREA_WIDTH (f);
8329 }
8330
8331 w32_set_clip_rectangle (hdc, &clip_rect);
3997} 8332}
3998 8333
3999/* Clear the cursor of frame F to background color, 8334
4000 and mark the cursor as not shown. 8335/* Draw a hollow box cursor on window W in glyph row ROW. */
4001 This is used when the text where the cursor is
4002 is about to be rewritten. */
4003 8336
4004static void 8337static void
4005clear_cursor (f) 8338x_draw_hollow_cursor (w, row)
4006 struct frame *f; 8339 struct window *w;
8340 struct glyph_row *row;
4007{ 8341{
4008 if (! FRAME_VISIBLE_P (f) 8342 struct frame *f = XFRAME (WINDOW_FRAME (w));
4009 || !f->phys_cursor_on) 8343 HDC hdc = get_frame_dc (f);
8344 RECT rect;
8345 int wd;
8346 struct glyph *cursor_glyph;
8347 HBRUSH hb = CreateSolidBrush (f->output_data.w32->cursor_pixel);
8348
8349 /* Compute frame-relative coordinates from window-relative
8350 coordinates. */
8351 rect.left = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
8352 rect.top = (WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y)
8353 + row->ascent - w->phys_cursor_ascent);
8354 rect.bottom = rect.top + row->height - 1;
8355
8356 /* Get the glyph the cursor is on. If we can't tell because
8357 the current matrix is invalid or such, give up. */
8358 cursor_glyph = get_phys_cursor_glyph (w);
8359 if (cursor_glyph == NULL)
4010 return; 8360 return;
4011 8361
4012 x_display_cursor (f, 0); 8362 /* Compute the width of the rectangle to draw. If on a stretch
4013 f->phys_cursor_on = 0; 8363 glyph, and `x-stretch-block-cursor' is nil, don't draw a
8364 rectangle as wide as the glyph, but use a canonical character
8365 width instead. */
8366 wd = cursor_glyph->pixel_width - 1;
8367 if (cursor_glyph->type == STRETCH_GLYPH
8368 && !x_stretch_cursor_p)
8369 wd = min (CANON_X_UNIT (f), wd);
8370
8371 rect.right = rect.left + wd;
8372
8373 FrameRect (hdc, &rect, hb);
8374 DeleteObject (hb);
8375
8376 release_frame_dc (f, hdc);
4014} 8377}
4015 8378
4016/* Redraw the glyph at ROW, COLUMN on frame F, in the style 8379
4017 HIGHLIGHT. HIGHLIGHT is as defined for dumpglyphs. Return the 8380/* Draw a bar cursor on window W in glyph row ROW.
4018 glyph drawn. */ 8381
8382 Implementation note: One would like to draw a bar cursor with an
8383 angle equal to the one given by the font property XA_ITALIC_ANGLE.
8384 Unfortunately, I didn't find a font yet that has this property set.
8385 --gerd. */
4019 8386
4020static void 8387static void
4021x_draw_single_glyph (f, row, column, glyph, highlight) 8388x_draw_bar_cursor (w, row)
4022 struct frame *f; 8389 struct window *w;
4023 int row, column; 8390 struct glyph_row *row;
4024 GLYPH glyph;
4025 int highlight;
4026{ 8391{
4027 dumpglyphs (f, 8392 /* If cursor hpos is out of bounds, don't draw garbage. This can
4028 CHAR_TO_PIXEL_COL (f, column), 8393 happen in mini-buffer windows when switching between echo area
4029 CHAR_TO_PIXEL_ROW (f, row), 8394 glyphs and mini-buffer. */
4030 &glyph, 1, highlight, 0, NULL); 8395 if (w->phys_cursor.hpos < row->used[TEXT_AREA])
8396 {
8397 struct frame *f = XFRAME (w->frame);
8398 struct glyph *cursor_glyph;
8399 int x;
8400 HDC hdc = get_frame_dc (f);
8401
8402 cursor_glyph = get_phys_cursor_glyph (w);
8403 if (cursor_glyph == NULL)
8404 return;
8405
8406 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
8407
8408 w32_fill_area (f, hdc, f->output_data.w32->cursor_pixel,
8409 x,
8410 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
8411 min (cursor_glyph->pixel_width,
8412 f->output_data.w32->cursor_width),
8413 row->height);
8414 release_frame_dc (f, hdc);
8415 }
4031} 8416}
4032 8417
8418
8419/* Clear the cursor of window W to background color, and mark the
8420 cursor as not shown. This is used when the text where the cursor
8421 is is about to be rewritten. */
8422
4033static void 8423static void
4034x_display_bar_cursor (f, on) 8424x_clear_cursor (w)
4035 struct frame *f; 8425 struct window *w;
4036 int on;
4037{ 8426{
4038 struct frame_glyphs *current_glyphs = FRAME_CURRENT_GLYPHS (f); 8427 if (FRAME_VISIBLE_P (XFRAME (w->frame)) && w->phys_cursor_on_p)
8428 x_update_window_cursor (w, 0);
8429}
4039 8430
4040 /* This is pointless on invisible frames, and dangerous on garbaged
4041 frames; in the latter case, the frame may be in the midst of
4042 changing its size, and curs_x and curs_y may be off the frame. */
4043 if (! FRAME_VISIBLE_P (f) || FRAME_GARBAGED_P (f))
4044 return;
4045 8431
4046 if (! on && ! f->phys_cursor_on) 8432/* Draw the cursor glyph of window W in glyph row ROW. See the
4047 return; 8433 comment of x_draw_glyphs for the meaning of HL. */
4048 8434
4049 /* If there is anything wrong with the current cursor state, remove it. */ 8435static void
4050 if (f->phys_cursor_on 8436x_draw_phys_cursor_glyph (w, row, hl)
4051 && (!on 8437 struct window *w;
4052 || f->phys_cursor_x != curs_x 8438 struct glyph_row *row;
4053 || f->phys_cursor_y != curs_y 8439 enum draw_glyphs_face hl;
4054 || f->output_data.w32->current_cursor != bar_cursor)) 8440{
8441 /* If cursor hpos is out of bounds, don't draw garbage. This can
8442 happen in mini-buffer windows when switching between echo area
8443 glyphs and mini-buffer. */
8444 if (w->phys_cursor.hpos < row->used[TEXT_AREA])
4055 { 8445 {
4056 /* Erase the cursor by redrawing the character underneath it. */ 8446 x_draw_glyphs (w, w->phys_cursor.x, row, TEXT_AREA,
4057 x_draw_single_glyph (f, f->phys_cursor_y, f->phys_cursor_x, 8447 w->phys_cursor.hpos, w->phys_cursor.hpos + 1,
4058 f->phys_cursor_glyph, 8448 hl, 0, 0, 0);
4059 current_glyphs->highlight[f->phys_cursor_y]); 8449
4060 f->phys_cursor_on = 0; 8450 /* When we erase the cursor, and ROW is overlapped by other
8451 rows, make sure that these overlapping parts of other rows
8452 are redrawn. */
8453 if (hl == DRAW_NORMAL_TEXT && row->overlapped_p)
8454 {
8455 if (row > w->current_matrix->rows
8456 && MATRIX_ROW_OVERLAPS_SUCC_P (row - 1))
8457 x_fix_overlapping_area (w, row - 1, TEXT_AREA);
8458
8459 if (MATRIX_ROW_BOTTOM_Y (row) < window_text_bottom_y (w)
8460 && MATRIX_ROW_OVERLAPS_PRED_P (row + 1))
8461 x_fix_overlapping_area (w, row + 1, TEXT_AREA);
8462 }
4061 } 8463 }
8464}
8465
8466
8467/* Erase the image of a cursor of window W from the screen. */
4062 8468
4063 /* If we now need a cursor in the new place or in the new form, do it so. */ 8469static void
4064 if (on 8470x_erase_phys_cursor (w)
4065 && (! f->phys_cursor_on 8471 struct window *w;
4066 || (f->output_data.w32->current_cursor != bar_cursor))) 8472{
8473 struct frame *f = XFRAME (w->frame);
8474 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
8475 int hpos = w->phys_cursor.hpos;
8476 int vpos = w->phys_cursor.vpos;
8477 int mouse_face_here_p = 0;
8478 struct glyph_matrix *active_glyphs = w->current_matrix;
8479 struct glyph_row *cursor_row;
8480 struct glyph *cursor_glyph;
8481 enum draw_glyphs_face hl;
8482
8483 /* No cursor displayed or row invalidated => nothing to do on the
8484 screen. */
8485 if (w->phys_cursor_type == NO_CURSOR)
8486 goto mark_cursor_off;
8487
8488 /* VPOS >= active_glyphs->nrows means that window has been resized.
8489 Don't bother to erase the cursor. */
8490 if (vpos >= active_glyphs->nrows)
8491 goto mark_cursor_off;
8492
8493 /* If row containing cursor is marked invalid, there is nothing we
8494 can do. */
8495 cursor_row = MATRIX_ROW (active_glyphs, vpos);
8496 if (!cursor_row->enabled_p)
8497 goto mark_cursor_off;
8498
8499 /* This can happen when the new row is shorter than the old one.
8500 In this case, either x_draw_glyphs or clear_end_of_line
8501 should have cleared the cursor. Note that we wouldn't be
8502 able to erase the cursor in this case because we don't have a
8503 cursor glyph at hand. */
8504 if (w->phys_cursor.hpos >= cursor_row->used[TEXT_AREA])
8505 goto mark_cursor_off;
8506
8507 /* If the cursor is in the mouse face area, redisplay that when
8508 we clear the cursor. */
8509 if (w == XWINDOW (dpyinfo->mouse_face_window)
8510 && (vpos > dpyinfo->mouse_face_beg_row
8511 || (vpos == dpyinfo->mouse_face_beg_row
8512 && hpos >= dpyinfo->mouse_face_beg_col))
8513 && (vpos < dpyinfo->mouse_face_end_row
8514 || (vpos == dpyinfo->mouse_face_end_row
8515 && hpos < dpyinfo->mouse_face_end_col))
8516 /* Don't redraw the cursor's spot in mouse face if it is at the
8517 end of a line (on a newline). The cursor appears there, but
8518 mouse highlighting does not. */
8519 && cursor_row->used[TEXT_AREA] > hpos)
8520 mouse_face_here_p = 1;
8521
8522 /* Maybe clear the display under the cursor. */
8523 if (w->phys_cursor_type == HOLLOW_BOX_CURSOR)
4067 { 8524 {
4068 f->phys_cursor_glyph 8525 int x;
4069 = ((current_glyphs->enable[curs_y] 8526 int header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
4070 && curs_x < current_glyphs->used[curs_y])
4071 ? current_glyphs->glyphs[curs_y][curs_x]
4072 : SPACEGLYPH);
4073 w32_fill_area (f, NULL, f->output_data.w32->cursor_pixel,
4074 CHAR_TO_PIXEL_COL (f, curs_x),
4075 CHAR_TO_PIXEL_ROW (f, curs_y),
4076 max (f->output_data.w32->cursor_width, 1),
4077 f->output_data.w32->line_height);
4078 8527
4079 f->phys_cursor_x = curs_x; 8528 cursor_glyph = get_phys_cursor_glyph (w);
4080 f->phys_cursor_y = curs_y; 8529 if (cursor_glyph == NULL)
4081 f->phys_cursor_on = 1; 8530 goto mark_cursor_off;
4082 8531
4083 f->output_data.w32->current_cursor = bar_cursor; 8532 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
8533
8534 w32_clear_area (f, NULL, x,
8535 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
8536 cursor_row->y)),
8537 cursor_glyph->pixel_width,
8538 cursor_row->visible_height);
4084 } 8539 }
8540
8541 /* Erase the cursor by redrawing the character underneath it. */
8542 if (mouse_face_here_p)
8543 hl = DRAW_MOUSE_FACE;
8544 else if (cursor_row->inverse_p)
8545 hl = DRAW_INVERSE_VIDEO;
8546 else
8547 hl = DRAW_NORMAL_TEXT;
8548 x_draw_phys_cursor_glyph (w, cursor_row, hl);
8549
8550 mark_cursor_off:
8551 w->phys_cursor_on_p = 0;
8552 w->phys_cursor_type = NO_CURSOR;
4085} 8553}
4086 8554
4087 8555
4088/* Turn the displayed cursor of frame F on or off according to ON. 8556/* Display or clear cursor of window W. If ON is zero, clear the
4089 If ON is nonzero, where to put the cursor is specified 8557 cursor. If it is non-zero, display the cursor. If ON is nonzero,
4090 by F->cursor_x and F->cursor_y. */ 8558 where to put the cursor is specified by HPOS, VPOS, X and Y. */
4091 8559
4092static void 8560void
4093x_display_box_cursor (f, on) 8561x_display_and_set_cursor (w, on, hpos, vpos, x, y)
4094 struct frame *f; 8562 struct window *w;
4095 int on; 8563 int on, hpos, vpos, x, y;
4096{ 8564{
4097 struct frame_glyphs *current_glyphs = FRAME_CURRENT_GLYPHS (f); 8565 struct frame *f = XFRAME (w->frame);
8566 int new_cursor_type;
8567 struct glyph_matrix *current_glyphs;
8568 struct glyph_row *glyph_row;
8569 struct glyph *glyph;
4098 8570
4099 /* This is pointless on invisible frames, and dangerous on garbaged 8571 /* This is pointless on invisible frames, and dangerous on garbaged
4100 frames; in the latter case, the frame may be in the midst of 8572 windows and frames; in the latter case, the frame or window may
4101 changing its size, and curs_x and curs_y may be off the frame. */ 8573 be in the midst of changing its size, and x and y may be off the
4102 if (! FRAME_VISIBLE_P (f) || FRAME_GARBAGED_P (f)) 8574 window. */
8575 if (! FRAME_VISIBLE_P (f)
8576 || FRAME_GARBAGED_P (f)
8577 || vpos >= w->current_matrix->nrows
8578 || hpos >= w->current_matrix->matrix_w)
4103 return; 8579 return;
4104 8580
4105 /* If cursor is off and we want it off, return quickly. */ 8581 /* If cursor is off and we want it off, return quickly. */
4106 if (!on && ! f->phys_cursor_on) 8582 if (!on && !w->phys_cursor_on_p)
4107 return; 8583 return;
4108 8584
4109 /* If cursor is currently being shown and we don't want it to be 8585 current_glyphs = w->current_matrix;
4110 or it is in the wrong place, 8586 glyph_row = MATRIX_ROW (current_glyphs, vpos);
4111 or we want a hollow box and it's not so, (pout!) 8587 glyph = glyph_row->glyphs[TEXT_AREA] + hpos;
8588
8589 /* If cursor row is not enabled, we don't really know where to
8590 display the cursor. */
8591 if (!glyph_row->enabled_p)
8592 {
8593 w->phys_cursor_on_p = 0;
8594 return;
8595 }
8596
8597 xassert (interrupt_input_blocked);
8598
8599 /* Set new_cursor_type to the cursor we want to be displayed. In a
8600 mini-buffer window, we want the cursor only to appear if we are
8601 reading input from this window. For the selected window, we want
8602 the cursor type given by the frame parameter. If explicitly
8603 marked off, draw no cursor. In all other cases, we want a hollow
8604 box cursor. */
8605 if (cursor_in_echo_area
8606 && FRAME_HAS_MINIBUF_P (f)
8607 && EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window))
8608 {
8609 if (w == XWINDOW (echo_area_window))
8610 new_cursor_type = FRAME_DESIRED_CURSOR (f);
8611 else
8612 new_cursor_type = HOLLOW_BOX_CURSOR;
8613 }
8614 else
8615 {
8616 if (w != XWINDOW (selected_window)
8617 || f != FRAME_W32_DISPLAY_INFO (f)->w32_highlight_frame)
8618 {
8619 if (MINI_WINDOW_P (w))
8620 new_cursor_type = NO_CURSOR;
8621 else
8622 new_cursor_type = HOLLOW_BOX_CURSOR;
8623 }
8624 else if (w->cursor_off_p)
8625 new_cursor_type = NO_CURSOR;
8626 else
8627 new_cursor_type = FRAME_DESIRED_CURSOR (f);
8628 }
8629
8630 /* If cursor is currently being shown and we don't want it to be or
8631 it is in the wrong place, or the cursor type is not what we want,
4112 erase it. */ 8632 erase it. */
4113 if (f->phys_cursor_on 8633 if (w->phys_cursor_on_p
4114 && (!on 8634 && (!on
4115 || f->phys_cursor_x != curs_x 8635 || w->phys_cursor.x != x
4116 || f->phys_cursor_y != curs_y 8636 || w->phys_cursor.y != y
4117 || (f->output_data.w32->current_cursor != hollow_box_cursor 8637 || new_cursor_type != w->phys_cursor_type))
4118 && (f != FRAME_W32_DISPLAY_INFO (f)->w32_highlight_frame)))) 8638 x_erase_phys_cursor (w);
4119 { 8639
4120 int mouse_face_here = 0; 8640 /* If the cursor is now invisible and we want it to be visible,
4121 struct frame_glyphs *active_glyphs = FRAME_CURRENT_GLYPHS (f); 8641 display it. */
4122 8642 if (on && !w->phys_cursor_on_p)
4123 /* If the cursor is in the mouse face area, redisplay that when 8643 {
4124 we clear the cursor. */ 8644 w->phys_cursor_ascent = glyph_row->ascent;
4125 if (f == FRAME_W32_DISPLAY_INFO (f)->mouse_face_mouse_frame 8645 w->phys_cursor_height = glyph_row->height;
4126 && (f->phys_cursor_y > FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_row 8646
4127 || (f->phys_cursor_y == FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_row 8647 /* Set phys_cursor_.* before x_draw_.* is called because some
4128 && f->phys_cursor_x >= FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_col)) 8648 of them may need the information. */
4129 && (f->phys_cursor_y < FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_row 8649 w->phys_cursor.x = x;
4130 || (f->phys_cursor_y == FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_row 8650 w->phys_cursor.y = glyph_row->y;
4131 && f->phys_cursor_x < FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_col)) 8651 w->phys_cursor.hpos = hpos;
4132 /* Don't redraw the cursor's spot in mouse face 8652 w->phys_cursor.vpos = vpos;
4133 if it is at the end of a line (on a newline). 8653 w->phys_cursor_type = new_cursor_type;
4134 The cursor appears there, but mouse highlighting does not. */ 8654 w->phys_cursor_on_p = 1;
4135 && active_glyphs->used[f->phys_cursor_y] > f->phys_cursor_x) 8655
4136 mouse_face_here = 1; 8656 switch (new_cursor_type)
4137
4138 /* If the font is not as tall as a whole line,
4139 we must explicitly clear the line's whole height. */
4140 if (FONT_HEIGHT (f->output_data.w32->font) != f->output_data.w32->line_height)
4141 w32_clear_area (f, NULL,
4142 CHAR_TO_PIXEL_COL (f, f->phys_cursor_x),
4143 CHAR_TO_PIXEL_ROW (f, f->phys_cursor_y),
4144 FONT_WIDTH (f->output_data.w32->font),
4145 f->output_data.w32->line_height);
4146 /* Erase the cursor by redrawing the character underneath it. */
4147 x_draw_single_glyph (f, f->phys_cursor_y, f->phys_cursor_x,
4148 f->phys_cursor_glyph,
4149 (mouse_face_here
4150 ? 3
4151 : current_glyphs->highlight[f->phys_cursor_y]));
4152 f->phys_cursor_on = 0;
4153 }
4154
4155 /* If we want to show a cursor,
4156 or we want a box cursor and it's not so,
4157 write it in the right place. */
4158 if (on
4159 && (! f->phys_cursor_on
4160 || (f->output_data.w32->current_cursor != filled_box_cursor
4161 && f == FRAME_W32_DISPLAY_INFO (f)->w32_highlight_frame)))
4162 {
4163 f->phys_cursor_glyph
4164 = ((current_glyphs->enable[curs_y]
4165 && curs_x < current_glyphs->used[curs_y])
4166 ? current_glyphs->glyphs[curs_y][curs_x]
4167 : SPACEGLYPH);
4168 if (f != FRAME_W32_DISPLAY_INFO (f)->w32_highlight_frame)
4169 {
4170 x_draw_box (f);
4171 f->output_data.w32->current_cursor = hollow_box_cursor;
4172 }
4173 else
4174 { 8657 {
4175 x_draw_single_glyph (f, curs_y, curs_x, 8658 case HOLLOW_BOX_CURSOR:
4176 f->phys_cursor_glyph, 2); 8659 x_draw_hollow_cursor (w, glyph_row);
4177 f->output_data.w32->current_cursor = filled_box_cursor; 8660 break;
4178 } 8661
8662 case FILLED_BOX_CURSOR:
8663 x_draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
8664 break;
8665
8666 case BAR_CURSOR:
8667 x_draw_bar_cursor (w, glyph_row);
8668 break;
8669
8670 case NO_CURSOR:
8671 break;
4179 8672
4180 f->phys_cursor_x = curs_x; 8673 default:
4181 f->phys_cursor_y = curs_y; 8674 abort ();
4182 f->phys_cursor_on = 1; 8675 }
4183 } 8676 }
4184} 8677}
4185 8678
4186/* Display the cursor on frame F, or clear it, according to ON.
4187 Use the position specified by curs_x and curs_y
4188 if we are doing an update of frame F now.
4189 Otherwise use the position in the FRAME_CURSOR_X and FRAME_CURSOR_Y fields
4190 of F. */
4191 8679
4192x_display_cursor (f, on) 8680/* Display the cursor on window W, or clear it. X and Y are window
4193 struct frame *f; 8681 relative pixel coordinates. HPOS and VPOS are glyph matrix
4194 int on; 8682 positions. If W is not the selected window, display a hollow
8683 cursor. ON non-zero means display the cursor at X, Y which
8684 correspond to HPOS, VPOS, otherwise it is cleared. */
8685
8686void
8687x_display_cursor (w, on, hpos, vpos, x, y)
8688 struct window *w;
8689 int on, hpos, vpos, x, y;
4195{ 8690{
4196 BLOCK_INPUT; 8691 BLOCK_INPUT;
8692 x_display_and_set_cursor (w, on, hpos, vpos, x, y);
8693 UNBLOCK_INPUT;
8694}
8695
8696
8697/* Display the cursor on window W, or clear it, according to ON_P.
8698 Don't change the cursor's position. */
8699
8700void
8701x_update_cursor (f, on_p)
8702 struct frame *f;
8703 int on_p;
8704{
8705 x_update_cursor_in_window_tree (XWINDOW (f->root_window), on_p);
8706}
8707
4197 8708
4198 /* If we're not updating, then we want to use the current frame's 8709/* Call x_update_window_cursor with parameter ON_P on all leaf windows
4199 cursor position, not our local idea of where the cursor ought to be. */ 8710 in the window tree rooted at W. */
4200 if (f != updating_frame) 8711
8712static void
8713x_update_cursor_in_window_tree (w, on_p)
8714 struct window *w;
8715 int on_p;
8716{
8717 while (w)
4201 { 8718 {
4202 curs_x = FRAME_CURSOR_X (f); 8719 if (!NILP (w->hchild))
4203 curs_y = FRAME_CURSOR_Y (f); 8720 x_update_cursor_in_window_tree (XWINDOW (w->hchild), on_p);
8721 else if (!NILP (w->vchild))
8722 x_update_cursor_in_window_tree (XWINDOW (w->vchild), on_p);
8723 else
8724 x_update_window_cursor (w, on_p);
8725
8726 w = NILP (w->next) ? 0 : XWINDOW (w->next);
4204 } 8727 }
8728}
4205 8729
4206 if (FRAME_DESIRED_CURSOR (f) == filled_box_cursor)
4207 x_display_box_cursor (f, on);
4208 else if (FRAME_DESIRED_CURSOR (f) == bar_cursor)
4209 x_display_bar_cursor (f, on);
4210 else
4211 /* Those are the only two we have implemented! */
4212 abort ();
4213 8730
8731/* Switch the display of W's cursor on or off, according to the value
8732 of ON. */
8733
8734static void
8735x_update_window_cursor (w, on)
8736 struct window *w;
8737 int on;
8738{
8739 BLOCK_INPUT;
8740 x_display_and_set_cursor (w, on, w->phys_cursor.hpos, w->phys_cursor.vpos,
8741 w->phys_cursor.x, w->phys_cursor.y);
4214 UNBLOCK_INPUT; 8742 UNBLOCK_INPUT;
4215} 8743}
8744
8745
4216 8746
4217/* Icons. */ 8747/* Icons. */
4218 8748
@@ -4260,7 +8790,8 @@ x_bitmap_icon (f, icon)
4260 if (hicon == NULL) 8790 if (hicon == NULL)
4261 return 1; 8791 return 1;
4262 8792
4263 PostMessage (FRAME_W32_WINDOW (f), WM_SETICON, (WPARAM) ICON_BIG, (LPARAM) hicon); 8793 PostMessage (FRAME_W32_WINDOW (f), WM_SETICON, (WPARAM) ICON_BIG,
8794 (LPARAM) hicon);
4264 8795
4265 return 0; 8796 return 0;
4266} 8797}
@@ -4283,11 +8814,10 @@ x_new_font (f, fontname)
4283 fontname, -1); 8814 fontname, -1);
4284 8815
4285 if (!fontp) 8816 if (!fontp)
4286 return Qnil; 8817 return Qnil;
4287 8818
4288 FRAME_FONT (f) = (XFontStruct *) (fontp->font); 8819 FRAME_FONT (f) = (XFontStruct *) (fontp->font);
4289 f->output_data.w32->font_baseline 8820 FRAME_BASELINE_OFFSET (f) = fontp->baseline_offset;
4290 = FONT_BASE (FRAME_FONT (f)) + fontp->baseline_offset;
4291 FRAME_FONTSET (f) = -1; 8821 FRAME_FONTSET (f) = -1;
4292 8822
4293 /* Compute the scroll bar width in character columns. */ 8823 /* Compute the scroll bar width in character columns. */
@@ -4310,13 +8840,7 @@ x_new_font (f, fontname)
4310 there are no faces yet, so this font's height is the line height. */ 8840 there are no faces yet, so this font's height is the line height. */
4311 f->output_data.w32->line_height = FONT_HEIGHT (f->output_data.w32->font); 8841 f->output_data.w32->line_height = FONT_HEIGHT (f->output_data.w32->font);
4312 8842
4313 { 8843 return build_string (fontp->full_name);
4314 Lisp_Object lispy_name;
4315
4316 lispy_name = build_string (fontname);
4317
4318 return lispy_name;
4319 }
4320} 8844}
4321 8845
4322/* Give frame F the fontset named FONTSETNAME as its default font, and 8846/* Give frame F the fontset named FONTSETNAME as its default font, and
@@ -4360,6 +8884,99 @@ x_new_fontset (f, fontsetname)
4360 8884
4361 return build_string (fontsetname); 8885 return build_string (fontsetname);
4362} 8886}
8887
8888
8889#if GLYPH_DEBUG
8890
8891/* Check that FONT is valid on frame F. It is if it can be found in F's
8892 font table. */
8893
8894static void
8895x_check_font (f, font)
8896 struct frame *f;
8897 XFontStruct *font;
8898{
8899 int i;
8900 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
8901
8902 xassert (font != NULL);
8903
8904 for (i = 0; i < dpyinfo->n_fonts; i++)
8905 if (dpyinfo->font_table[i].name
8906 && font == dpyinfo->font_table[i].font)
8907 break;
8908
8909 xassert (i < dpyinfo->n_fonts);
8910}
8911
8912#endif /* GLYPH_DEBUG != 0 */
8913
8914/* Set *W to the minimum width, *H to the minimum font height of FONT.
8915 Note: There are (broken) X fonts out there with invalid XFontStruct
8916 min_bounds contents. For example, handa@etl.go.jp reports that
8917 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
8918 have font->min_bounds.width == 0. */
8919
8920static INLINE void
8921x_font_min_bounds (font, w, h)
8922 XFontStruct *font;
8923 int *w, *h;
8924{
8925 *h = FONT_HEIGHT (font);
8926 *w = FONT_WIDTH (font);
8927#if 0 /* NTEMACS_TODO: min/max bounds of Windows fonts */
8928 *w = font->min_bounds.width;
8929
8930 /* Try to handle the case where FONT->min_bounds has invalid
8931 contents. Since the only font known to have invalid min_bounds
8932 is fixed-width, use max_bounds if min_bounds seems to be invalid. */
8933 if (*w <= 0)
8934 *w = font->max_bounds.width;
8935#endif
8936}
8937
8938
8939/* Compute the smallest character width and smallest font height over
8940 all fonts available on frame F. Set the members smallest_char_width
8941 and smallest_font_height in F's x_display_info structure to
8942 the values computed. Value is non-zero if smallest_font_height or
8943 smallest_char_width become smaller than they were before. */
8944
8945int
8946x_compute_min_glyph_bounds (f)
8947 struct frame *f;
8948{
8949 int i;
8950 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
8951 XFontStruct *font;
8952 int old_width = dpyinfo->smallest_char_width;
8953 int old_height = dpyinfo->smallest_font_height;
8954
8955 dpyinfo->smallest_font_height = 100000;
8956 dpyinfo->smallest_char_width = 100000;
8957
8958 for (i = 0; i < dpyinfo->n_fonts; ++i)
8959 if (dpyinfo->font_table[i].name)
8960 {
8961 struct font_info *fontp = dpyinfo->font_table + i;
8962 int w, h;
8963
8964 font = (XFontStruct *) fontp->font;
8965 xassert (font != (XFontStruct *) ~0);
8966 x_font_min_bounds (font, &w, &h);
8967
8968 dpyinfo->smallest_font_height = min (dpyinfo->smallest_font_height, h);
8969 dpyinfo->smallest_char_width = min (dpyinfo->smallest_char_width, w);
8970 }
8971
8972 xassert (dpyinfo->smallest_char_width > 0
8973 && dpyinfo->smallest_font_height > 0);
8974
8975 return (dpyinfo->n_fonts == 1
8976 || dpyinfo->smallest_char_width < old_width
8977 || dpyinfo->smallest_font_height < old_height);
8978}
8979
4363 8980
4364/* Calculate the absolute position in frame F 8981/* Calculate the absolute position in frame F
4365 from its current recorded position values and gravity. */ 8982 from its current recorded position values and gravity. */
@@ -4367,7 +8984,7 @@ x_new_fontset (f, fontsetname)
4367x_calc_absolute_position (f) 8984x_calc_absolute_position (f)
4368 struct frame *f; 8985 struct frame *f;
4369{ 8986{
4370 Window win, child; 8987 Window child;
4371 POINT pt; 8988 POINT pt;
4372 int flags = f->output_data.w32->size_hint_flags; 8989 int flags = f->output_data.w32->size_hint_flags;
4373 8990
@@ -4404,7 +9021,7 @@ x_calc_absolute_position (f)
4404 - 2 * f->output_data.w32->border_width - pt.x 9021 - 2 * f->output_data.w32->border_width - pt.x
4405 - PIXEL_WIDTH (f) 9022 - PIXEL_WIDTH (f)
4406 + f->output_data.w32->left_pos); 9023 + f->output_data.w32->left_pos);
4407 9024 /* NTEMACS_TODO: Subtract menubar height? */
4408 if (flags & YNegative) 9025 if (flags & YNegative)
4409 f->output_data.w32->top_pos = (FRAME_W32_DISPLAY_INFO (f)->height 9026 f->output_data.w32->top_pos = (FRAME_W32_DISPLAY_INFO (f)->height
4410 - 2 * f->output_data.w32->border_width - pt.y 9027 - 2 * f->output_data.w32->border_width - pt.y
@@ -4470,14 +9087,13 @@ x_set_offset (f, xoff, yoff, change_gravity)
4470 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity 9087 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
4471 for this size change and subsequent size changes. 9088 for this size change and subsequent size changes.
4472 Otherwise we leave the window gravity unchanged. */ 9089 Otherwise we leave the window gravity unchanged. */
4473 9090void
4474x_set_window_size (f, change_gravity, cols, rows) 9091x_set_window_size (f, change_gravity, cols, rows)
4475 struct frame *f; 9092 struct frame *f;
4476 int change_gravity; 9093 int change_gravity;
4477 int cols, rows; 9094 int cols, rows;
4478{ 9095{
4479 int pixelwidth, pixelheight; 9096 int pixelwidth, pixelheight;
4480 struct w32_display_info *dpyinfo = &one_w32_display_info;
4481 9097
4482 BLOCK_INPUT; 9098 BLOCK_INPUT;
4483 9099
@@ -4485,9 +9101,9 @@ x_set_window_size (f, change_gravity, cols, rows)
4485 f->output_data.w32->vertical_scroll_bar_extra 9101 f->output_data.w32->vertical_scroll_bar_extra
4486 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f) 9102 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
4487 ? 0 9103 ? 0
4488 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0
4489 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f)
4490 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.w32->font))); 9104 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.w32->font)));
9105 f->output_data.w32->flags_areas_extra
9106 = FRAME_FLAGS_AREA_WIDTH (f);
4491 pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols); 9107 pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols);
4492 pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows); 9108 pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows);
4493 9109
@@ -4521,8 +9137,11 @@ x_set_window_size (f, change_gravity, cols, rows)
4521 and let the ConfigureNotify event set everything up, but that 9137 and let the ConfigureNotify event set everything up, but that
4522 might be kind of confusing to the lisp code, since size changes 9138 might be kind of confusing to the lisp code, since size changes
4523 wouldn't be reported in the frame parameters until some random 9139 wouldn't be reported in the frame parameters until some random
4524 point in the future when the ConfigureNotify event arrives. */ 9140 point in the future when the ConfigureNotify event arrives.
4525 change_frame_size (f, rows, cols, 0, 0); 9141
9142 We pass 1 for DELAY since we can't run Lisp code inside of
9143 a BLOCK_INPUT. */
9144 change_frame_size (f, rows, cols, 0, 1, 0);
4526 PIXEL_WIDTH (f) = pixelwidth; 9145 PIXEL_WIDTH (f) = pixelwidth;
4527 PIXEL_HEIGHT (f) = pixelheight; 9146 PIXEL_HEIGHT (f) = pixelheight;
4528 9147
@@ -4533,13 +9152,7 @@ x_set_window_size (f, change_gravity, cols, rows)
4533 SET_FRAME_GARBAGED (f); 9152 SET_FRAME_GARBAGED (f);
4534 9153
4535 /* If cursor was outside the new size, mark it as off. */ 9154 /* If cursor was outside the new size, mark it as off. */
4536 if (f->phys_cursor_y >= rows 9155 mark_window_cursors_off (XWINDOW (f->root_window));
4537 || f->phys_cursor_x >= cols)
4538 {
4539 f->phys_cursor_x = 0;
4540 f->phys_cursor_y = 0;
4541 f->phys_cursor_on = 0;
4542 }
4543 9156
4544 /* Clear out any recollection of where the mouse highlighting was, 9157 /* Clear out any recollection of where the mouse highlighting was,
4545 since it might be in a place that's outside the new frame size. 9158 since it might be in a place that's outside the new frame size.
@@ -4616,7 +9229,7 @@ x_unfocus_frame (f)
4616} 9229}
4617 9230
4618/* Raise frame F. */ 9231/* Raise frame F. */
4619 9232void
4620x_raise_frame (f) 9233x_raise_frame (f)
4621 struct frame *f; 9234 struct frame *f;
4622{ 9235{
@@ -4676,7 +9289,7 @@ x_raise_frame (f)
4676} 9289}
4677 9290
4678/* Lower frame F. */ 9291/* Lower frame F. */
4679 9292void
4680x_lower_frame (f) 9293x_lower_frame (f)
4681 struct frame *f; 9294 struct frame *f;
4682{ 9295{
@@ -4740,22 +9353,22 @@ x_make_frame_visible (f)
4740 so that incoming events are handled. */ 9353 so that incoming events are handled. */
4741 { 9354 {
4742 Lisp_Object frame; 9355 Lisp_Object frame;
4743 int count = input_signal_count; 9356 int count;
4744 9357
4745 /* This must come after we set COUNT. */ 9358 /* This must come after we set COUNT. */
4746 UNBLOCK_INPUT; 9359 UNBLOCK_INPUT;
4747 9360
4748 XSETFRAME (frame, f); 9361 XSETFRAME (frame, f);
4749 9362
4750 while (1) 9363 /* Wait until the frame is visible. Process X events until a
9364 MapNotify event has been seen, or until we think we won't get a
9365 MapNotify at all.. */
9366 for (count = input_signal_count + 10;
9367 input_signal_count < count && !FRAME_VISIBLE_P (f);)
4751 { 9368 {
4752 /* Once we have handled input events, 9369 /* Force processing of queued events. */
4753 we should have received the MapNotify if one is coming. 9370 /* NTEMACS_TODO: x_sync equivalent? */
4754 So if we have not got it yet, stop looping. 9371
4755 Some window managers make their own decisions
4756 about visibility. */
4757 if (input_signal_count != count)
4758 break;
4759 /* Machines that do polling rather than SIGIO have been observed 9372 /* Machines that do polling rather than SIGIO have been observed
4760 to go into a busy-wait here. So we'll fake an alarm signal 9373 to go into a busy-wait here. So we'll fake an alarm signal
4761 to let the handler know that there's something to be read. 9374 to let the handler know that there's something to be read.
@@ -4768,13 +9381,6 @@ x_make_frame_visible (f)
4768 alarm (0); 9381 alarm (0);
4769 input_poll_signal (0); 9382 input_poll_signal (0);
4770 } 9383 }
4771 /* Once we have handled input events,
4772 we should have received the MapNotify if one is coming.
4773 So if we have not got it yet, stop looping.
4774 Some window managers make their own decisions
4775 about visibility. */
4776 if (input_signal_count != count)
4777 break;
4778 } 9384 }
4779 FRAME_SAMPLE_VISIBILITY (f); 9385 FRAME_SAMPLE_VISIBILITY (f);
4780 } 9386 }
@@ -4787,8 +9393,6 @@ x_make_frame_visible (f)
4787x_make_frame_invisible (f) 9393x_make_frame_invisible (f)
4788 struct frame *f; 9394 struct frame *f;
4789{ 9395{
4790 Window window;
4791
4792 /* Don't keep the highlight on an invisible frame. */ 9396 /* Don't keep the highlight on an invisible frame. */
4793 if (FRAME_W32_DISPLAY_INFO (f)->w32_highlight_frame == f) 9397 if (FRAME_W32_DISPLAY_INFO (f)->w32_highlight_frame == f)
4794 FRAME_W32_DISPLAY_INFO (f)->w32_highlight_frame = 0; 9398 FRAME_W32_DISPLAY_INFO (f)->w32_highlight_frame = 0;
@@ -4881,7 +9485,7 @@ x_destroy_window (f)
4881 that the window now has. 9485 that the window now has.
4882 If USER_POSITION is nonzero, we set the USPosition 9486 If USER_POSITION is nonzero, we set the USPosition
4883 flag (this is useful when FLAGS is 0). */ 9487 flag (this is useful when FLAGS is 0). */
4884 9488void
4885x_wm_set_size_hint (f, flags, user_position) 9489x_wm_set_size_hint (f, flags, user_position)
4886 struct frame *f; 9490 struct frame *f;
4887 long flags; 9491 long flags;
@@ -4889,8 +9493,6 @@ x_wm_set_size_hint (f, flags, user_position)
4889{ 9493{
4890 Window window = FRAME_W32_WINDOW (f); 9494 Window window = FRAME_W32_WINDOW (f);
4891 9495
4892 flexlines = f->height;
4893
4894 enter_crit (); 9496 enter_crit ();
4895 9497
4896 SetWindowLong (window, WND_FONTWIDTH_INDEX, FONT_WIDTH (f->output_data.w32->font)); 9498 SetWindowLong (window, WND_FONTWIDTH_INDEX, FONT_WIDTH (f->output_data.w32->font));
@@ -4918,26 +9520,9 @@ x_wm_set_icon_position (f, icon_x, icon_y)
4918} 9520}
4919 9521
4920 9522
4921/* Initialization. */ 9523/***********************************************************************
4922 9524 Initialization
4923#ifdef USE_X_TOOLKIT 9525 ***********************************************************************/
4924static XrmOptionDescRec emacs_options[] = {
4925 {"-geometry", ".geometry", XrmoptionSepArg, NULL},
4926 {"-iconic", ".iconic", XrmoptionNoArg, (XtPointer) "yes"},
4927
4928 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
4929 XrmoptionSepArg, NULL},
4930 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg, NULL},
4931
4932 {"-T", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
4933 {"-wn", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
4934 {"-title", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
4935 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
4936 {"-in", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
4937 {"-mc", "*pointerColor", XrmoptionSepArg, (XtPointer) NULL},
4938 {"-cr", "*cursorColor", XrmoptionSepArg, (XtPointer) NULL}
4939};
4940#endif /* USE_X_TOOLKIT */
4941 9526
4942static int w32_initialized = 0; 9527static int w32_initialized = 0;
4943 9528
@@ -4947,8 +9532,6 @@ w32_term_init (display_name, xrm_option, resource_name)
4947 char *xrm_option; 9532 char *xrm_option;
4948 char *resource_name; 9533 char *resource_name;
4949{ 9534{
4950 Lisp_Object frame;
4951 char *defaultvalue;
4952 struct w32_display_info *dpyinfo; 9535 struct w32_display_info *dpyinfo;
4953 HDC hdc; 9536 HDC hdc;
4954 9537
@@ -4980,7 +9563,7 @@ w32_term_init (display_name, xrm_option, resource_name)
4980 9563
4981 /* Put it on w32_display_name_list as well, to keep them parallel. */ 9564 /* Put it on w32_display_name_list as well, to keep them parallel. */
4982 w32_display_name_list = Fcons (Fcons (display_name, Qnil), 9565 w32_display_name_list = Fcons (Fcons (display_name, Qnil),
4983 w32_display_name_list); 9566 w32_display_name_list);
4984 dpyinfo->name_list_element = XCAR (w32_display_name_list); 9567 dpyinfo->name_list_element = XCAR (w32_display_name_list);
4985 9568
4986 dpyinfo->w32_id_name 9569 dpyinfo->w32_id_name
@@ -4999,7 +9582,7 @@ w32_term_init (display_name, xrm_option, resource_name)
4999 dpyinfo->xrdb = xrdb; 9582 dpyinfo->xrdb = xrdb;
5000#endif 9583#endif
5001 hdc = GetDC (GetDesktopWindow ()); 9584 hdc = GetDC (GetDesktopWindow ());
5002 9585
5003 dpyinfo->height = GetDeviceCaps (hdc, VERTRES); 9586 dpyinfo->height = GetDeviceCaps (hdc, VERTRES);
5004 dpyinfo->width = GetDeviceCaps (hdc, HORZRES); 9587 dpyinfo->width = GetDeviceCaps (hdc, HORZRES);
5005 dpyinfo->root_window = GetDesktopWindow (); 9588 dpyinfo->root_window = GetDesktopWindow ();
@@ -5010,25 +9593,29 @@ w32_term_init (display_name, xrm_option, resource_name)
5010 dpyinfo->has_palette = GetDeviceCaps (hdc, RASTERCAPS) & RC_PALETTE; 9593 dpyinfo->has_palette = GetDeviceCaps (hdc, RASTERCAPS) & RC_PALETTE;
5011 dpyinfo->grabbed = 0; 9594 dpyinfo->grabbed = 0;
5012 dpyinfo->reference_count = 0; 9595 dpyinfo->reference_count = 0;
9596 dpyinfo->font_table = NULL;
5013 dpyinfo->n_fonts = 0; 9597 dpyinfo->n_fonts = 0;
5014 dpyinfo->font_table_size = 0; 9598 dpyinfo->font_table_size = 0;
5015 dpyinfo->bitmaps = 0; 9599 dpyinfo->bitmaps = 0;
5016 dpyinfo->bitmaps_size = 0; 9600 dpyinfo->bitmaps_size = 0;
5017 dpyinfo->bitmaps_last = 0; 9601 dpyinfo->bitmaps_last = 0;
9602 dpyinfo->scratch_cursor_gc = NULL;
5018 dpyinfo->mouse_face_mouse_frame = 0; 9603 dpyinfo->mouse_face_mouse_frame = 0;
5019 dpyinfo->mouse_face_deferred_gc = 0; 9604 dpyinfo->mouse_face_deferred_gc = 0;
5020 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1; 9605 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
5021 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1; 9606 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
5022 dpyinfo->mouse_face_face_id = 0; 9607 dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
5023 dpyinfo->mouse_face_window = Qnil; 9608 dpyinfo->mouse_face_window = Qnil;
5024 dpyinfo->mouse_face_mouse_x = dpyinfo->mouse_face_mouse_y = 0; 9609 dpyinfo->mouse_face_mouse_x = dpyinfo->mouse_face_mouse_y = 0;
5025 dpyinfo->mouse_face_defer = 0; 9610 dpyinfo->mouse_face_defer = 0;
5026 dpyinfo->w32_focus_frame = 0; 9611 dpyinfo->w32_focus_frame = 0;
5027 dpyinfo->w32_focus_event_frame = 0; 9612 dpyinfo->w32_focus_event_frame = 0;
5028 dpyinfo->w32_highlight_frame = 0; 9613 dpyinfo->w32_highlight_frame = 0;
5029 9614 dpyinfo->image_cache = make_image_cache ();
9615 dpyinfo->resx = dpyinfo->height / dpyinfo->height_in;
9616 dpyinfo->resy = dpyinfo->width / dpyinfo->width_in;
5030 ReleaseDC (GetDesktopWindow (), hdc); 9617 ReleaseDC (GetDesktopWindow (), hdc);
5031 9618 /* NTEMACS_TODO: dpyinfo->gray */
5032 /* Determine if there is a middle mouse button, to allow parse_button 9619 /* Determine if there is a middle mouse button, to allow parse_button
5033 to decide whether right mouse events should be mouse-2 or 9620 to decide whether right mouse events should be mouse-2 or
5034 mouse-3. */ 9621 mouse-3. */
@@ -5113,26 +9700,45 @@ x_delete_display (dpyinfo)
5113 9700
5114DWORD w32_msg_worker (); 9701DWORD w32_msg_worker ();
5115 9702
9703void
9704x_flush (struct frame * f)
9705{ /* Nothing to do */ }
9706
9707static struct redisplay_interface w32_redisplay_interface =
9708{
9709 x_produce_glyphs,
9710 x_write_glyphs,
9711 x_insert_glyphs,
9712 x_clear_end_of_line,
9713 x_scroll_run,
9714 x_after_update_window_line,
9715 x_update_window_begin,
9716 x_update_window_end,
9717 w32_cursor_to,
9718 x_flush,
9719 x_get_glyph_overhangs,
9720 x_fix_overlapping_area
9721};
9722
9723void
5116w32_initialize () 9724w32_initialize ()
5117{ 9725{
9726 rif = &w32_redisplay_interface;
9727
5118 /* MSVC does not type K&R functions with no arguments correctly, and 9728 /* MSVC does not type K&R functions with no arguments correctly, and
5119 so we must explicitly cast them. */ 9729 so we must explicitly cast them. */
5120 clear_frame_hook = (void (*)(void)) w32_clear_frame; 9730 clear_frame_hook = (void (*)(void)) x_clear_frame;
5121 clear_end_of_line_hook = w32_clear_end_of_line; 9731 ins_del_lines_hook = x_ins_del_lines;
5122 ins_del_lines_hook = w32_ins_del_lines; 9732 change_line_highlight_hook = x_change_line_highlight;
5123 change_line_highlight_hook = w32_change_line_highlight; 9733 delete_glyphs_hook = x_delete_glyphs;
5124 insert_glyphs_hook = w32_insert_glyphs;
5125 write_glyphs_hook = w32_write_glyphs;
5126 delete_glyphs_hook = w32_delete_glyphs;
5127 ring_bell_hook = (void (*)(void)) w32_ring_bell; 9734 ring_bell_hook = (void (*)(void)) w32_ring_bell;
5128 reset_terminal_modes_hook = (void (*)(void)) w32_reset_terminal_modes; 9735 reset_terminal_modes_hook = (void (*)(void)) w32_reset_terminal_modes;
5129 set_terminal_modes_hook = (void (*)(void)) w32_set_terminal_modes; 9736 set_terminal_modes_hook = (void (*)(void)) w32_set_terminal_modes;
5130 update_begin_hook = w32_update_begin; 9737 update_begin_hook = x_update_begin;
5131 update_end_hook = w32_update_end; 9738 update_end_hook = x_update_end;
5132 set_terminal_window_hook = w32_set_terminal_window; 9739 set_terminal_window_hook = w32_set_terminal_window;
5133 read_socket_hook = w32_read_socket; 9740 read_socket_hook = w32_read_socket;
5134 frame_up_to_date_hook = w32_frame_up_to_date; 9741 frame_up_to_date_hook = w32_frame_up_to_date;
5135 cursor_to_hook = w32_cursor_to;
5136 reassert_line_highlight_hook = w32_reassert_line_highlight; 9742 reassert_line_highlight_hook = w32_reassert_line_highlight;
5137 mouse_position_hook = w32_mouse_position; 9743 mouse_position_hook = w32_mouse_position;
5138 frame_rehighlight_hook = w32_frame_rehighlight; 9744 frame_rehighlight_hook = w32_frame_rehighlight;
@@ -5141,6 +9747,7 @@ w32_initialize ()
5141 condemn_scroll_bars_hook = w32_condemn_scroll_bars; 9747 condemn_scroll_bars_hook = w32_condemn_scroll_bars;
5142 redeem_scroll_bar_hook = w32_redeem_scroll_bar; 9748 redeem_scroll_bar_hook = w32_redeem_scroll_bar;
5143 judge_scroll_bars_hook = w32_judge_scroll_bars; 9749 judge_scroll_bars_hook = w32_judge_scroll_bars;
9750 estimate_mode_line_height_hook = x_estimate_mode_line_height;
5144 9751
5145 scroll_region_ok = 1; /* we'll scroll partial frames */ 9752 scroll_region_ok = 1; /* we'll scroll partial frames */
5146 char_ins_del_ok = 0; /* just as fast to write the line */ 9753 char_ins_del_ok = 0; /* just as fast to write the line */
@@ -5150,6 +9757,9 @@ w32_initialize ()
5150 off the bottom */ 9757 off the bottom */
5151 baud_rate = 19200; 9758 baud_rate = 19200;
5152 9759
9760 last_tool_bar_item = -1;
9761 any_help_event_p = 0;
9762
5153 /* Initialize input mode: interrupt_input off, no flow control, allow 9763 /* Initialize input mode: interrupt_input off, no flow control, allow
5154 8 bit character input, standard quit char. */ 9764 8 bit character input, standard quit char. */
5155 Fset_input_mode (Qnil, Qnil, make_number (2), Qnil); 9765 Fset_input_mode (Qnil, Qnil, make_number (2), Qnil);
@@ -5327,4 +9937,22 @@ affect on NT machines.");
5327 XSETFASTINT (codepage, 1252); 9937 XSETFASTINT (codepage, 1252);
5328 store_in_alist (&Vw32_charset_to_codepage_alist, 9938 store_in_alist (&Vw32_charset_to_codepage_alist,
5329 build_string ("iso8859-1"), codepage); 9939 build_string ("iso8859-1"), codepage);
9940
9941 staticpro (&help_echo);
9942 help_echo = Qnil;
9943 staticpro (&previous_help_echo);
9944 previous_help_echo = Qnil;
9945
9946 DEFVAR_BOOL ("x-stretch-cursor", &x_stretch_cursor_p,
9947 "*Non-nil means draw block cursor as wide as the glyph under it.\n\
9948For example, if a block cursor is over a tab, it will be drawn as\n\
9949wide as that tab on the display.");
9950 x_stretch_cursor_p = 0;
9951
9952 DEFVAR_BOOL ("x-toolkit-scroll-bars-p", &x_toolkit_scroll_bars_p,
9953 "If not nil, Emacs uses toolkit scroll bars.");
9954 x_toolkit_scroll_bars_p = 1;
9955
9956 staticpro (&last_mouse_motion_frame);
9957 last_mouse_motion_frame = Qnil;
5330} 9958}