]> code.delx.au - gnu-emacs/blob - src/w32term.c
Remove consolidated defines and code.
[gnu-emacs] / src / w32term.c
1 /* Implementation of GUI terminal on the Microsoft W32 API.
2 Copyright (C) 1989, 93, 94, 95, 96, 1997, 1998, 1999, 2000, 2001
3 Free Software Foundation, Inc.
4
5 This file is part of GNU Emacs.
6
7 GNU Emacs is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
11
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
21
22 #include <config.h>
23 #include <signal.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include "lisp.h"
27 #include "charset.h"
28 #include "blockinput.h"
29
30 #include "w32heap.h"
31 #include "w32term.h"
32 #include "w32bdf.h"
33 #include <shellapi.h>
34
35 #include "systty.h"
36 #include "systime.h"
37 #include "atimer.h"
38 #include "keymap.h"
39
40 #include <ctype.h>
41 #include <errno.h>
42 #include <setjmp.h>
43 #include <sys/stat.h>
44
45 #include "keyboard.h"
46 #include "frame.h"
47 #include "dispextern.h"
48 #include "fontset.h"
49 #include "termhooks.h"
50 #include "termopts.h"
51 #include "termchar.h"
52 #include "gnu.h"
53 #include "disptab.h"
54 #include "buffer.h"
55 #include "window.h"
56 #include "intervals.h"
57 #include "composite.h"
58 #include "coding.h"
59
60 #define abs(x) ((x) < 0 ? -(x) : (x))
61
62 #define BETWEEN(X, LOWER, UPPER) ((X) >= (LOWER) && (X) < (UPPER))
63
64 \f
65 /* Fringe bitmaps. */
66
67 static HBITMAP fringe_bmp[MAX_FRINGE_BITMAPS];
68
69 extern Lisp_Object Qhelp_echo;
70
71 /* Non-nil means Emacs uses toolkit scroll bars. */
72
73 Lisp_Object Vx_toolkit_scroll_bars;
74
75 /* If a string, w32_read_socket generates an event to display that string.
76 (The display is done in read_char.) */
77
78 static Lisp_Object help_echo;
79 static Lisp_Object help_echo_window;
80 static Lisp_Object help_echo_object;
81 static int help_echo_pos;
82
83 /* Temporary variables for w32_read_socket. */
84
85 static Lisp_Object previous_help_echo;
86 static int last_mousemove_x = 0;
87 static int last_mousemove_y = 0;
88
89 /* Non-zero means that a HELP_EVENT has been generated since Emacs
90 start. */
91
92 static int any_help_event_p;
93
94 /* Non-zero means autoselect window with the mouse cursor. */
95
96 int mouse_autoselect_window;
97
98 /* Last window where we saw the mouse. Used by mouse-autoselect-window. */
99 static Lisp_Object last_window;
100
101 /* Non-zero means draw block and hollow cursor as wide as the glyph
102 under it. For example, if a block cursor is over a tab, it will be
103 drawn as wide as that tab on the display. */
104
105 int x_stretch_cursor_p;
106
107 /* Non-zero means make use of UNDERLINE_POSITION font properties. */
108
109 int x_use_underline_position_properties;
110
111 extern unsigned int msh_mousewheel;
112
113 extern void free_frame_menubar ();
114
115 extern int w32_codepage_for_font (char *fontname);
116 extern Cursor w32_load_cursor (LPCTSTR name);
117
118 extern glyph_metric *w32_BDF_TextMetric(bdffont *fontp,
119 unsigned char *text, int dim);
120 extern Lisp_Object Vwindow_system;
121
122 #define x_any_window_to_frame x_window_to_frame
123 #define x_top_window_to_frame x_window_to_frame
124
125 \f
126 /* This is display since w32 does not support multiple ones. */
127 struct w32_display_info one_w32_display_info;
128 struct w32_display_info *x_display_list;
129
130 /* This is a list of cons cells, each of the form (NAME . FONT-LIST-CACHE),
131 one for each element of w32_display_list and in the same order.
132 NAME is the name of the frame.
133 FONT-LIST-CACHE records previous values returned by x-list-fonts. */
134 Lisp_Object w32_display_name_list;
135
136 /* Frame being updated by update_frame. This is declared in term.c.
137 This is set by update_begin and looked at by all the
138 w32 functions. It is zero while not inside an update.
139 In that case, the w32 functions assume that `SELECTED_FRAME ()'
140 is the frame to apply to. */
141 extern struct frame *updating_frame;
142
143 /* This is a frame waiting to be autoraised, within w32_read_socket. */
144 struct frame *pending_autoraise_frame;
145
146 /* Nominal cursor position -- where to draw output.
147 HPOS and VPOS are window relative glyph matrix coordinates.
148 X and Y are window relative pixel coordinates. */
149
150 struct cursor_pos output_cursor;
151
152 /* The handle of the frame that currently owns the system caret. */
153 HWND w32_system_caret_hwnd;
154 int w32_system_caret_height;
155 int w32_system_caret_x;
156 int w32_system_caret_y;
157 int w32_use_visible_system_caret;
158
159 /* Flag to enable Unicode output in case users wish to use programs
160 like Twinbridge on '95 rather than installed system level support
161 for Far East languages. */
162 int w32_enable_unicode_output;
163
164 DWORD dwWindowsThreadId = 0;
165 HANDLE hWindowsThread = NULL;
166 DWORD dwMainThreadId = 0;
167 HANDLE hMainThread = NULL;
168
169 #ifndef SIF_ALL
170 /* These definitions are new with Windows 95. */
171 #define SIF_RANGE 0x0001
172 #define SIF_PAGE 0x0002
173 #define SIF_POS 0x0004
174 #define SIF_DISABLENOSCROLL 0x0008
175 #define SIF_TRACKPOS 0x0010
176 #define SIF_ALL (SIF_RANGE | SIF_PAGE | SIF_POS | SIF_TRACKPOS)
177
178 typedef struct tagSCROLLINFO
179 {
180 UINT cbSize;
181 UINT fMask;
182 int nMin;
183 int nMax;
184 UINT nPage;
185 int nPos;
186 int nTrackPos;
187 } SCROLLINFO, FAR *LPSCROLLINFO;
188 typedef SCROLLINFO CONST FAR *LPCSCROLLINFO;
189 #endif /* SIF_ALL */
190
191 /* Dynamic linking to new proportional scroll bar functions. */
192 int (PASCAL *pfnSetScrollInfo) (HWND hwnd, int fnBar, LPSCROLLINFO lpsi, BOOL fRedraw);
193 BOOL (PASCAL *pfnGetScrollInfo) (HWND hwnd, int fnBar, LPSCROLLINFO lpsi);
194
195 int vertical_scroll_bar_min_handle;
196 int vertical_scroll_bar_top_border;
197 int vertical_scroll_bar_bottom_border;
198
199 int last_scroll_bar_drag_pos;
200
201 /* Mouse movement. */
202
203 /* Where the mouse was last time we reported a mouse event. */
204
205 FRAME_PTR last_mouse_frame;
206 static RECT last_mouse_glyph;
207 static Lisp_Object last_mouse_press_frame;
208
209 Lisp_Object Vw32_num_mouse_buttons;
210
211 Lisp_Object Vw32_swap_mouse_buttons;
212
213 /* Control whether x_raise_frame also sets input focus. */
214 Lisp_Object Vw32_grab_focus_on_raise;
215
216 /* Control whether Caps Lock affects non-ascii characters. */
217 Lisp_Object Vw32_capslock_is_shiftlock;
218
219 /* Control whether right-alt and left-ctrl should be recognized as AltGr. */
220 Lisp_Object Vw32_recognize_altgr;
221
222 /* The scroll bar in which the last motion event occurred.
223
224 If the last motion event occurred in a scroll bar, we set this
225 so w32_mouse_position can know whether to report a scroll bar motion or
226 an ordinary motion.
227
228 If the last motion event didn't occur in a scroll bar, we set this
229 to Qnil, to tell w32_mouse_position to return an ordinary motion event. */
230 static Lisp_Object last_mouse_scroll_bar;
231 static int last_mouse_scroll_bar_pos;
232
233 /* This is a hack. We would really prefer that w32_mouse_position would
234 return the time associated with the position it returns, but there
235 doesn't seem to be any way to wrest the time-stamp from the server
236 along with the position query. So, we just keep track of the time
237 of the last movement we received, and return that in hopes that
238 it's somewhat accurate. */
239
240 static Time last_mouse_movement_time;
241
242 /* Incremented by w32_read_socket whenever it really tries to read
243 events. */
244
245 #ifdef __STDC__
246 static int volatile input_signal_count;
247 #else
248 static int input_signal_count;
249 #endif
250
251 extern Lisp_Object Vcommand_line_args, Vsystem_name;
252
253 extern Lisp_Object Qface, Qmouse_face;
254
255 #ifndef USE_CRT_DLL
256 extern int errno;
257 #endif
258
259 /* A mask of extra modifier bits to put into every keyboard char. */
260
261 extern EMACS_INT extra_keyboard_modifiers;
262
263 static void x_update_window_end P_ ((struct window *, int, int));
264 static void frame_to_window_pixel_xy P_ ((struct window *, int *, int *));
265 void w32_delete_display P_ ((struct w32_display_info *));
266 static int fast_find_position P_ ((struct window *, int, int *, int *,
267 int *, int *, Lisp_Object));
268 static int fast_find_string_pos P_ ((struct window *, int, Lisp_Object,
269 int *, int *, int *, int *, int));
270 static void set_output_cursor P_ ((struct cursor_pos *));
271 static struct glyph *x_y_to_hpos_vpos P_ ((struct window *, int, int,
272 int *, int *, int *, int));
273 static void note_mode_line_or_margin_highlight P_ ((struct window *, int,
274 int, int));
275 static void note_mouse_highlight P_ ((struct frame *, int, int));
276 static void note_tool_bar_highlight P_ ((struct frame *f, int, int));
277 static void w32_handle_tool_bar_click P_ ((struct frame *,
278 struct input_event *));
279 static void show_mouse_face P_ ((struct w32_display_info *,
280 enum draw_glyphs_face));
281 static int cursor_in_mouse_face_p P_ ((struct window *));
282 static int clear_mouse_face P_ ((struct w32_display_info *));
283 void w32_define_cursor P_ ((Window, Cursor));
284
285 void x_lower_frame P_ ((struct frame *));
286 void x_scroll_bar_clear P_ ((struct frame *));
287 void x_wm_set_size_hint P_ ((struct frame *, long, int));
288 void x_raise_frame P_ ((struct frame *));
289 void x_set_window_size P_ ((struct frame *, int, int, int));
290 void x_wm_set_window_state P_ ((struct frame *, int));
291 void x_wm_set_icon_pixmap P_ ((struct frame *, int));
292 void w32_initialize P_ ((void));
293 static void x_font_min_bounds P_ ((XFontStruct *, int *, int *));
294 int x_compute_min_glyph_bounds P_ ((struct frame *));
295 static void x_draw_phys_cursor_glyph P_ ((struct window *,
296 struct glyph_row *,
297 enum draw_glyphs_face));
298 static void x_update_end P_ ((struct frame *));
299 static void w32_frame_up_to_date P_ ((struct frame *));
300 static void w32_set_terminal_modes P_ ((void));
301 static void w32_reset_terminal_modes P_ ((void));
302 static void w32_cursor_to P_ ((int, int, int, int));
303 static void x_write_glyphs P_ ((struct glyph *, int));
304 static void x_clear_end_of_line P_ ((int));
305 static void x_clear_frame P_ ((void));
306 static void x_clear_cursor P_ ((struct window *));
307 static void frame_highlight P_ ((struct frame *));
308 static void frame_unhighlight P_ ((struct frame *));
309 static void x_new_focus_frame P_ ((struct w32_display_info *,
310 struct frame *));
311 static void w32_frame_rehighlight P_ ((struct frame *));
312 static void x_frame_rehighlight P_ ((struct w32_display_info *));
313 static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *));
314 static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int,
315 enum text_cursor_kinds));
316 static void expose_frame P_ ((struct frame *, int, int, int, int));
317 static int expose_window_tree P_ ((struct window *, RECT *));
318 static void expose_overlaps P_ ((struct window *, struct glyph_row *,
319 struct glyph_row *));
320 static int expose_window P_ ((struct window *, RECT *));
321 static void expose_area P_ ((struct window *, struct glyph_row *,
322 RECT *, enum glyph_row_area));
323 static int expose_line P_ ((struct window *, struct glyph_row *,
324 RECT *));
325 void x_update_cursor P_ ((struct frame *, int));
326 static void x_update_cursor_in_window_tree P_ ((struct window *, int));
327 static void x_update_window_cursor P_ ((struct window *, int));
328 static void x_erase_phys_cursor P_ ((struct window *));
329 void x_display_cursor P_ ((struct window *w, int, int, int, int, int));
330 void x_display_and_set_cursor P_ ((struct window *, int, int, int, int, int));
331 static void w32_clip_to_row P_ ((struct window *, struct glyph_row *,
332 HDC, int));
333 static int x_phys_cursor_in_rect_p P_ ((struct window *, RECT *));
334
335 static Lisp_Object Qvendor_specific_keysyms;
336
337 \f
338 /***********************************************************************
339 Debugging
340 ***********************************************************************/
341
342 #if 0
343
344 /* This is a function useful for recording debugging information about
345 the sequence of occurrences in this file. */
346
347 struct record
348 {
349 char *locus;
350 int type;
351 };
352
353 struct record event_record[100];
354
355 int event_record_index;
356
357 record_event (locus, type)
358 char *locus;
359 int type;
360 {
361 if (event_record_index == sizeof (event_record) / sizeof (struct record))
362 event_record_index = 0;
363
364 event_record[event_record_index].locus = locus;
365 event_record[event_record_index].type = type;
366 event_record_index++;
367 }
368
369 #endif /* 0 */
370 \f
371
372 void XChangeGC (void * ignore, XGCValues* gc, unsigned long mask,
373 XGCValues *xgcv)
374 {
375 if (mask & GCForeground)
376 gc->foreground = xgcv->foreground;
377 if (mask & GCBackground)
378 gc->background = xgcv->background;
379 if (mask & GCFont)
380 gc->font = xgcv->font;
381 }
382
383 XGCValues *XCreateGC (void * ignore, Window window, unsigned long mask,
384 XGCValues *xgcv)
385 {
386 XGCValues *gc = (XGCValues *) xmalloc (sizeof (XGCValues));
387 bzero (gc, sizeof (XGCValues));
388
389 XChangeGC (ignore, gc, mask, xgcv);
390
391 return gc;
392 }
393
394 void XGetGCValues (void* ignore, XGCValues *gc,
395 unsigned long mask, XGCValues *xgcv)
396 {
397 XChangeGC (ignore, xgcv, mask, gc);
398 }
399
400 static void
401 w32_set_clip_rectangle (HDC hdc, RECT *rect)
402 {
403 if (rect)
404 {
405 HRGN clip_region = CreateRectRgnIndirect (rect);
406 SelectClipRgn (hdc, clip_region);
407 DeleteObject (clip_region);
408 }
409 else
410 SelectClipRgn (hdc, NULL);
411 }
412
413
414 /* Draw a hollow rectangle at the specified position. */
415 void
416 w32_draw_rectangle (HDC hdc, XGCValues *gc, int x, int y,
417 int width, int height)
418 {
419 HBRUSH hb, oldhb;
420 HPEN hp, oldhp;
421
422 hb = CreateSolidBrush (gc->background);
423 hp = CreatePen (PS_SOLID, 0, gc->foreground);
424 oldhb = SelectObject (hdc, hb);
425 oldhp = SelectObject (hdc, hp);
426
427 Rectangle (hdc, x, y, x + width, y + height);
428
429 SelectObject (hdc, oldhb);
430 SelectObject (hdc, oldhp);
431 DeleteObject (hb);
432 DeleteObject (hp);
433 }
434
435 /* Draw a filled rectangle at the specified position. */
436 void
437 w32_fill_rect (f, hdc, pix, lprect)
438 FRAME_PTR f;
439 HDC hdc;
440 COLORREF pix;
441 RECT * lprect;
442 {
443 HBRUSH hb;
444
445 hb = CreateSolidBrush (pix);
446 FillRect (hdc, lprect, hb);
447 DeleteObject (hb);
448 }
449
450 void
451 w32_clear_window (f)
452 FRAME_PTR f;
453 {
454 RECT rect;
455 HDC hdc = get_frame_dc (f);
456
457 /* Under certain conditions, this can be called at startup with
458 a console frame pointer before the GUI frame is created. An HDC
459 of 0 indicates this. */
460 if (hdc)
461 {
462 GetClientRect (FRAME_W32_WINDOW (f), &rect);
463 w32_clear_rect (f, hdc, &rect);
464 }
465
466 release_frame_dc (f, hdc);
467 }
468
469 \f
470 /***********************************************************************
471 Starting and ending an update
472 ***********************************************************************/
473
474 /* Start an update of frame F. This function is installed as a hook
475 for update_begin, i.e. it is called when update_begin is called.
476 This function is called prior to calls to x_update_window_begin for
477 each window being updated. */
478
479 static void
480 x_update_begin (f)
481 struct frame *f;
482 {
483 struct w32_display_info *display_info = FRAME_W32_DISPLAY_INFO (f);
484
485 if (! FRAME_W32_P (f))
486 return;
487
488 /* Regenerate display palette before drawing if list of requested
489 colors has changed. */
490 if (display_info->regen_palette)
491 {
492 w32_regenerate_palette (f);
493 display_info->regen_palette = FALSE;
494 }
495 }
496
497
498 /* Start update of window W. Set the global variable updated_window
499 to the window being updated and set output_cursor to the cursor
500 position of W. */
501
502 static void
503 x_update_window_begin (w)
504 struct window *w;
505 {
506 struct frame *f = XFRAME (WINDOW_FRAME (w));
507 struct w32_display_info *display_info = FRAME_W32_DISPLAY_INFO (f);
508
509 /* Hide the system caret during an update. */
510 if (w32_use_visible_system_caret && w32_system_caret_hwnd)
511 {
512 SendMessage (w32_system_caret_hwnd, WM_EMACS_HIDE_CARET, 0, 0);
513 }
514
515 updated_window = w;
516 set_output_cursor (&w->cursor);
517
518 BLOCK_INPUT;
519
520 if (f == display_info->mouse_face_mouse_frame)
521 {
522 /* Don't do highlighting for mouse motion during the update. */
523 display_info->mouse_face_defer = 1;
524
525 /* If F needs to be redrawn, simply forget about any prior mouse
526 highlighting. */
527 if (FRAME_GARBAGED_P (f))
528 display_info->mouse_face_window = Qnil;
529
530 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
531 their mouse_face_p flag set, which means that they are always
532 unequal to rows in a desired matrix which never have that
533 flag set. So, rows containing mouse-face glyphs are never
534 scrolled, and we don't have to switch the mouse highlight off
535 here to prevent it from being scrolled. */
536
537 /* Can we tell that this update does not affect the window
538 where the mouse highlight is? If so, no need to turn off.
539 Likewise, don't do anything if the frame is garbaged;
540 in that case, the frame's current matrix that we would use
541 is all wrong, and we will redisplay that line anyway. */
542 if (!NILP (display_info->mouse_face_window)
543 && w == XWINDOW (display_info->mouse_face_window))
544 {
545 int i;
546
547 for (i = 0; i < w->desired_matrix->nrows; ++i)
548 if (MATRIX_ROW_ENABLED_P (w->desired_matrix, i))
549 break;
550
551 if (i < w->desired_matrix->nrows)
552 clear_mouse_face (display_info);
553 }
554 #endif /* 0 */
555 }
556
557 UNBLOCK_INPUT;
558 }
559
560
561 /* Draw a vertical window border to the right of window W if W doesn't
562 have vertical scroll bars. */
563
564 static void
565 x_draw_vertical_border (w)
566 struct window *w;
567 {
568 struct frame *f = XFRAME (WINDOW_FRAME (w));
569
570 /* Redraw borders between horizontally adjacent windows. Don't
571 do it for frames with vertical scroll bars because either the
572 right scroll bar of a window, or the left scroll bar of its
573 neighbor will suffice as a border. */
574 if (!WINDOW_RIGHTMOST_P (w)
575 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
576 {
577 RECT r;
578 HDC hdc;
579
580 window_box_edges (w, -1, (int *) &r.left, (int *) &r.top,
581 (int *) &r.right, (int *) &r.bottom);
582 r.left = r.right + FRAME_X_RIGHT_FRINGE_WIDTH (f);
583 r.right = r.left + 1;
584 r.bottom -= 1;
585
586 hdc = get_frame_dc (f);
587 w32_fill_rect (f, hdc, FRAME_FOREGROUND_PIXEL (f), &r);
588 release_frame_dc (f, hdc);
589 }
590 }
591
592
593 /* End update of window W (which is equal to updated_window).
594
595 Draw vertical borders between horizontally adjacent windows, and
596 display W's cursor if CURSOR_ON_P is non-zero.
597
598 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
599 glyphs in mouse-face were overwritten. In that case we have to
600 make sure that the mouse-highlight is properly redrawn.
601
602 W may be a menu bar pseudo-window in case we don't have X toolkit
603 support. Such windows don't have a cursor, so don't display it
604 here. */
605
606 static void
607 x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p)
608 struct window *w;
609 int cursor_on_p, mouse_face_overwritten_p;
610 {
611 struct w32_display_info *dpyinfo
612 = FRAME_W32_DISPLAY_INFO (XFRAME (w->frame));
613
614 if (!w->pseudo_window_p)
615 {
616 BLOCK_INPUT;
617
618 if (cursor_on_p)
619 x_display_and_set_cursor (w, 1, output_cursor.hpos,
620 output_cursor.vpos,
621 output_cursor.x, output_cursor.y);
622
623 x_draw_vertical_border (w);
624 UNBLOCK_INPUT;
625 }
626
627 /* If a row with mouse-face was overwritten, arrange for
628 XTframe_up_to_date to redisplay the mouse highlight. */
629 if (mouse_face_overwritten_p)
630 {
631 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
632 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
633 dpyinfo->mouse_face_window = Qnil;
634 }
635
636 /* Unhide the caret. This won't actually show the cursor, unless it
637 was visible before the corresponding call to HideCaret in
638 x_update_window_begin. */
639 if (w32_use_visible_system_caret && w32_system_caret_hwnd)
640 {
641 SendMessage (w32_system_caret_hwnd, WM_EMACS_SHOW_CARET, 0, 0);
642 }
643
644 updated_window = NULL;
645 }
646
647
648 /* End update of frame F. This function is installed as a hook in
649 update_end. */
650
651 static void
652 x_update_end (f)
653 struct frame *f;
654 {
655 if (! FRAME_W32_P (f))
656 return;
657
658 /* Mouse highlight may be displayed again. */
659 FRAME_W32_DISPLAY_INFO (f)->mouse_face_defer = 0;
660 }
661
662
663 /* This function is called from various places in xdisp.c whenever a
664 complete update has been performed. The global variable
665 updated_window is not available here. */
666
667 static void
668 w32_frame_up_to_date (f)
669 struct frame *f;
670 {
671 if (FRAME_W32_P (f))
672 {
673 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
674 if (dpyinfo->mouse_face_deferred_gc
675 || f == dpyinfo->mouse_face_mouse_frame)
676 {
677 BLOCK_INPUT;
678 if (dpyinfo->mouse_face_mouse_frame)
679 note_mouse_highlight (dpyinfo->mouse_face_mouse_frame,
680 dpyinfo->mouse_face_mouse_x,
681 dpyinfo->mouse_face_mouse_y);
682 dpyinfo->mouse_face_deferred_gc = 0;
683 UNBLOCK_INPUT;
684 }
685 }
686 }
687
688
689 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
690 arrow bitmaps, or clear the fringes if no bitmaps are required
691 before DESIRED_ROW is made current. The window being updated is
692 found in updated_window. This function is called from
693 update_window_line only if it is known that there are differences
694 between bitmaps to be drawn between current row and DESIRED_ROW. */
695
696 static void
697 x_after_update_window_line (desired_row)
698 struct glyph_row *desired_row;
699 {
700 struct window *w = updated_window;
701 struct frame *f;
702 int width, height;
703
704 xassert (w);
705
706 if (!desired_row->mode_line_p && !w->pseudo_window_p)
707 {
708 BLOCK_INPUT;
709 draw_row_fringe_bitmaps (w, desired_row);
710 UNBLOCK_INPUT;
711 }
712
713 /* When a window has disappeared, make sure that no rest of
714 full-width rows stays visible in the internal border. Could
715 check here if updated_window is the leftmost/rightmost window,
716 but I guess it's not worth doing since vertically split windows
717 are almost never used, internal border is rarely set, and the
718 overhead is very small. */
719 if (windows_or_buffers_changed
720 && desired_row->full_width_p
721 && (f = XFRAME (w->frame),
722 width = FRAME_INTERNAL_BORDER_WIDTH (f),
723 width != 0)
724 && (height = desired_row->visible_height,
725 height > 0))
726 {
727 int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
728 /* Internal border is drawn below the tool bar. */
729 if (WINDOWP (f->tool_bar_window)
730 && w == XWINDOW (f->tool_bar_window))
731 y -= width;
732
733 BLOCK_INPUT;
734 {
735 HDC hdc = get_frame_dc (f);
736 w32_clear_area (f, hdc, 0, y, width, height);
737 w32_clear_area (f, hdc, f->output_data.w32->pixel_width - width,
738 y, width, height);
739 release_frame_dc (f, hdc);
740 }
741 UNBLOCK_INPUT;
742 }
743 }
744
745
746 /* Draw the bitmap WHICH in one of the left or right fringes of
747 window W. ROW is the glyph row for which to display the bitmap; it
748 determines the vertical position at which the bitmap has to be
749 drawn. */
750
751 static void
752 w32_draw_fringe_bitmap (w, row, p)
753 struct window *w;
754 struct glyph_row *row;
755 struct draw_fringe_bitmap_params *p;
756 {
757 struct frame *f = XFRAME (WINDOW_FRAME (w));
758 HDC hdc;
759 struct face *face = p->face;
760
761 hdc = get_frame_dc (f);
762
763 /* Must clip because of partially visible lines. */
764 w32_clip_to_row (w, row, hdc, 1);
765
766 if (p->bx >= 0)
767 {
768 w32_fill_area (f, hdc, face->background,
769 p->bx, p->by, p->nx, p->ny);
770 }
771
772 if (p->which != NO_FRINGE_BITMAP)
773 {
774 HBITMAP pixmap = fringe_bmp[p->which];
775 HDC compat_hdc;
776 HANDLE horig_obj;
777
778 compat_hdc = CreateCompatibleDC (hdc);
779 SaveDC (hdc);
780
781 horig_obj = SelectObject (compat_hdc, pixmap);
782 SetTextColor (hdc, face->background);
783 SetBkColor (hdc, face->foreground);
784
785 BitBlt (hdc, p->x, p->y, p->wd, p->h,
786 compat_hdc, 0, p->dh,
787 SRCCOPY);
788
789 SelectObject (compat_hdc, horig_obj);
790 DeleteDC (compat_hdc);
791 RestoreDC (hdc, -1);
792 }
793
794 w32_set_clip_rectangle (hdc, NULL);
795
796 release_frame_dc (f, hdc);
797 }
798
799 \f
800 /* This is called when starting Emacs and when restarting after
801 suspend. When starting Emacs, no window is mapped. And nothing
802 must be done to Emacs's own window if it is suspended (though that
803 rarely happens). */
804
805 static void
806 w32_set_terminal_modes (void)
807 {
808 }
809
810 /* This is called when exiting or suspending Emacs. Exiting will make
811 the W32 windows go away, and suspending requires no action. */
812
813 static void
814 w32_reset_terminal_modes (void)
815 {
816 }
817
818
819 \f
820 /***********************************************************************
821 Output Cursor
822 ***********************************************************************/
823
824 /* Set the global variable output_cursor to CURSOR. All cursor
825 positions are relative to updated_window. */
826
827 static void
828 set_output_cursor (cursor)
829 struct cursor_pos *cursor;
830 {
831 output_cursor.hpos = cursor->hpos;
832 output_cursor.vpos = cursor->vpos;
833 output_cursor.x = cursor->x;
834 output_cursor.y = cursor->y;
835 }
836
837
838 /* Set a nominal cursor position.
839
840 HPOS and VPOS are column/row positions in a window glyph matrix. X
841 and Y are window text area relative pixel positions.
842
843 If this is done during an update, updated_window will contain the
844 window that is being updated and the position is the future output
845 cursor position for that window. If updated_window is null, use
846 selected_window and display the cursor at the given position. */
847
848 static void
849 w32_cursor_to (vpos, hpos, y, x)
850 int vpos, hpos, y, x;
851 {
852 struct window *w;
853
854 /* If updated_window is not set, work on selected_window. */
855 if (updated_window)
856 w = updated_window;
857 else
858 w = XWINDOW (selected_window);
859
860 /* Set the output cursor. */
861 output_cursor.hpos = hpos;
862 output_cursor.vpos = vpos;
863 output_cursor.x = x;
864 output_cursor.y = y;
865
866 /* If not called as part of an update, really display the cursor.
867 This will also set the cursor position of W. */
868 if (updated_window == NULL)
869 {
870 BLOCK_INPUT;
871 x_display_cursor (w, 1, hpos, vpos, x, y);
872 UNBLOCK_INPUT;
873 }
874 }
875
876
877 \f
878 /***********************************************************************
879 Display Iterator
880 ***********************************************************************/
881
882 /* Function prototypes of this page. */
883
884 static XCharStruct *w32_per_char_metric P_ ((XFontStruct *,
885 wchar_t *, int));
886 static int w32_encode_char P_ ((int, wchar_t *, struct font_info *, int *));
887
888
889 /* Get metrics of character CHAR2B in FONT. Value is always non-null.
890 If CHAR2B is not contained in FONT, the font's default character
891 metric is returned. */
892
893 static int
894 w32_bdf_per_char_metric (font, char2b, dim, pcm)
895 XFontStruct *font;
896 wchar_t *char2b;
897 int dim;
898 XCharStruct * pcm;
899 {
900 glyph_metric * bdf_metric;
901 char buf[2];
902
903 if (dim == 1)
904 buf[0] = (char)(*char2b);
905 else
906 {
907 buf[0] = XCHAR2B_BYTE1 (char2b);
908 buf[1] = XCHAR2B_BYTE2 (char2b);
909 }
910
911 bdf_metric = w32_BDF_TextMetric (font->bdf, buf, dim);
912
913 if (bdf_metric)
914 {
915 pcm->width = bdf_metric->dwidth;
916 pcm->lbearing = bdf_metric->bbox;
917 pcm->rbearing = bdf_metric->dwidth
918 - (bdf_metric->bbox + bdf_metric->bbw);
919 pcm->ascent = bdf_metric->bboy + bdf_metric->bbh;
920 pcm->descent = -bdf_metric->bboy;
921
922 return 1;
923 }
924 return 0;
925 }
926
927
928 static int
929 w32_native_per_char_metric (font, char2b, font_type, pcm)
930 XFontStruct *font;
931 wchar_t *char2b;
932 enum w32_char_font_type font_type;
933 XCharStruct * pcm;
934 {
935 HDC hdc = GetDC (NULL);
936 HFONT old_font;
937 BOOL retval = FALSE;
938
939 xassert (font && char2b);
940 xassert (font->hfont);
941 xassert (font_type == UNICODE_FONT || font_type == ANSI_FONT);
942
943 old_font = SelectObject (hdc, font->hfont);
944
945 if ((font->tm.tmPitchAndFamily & TMPF_TRUETYPE) != 0)
946 {
947 ABC char_widths;
948
949 if (font_type == UNICODE_FONT)
950 retval = GetCharABCWidthsW (hdc, *char2b, *char2b, &char_widths);
951 else
952 retval = GetCharABCWidthsA (hdc, *char2b, *char2b, &char_widths);
953
954 if (retval)
955 {
956 #if 0
957 /* Disabled until we can find a way to get the right results
958 on all versions of Windows. */
959
960 /* Don't trust the ABC widths. For synthesized fonts they are
961 wrong, and so is the result of GetCharWidth()! */
962 int real_width;
963 GetCharWidth (hdc, *char2b, *char2b, &real_width);
964 #endif
965 pcm->width = char_widths.abcA + char_widths.abcB + char_widths.abcC;
966 #if 0
967 /* As far as I can tell, this is the best way to determine what
968 ExtTextOut will do with the broken font. */
969 if (pcm->width != real_width)
970 pcm->width = (pcm->width + real_width) / 2;
971 #endif
972 pcm->lbearing = char_widths.abcA;
973 pcm->rbearing = char_widths.abcA + char_widths.abcB;
974 pcm->ascent = FONT_BASE (font);
975 pcm->descent = FONT_DESCENT (font);
976 }
977 }
978
979 if (!retval)
980 {
981 /* Either font is not a True-type font, or GetCharABCWidthsW
982 failed (it is not supported on Windows 9x for instance), so we
983 can't determine the full info we would like. All is not lost
984 though - we can call GetTextExtentPoint32 to get rbearing and
985 deduce width based on the font's per-string overhang. lbearing
986 is assumed to be zero. */
987
988 /* TODO: Some Thai characters (and other composites if Windows
989 supports them) do have lbearing, and report their total width
990 as zero. Need some way of handling them when
991 GetCharABCWidthsW fails. */
992 SIZE sz;
993
994 if (font_type == UNICODE_FONT)
995 retval = GetTextExtentPoint32W (hdc, char2b, 1, &sz);
996 else
997 retval = GetTextExtentPoint32A (hdc, (char*)char2b, 1, &sz);
998
999 if (retval)
1000 {
1001 pcm->width = sz.cx - font->tm.tmOverhang;
1002 pcm->rbearing = sz.cx;
1003 pcm->lbearing = 0;
1004 pcm->ascent = FONT_BASE (font);
1005 pcm->descent = FONT_DESCENT (font);
1006 }
1007 }
1008
1009
1010 if (pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0)
1011 {
1012 retval = FALSE;
1013 }
1014
1015 SelectObject (hdc, old_font);
1016 ReleaseDC (NULL, hdc);
1017
1018 return retval;
1019 }
1020
1021
1022 static XCharStruct *
1023 w32_per_char_metric (font, char2b, font_type)
1024 XFontStruct *font;
1025 wchar_t *char2b;
1026 int /* enum w32_char_font_type */ font_type;
1027 {
1028 /* The result metric information. */
1029 XCharStruct *pcm;
1030 BOOL retval;
1031
1032 xassert (font && char2b);
1033 xassert (font_type != UNKNOWN_FONT);
1034
1035 /* Handle the common cases quickly. */
1036 if (!font->bdf && font->per_char == NULL)
1037 /* TODO: determine whether char2b exists in font? */
1038 return &font->max_bounds;
1039 else if (!font->bdf && *char2b < 128)
1040 return &font->per_char[*char2b];
1041
1042 pcm = &font->scratch;
1043
1044 if (font_type == BDF_1D_FONT)
1045 retval = w32_bdf_per_char_metric (font, char2b, 1, pcm);
1046 else if (font_type == BDF_2D_FONT)
1047 retval = w32_bdf_per_char_metric (font, char2b, 2, pcm);
1048 else
1049 retval = w32_native_per_char_metric (font, char2b, font_type, pcm);
1050
1051 if (retval)
1052 return pcm;
1053
1054 return NULL;
1055 }
1056
1057 void
1058 w32_cache_char_metrics (font)
1059 XFontStruct *font;
1060 {
1061 wchar_t char2b = L'x';
1062
1063 /* Cache char metrics for the common cases. */
1064 if (font->bdf)
1065 {
1066 /* TODO: determine whether font is fixed-pitch. */
1067 if (!w32_bdf_per_char_metric (font, &char2b, 1, &font->max_bounds))
1068 {
1069 /* Use the font width and height as max bounds, as not all BDF
1070 fonts contain the letter 'x'. */
1071 font->max_bounds.width = FONT_MAX_WIDTH (font);
1072 font->max_bounds.lbearing = -font->bdf->llx;
1073 font->max_bounds.rbearing = FONT_MAX_WIDTH (font) - font->bdf->urx;
1074 font->max_bounds.ascent = FONT_BASE (font);
1075 font->max_bounds.descent = FONT_DESCENT (font);
1076 }
1077 }
1078 else
1079 {
1080 if (((font->tm.tmPitchAndFamily & TMPF_FIXED_PITCH) != 0)
1081 /* Some fonts (eg DBCS fonts) are marked as fixed width even
1082 though they contain characters of different widths. */
1083 || (font->tm.tmMaxCharWidth != font->tm.tmAveCharWidth))
1084 {
1085 /* Font is not fixed pitch, so cache per_char info for the
1086 ASCII characters. It would be much more work, and probably
1087 not worth it, to cache other chars, since we may change
1088 between using Unicode and ANSI text drawing functions at
1089 run-time. */
1090 int i;
1091
1092 font->per_char = xmalloc (128 * sizeof(XCharStruct));
1093 for (i = 0; i < 128; i++)
1094 {
1095 char2b = i;
1096 w32_native_per_char_metric (font, &char2b, ANSI_FONT,
1097 &font->per_char[i]);
1098 }
1099 }
1100 else
1101 w32_native_per_char_metric (font, &char2b, ANSI_FONT,
1102 &font->max_bounds);
1103 }
1104 }
1105
1106
1107 /* Determine if a font is double byte. */
1108 int w32_font_is_double_byte (XFontStruct *font)
1109 {
1110 return font->double_byte_p;
1111 }
1112
1113
1114 static BOOL
1115 w32_use_unicode_for_codepage (codepage)
1116 int codepage;
1117 {
1118 /* If the current codepage is supported, use Unicode for output. */
1119 return (w32_enable_unicode_output
1120 && codepage != CP_8BIT
1121 && (codepage == CP_UNICODE || IsValidCodePage (codepage)));
1122 }
1123
1124 /* Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
1125 the two-byte form of C. Encoding is returned in *CHAR2B. */
1126
1127 static int /* enum w32_char_font_type */
1128 w32_encode_char (c, char2b, font_info, two_byte_p)
1129 int c;
1130 wchar_t *char2b;
1131 struct font_info *font_info;
1132 int * two_byte_p;
1133 {
1134 int charset = CHAR_CHARSET (c);
1135 int codepage;
1136 int unicode_p = 0;
1137
1138 XFontStruct *font = font_info->font;
1139
1140 xassert (two_byte_p);
1141
1142 if (two_byte_p)
1143 *two_byte_p = w32_font_is_double_byte (font);
1144
1145 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
1146 This may be either a program in a special encoder language or a
1147 fixed encoding. */
1148 if (font_info->font_encoder)
1149 {
1150 /* It's a program. */
1151 struct ccl_program *ccl = font_info->font_encoder;
1152
1153 if (CHARSET_DIMENSION (charset) == 1)
1154 {
1155 ccl->reg[0] = charset;
1156 ccl->reg[1] = XCHAR2B_BYTE2 (char2b);
1157 ccl->reg[2] = -1;
1158 }
1159 else
1160 {
1161 ccl->reg[0] = charset;
1162 ccl->reg[1] = XCHAR2B_BYTE1 (char2b);
1163 ccl->reg[2] = XCHAR2B_BYTE2 (char2b);
1164 }
1165
1166 ccl_driver (ccl, NULL, NULL, 0, 0, NULL);
1167
1168 /* We assume that MSBs are appropriately set/reset by CCL
1169 program. */
1170 if (!*two_byte_p) /* 1-byte font */
1171 STORE_XCHAR2B (char2b, 0, ccl->reg[1]);
1172 else
1173 STORE_XCHAR2B (char2b, ccl->reg[1], ccl->reg[2]);
1174 }
1175 else if (font_info->encoding[charset])
1176 {
1177 /* Fixed encoding scheme. See fontset.h for the meaning of the
1178 encoding numbers. */
1179 int enc = font_info->encoding[charset];
1180
1181 if ((enc == 1 || enc == 2)
1182 && CHARSET_DIMENSION (charset) == 2)
1183 STORE_XCHAR2B (char2b, XCHAR2B_BYTE1 (char2b) | 0x80, XCHAR2B_BYTE2 (char2b));
1184
1185 if (enc == 1 || enc == 3
1186 || (enc == 4 && CHARSET_DIMENSION (charset) == 1))
1187 STORE_XCHAR2B (char2b, XCHAR2B_BYTE1 (char2b), XCHAR2B_BYTE2 (char2b) | 0x80);
1188 else if (enc == 4)
1189 {
1190 int sjis1, sjis2;
1191
1192 ENCODE_SJIS (XCHAR2B_BYTE1 (char2b), XCHAR2B_BYTE2 (char2b),
1193 sjis1, sjis2);
1194 STORE_XCHAR2B (char2b, sjis1, sjis2);
1195 }
1196 }
1197 codepage = font_info->codepage;
1198
1199 /* If charset is not ASCII or Latin-1, may need to move it into
1200 Unicode space. */
1201 if ( font && !font->bdf && w32_use_unicode_for_codepage (codepage)
1202 && charset != CHARSET_ASCII && charset != charset_latin_iso8859_1
1203 && charset != CHARSET_8_BIT_CONTROL && charset != CHARSET_8_BIT_GRAPHIC)
1204 {
1205 char temp[3];
1206 temp[0] = XCHAR2B_BYTE1 (char2b);
1207 temp[1] = XCHAR2B_BYTE2 (char2b);
1208 temp[2] = '\0';
1209 if (codepage != CP_UNICODE)
1210 {
1211 if (temp[0])
1212 MultiByteToWideChar (codepage, 0, temp, 2, char2b, 1);
1213 else
1214 MultiByteToWideChar (codepage, 0, temp+1, 1, char2b, 1);
1215 }
1216 unicode_p = 1;
1217 *two_byte_p = 1;
1218 }
1219 if (!font)
1220 return UNKNOWN_FONT;
1221 else if (font->bdf && CHARSET_DIMENSION (charset) == 1)
1222 return BDF_1D_FONT;
1223 else if (font->bdf)
1224 return BDF_2D_FONT;
1225 else if (unicode_p)
1226 return UNICODE_FONT;
1227 else
1228 return ANSI_FONT;
1229 }
1230
1231
1232 /* Estimate the pixel height of the mode or top line on frame F.
1233 FACE_ID specifies what line's height to estimate. */
1234
1235 int
1236 x_estimate_mode_line_height (f, face_id)
1237 struct frame *f;
1238 enum face_id face_id;
1239 {
1240 int height = FONT_HEIGHT (FRAME_FONT (f));
1241
1242 /* This function is called so early when Emacs starts that the face
1243 cache and mode line face are not yet initialized. */
1244 if (FRAME_FACE_CACHE (f))
1245 {
1246 struct face *face = FACE_FROM_ID (f, face_id);
1247 if (face)
1248 {
1249 if (face->font)
1250 height = FONT_HEIGHT (face->font);
1251 if (face->box_line_width > 0)
1252 height += 2 * face->box_line_width;
1253 }
1254 }
1255
1256 return height;
1257 }
1258
1259 \f
1260 /***********************************************************************
1261 Glyph display
1262 ***********************************************************************/
1263
1264
1265 /* Encapsulate the different ways of displaying text under W32. */
1266
1267 static void
1268 w32_text_out (s, x, y,chars,nchars)
1269 struct glyph_string * s;
1270 int x, y;
1271 wchar_t * chars;
1272 int nchars;
1273 {
1274 int charset_dim = w32_font_is_double_byte (s->gc->font) ? 2 : 1;
1275 if (s->gc->font->bdf)
1276 w32_BDF_TextOut (s->gc->font->bdf, s->hdc,
1277 x, y, (char *) chars, charset_dim,
1278 nchars * charset_dim, 0);
1279 else if (s->first_glyph->font_type == UNICODE_FONT)
1280 ExtTextOutW (s->hdc, x, y, 0, NULL, chars, nchars, NULL);
1281 else
1282 ExtTextOutA (s->hdc, x, y, 0, NULL, (char *) chars,
1283 nchars * charset_dim, NULL);
1284 }
1285
1286
1287
1288 static void x_set_glyph_string_clipping P_ ((struct glyph_string *));
1289 static void x_set_glyph_string_gc P_ ((struct glyph_string *));
1290 static void x_draw_glyph_string_background P_ ((struct glyph_string *,
1291 int));
1292 static void x_draw_glyph_string_foreground P_ ((struct glyph_string *));
1293 static void x_draw_composite_glyph_string_foreground P_ ((struct glyph_string *));
1294 static void x_draw_glyph_string_box P_ ((struct glyph_string *));
1295 static void x_draw_glyph_string P_ ((struct glyph_string *));
1296 static void x_set_cursor_gc P_ ((struct glyph_string *));
1297 static void x_set_mode_line_face_gc P_ ((struct glyph_string *));
1298 static void x_set_mouse_face_gc P_ ((struct glyph_string *));
1299 static int w32_alloc_lighter_color (struct frame *, COLORREF *, double, int);
1300 static void w32_setup_relief_color P_ ((struct frame *, struct relief *,
1301 double, int, COLORREF));
1302 static void x_setup_relief_colors P_ ((struct glyph_string *));
1303 static void x_draw_image_glyph_string P_ ((struct glyph_string *));
1304 static void x_draw_image_relief P_ ((struct glyph_string *));
1305 static void x_draw_image_foreground P_ ((struct glyph_string *));
1306 static void w32_draw_image_foreground_1 P_ ((struct glyph_string *, HBITMAP));
1307 static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int,
1308 int, int, int));
1309 static void w32_draw_relief_rect P_ ((struct frame *, int, int, int, int,
1310 int, int, int, int, RECT *));
1311 static void w32_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,
1312 int, int, int, RECT *));
1313 static void x_fix_overlapping_area P_ ((struct window *, struct glyph_row *,
1314 enum glyph_row_area));
1315
1316 #if GLYPH_DEBUG
1317 static void x_check_font P_ ((struct frame *, XFontStruct *));
1318 #endif
1319
1320
1321 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
1322 face. */
1323
1324 static void
1325 x_set_cursor_gc (s)
1326 struct glyph_string *s;
1327 {
1328 if (s->font == FRAME_FONT (s->f)
1329 && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
1330 && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
1331 && !s->cmp)
1332 s->gc = s->f->output_data.w32->cursor_gc;
1333 else
1334 {
1335 /* Cursor on non-default face: must merge. */
1336 XGCValues xgcv;
1337 unsigned long mask;
1338
1339 xgcv.background = s->f->output_data.w32->cursor_pixel;
1340 xgcv.foreground = s->face->background;
1341
1342 /* If the glyph would be invisible, try a different foreground. */
1343 if (xgcv.foreground == xgcv.background)
1344 xgcv.foreground = s->face->foreground;
1345 if (xgcv.foreground == xgcv.background)
1346 xgcv.foreground = s->f->output_data.w32->cursor_foreground_pixel;
1347 if (xgcv.foreground == xgcv.background)
1348 xgcv.foreground = s->face->foreground;
1349
1350 /* Make sure the cursor is distinct from text in this face. */
1351 if (xgcv.background == s->face->background
1352 && xgcv.foreground == s->face->foreground)
1353 {
1354 xgcv.background = s->face->foreground;
1355 xgcv.foreground = s->face->background;
1356 }
1357
1358 IF_DEBUG (x_check_font (s->f, s->font));
1359 xgcv.font = s->font;
1360 mask = GCForeground | GCBackground | GCFont;
1361
1362 if (FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc)
1363 XChangeGC (NULL, FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc,
1364 mask, &xgcv);
1365 else
1366 FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc
1367 = XCreateGC (NULL, s->window, mask, &xgcv);
1368
1369 s->gc = FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc;
1370 }
1371 }
1372
1373
1374 /* Set up S->gc of glyph string S for drawing text in mouse face. */
1375
1376 static void
1377 x_set_mouse_face_gc (s)
1378 struct glyph_string *s;
1379 {
1380 int face_id;
1381 struct face *face;
1382
1383 /* What face has to be used last for the mouse face? */
1384 face_id = FRAME_W32_DISPLAY_INFO (s->f)->mouse_face_face_id;
1385 face = FACE_FROM_ID (s->f, face_id);
1386 if (face == NULL)
1387 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
1388
1389 if (s->first_glyph->type == CHAR_GLYPH)
1390 face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch);
1391 else
1392 face_id = FACE_FOR_CHAR (s->f, face, 0);
1393 s->face = FACE_FROM_ID (s->f, face_id);
1394 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
1395
1396 /* If font in this face is same as S->font, use it. */
1397 if (s->font == s->face->font)
1398 s->gc = s->face->gc;
1399 else
1400 {
1401 /* Otherwise construct scratch_cursor_gc with values from FACE
1402 but font FONT. */
1403 XGCValues xgcv;
1404 unsigned long mask;
1405
1406 xgcv.background = s->face->background;
1407 xgcv.foreground = s->face->foreground;
1408 IF_DEBUG (x_check_font (s->f, s->font));
1409 xgcv.font = s->font;
1410 mask = GCForeground | GCBackground | GCFont;
1411
1412 if (FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc)
1413 XChangeGC (NULL, FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc,
1414 mask, &xgcv);
1415 else
1416 FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc
1417 = XCreateGC (NULL, s->window, mask, &xgcv);
1418
1419 s->gc = FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc;
1420 }
1421
1422 xassert (s->gc != 0);
1423 }
1424
1425
1426 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
1427 Faces to use in the mode line have already been computed when the
1428 matrix was built, so there isn't much to do, here. */
1429
1430 static INLINE void
1431 x_set_mode_line_face_gc (s)
1432 struct glyph_string *s;
1433 {
1434 s->gc = s->face->gc;
1435 }
1436
1437
1438 /* Set S->gc of glyph string S for drawing that glyph string. Set
1439 S->stippled_p to a non-zero value if the face of S has a stipple
1440 pattern. */
1441
1442 static INLINE void
1443 x_set_glyph_string_gc (s)
1444 struct glyph_string *s;
1445 {
1446 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
1447
1448 if (s->hl == DRAW_NORMAL_TEXT)
1449 {
1450 s->gc = s->face->gc;
1451 s->stippled_p = s->face->stipple != 0;
1452 }
1453 else if (s->hl == DRAW_INVERSE_VIDEO)
1454 {
1455 x_set_mode_line_face_gc (s);
1456 s->stippled_p = s->face->stipple != 0;
1457 }
1458 else if (s->hl == DRAW_CURSOR)
1459 {
1460 x_set_cursor_gc (s);
1461 s->stippled_p = 0;
1462 }
1463 else if (s->hl == DRAW_MOUSE_FACE)
1464 {
1465 x_set_mouse_face_gc (s);
1466 s->stippled_p = s->face->stipple != 0;
1467 }
1468 else if (s->hl == DRAW_IMAGE_RAISED
1469 || s->hl == DRAW_IMAGE_SUNKEN)
1470 {
1471 s->gc = s->face->gc;
1472 s->stippled_p = s->face->stipple != 0;
1473 }
1474 else
1475 {
1476 s->gc = s->face->gc;
1477 s->stippled_p = s->face->stipple != 0;
1478 }
1479
1480 /* GC must have been set. */
1481 xassert (s->gc != 0);
1482 }
1483
1484
1485 /* Return in *R the clipping rectangle for glyph string S. */
1486
1487 static void
1488 w32_get_glyph_string_clip_rect (s, r)
1489 struct glyph_string *s;
1490 RECT *r;
1491 {
1492 int r_height, r_width;
1493
1494 if (s->row->full_width_p)
1495 {
1496 /* Draw full-width. X coordinates are relative to S->w->left. */
1497 int canon_x = CANON_X_UNIT (s->f);
1498
1499 r->left = WINDOW_LEFT_MARGIN (s->w) * canon_x;
1500 r_width = XFASTINT (s->w->width) * canon_x;
1501
1502 if (FRAME_HAS_VERTICAL_SCROLL_BARS (s->f))
1503 {
1504 int width = FRAME_SCROLL_BAR_WIDTH (s->f) * canon_x;
1505 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (s->f))
1506 r->left -= width;
1507 }
1508
1509 r->left += FRAME_INTERNAL_BORDER_WIDTH (s->f);
1510
1511 /* Unless displaying a mode or menu bar line, which are always
1512 fully visible, clip to the visible part of the row. */
1513 if (s->w->pseudo_window_p)
1514 r_height = s->row->visible_height;
1515 else
1516 r_height = s->height;
1517 }
1518 else
1519 {
1520 /* This is a text line that may be partially visible. */
1521 r->left = WINDOW_AREA_TO_FRAME_PIXEL_X (s->w, s->area, 0);
1522 r_width = window_box_width (s->w, s->area);
1523 r_height = s->row->visible_height;
1524 }
1525
1526 /* If S draws overlapping rows, it's sufficient to use the top and
1527 bottom of the window for clipping because this glyph string
1528 intentionally draws over other lines. */
1529 if (s->for_overlaps_p)
1530 {
1531 r->top = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
1532 r_height = window_text_bottom_y (s->w) - r->top;
1533 }
1534 else
1535 {
1536 /* Don't use S->y for clipping because it doesn't take partially
1537 visible lines into account. For example, it can be negative for
1538 partially visible lines at the top of a window. */
1539 if (!s->row->full_width_p
1540 && MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (s->w, s->row))
1541 r->top = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
1542 else
1543 r->top = max (0, s->row->y);
1544
1545 /* If drawing a tool-bar window, draw it over the internal border
1546 at the top of the window. */
1547 if (s->w == XWINDOW (s->f->tool_bar_window))
1548 r->top -= s->f->output_data.w32->internal_border_width;
1549 }
1550
1551 r->top = WINDOW_TO_FRAME_PIXEL_Y (s->w, r->top);
1552
1553 /* If drawing the cursor, don't let glyph draw outside its
1554 advertised boundaries. Cleartype does this under some circumstances. */
1555 if (s->hl == DRAW_CURSOR)
1556 {
1557 if (s->x > r->left)
1558 {
1559 r_width -= s->x - r->left;
1560 r->left = s->x;
1561 }
1562 r_width = min (r_width, s->first_glyph->pixel_width);
1563 }
1564
1565 r->bottom = r->top + r_height;
1566 r->right = r->left + r_width;
1567 }
1568
1569
1570 /* Set clipping for output of glyph string S. S may be part of a mode
1571 line or menu if we don't have X toolkit support. */
1572
1573 static INLINE void
1574 x_set_glyph_string_clipping (s)
1575 struct glyph_string *s;
1576 {
1577 RECT r;
1578 w32_get_glyph_string_clip_rect (s, &r);
1579 w32_set_clip_rectangle (s->hdc, &r);
1580 }
1581
1582
1583 /* RIF:
1584 Compute left and right overhang of glyph string S. If S is a glyph
1585 string for a composition, assume overhangs don't exist. */
1586
1587 static void
1588 w32_compute_glyph_string_overhangs (s)
1589 struct glyph_string *s;
1590 {
1591 /* TODO: Windows does not appear to have a method for
1592 getting this info without getting the ABC widths for each
1593 individual character and working it out manually. */
1594 }
1595
1596
1597 static void
1598 w32_get_glyph_overhangs (glyph, f, left, right)
1599 struct glyph *glyph;
1600 struct frame *f;
1601 int *left, *right;
1602 {
1603 HDC hdc = get_frame_dc (f);
1604 /* Convert to unicode! */
1605 x_get_glyph_overhangs (glyph, f, left, right);
1606 release_frame_dc (f, hdc);
1607 }
1608
1609
1610 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
1611
1612 static INLINE void
1613 x_clear_glyph_string_rect (s, x, y, w, h)
1614 struct glyph_string *s;
1615 int x, y, w, h;
1616 {
1617 int real_x = x;
1618 int real_y = y;
1619 int real_w = w;
1620 int real_h = h;
1621 #if 0
1622 /* Take clipping into account. */
1623 if (s->gc->clip_mask == Rect)
1624 {
1625 real_x = max (real_x, s->gc->clip_rectangle.left);
1626 real_y = max (real_y, s->gc->clip_rectangle.top);
1627 real_w = min (real_w, s->gc->clip_rectangle.right
1628 - s->gc->clip_rectangle.left);
1629 real_h = min (real_h, s->gc->clip_rectangle.bottom
1630 - s->gc->clip_rectangle.top);
1631 }
1632 #endif
1633 w32_fill_area (s->f, s->hdc, s->gc->background, real_x, real_y,
1634 real_w, real_h);
1635 }
1636
1637
1638 /* Draw the background of glyph_string S. If S->background_filled_p
1639 is non-zero don't draw it. FORCE_P non-zero means draw the
1640 background even if it wouldn't be drawn normally. This is used
1641 when a string preceding S draws into the background of S, or S
1642 contains the first component of a composition. */
1643
1644 static void
1645 x_draw_glyph_string_background (s, force_p)
1646 struct glyph_string *s;
1647 int force_p;
1648 {
1649 /* Nothing to do if background has already been drawn or if it
1650 shouldn't be drawn in the first place. */
1651 if (!s->background_filled_p)
1652 {
1653 int box_line_width = max (s->face->box_line_width, 0);
1654
1655 #if 0 /* TODO: stipple */
1656 if (s->stippled_p)
1657 {
1658 /* Fill background with a stipple pattern. */
1659 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
1660 XFillRectangle (s->display, s->window, s->gc, s->x,
1661 s->y + box_line_width,
1662 s->background_width,
1663 s->height - 2 * box_line_width);
1664 XSetFillStyle (s->display, s->gc, FillSolid);
1665 s->background_filled_p = 1;
1666 }
1667 else
1668 #endif
1669 if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
1670 || s->font_not_found_p
1671 || s->extends_to_end_of_line_p
1672 || s->font->bdf
1673 || force_p)
1674 {
1675 x_clear_glyph_string_rect (s, s->x, s->y + box_line_width,
1676 s->background_width,
1677 s->height - 2 * box_line_width);
1678 s->background_filled_p = 1;
1679 }
1680 }
1681 }
1682
1683
1684 /* Draw the foreground of glyph string S. */
1685
1686 static void
1687 x_draw_glyph_string_foreground (s)
1688 struct glyph_string *s;
1689 {
1690 int i, x;
1691 HFONT old_font;
1692
1693 /* If first glyph of S has a left box line, start drawing the text
1694 of S to the right of that box line. */
1695 if (s->face->box != FACE_NO_BOX
1696 && s->first_glyph->left_box_line_p)
1697 x = s->x + abs (s->face->box_line_width);
1698 else
1699 x = s->x;
1700
1701 if (s->for_overlaps_p || (s->background_filled_p && s->hl != DRAW_CURSOR))
1702 SetBkMode (s->hdc, TRANSPARENT);
1703 else
1704 SetBkMode (s->hdc, OPAQUE);
1705
1706 SetTextColor (s->hdc, s->gc->foreground);
1707 SetBkColor (s->hdc, s->gc->background);
1708 SetTextAlign (s->hdc, TA_BASELINE | TA_LEFT);
1709
1710 if (s->font && s->font->hfont)
1711 old_font = SelectObject (s->hdc, s->font->hfont);
1712
1713 /* Draw characters of S as rectangles if S's font could not be
1714 loaded. */
1715 if (s->font_not_found_p)
1716 {
1717 for (i = 0; i < s->nchars; ++i)
1718 {
1719 struct glyph *g = s->first_glyph + i;
1720
1721 w32_draw_rectangle (s->hdc, s->gc, x, s->y, g->pixel_width - 1,
1722 s->height - 1);
1723 x += g->pixel_width;
1724 }
1725 }
1726 else
1727 {
1728 char *char1b = (char *) s->char2b;
1729 int boff = s->font_info->baseline_offset;
1730
1731 if (s->font_info->vertical_centering)
1732 boff = VCENTER_BASELINE_OFFSET (s->font, s->f) - boff;
1733
1734 /* If we can use 8-bit functions, condense S->char2b. */
1735 if (!s->two_byte_p)
1736 for (i = 0; i < s->nchars; ++i)
1737 char1b[i] = XCHAR2B_BYTE2 (&s->char2b[i]);
1738
1739 /* Draw text with TextOut and friends. */
1740 w32_text_out (s, x, s->ybase - boff, s->char2b, s->nchars);
1741
1742 if (s->face->overstrike)
1743 {
1744 /* For overstriking (to simulate bold-face), draw the
1745 characters again shifted to the right by one pixel. */
1746 w32_text_out (s, x + 1, s->ybase - boff, s->char2b, s->nchars);
1747 }
1748 }
1749 if (s->font && s->font->hfont)
1750 SelectObject (s->hdc, old_font);
1751 }
1752
1753 /* Draw the foreground of composite glyph string S. */
1754
1755 static void
1756 x_draw_composite_glyph_string_foreground (s)
1757 struct glyph_string *s;
1758 {
1759 int i, x;
1760 HFONT old_font;
1761
1762 /* If first glyph of S has a left box line, start drawing the text
1763 of S to the right of that box line. */
1764 if (s->face->box != FACE_NO_BOX
1765 && s->first_glyph->left_box_line_p)
1766 x = s->x + abs (s->face->box_line_width);
1767 else
1768 x = s->x;
1769
1770 /* S is a glyph string for a composition. S->gidx is the index of
1771 the first character drawn for glyphs of this composition.
1772 S->gidx == 0 means we are drawing the very first character of
1773 this composition. */
1774
1775 SetTextColor (s->hdc, s->gc->foreground);
1776 SetBkColor (s->hdc, s->gc->background);
1777 SetBkMode (s->hdc, TRANSPARENT);
1778 SetTextAlign (s->hdc, TA_BASELINE | TA_LEFT);
1779
1780 if (s->font && s->font->hfont)
1781 old_font = SelectObject (s->hdc, s->font->hfont);
1782
1783 /* Draw a rectangle for the composition if the font for the very
1784 first character of the composition could not be loaded. */
1785 if (s->font_not_found_p)
1786 {
1787 if (s->gidx == 0)
1788 w32_draw_rectangle (s->hdc, s->gc, x, s->y, s->width - 1,
1789 s->height - 1);
1790 }
1791 else
1792 {
1793 for (i = 0; i < s->nchars; i++, ++s->gidx)
1794 {
1795 w32_text_out (s, x + s->cmp->offsets[s->gidx * 2],
1796 s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
1797 s->char2b + i, 1);
1798 if (s->face->overstrike)
1799 w32_text_out (s, x + s->cmp->offsets[s->gidx * 2] + 1,
1800 s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
1801 s->char2b + i, 1);
1802 }
1803 }
1804
1805 if (s->font && s->font->hfont)
1806 SelectObject (s->hdc, old_font);
1807 }
1808
1809
1810 /* Brightness beyond which a color won't have its highlight brightness
1811 boosted.
1812
1813 Nominally, highlight colors for `3d' faces are calculated by
1814 brightening an object's color by a constant scale factor, but this
1815 doesn't yield good results for dark colors, so for colors who's
1816 brightness is less than this value (on a scale of 0-255) have to
1817 use an additional additive factor.
1818
1819 The value here is set so that the default menu-bar/mode-line color
1820 (grey75) will not have its highlights changed at all. */
1821 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 187
1822
1823
1824 /* Allocate a color which is lighter or darker than *COLOR by FACTOR
1825 or DELTA. Try a color with RGB values multiplied by FACTOR first.
1826 If this produces the same color as COLOR, try a color where all RGB
1827 values have DELTA added. Return the allocated color in *COLOR.
1828 DISPLAY is the X display, CMAP is the colormap to operate on.
1829 Value is non-zero if successful. */
1830
1831 static int
1832 w32_alloc_lighter_color (f, color, factor, delta)
1833 struct frame *f;
1834 COLORREF *color;
1835 double factor;
1836 int delta;
1837 {
1838 COLORREF new;
1839 long bright;
1840
1841 /* On Windows, RGB values are 0-255, not 0-65535, so scale delta. */
1842 delta /= 256;
1843
1844 /* Change RGB values by specified FACTOR. Avoid overflow! */
1845 xassert (factor >= 0);
1846 new = PALETTERGB (min (0xff, factor * GetRValue (*color)),
1847 min (0xff, factor * GetGValue (*color)),
1848 min (0xff, factor * GetBValue (*color)));
1849
1850 /* Calculate brightness of COLOR. */
1851 bright = (2 * GetRValue (*color) + 3 * GetGValue (*color)
1852 + GetBValue (*color)) / 6;
1853
1854 /* We only boost colors that are darker than
1855 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
1856 if (bright < HIGHLIGHT_COLOR_DARK_BOOST_LIMIT)
1857 /* Make an additive adjustment to NEW, because it's dark enough so
1858 that scaling by FACTOR alone isn't enough. */
1859 {
1860 /* How far below the limit this color is (0 - 1, 1 being darker). */
1861 double dimness = 1 - (double)bright / HIGHLIGHT_COLOR_DARK_BOOST_LIMIT;
1862 /* The additive adjustment. */
1863 int min_delta = delta * dimness * factor / 2;
1864
1865 if (factor < 1)
1866 new = PALETTERGB (max (0, min (0xff, min_delta - GetRValue (*color))),
1867 max (0, min (0xff, min_delta - GetGValue (*color))),
1868 max (0, min (0xff, min_delta - GetBValue (*color))));
1869 else
1870 new = PALETTERGB (max (0, min (0xff, min_delta + GetRValue (*color))),
1871 max (0, min (0xff, min_delta + GetGValue (*color))),
1872 max (0, min (0xff, min_delta + GetBValue (*color))));
1873 }
1874
1875 if (new == *color)
1876 new = PALETTERGB (max (0, min (0xff, delta + GetRValue (*color))),
1877 max (0, min (0xff, delta + GetGValue (*color))),
1878 max (0, min (0xff, delta + GetBValue (*color))));
1879
1880 /* TODO: Map to palette and retry with delta if same? */
1881 /* TODO: Free colors (if using palette)? */
1882
1883 if (new == *color)
1884 return 0;
1885
1886 *color = new;
1887
1888 return 1;
1889 }
1890
1891
1892 /* Set up the foreground color for drawing relief lines of glyph
1893 string S. RELIEF is a pointer to a struct relief containing the GC
1894 with which lines will be drawn. Use a color that is FACTOR or
1895 DELTA lighter or darker than the relief's background which is found
1896 in S->f->output_data.x->relief_background. If such a color cannot
1897 be allocated, use DEFAULT_PIXEL, instead. */
1898
1899 static void
1900 w32_setup_relief_color (f, relief, factor, delta, default_pixel)
1901 struct frame *f;
1902 struct relief *relief;
1903 double factor;
1904 int delta;
1905 COLORREF default_pixel;
1906 {
1907 XGCValues xgcv;
1908 struct w32_output *di = f->output_data.w32;
1909 unsigned long mask = GCForeground;
1910 COLORREF pixel;
1911 COLORREF background = di->relief_background;
1912 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
1913
1914 /* TODO: Free colors (if using palette)? */
1915
1916 /* Allocate new color. */
1917 xgcv.foreground = default_pixel;
1918 pixel = background;
1919 if (w32_alloc_lighter_color (f, &pixel, factor, delta))
1920 {
1921 relief->allocated_p = 1;
1922 xgcv.foreground = relief->pixel = pixel;
1923 }
1924
1925 if (relief->gc == 0)
1926 {
1927 #if 0 /* TODO: stipple */
1928 xgcv.stipple = dpyinfo->gray;
1929 mask |= GCStipple;
1930 #endif
1931 relief->gc = XCreateGC (NULL, FRAME_W32_WINDOW (f), mask, &xgcv);
1932 }
1933 else
1934 XChangeGC (NULL, relief->gc, mask, &xgcv);
1935 }
1936
1937
1938 /* Set up colors for the relief lines around glyph string S. */
1939
1940 static void
1941 x_setup_relief_colors (s)
1942 struct glyph_string *s;
1943 {
1944 struct w32_output *di = s->f->output_data.w32;
1945 COLORREF color;
1946
1947 if (s->face->use_box_color_for_shadows_p)
1948 color = s->face->box_color;
1949 else if (s->first_glyph->type == IMAGE_GLYPH
1950 && s->img->pixmap
1951 && !IMAGE_BACKGROUND_TRANSPARENT (s->img, s->f, 0))
1952 color = IMAGE_BACKGROUND (s->img, s->f, 0);
1953 else
1954 color = s->gc->background;
1955
1956 if (di->white_relief.gc == 0
1957 || color != di->relief_background)
1958 {
1959 di->relief_background = color;
1960 w32_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
1961 WHITE_PIX_DEFAULT (s->f));
1962 w32_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
1963 BLACK_PIX_DEFAULT (s->f));
1964 }
1965 }
1966
1967
1968 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
1969 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
1970 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
1971 relief. LEFT_P non-zero means draw a relief on the left side of
1972 the rectangle. RIGHT_P non-zero means draw a relief on the right
1973 side of the rectangle. CLIP_RECT is the clipping rectangle to use
1974 when drawing. */
1975
1976 static void
1977 w32_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
1978 raised_p, left_p, right_p, clip_rect)
1979 struct frame *f;
1980 int left_x, top_y, right_x, bottom_y, width, left_p, right_p, raised_p;
1981 RECT *clip_rect;
1982 {
1983 int i;
1984 XGCValues gc;
1985 HDC hdc = get_frame_dc (f);
1986
1987 if (raised_p)
1988 gc.foreground = f->output_data.w32->white_relief.gc->foreground;
1989 else
1990 gc.foreground = f->output_data.w32->black_relief.gc->foreground;
1991
1992 w32_set_clip_rectangle (hdc, clip_rect);
1993
1994 /* Top. */
1995 for (i = 0; i < width; ++i)
1996 w32_fill_area (f, hdc, gc.foreground,
1997 left_x + i * left_p, top_y + i,
1998 right_x - left_x - i * (left_p + right_p ) + 1, 1);
1999
2000 /* Left. */
2001 if (left_p)
2002 for (i = 0; i < width; ++i)
2003 w32_fill_area (f, hdc, gc.foreground,
2004 left_x + i, top_y + i, 1,
2005 bottom_y - top_y - 2 * i + 1);
2006
2007 if (raised_p)
2008 gc.foreground = f->output_data.w32->black_relief.gc->foreground;
2009 else
2010 gc.foreground = f->output_data.w32->white_relief.gc->foreground;
2011
2012 /* Bottom. */
2013 for (i = 0; i < width; ++i)
2014 w32_fill_area (f, hdc, gc.foreground,
2015 left_x + i * left_p, bottom_y - i,
2016 right_x - left_x - i * (left_p + right_p) + 1, 1);
2017
2018 /* Right. */
2019 if (right_p)
2020 for (i = 0; i < width; ++i)
2021 w32_fill_area (f, hdc, gc.foreground,
2022 right_x - i, top_y + i + 1, 1,
2023 bottom_y - top_y - 2 * i - 1);
2024
2025 w32_set_clip_rectangle (hdc, NULL);
2026
2027 release_frame_dc (f, hdc);
2028 }
2029
2030
2031 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
2032 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
2033 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
2034 left side of the rectangle. RIGHT_P non-zero means draw a line
2035 on the right side of the rectangle. CLIP_RECT is the clipping
2036 rectangle to use when drawing. */
2037
2038 static void
2039 w32_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
2040 left_p, right_p, clip_rect)
2041 struct glyph_string *s;
2042 int left_x, top_y, right_x, bottom_y, width, left_p, right_p;
2043 RECT *clip_rect;
2044 {
2045 w32_set_clip_rectangle (s->hdc, clip_rect);
2046
2047 /* Top. */
2048 w32_fill_area (s->f, s->hdc, s->face->box_color,
2049 left_x, top_y, right_x - left_x + 1, width);
2050
2051 /* Left. */
2052 if (left_p)
2053 {
2054 w32_fill_area (s->f, s->hdc, s->face->box_color,
2055 left_x, top_y, width, bottom_y - top_y + 1);
2056 }
2057
2058 /* Bottom. */
2059 w32_fill_area (s->f, s->hdc, s->face->box_color,
2060 left_x, bottom_y - width + 1, right_x - left_x + 1, width);
2061
2062 /* Right. */
2063 if (right_p)
2064 {
2065 w32_fill_area (s->f, s->hdc, s->face->box_color,
2066 right_x - width + 1, top_y, width, bottom_y - top_y + 1);
2067 }
2068
2069 w32_set_clip_rectangle (s->hdc, NULL);
2070 }
2071
2072
2073 /* Draw a box around glyph string S. */
2074
2075 static void
2076 x_draw_glyph_string_box (s)
2077 struct glyph_string *s;
2078 {
2079 int width, left_x, right_x, top_y, bottom_y, last_x, raised_p;
2080 int left_p, right_p;
2081 struct glyph *last_glyph;
2082 RECT clip_rect;
2083
2084 last_x = window_box_right (s->w, s->area);
2085 if (s->row->full_width_p
2086 && !s->w->pseudo_window_p)
2087 {
2088 last_x += FRAME_X_RIGHT_FRINGE_WIDTH (s->f);
2089 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (s->f))
2090 last_x += FRAME_SCROLL_BAR_WIDTH (s->f) * CANON_X_UNIT (s->f);
2091 }
2092
2093 /* The glyph that may have a right box line. */
2094 last_glyph = (s->cmp || s->img
2095 ? s->first_glyph
2096 : s->first_glyph + s->nchars - 1);
2097
2098 width = abs (s->face->box_line_width);
2099 raised_p = s->face->box == FACE_RAISED_BOX;
2100 left_x = s->x;
2101 right_x = ((s->row->full_width_p && s->extends_to_end_of_line_p
2102 ? last_x - 1
2103 : min (last_x, s->x + s->background_width) - 1));
2104 top_y = s->y;
2105 bottom_y = top_y + s->height - 1;
2106
2107 left_p = (s->first_glyph->left_box_line_p
2108 || (s->hl == DRAW_MOUSE_FACE
2109 && (s->prev == NULL
2110 || s->prev->hl != s->hl)));
2111 right_p = (last_glyph->right_box_line_p
2112 || (s->hl == DRAW_MOUSE_FACE
2113 && (s->next == NULL
2114 || s->next->hl != s->hl)));
2115
2116 w32_get_glyph_string_clip_rect (s, &clip_rect);
2117
2118 if (s->face->box == FACE_SIMPLE_BOX)
2119 w32_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
2120 left_p, right_p, &clip_rect);
2121 else
2122 {
2123 x_setup_relief_colors (s);
2124 w32_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
2125 width, raised_p, left_p, right_p, &clip_rect);
2126 }
2127 }
2128
2129
2130 /* Draw foreground of image glyph string S. */
2131
2132 static void
2133 x_draw_image_foreground (s)
2134 struct glyph_string *s;
2135 {
2136 int x;
2137 int y = s->ybase - image_ascent (s->img, s->face);
2138
2139 /* If first glyph of S has a left box line, start drawing it to the
2140 right of that line. */
2141 if (s->face->box != FACE_NO_BOX
2142 && s->first_glyph->left_box_line_p)
2143 x = s->x + abs (s->face->box_line_width);
2144 else
2145 x = s->x;
2146
2147 /* If there is a margin around the image, adjust x- and y-position
2148 by that margin. */
2149 x += s->img->hmargin;
2150 y += s->img->vmargin;
2151
2152 SaveDC (s->hdc);
2153
2154 if (s->img->pixmap)
2155 {
2156 HDC compat_hdc = CreateCompatibleDC (s->hdc);
2157 HBRUSH fg_brush = CreateSolidBrush (s->gc->foreground);
2158 HBRUSH orig_brush = SelectObject (s->hdc, fg_brush);
2159 HGDIOBJ orig_obj = SelectObject (compat_hdc, s->img->pixmap);
2160 SetBkColor (compat_hdc, RGB (255, 255, 255));
2161 SetTextColor (s->hdc, RGB (0, 0, 0));
2162 x_set_glyph_string_clipping (s);
2163
2164 if (s->img->mask)
2165 {
2166 HDC mask_dc = CreateCompatibleDC (s->hdc);
2167 HGDIOBJ mask_orig_obj = SelectObject (mask_dc, s->img->mask);
2168
2169 SetTextColor (s->hdc, RGB (255, 255, 255));
2170 SetBkColor (s->hdc, RGB (0, 0, 0));
2171
2172 BitBlt (s->hdc, x, y, s->img->width, s->img->height,
2173 compat_hdc, 0, 0, SRCINVERT);
2174 BitBlt (s->hdc, x, y, s->img->width, s->img->height,
2175 mask_dc, 0, 0, SRCAND);
2176 BitBlt (s->hdc, x, y, s->img->width, s->img->height,
2177 compat_hdc, 0, 0, SRCINVERT);
2178
2179 SelectObject (mask_dc, mask_orig_obj);
2180 DeleteDC (mask_dc);
2181 }
2182 else
2183 {
2184 SetTextColor (s->hdc, s->gc->foreground);
2185 SetBkColor (s->hdc, s->gc->background);
2186
2187 BitBlt (s->hdc, x, y, s->img->width, s->img->height,
2188 compat_hdc, 0, 0, SRCCOPY);
2189
2190 /* When the image has a mask, we can expect that at
2191 least part of a mouse highlight or a block cursor will
2192 be visible. If the image doesn't have a mask, make
2193 a block cursor visible by drawing a rectangle around
2194 the image. I believe it's looking better if we do
2195 nothing here for mouse-face. */
2196 if (s->hl == DRAW_CURSOR)
2197 {
2198 int r = s->img->relief;
2199 if (r < 0) r = -r;
2200 w32_draw_rectangle (s->hdc, s->gc, x - r, y - r ,
2201 s->img->width + r*2 - 1, s->img->height + r*2 - 1);
2202 }
2203 }
2204
2205 w32_set_clip_rectangle (s->hdc, NULL);
2206 SelectObject (s->hdc, orig_brush);
2207 DeleteObject (fg_brush);
2208 SelectObject (compat_hdc, orig_obj);
2209 DeleteDC (compat_hdc);
2210 }
2211 else
2212 w32_draw_rectangle (s->hdc, s->gc, x, y, s->img->width -1,
2213 s->img->height - 1);
2214
2215 RestoreDC (s->hdc ,-1);
2216 }
2217
2218
2219
2220 /* Draw a relief around the image glyph string S. */
2221
2222 static void
2223 x_draw_image_relief (s)
2224 struct glyph_string *s;
2225 {
2226 int x0, y0, x1, y1, thick, raised_p;
2227 RECT r;
2228 int x;
2229 int y = s->ybase - image_ascent (s->img, s->face);
2230
2231 /* If first glyph of S has a left box line, start drawing it to the
2232 right of that line. */
2233 if (s->face->box != FACE_NO_BOX
2234 && s->first_glyph->left_box_line_p)
2235 x = s->x + abs (s->face->box_line_width);
2236 else
2237 x = s->x;
2238
2239 /* If there is a margin around the image, adjust x- and y-position
2240 by that margin. */
2241 x += s->img->hmargin;
2242 y += s->img->vmargin;
2243
2244 if (s->hl == DRAW_IMAGE_SUNKEN
2245 || s->hl == DRAW_IMAGE_RAISED)
2246 {
2247 thick = tool_bar_button_relief >= 0 ? tool_bar_button_relief : DEFAULT_TOOL_BAR_BUTTON_RELIEF;
2248 raised_p = s->hl == DRAW_IMAGE_RAISED;
2249 }
2250 else
2251 {
2252 thick = abs (s->img->relief);
2253 raised_p = s->img->relief > 0;
2254 }
2255
2256 x0 = x - thick;
2257 y0 = y - thick;
2258 x1 = x + s->img->width + thick - 1;
2259 y1 = y + s->img->height + thick - 1;
2260
2261 x_setup_relief_colors (s);
2262 w32_get_glyph_string_clip_rect (s, &r);
2263 w32_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p, 1, 1, &r);
2264 }
2265
2266
2267 /* Draw the foreground of image glyph string S to PIXMAP. */
2268
2269 static void
2270 w32_draw_image_foreground_1 (s, pixmap)
2271 struct glyph_string *s;
2272 HBITMAP pixmap;
2273 {
2274 HDC hdc = CreateCompatibleDC (s->hdc);
2275 HGDIOBJ orig_hdc_obj = SelectObject (hdc, pixmap);
2276 int x;
2277 int y = s->ybase - s->y - image_ascent (s->img, s->face);
2278
2279 /* If first glyph of S has a left box line, start drawing it to the
2280 right of that line. */
2281 if (s->face->box != FACE_NO_BOX
2282 && s->first_glyph->left_box_line_p)
2283 x = abs (s->face->box_line_width);
2284 else
2285 x = 0;
2286
2287 /* If there is a margin around the image, adjust x- and y-position
2288 by that margin. */
2289 x += s->img->hmargin;
2290 y += s->img->vmargin;
2291
2292 if (s->img->pixmap)
2293 {
2294 HDC compat_hdc = CreateCompatibleDC (hdc);
2295 HBRUSH fg_brush = CreateSolidBrush (s->gc->foreground);
2296 HBRUSH orig_brush = SelectObject (hdc, fg_brush);
2297 HGDIOBJ orig_obj = SelectObject (compat_hdc, s->img->pixmap);
2298
2299 if (s->img->mask)
2300 {
2301 HDC mask_dc = CreateCompatibleDC (hdc);
2302 HGDIOBJ mask_orig_obj = SelectObject (mask_dc, s->img->mask);
2303
2304 SetTextColor (hdc, RGB (0, 0, 0));
2305 SetBkColor (hdc, RGB (255, 255, 255));
2306 BitBlt (hdc, x, y, s->img->width, s->img->height,
2307 compat_hdc, 0, 0, SRCINVERT);
2308 BitBlt (hdc, x, y, s->img->width, s->img->height,
2309 mask_dc, 0, 0, SRCAND);
2310 BitBlt (hdc, x, y, s->img->width, s->img->height,
2311 compat_hdc, 0, 0, SRCINVERT);
2312
2313 SelectObject (mask_dc, mask_orig_obj);
2314 DeleteDC (mask_dc);
2315 }
2316 else
2317 {
2318 SetTextColor (hdc, s->gc->foreground);
2319 SetBkColor (hdc, s->gc->background);
2320
2321 BitBlt (hdc, x, y, s->img->width, s->img->height,
2322 compat_hdc, 0, 0, SRCCOPY);
2323
2324 /* When the image has a mask, we can expect that at
2325 least part of a mouse highlight or a block cursor will
2326 be visible. If the image doesn't have a mask, make
2327 a block cursor visible by drawing a rectangle around
2328 the image. I believe it's looking better if we do
2329 nothing here for mouse-face. */
2330 if (s->hl == DRAW_CURSOR)
2331 {
2332 int r = s->img->relief;
2333 if (r < 0) r = -r;
2334 w32_draw_rectangle (hdc, s->gc, x - r, y - r ,
2335 s->img->width + r*2 - 1, s->img->height + r*2 - 1);
2336 }
2337 }
2338
2339 SelectObject (hdc, orig_brush);
2340 DeleteObject (fg_brush);
2341 SelectObject (compat_hdc, orig_obj);
2342 DeleteDC (compat_hdc);
2343 }
2344 else
2345 w32_draw_rectangle (hdc, s->gc, x, y, s->img->width - 1,
2346 s->img->height - 1);
2347
2348 SelectObject (hdc, orig_hdc_obj);
2349 DeleteDC (hdc);
2350 }
2351
2352
2353 /* Draw part of the background of glyph string S. X, Y, W, and H
2354 give the rectangle to draw. */
2355
2356 static void
2357 x_draw_glyph_string_bg_rect (s, x, y, w, h)
2358 struct glyph_string *s;
2359 int x, y, w, h;
2360 {
2361 #if 0 /* TODO: stipple */
2362 if (s->stippled_p)
2363 {
2364 /* Fill background with a stipple pattern. */
2365 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
2366 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
2367 XSetFillStyle (s->display, s->gc, FillSolid);
2368 }
2369 else
2370 #endif
2371 x_clear_glyph_string_rect (s, x, y, w, h);
2372 }
2373
2374
2375 /* Draw image glyph string S.
2376
2377 s->y
2378 s->x +-------------------------
2379 | s->face->box
2380 |
2381 | +-------------------------
2382 | | s->img->vmargin
2383 | |
2384 | | +-------------------
2385 | | | the image
2386
2387 */
2388
2389 static void
2390 x_draw_image_glyph_string (s)
2391 struct glyph_string *s;
2392 {
2393 int x, y;
2394 int box_line_hwidth = abs (s->face->box_line_width);
2395 int box_line_vwidth = max (s->face->box_line_width, 0);
2396 int height;
2397 HBITMAP pixmap = 0;
2398
2399 height = s->height - 2 * box_line_vwidth;
2400
2401 /* Fill background with face under the image. Do it only if row is
2402 taller than image or if image has a clip mask to reduce
2403 flickering. */
2404 s->stippled_p = s->face->stipple != 0;
2405 if (height > s->img->height
2406 || s->img->hmargin
2407 || s->img->vmargin
2408 || s->img->mask
2409 || s->img->pixmap == 0
2410 || s->width != s->background_width)
2411 {
2412 if (box_line_hwidth && s->first_glyph->left_box_line_p)
2413 x = s->x + box_line_hwidth;
2414 else
2415 x = s->x;
2416
2417 y = s->y + box_line_vwidth;
2418 #if 0 /* TODO: figure out if we need to do this on Windows. */
2419 if (s->img->mask)
2420 {
2421 /* Create a pixmap as large as the glyph string. Fill it
2422 with the background color. Copy the image to it, using
2423 its mask. Copy the temporary pixmap to the display. */
2424 Screen *screen = FRAME_X_SCREEN (s->f);
2425 int depth = DefaultDepthOfScreen (screen);
2426
2427 /* Create a pixmap as large as the glyph string. */
2428 pixmap = XCreatePixmap (s->display, s->window,
2429 s->background_width,
2430 s->height, depth);
2431
2432 /* Don't clip in the following because we're working on the
2433 pixmap. */
2434 XSetClipMask (s->display, s->gc, None);
2435
2436 /* Fill the pixmap with the background color/stipple. */
2437 if (s->stippled_p)
2438 {
2439 /* Fill background with a stipple pattern. */
2440 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
2441 XFillRectangle (s->display, pixmap, s->gc,
2442 0, 0, s->background_width, s->height);
2443 XSetFillStyle (s->display, s->gc, FillSolid);
2444 }
2445 else
2446 {
2447 XGCValues xgcv;
2448 XGetGCValues (s->display, s->gc, GCForeground | GCBackground,
2449 &xgcv);
2450 XSetForeground (s->display, s->gc, xgcv.background);
2451 XFillRectangle (s->display, pixmap, s->gc,
2452 0, 0, s->background_width, s->height);
2453 XSetForeground (s->display, s->gc, xgcv.foreground);
2454 }
2455 }
2456 else
2457 #endif
2458 x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
2459
2460 s->background_filled_p = 1;
2461 }
2462
2463 /* Draw the foreground. */
2464 if (pixmap != 0)
2465 {
2466 w32_draw_image_foreground_1 (s, pixmap);
2467 x_set_glyph_string_clipping (s);
2468 {
2469 HDC compat_hdc = CreateCompatibleDC (s->hdc);
2470 HBRUSH fg_brush = CreateSolidBrush (s->gc->foreground);
2471 HBRUSH orig_brush = SelectObject (s->hdc, fg_brush);
2472 HGDIOBJ orig_obj = SelectObject (compat_hdc, pixmap);
2473
2474 SetTextColor (s->hdc, s->gc->foreground);
2475 SetBkColor (s->hdc, s->gc->background);
2476 BitBlt (s->hdc, s->x, s->y, s->background_width, s->height,
2477 compat_hdc, 0, 0, SRCCOPY);
2478
2479 SelectObject (s->hdc, orig_brush);
2480 DeleteObject (fg_brush);
2481 SelectObject (compat_hdc, orig_obj);
2482 DeleteDC (compat_hdc);
2483 }
2484 DeleteObject (pixmap);
2485 pixmap = 0;
2486 }
2487 else
2488 x_draw_image_foreground (s);
2489
2490 /* If we must draw a relief around the image, do it. */
2491 if (s->img->relief
2492 || s->hl == DRAW_IMAGE_RAISED
2493 || s->hl == DRAW_IMAGE_SUNKEN)
2494 x_draw_image_relief (s);
2495 }
2496
2497
2498 /* Draw stretch glyph string S. */
2499
2500 static void
2501 x_draw_stretch_glyph_string (s)
2502 struct glyph_string *s;
2503 {
2504 xassert (s->first_glyph->type == STRETCH_GLYPH);
2505 s->stippled_p = s->face->stipple != 0;
2506
2507 if (s->hl == DRAW_CURSOR
2508 && !x_stretch_cursor_p)
2509 {
2510 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
2511 as wide as the stretch glyph. */
2512 int width = min (CANON_X_UNIT (s->f), s->background_width);
2513
2514 /* Draw cursor. */
2515 x_draw_glyph_string_bg_rect (s, s->x, s->y, width, s->height);
2516
2517 /* Clear rest using the GC of the original non-cursor face. */
2518 if (width < s->background_width)
2519 {
2520 XGCValues *gc = s->face->gc;
2521 int x = s->x + width, y = s->y;
2522 int w = s->background_width - width, h = s->height;
2523 RECT r;
2524 HDC hdc = s->hdc;
2525
2526 if (s->row->mouse_face_p
2527 && cursor_in_mouse_face_p (s->w))
2528 {
2529 x_set_mouse_face_gc (s);
2530 gc = s->gc;
2531 }
2532 else
2533 gc = s->face->gc;
2534
2535 w32_get_glyph_string_clip_rect (s, &r);
2536 w32_set_clip_rectangle (hdc, &r);
2537
2538 #if 0 /* TODO: stipple */
2539 if (s->face->stipple)
2540 {
2541 /* Fill background with a stipple pattern. */
2542 XSetFillStyle (s->display, gc, FillOpaqueStippled);
2543 XFillRectangle (s->display, s->window, gc, x, y, w, h);
2544 XSetFillStyle (s->display, gc, FillSolid);
2545 }
2546 else
2547 #endif
2548 {
2549 w32_fill_area (s->f, s->hdc, gc->background, x, y, w, h);
2550 }
2551 }
2552 }
2553 else if (!s->background_filled_p)
2554 x_draw_glyph_string_bg_rect (s, s->x, s->y, s->background_width,
2555 s->height);
2556
2557 s->background_filled_p = 1;
2558 }
2559
2560
2561 /* Draw glyph string S. */
2562
2563 static void
2564 x_draw_glyph_string (s)
2565 struct glyph_string *s;
2566 {
2567 int relief_drawn_p = 0;
2568
2569 /* If S draws into the background of its successor, draw the
2570 background of the successor first so that S can draw into it.
2571 This makes S->next use XDrawString instead of XDrawImageString. */
2572 if (s->next && s->right_overhang && !s->for_overlaps_p)
2573 {
2574 xassert (s->next->img == NULL);
2575 x_set_glyph_string_gc (s->next);
2576 x_set_glyph_string_clipping (s->next);
2577 x_draw_glyph_string_background (s->next, 1);
2578 }
2579
2580 /* Set up S->gc, set clipping and draw S. */
2581 x_set_glyph_string_gc (s);
2582
2583 /* Draw relief (if any) in advance for char/composition so that the
2584 glyph string can be drawn over it. */
2585 if (!s->for_overlaps_p
2586 && s->face->box != FACE_NO_BOX
2587 && (s->first_glyph->type == CHAR_GLYPH
2588 || s->first_glyph->type == COMPOSITE_GLYPH))
2589
2590 {
2591 x_set_glyph_string_clipping (s);
2592 x_draw_glyph_string_background (s, 1);
2593 x_draw_glyph_string_box (s);
2594 x_set_glyph_string_clipping (s);
2595 relief_drawn_p = 1;
2596 }
2597 else
2598 x_set_glyph_string_clipping (s);
2599
2600 switch (s->first_glyph->type)
2601 {
2602 case IMAGE_GLYPH:
2603 x_draw_image_glyph_string (s);
2604 break;
2605
2606 case STRETCH_GLYPH:
2607 x_draw_stretch_glyph_string (s);
2608 break;
2609
2610 case CHAR_GLYPH:
2611 if (s->for_overlaps_p)
2612 s->background_filled_p = 1;
2613 else
2614 x_draw_glyph_string_background (s, 0);
2615 x_draw_glyph_string_foreground (s);
2616 break;
2617
2618 case COMPOSITE_GLYPH:
2619 if (s->for_overlaps_p || s->gidx > 0)
2620 s->background_filled_p = 1;
2621 else
2622 x_draw_glyph_string_background (s, 1);
2623 x_draw_composite_glyph_string_foreground (s);
2624 break;
2625
2626 default:
2627 abort ();
2628 }
2629
2630 if (!s->for_overlaps_p)
2631 {
2632 /* Draw underline. */
2633 if (s->face->underline_p
2634 && (s->font->bdf || !s->font->tm.tmUnderlined))
2635 {
2636 unsigned long h = 1;
2637 unsigned long dy = s->height - h;
2638
2639 /* TODO: Use font information for positioning and thickness
2640 of underline. See OUTLINETEXTMETRIC, and xterm.c. */
2641 if (s->face->underline_defaulted_p)
2642 {
2643 w32_fill_area (s->f, s->hdc, s->gc->foreground, s->x,
2644 s->y + dy, s->width, 1);
2645 }
2646 else
2647 {
2648 w32_fill_area (s->f, s->hdc, s->face->underline_color, s->x,
2649 s->y + dy, s->width, 1);
2650 }
2651 }
2652
2653 /* Draw overline. */
2654 if (s->face->overline_p)
2655 {
2656 unsigned long dy = 0, h = 1;
2657
2658 if (s->face->overline_color_defaulted_p)
2659 {
2660 w32_fill_area (s->f, s->hdc, s->gc->foreground, s->x,
2661 s->y + dy, s->width, h);
2662 }
2663 else
2664 {
2665 w32_fill_area (s->f, s->hdc, s->face->underline_color, s->x,
2666 s->y + dy, s->width, h);
2667 }
2668 }
2669
2670 /* Draw strike-through. */
2671 if (s->face->strike_through_p
2672 && (s->font->bdf || !s->font->tm.tmStruckOut))
2673 {
2674 unsigned long h = 1;
2675 unsigned long dy = (s->height - h) / 2;
2676
2677 if (s->face->strike_through_color_defaulted_p)
2678 {
2679 w32_fill_area (s->f, s->hdc, s->gc->foreground, s->x, s->y + dy,
2680 s->width, h);
2681 }
2682 else
2683 {
2684 w32_fill_area (s->f, s->hdc, s->face->underline_color, s->x,
2685 s->y + dy, s->width, h);
2686 }
2687 }
2688
2689 /* Draw relief. */
2690 if (!relief_drawn_p && s->face->box != FACE_NO_BOX)
2691 x_draw_glyph_string_box (s);
2692 }
2693
2694 /* Reset clipping. */
2695 w32_set_clip_rectangle (s->hdc, NULL);
2696 }
2697
2698
2699 /* Fix the display of area AREA of overlapping row ROW in window W. */
2700
2701 static void
2702 x_fix_overlapping_area (w, row, area)
2703 struct window *w;
2704 struct glyph_row *row;
2705 enum glyph_row_area area;
2706 {
2707 int i, x;
2708
2709 BLOCK_INPUT;
2710
2711 if (area == LEFT_MARGIN_AREA)
2712 x = 0;
2713 else if (area == TEXT_AREA)
2714 x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
2715 else
2716 x = (window_box_width (w, LEFT_MARGIN_AREA)
2717 + window_box_width (w, TEXT_AREA));
2718
2719 for (i = 0; i < row->used[area];)
2720 {
2721 if (row->glyphs[area][i].overlaps_vertically_p)
2722 {
2723 int start = i, start_x = x;
2724
2725 do
2726 {
2727 x += row->glyphs[area][i].pixel_width;
2728 ++i;
2729 }
2730 while (i < row->used[area]
2731 && row->glyphs[area][i].overlaps_vertically_p);
2732
2733 x_draw_glyphs (w, start_x, row, area, start, i,
2734 DRAW_NORMAL_TEXT, 1);
2735 }
2736 else
2737 {
2738 x += row->glyphs[area][i].pixel_width;
2739 ++i;
2740 }
2741 }
2742
2743 UNBLOCK_INPUT;
2744 }
2745
2746
2747 /* Output LEN glyphs starting at START at the nominal cursor position.
2748 Advance the nominal cursor over the text. The global variable
2749 updated_window contains the window being updated, updated_row is
2750 the glyph row being updated, and updated_area is the area of that
2751 row being updated. */
2752
2753 static void
2754 x_write_glyphs (start, len)
2755 struct glyph *start;
2756 int len;
2757 {
2758 int x, hpos;
2759
2760 xassert (updated_window && updated_row);
2761 BLOCK_INPUT;
2762
2763 /* Write glyphs. */
2764
2765 hpos = start - updated_row->glyphs[updated_area];
2766 x = x_draw_glyphs (updated_window, output_cursor.x,
2767 updated_row, updated_area,
2768 hpos, hpos + len,
2769 DRAW_NORMAL_TEXT, 0);
2770
2771 /* Invalidate old phys cursor if the glyph at its hpos is redrawn. */
2772 if (updated_area == TEXT_AREA
2773 && updated_window->phys_cursor_on_p
2774 && updated_window->phys_cursor.vpos == output_cursor.vpos
2775 && updated_window->phys_cursor.hpos >= hpos
2776 && updated_window->phys_cursor.hpos < hpos + len)
2777 updated_window->phys_cursor_on_p = 0;
2778
2779 UNBLOCK_INPUT;
2780
2781 /* Advance the output cursor. */
2782 output_cursor.hpos += len;
2783 output_cursor.x = x;
2784 }
2785
2786
2787 /* Insert LEN glyphs from START at the nominal cursor position. */
2788
2789 static void
2790 x_insert_glyphs (start, len)
2791 struct glyph *start;
2792 register int len;
2793 {
2794 struct frame *f;
2795 struct window *w;
2796 int line_height, shift_by_width, shifted_region_width;
2797 struct glyph_row *row;
2798 struct glyph *glyph;
2799 int frame_x, frame_y, hpos;
2800 HDC hdc;
2801
2802 xassert (updated_window && updated_row);
2803 BLOCK_INPUT;
2804 w = updated_window;
2805 f = XFRAME (WINDOW_FRAME (w));
2806 hdc = get_frame_dc (f);
2807
2808 /* Get the height of the line we are in. */
2809 row = updated_row;
2810 line_height = row->height;
2811
2812 /* Get the width of the glyphs to insert. */
2813 shift_by_width = 0;
2814 for (glyph = start; glyph < start + len; ++glyph)
2815 shift_by_width += glyph->pixel_width;
2816
2817 /* Get the width of the region to shift right. */
2818 shifted_region_width = (window_box_width (w, updated_area)
2819 - output_cursor.x
2820 - shift_by_width);
2821
2822 /* Shift right. */
2823 frame_x = window_box_left (w, updated_area) + output_cursor.x;
2824 frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, output_cursor.y);
2825 BitBlt (hdc, frame_x + shift_by_width, frame_y,
2826 shifted_region_width, line_height,
2827 hdc, frame_x, frame_y, SRCCOPY);
2828
2829 /* Write the glyphs. */
2830 hpos = start - row->glyphs[updated_area];
2831 x_draw_glyphs (w, output_cursor.x, row, updated_area, hpos, hpos + len,
2832 DRAW_NORMAL_TEXT, 0);
2833
2834 /* Advance the output cursor. */
2835 output_cursor.hpos += len;
2836 output_cursor.x += shift_by_width;
2837 release_frame_dc (f, hdc);
2838
2839 UNBLOCK_INPUT;
2840 }
2841
2842
2843 /* Delete N glyphs at the nominal cursor position. Not implemented
2844 for X frames. */
2845
2846 static void
2847 x_delete_glyphs (n)
2848 register int n;
2849 {
2850 struct frame *f;
2851
2852 if (updating_frame)
2853 f = updating_frame;
2854 else
2855 f = SELECTED_FRAME ();
2856
2857 if (! FRAME_W32_P (f))
2858 return;
2859
2860 abort ();
2861 }
2862
2863
2864 /* Erase the current text line from the nominal cursor position
2865 (inclusive) to pixel column TO_X (exclusive). The idea is that
2866 everything from TO_X onward is already erased.
2867
2868 TO_X is a pixel position relative to updated_area of
2869 updated_window. TO_X == -1 means clear to the end of this area. */
2870
2871 static void
2872 x_clear_end_of_line (to_x)
2873 int to_x;
2874 {
2875 struct frame *f;
2876 struct window *w = updated_window;
2877 int max_x, min_y, max_y;
2878 int from_x, from_y, to_y;
2879
2880 xassert (updated_window && updated_row);
2881 f = XFRAME (w->frame);
2882
2883 if (updated_row->full_width_p)
2884 {
2885 max_x = XFASTINT (w->width) * CANON_X_UNIT (f);
2886 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f)
2887 && !w->pseudo_window_p)
2888 max_x += FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
2889 }
2890 else
2891 max_x = window_box_width (w, updated_area);
2892 max_y = window_text_bottom_y (w);
2893
2894 /* TO_X == 0 means don't do anything. TO_X < 0 means clear to end
2895 of window. For TO_X > 0, truncate to end of drawing area. */
2896 if (to_x == 0)
2897 return;
2898 else if (to_x < 0)
2899 to_x = max_x;
2900 else
2901 to_x = min (to_x, max_x);
2902
2903 to_y = min (max_y, output_cursor.y + updated_row->height);
2904
2905 /* Notice if the cursor will be cleared by this operation. */
2906 if (!updated_row->full_width_p)
2907 notice_overwritten_cursor (w, updated_area,
2908 output_cursor.x, -1,
2909 updated_row->y,
2910 MATRIX_ROW_BOTTOM_Y (updated_row));
2911
2912 from_x = output_cursor.x;
2913
2914 /* Translate to frame coordinates. */
2915 if (updated_row->full_width_p)
2916 {
2917 from_x = WINDOW_TO_FRAME_PIXEL_X (w, from_x);
2918 to_x = WINDOW_TO_FRAME_PIXEL_X (w, to_x);
2919 }
2920 else
2921 {
2922 from_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, from_x);
2923 to_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, to_x);
2924 }
2925
2926 min_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
2927 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, max (min_y, output_cursor.y));
2928 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, to_y);
2929
2930 /* Prevent inadvertently clearing to end of the X window. */
2931 if (to_x > from_x && to_y > from_y)
2932 {
2933 HDC hdc;
2934 BLOCK_INPUT;
2935 hdc = get_frame_dc (f);
2936
2937 w32_clear_area (f, hdc, from_x, from_y, to_x - from_x, to_y - from_y);
2938 release_frame_dc (f, hdc);
2939 UNBLOCK_INPUT;
2940 }
2941 }
2942
2943
2944 /* Clear entire frame. If updating_frame is non-null, clear that
2945 frame. Otherwise clear the selected frame. */
2946
2947 static void
2948 x_clear_frame ()
2949 {
2950 struct frame *f;
2951
2952 if (updating_frame)
2953 f = updating_frame;
2954 else
2955 f = SELECTED_FRAME ();
2956
2957 if (! FRAME_W32_P (f))
2958 return;
2959
2960 /* Clearing the frame will erase any cursor, so mark them all as no
2961 longer visible. */
2962 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
2963 output_cursor.hpos = output_cursor.vpos = 0;
2964 output_cursor.x = -1;
2965
2966 /* We don't set the output cursor here because there will always
2967 follow an explicit cursor_to. */
2968 BLOCK_INPUT;
2969
2970 w32_clear_window (f);
2971
2972 /* We have to clear the scroll bars, too. If we have changed
2973 colors or something like that, then they should be notified. */
2974 x_scroll_bar_clear (f);
2975
2976 UNBLOCK_INPUT;
2977 }
2978
2979 \f
2980 /* Make audible bell. */
2981
2982 static void
2983 w32_ring_bell (void)
2984 {
2985 struct frame *f;
2986
2987 f = SELECTED_FRAME ();
2988
2989 BLOCK_INPUT;
2990
2991 if (FRAME_W32_P (f) && visible_bell)
2992 {
2993 int i;
2994 HWND hwnd = FRAME_W32_WINDOW (SELECTED_FRAME ());
2995
2996 for (i = 0; i < 5; i++)
2997 {
2998 FlashWindow (hwnd, TRUE);
2999 Sleep (10);
3000 }
3001 FlashWindow (hwnd, FALSE);
3002 }
3003 else
3004 w32_sys_ring_bell ();
3005
3006 UNBLOCK_INPUT;
3007 }
3008
3009 \f
3010 /* Specify how many text lines, from the top of the window,
3011 should be affected by insert-lines and delete-lines operations.
3012 This, and those operations, are used only within an update
3013 that is bounded by calls to x_update_begin and x_update_end. */
3014
3015 static void
3016 w32_set_terminal_window (n)
3017 register int n;
3018 {
3019 /* This function intentionally left blank. */
3020 }
3021
3022 \f
3023 /***********************************************************************
3024 Line Dance
3025 ***********************************************************************/
3026
3027 /* Perform an insert-lines or delete-lines operation, inserting N
3028 lines or deleting -N lines at vertical position VPOS. */
3029
3030 static void
3031 x_ins_del_lines (vpos, n)
3032 int vpos, n;
3033 {
3034 struct frame *f;
3035
3036 if (updating_frame)
3037 f = updating_frame;
3038 else
3039 f = SELECTED_FRAME ();
3040
3041 if (! FRAME_W32_P (f))
3042 return;
3043
3044 abort ();
3045 }
3046
3047
3048 /* Scroll part of the display as described by RUN. */
3049
3050 static void
3051 x_scroll_run (w, run)
3052 struct window *w;
3053 struct run *run;
3054 {
3055 struct frame *f = XFRAME (w->frame);
3056 int x, y, width, height, from_y, to_y, bottom_y;
3057 HWND hwnd = FRAME_W32_WINDOW (f);
3058 HRGN expect_dirty;
3059
3060 /* Get frame-relative bounding box of the text display area of W,
3061 without mode lines. Include in this box the left and right
3062 fringes of W. */
3063 window_box (w, -1, &x, &y, &width, &height);
3064 width += FRAME_X_FRINGE_WIDTH (f);
3065 x -= FRAME_X_LEFT_FRINGE_WIDTH (f);
3066
3067 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
3068 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
3069 bottom_y = y + height;
3070
3071 if (to_y < from_y)
3072 {
3073 /* Scrolling up. Make sure we don't copy part of the mode
3074 line at the bottom. */
3075 if (from_y + run->height > bottom_y)
3076 height = bottom_y - from_y;
3077 else
3078 height = run->height;
3079 expect_dirty = CreateRectRgn (x, y + height, x + width, bottom_y);
3080 }
3081 else
3082 {
3083 /* Scolling down. Make sure we don't copy over the mode line.
3084 at the bottom. */
3085 if (to_y + run->height > bottom_y)
3086 height = bottom_y - to_y;
3087 else
3088 height = run->height;
3089 expect_dirty = CreateRectRgn (x, y, x + width, to_y);
3090 }
3091
3092 BLOCK_INPUT;
3093
3094 /* Cursor off. Will be switched on again in x_update_window_end. */
3095 updated_window = w;
3096 x_clear_cursor (w);
3097
3098 {
3099 RECT from;
3100 RECT to;
3101 HRGN dirty = CreateRectRgn (0, 0, 0, 0);
3102 HRGN combined = CreateRectRgn (0, 0, 0, 0);
3103
3104 from.left = to.left = x;
3105 from.right = to.right = x + width;
3106 from.top = from_y;
3107 from.bottom = from_y + height;
3108 to.top = y;
3109 to.bottom = bottom_y;
3110
3111 ScrollWindowEx (hwnd, 0, to_y - from_y, &from, &to, dirty,
3112 NULL, SW_INVALIDATE);
3113
3114 /* Combine this with what we expect to be dirty. This covers the
3115 case where not all of the region we expect is actually dirty. */
3116 CombineRgn (combined, dirty, expect_dirty, RGN_OR);
3117
3118 /* If the dirty region is not what we expected, redraw the entire frame. */
3119 if (!EqualRgn (combined, expect_dirty))
3120 SET_FRAME_GARBAGED (f);
3121 }
3122
3123 UNBLOCK_INPUT;
3124 }
3125
3126
3127 \f
3128 /***********************************************************************
3129 Exposure Events
3130 ***********************************************************************/
3131
3132 /* Redisplay an exposed area of frame F. X and Y are the upper-left
3133 corner of the exposed rectangle. W and H are width and height of
3134 the exposed area. All are pixel values. W or H zero means redraw
3135 the entire frame. */
3136
3137 static void
3138 expose_frame (f, x, y, w, h)
3139 struct frame *f;
3140 int x, y, w, h;
3141 {
3142 RECT r;
3143 int mouse_face_overwritten_p = 0;
3144
3145 TRACE ((stderr, "expose_frame "));
3146
3147 /* No need to redraw if frame will be redrawn soon. */
3148 if (FRAME_GARBAGED_P (f))
3149 {
3150 TRACE ((stderr, " garbaged\n"));
3151 return;
3152 }
3153
3154 /* If basic faces haven't been realized yet, there is no point in
3155 trying to redraw anything. This can happen when we get an expose
3156 event while Emacs is starting, e.g. by moving another window. */
3157 if (FRAME_FACE_CACHE (f) == NULL
3158 || FRAME_FACE_CACHE (f)->used < BASIC_FACE_ID_SENTINEL)
3159 {
3160 TRACE ((stderr, " no faces\n"));
3161 return;
3162 }
3163
3164 if (w == 0 || h == 0)
3165 {
3166 r.left = r.top = 0;
3167 r.right = CANON_X_UNIT (f) * f->width;
3168 r.bottom = CANON_Y_UNIT (f) * f->height;
3169 }
3170 else
3171 {
3172 r.left = x;
3173 r.top = y;
3174 r.right = x + w;
3175 r.bottom = y + h;
3176 }
3177
3178 TRACE ((stderr, "(%d, %d, %d, %d)\n", r.left, r.top, r.right, r.bottom));
3179 mouse_face_overwritten_p = expose_window_tree (XWINDOW (f->root_window), &r);
3180
3181 if (WINDOWP (f->tool_bar_window))
3182 mouse_face_overwritten_p
3183 |= expose_window (XWINDOW (f->tool_bar_window), &r);
3184
3185 /* Some window managers support a focus-follows-mouse style with
3186 delayed raising of frames. Imagine a partially obscured frame,
3187 and moving the mouse into partially obscured mouse-face on that
3188 frame. The visible part of the mouse-face will be highlighted,
3189 then the WM raises the obscured frame. With at least one WM, KDE
3190 2.1, Emacs is not getting any event for the raising of the frame
3191 (even tried with SubstructureRedirectMask), only Expose events.
3192 These expose events will draw text normally, i.e. not
3193 highlighted. Which means we must redo the highlight here.
3194 Subsume it under ``we love X''. --gerd 2001-08-15 */
3195 /* Included in Windows version because Windows most likely does not
3196 do the right thing if any third party tool offers
3197 focus-follows-mouse with delayed raise. --jason 2001-10-12 */
3198 if (mouse_face_overwritten_p && !FRAME_GARBAGED_P (f))
3199 {
3200 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
3201 if (f == dpyinfo->mouse_face_mouse_frame)
3202 {
3203 int x = dpyinfo->mouse_face_mouse_x;
3204 int y = dpyinfo->mouse_face_mouse_y;
3205 clear_mouse_face (dpyinfo);
3206 note_mouse_highlight (f, x, y);
3207 }
3208 }
3209 }
3210
3211
3212 /* Redraw (parts) of all windows in the window tree rooted at W that
3213 intersect R. R contains frame pixel coordinates. */
3214
3215 static int
3216 expose_window_tree (w, r)
3217 struct window *w;
3218 RECT *r;
3219 {
3220 struct frame *f = XFRAME (w->frame);
3221 int mouse_face_overwritten_p = 0;
3222
3223 while (w && !FRAME_GARBAGED_P (f))
3224 {
3225 if (!NILP (w->hchild))
3226 mouse_face_overwritten_p
3227 |= expose_window_tree (XWINDOW (w->hchild), r);
3228 else if (!NILP (w->vchild))
3229 mouse_face_overwritten_p
3230 |= expose_window_tree (XWINDOW (w->vchild), r);
3231 else
3232 mouse_face_overwritten_p |= expose_window (w, r);
3233
3234 w = NILP (w->next) ? NULL : XWINDOW (w->next);
3235 }
3236
3237 return mouse_face_overwritten_p;
3238 }
3239
3240
3241 /* Redraw the part of glyph row area AREA of glyph row ROW on window W
3242 which intersects rectangle R. R is in window-relative coordinates. */
3243
3244 static void
3245 expose_area (w, row, r, area)
3246 struct window *w;
3247 struct glyph_row *row;
3248 RECT *r;
3249 enum glyph_row_area area;
3250 {
3251 struct glyph *first = row->glyphs[area];
3252 struct glyph *end = row->glyphs[area] + row->used[area];
3253 struct glyph *last;
3254 int first_x, start_x, x;
3255
3256 if (area == TEXT_AREA && row->fill_line_p)
3257 /* If row extends face to end of line write the whole line. */
3258 x_draw_glyphs (w, 0, row, area,
3259 0, row->used[area],
3260 DRAW_NORMAL_TEXT, 0);
3261 else
3262 {
3263 /* Set START_X to the window-relative start position for drawing glyphs of
3264 AREA. The first glyph of the text area can be partially visible.
3265 The first glyphs of other areas cannot. */
3266 if (area == LEFT_MARGIN_AREA)
3267 start_x = 0;
3268 else if (area == TEXT_AREA)
3269 start_x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
3270 else
3271 start_x = (window_box_width (w, LEFT_MARGIN_AREA)
3272 + window_box_width (w, TEXT_AREA));
3273 x = start_x;
3274
3275 /* Find the first glyph that must be redrawn. */
3276 while (first < end
3277 && x + first->pixel_width < r->left)
3278 {
3279 x += first->pixel_width;
3280 ++first;
3281 }
3282
3283 /* Find the last one. */
3284 last = first;
3285 first_x = x;
3286 while (last < end
3287 && x < r->right)
3288 {
3289 x += last->pixel_width;
3290 ++last;
3291 }
3292
3293 /* Repaint. */
3294 if (last > first)
3295 x_draw_glyphs (w, first_x - start_x, row, area,
3296 first - row->glyphs[area],
3297 last - row->glyphs[area],
3298 DRAW_NORMAL_TEXT, 0);
3299 }
3300 }
3301
3302
3303 /* Redraw the parts of the glyph row ROW on window W intersecting
3304 rectangle R. R is in window-relative coordinates. Value is
3305 non-zero if mouse face was overwritten. */
3306
3307 static int
3308 expose_line (w, row, r)
3309 struct window *w;
3310 struct glyph_row *row;
3311 RECT *r;
3312 {
3313 xassert (row->enabled_p);
3314
3315 if (row->mode_line_p || w->pseudo_window_p)
3316 x_draw_glyphs (w, 0, row, TEXT_AREA, 0, row->used[TEXT_AREA],
3317 DRAW_NORMAL_TEXT, 0);
3318 else
3319 {
3320 if (row->used[LEFT_MARGIN_AREA])
3321 expose_area (w, row, r, LEFT_MARGIN_AREA);
3322 if (row->used[TEXT_AREA])
3323 expose_area (w, row, r, TEXT_AREA);
3324 if (row->used[RIGHT_MARGIN_AREA])
3325 expose_area (w, row, r, RIGHT_MARGIN_AREA);
3326 draw_row_fringe_bitmaps (w, row);
3327 }
3328
3329 return row->mouse_face_p;
3330 }
3331
3332
3333 /* Return non-zero if W's cursor intersects rectangle R. */
3334
3335 static int
3336 x_phys_cursor_in_rect_p (w, r)
3337 struct window *w;
3338 RECT *r;
3339 {
3340 RECT cr, result;
3341 struct glyph *cursor_glyph;
3342
3343 cursor_glyph = get_phys_cursor_glyph (w);
3344 if (cursor_glyph)
3345 {
3346 cr.left = w->phys_cursor.x;
3347 cr.top = w->phys_cursor.y;
3348 cr.right = cr.left + cursor_glyph->pixel_width;
3349 cr.bottom = cr.top + w->phys_cursor_height;
3350 return IntersectRect (&result, &cr, r);
3351 }
3352 else
3353 return 0;
3354 }
3355
3356
3357 /* Redraw those parts of glyphs rows during expose event handling that
3358 overlap other rows. Redrawing of an exposed line writes over parts
3359 of lines overlapping that exposed line; this function fixes that.
3360
3361 W is the window being exposed. FIRST_OVERLAPPING_ROW is the first
3362 row in W's current matrix that is exposed and overlaps other rows.
3363 LAST_OVERLAPPING_ROW is the last such row. */
3364
3365 static void
3366 expose_overlaps (w, first_overlapping_row, last_overlapping_row)
3367 struct window *w;
3368 struct glyph_row *first_overlapping_row;
3369 struct glyph_row *last_overlapping_row;
3370 {
3371 struct glyph_row *row;
3372
3373 for (row = first_overlapping_row; row <= last_overlapping_row; ++row)
3374 if (row->overlapping_p)
3375 {
3376 xassert (row->enabled_p && !row->mode_line_p);
3377
3378 if (row->used[LEFT_MARGIN_AREA])
3379 x_fix_overlapping_area (w, row, LEFT_MARGIN_AREA);
3380
3381 if (row->used[TEXT_AREA])
3382 x_fix_overlapping_area (w, row, TEXT_AREA);
3383
3384 if (row->used[RIGHT_MARGIN_AREA])
3385 x_fix_overlapping_area (w, row, RIGHT_MARGIN_AREA);
3386 }
3387 }
3388
3389
3390 /* Redraw the part of window W intersection rectagle FR. Pixel
3391 coordinates in FR are frame relative. Call this function with
3392 input blocked. Value is non-zero if the exposure overwrites
3393 mouse-face. */
3394
3395 static int
3396 expose_window (w, fr)
3397 struct window *w;
3398 RECT *fr;
3399 {
3400 struct frame *f = XFRAME (w->frame);
3401 RECT wr, r;
3402 int mouse_face_overwritten_p = 0;
3403
3404 /* If window is not yet fully initialized, do nothing. This can
3405 happen when toolkit scroll bars are used and a window is split.
3406 Reconfiguring the scroll bar will generate an expose for a newly
3407 created window. */
3408 if (w->current_matrix == NULL)
3409 return 0;
3410
3411 /* When we're currently updating the window, display and current
3412 matrix usually don't agree. Arrange for a thorough display
3413 later. */
3414 if (w == updated_window)
3415 {
3416 SET_FRAME_GARBAGED (f);
3417 return 0;
3418 }
3419
3420 /* Frame-relative pixel rectangle of W. */
3421 wr.left = XFASTINT (w->left) * CANON_X_UNIT (f);
3422 wr.top = XFASTINT (w->top) * CANON_Y_UNIT (f);
3423 wr.right = wr.left + XFASTINT (w->width) * CANON_X_UNIT (f);
3424 wr.bottom = wr.top + XFASTINT (w->height) * CANON_Y_UNIT (f);
3425
3426 if (IntersectRect(&r, fr, &wr))
3427 {
3428 int yb = window_text_bottom_y (w);
3429 struct glyph_row *row;
3430 int cursor_cleared_p;
3431 struct glyph_row *first_overlapping_row, *last_overlapping_row;
3432
3433 TRACE ((stderr, "expose_window (%d, %d, %d, %d)\n",
3434 r.left, r.top, r.right, r.bottom));
3435
3436 /* Convert to window coordinates. */
3437 r.left = FRAME_TO_WINDOW_PIXEL_X (w, r.left);
3438 r.right = FRAME_TO_WINDOW_PIXEL_X (w, r.right);
3439 r.top = FRAME_TO_WINDOW_PIXEL_Y (w, r.top);
3440 r.bottom = FRAME_TO_WINDOW_PIXEL_Y (w, r.bottom);
3441
3442 /* Turn off the cursor. */
3443 if (!w->pseudo_window_p
3444 && x_phys_cursor_in_rect_p (w, &r))
3445 {
3446 x_clear_cursor (w);
3447 cursor_cleared_p = 1;
3448 }
3449 else
3450 cursor_cleared_p = 0;
3451
3452 /* Update lines intersecting rectangle R. */
3453 first_overlapping_row = last_overlapping_row = NULL;
3454 for (row = w->current_matrix->rows;
3455 row->enabled_p;
3456 ++row)
3457 {
3458 int y0 = row->y;
3459 int y1 = MATRIX_ROW_BOTTOM_Y (row);
3460
3461 if ((y0 >= r.top && y0 < r.bottom)
3462 || (y1 > r.top && y1 < r.bottom)
3463 || (r.top >= y0 && r.top < y1)
3464 || (r.bottom > y0 && r.bottom < y1))
3465 {
3466 if (row->overlapping_p)
3467 {
3468 if (first_overlapping_row == NULL)
3469 first_overlapping_row = row;
3470 last_overlapping_row = row;
3471 }
3472
3473 if (expose_line (w, row, &r))
3474 mouse_face_overwritten_p = 1;
3475 }
3476
3477 if (y1 >= yb)
3478 break;
3479 }
3480
3481 /* Display the mode line if there is one. */
3482 if (WINDOW_WANTS_MODELINE_P (w)
3483 && (row = MATRIX_MODE_LINE_ROW (w->current_matrix),
3484 row->enabled_p)
3485 && row->y < r.bottom)
3486 {
3487 if (expose_line (w, row, &r))
3488 mouse_face_overwritten_p = 1;
3489 }
3490
3491 if (!w->pseudo_window_p)
3492 {
3493 /* Fix the display of overlapping rows. */
3494 if (first_overlapping_row)
3495 expose_overlaps (w, first_overlapping_row, last_overlapping_row);
3496
3497 /* Draw border between windows. */
3498 x_draw_vertical_border (w);
3499
3500 /* Turn the cursor on again. */
3501 if (cursor_cleared_p)
3502 x_update_window_cursor (w, 1);
3503 }
3504 }
3505
3506 return mouse_face_overwritten_p;
3507 }
3508
3509 \f
3510 static void
3511 frame_highlight (f)
3512 struct frame *f;
3513 {
3514 x_update_cursor (f, 1);
3515 }
3516
3517 static void
3518 frame_unhighlight (f)
3519 struct frame *f;
3520 {
3521 x_update_cursor (f, 1);
3522 }
3523
3524 /* The focus has changed. Update the frames as necessary to reflect
3525 the new situation. Note that we can't change the selected frame
3526 here, because the Lisp code we are interrupting might become confused.
3527 Each event gets marked with the frame in which it occurred, so the
3528 Lisp code can tell when the switch took place by examining the events. */
3529
3530 static void
3531 x_new_focus_frame (dpyinfo, frame)
3532 struct w32_display_info *dpyinfo;
3533 struct frame *frame;
3534 {
3535 struct frame *old_focus = dpyinfo->w32_focus_frame;
3536
3537 if (frame != dpyinfo->w32_focus_frame)
3538 {
3539 /* Set this before calling other routines, so that they see
3540 the correct value of w32_focus_frame. */
3541 dpyinfo->w32_focus_frame = frame;
3542
3543 if (old_focus && old_focus->auto_lower)
3544 x_lower_frame (old_focus);
3545
3546 if (dpyinfo->w32_focus_frame && dpyinfo->w32_focus_frame->auto_raise)
3547 pending_autoraise_frame = dpyinfo->w32_focus_frame;
3548 else
3549 pending_autoraise_frame = 0;
3550 }
3551
3552 x_frame_rehighlight (dpyinfo);
3553 }
3554
3555 /* Handle an event saying the mouse has moved out of an Emacs frame. */
3556
3557 void
3558 x_mouse_leave (dpyinfo)
3559 struct w32_display_info *dpyinfo;
3560 {
3561 x_new_focus_frame (dpyinfo, dpyinfo->w32_focus_event_frame);
3562 }
3563
3564 /* The focus has changed, or we have redirected a frame's focus to
3565 another frame (this happens when a frame uses a surrogate
3566 mini-buffer frame). Shift the highlight as appropriate.
3567
3568 The FRAME argument doesn't necessarily have anything to do with which
3569 frame is being highlighted or un-highlighted; we only use it to find
3570 the appropriate X display info. */
3571
3572 static void
3573 w32_frame_rehighlight (frame)
3574 struct frame *frame;
3575 {
3576 if (! FRAME_W32_P (frame))
3577 return;
3578 x_frame_rehighlight (FRAME_W32_DISPLAY_INFO (frame));
3579 }
3580
3581 static void
3582 x_frame_rehighlight (dpyinfo)
3583 struct w32_display_info *dpyinfo;
3584 {
3585 struct frame *old_highlight = dpyinfo->x_highlight_frame;
3586
3587 if (dpyinfo->w32_focus_frame)
3588 {
3589 dpyinfo->x_highlight_frame
3590 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->w32_focus_frame)))
3591 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->w32_focus_frame))
3592 : dpyinfo->w32_focus_frame);
3593 if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame))
3594 {
3595 FRAME_FOCUS_FRAME (dpyinfo->w32_focus_frame) = Qnil;
3596 dpyinfo->x_highlight_frame = dpyinfo->w32_focus_frame;
3597 }
3598 }
3599 else
3600 dpyinfo->x_highlight_frame = 0;
3601
3602 if (dpyinfo->x_highlight_frame != old_highlight)
3603 {
3604 if (old_highlight)
3605 frame_unhighlight (old_highlight);
3606 if (dpyinfo->x_highlight_frame)
3607 frame_highlight (dpyinfo->x_highlight_frame);
3608 }
3609 }
3610 \f
3611 /* Keyboard processing - modifier keys, etc. */
3612
3613 /* Convert a keysym to its name. */
3614
3615 char *
3616 x_get_keysym_name (keysym)
3617 int keysym;
3618 {
3619 /* Make static so we can always return it */
3620 static char value[100];
3621
3622 BLOCK_INPUT;
3623 GetKeyNameText (keysym, value, 100);
3624 UNBLOCK_INPUT;
3625
3626 return value;
3627 }
3628
3629
3630 \f
3631 /* Mouse clicks and mouse movement. Rah. */
3632
3633 /* Given a pixel position (PIX_X, PIX_Y) on frame F, return glyph
3634 co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle that the
3635 glyph at X, Y occupies, if BOUNDS != 0. If NOCLIP is non-zero, do
3636 not force the value into range. */
3637
3638 void
3639 pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds, noclip)
3640 FRAME_PTR f;
3641 register int pix_x, pix_y;
3642 register int *x, *y;
3643 RECT *bounds;
3644 int noclip;
3645 {
3646 /* Support tty mode: if Vwindow_system is nil, behave correctly. */
3647 if (NILP (Vwindow_system))
3648 {
3649 *x = pix_x;
3650 *y = pix_y;
3651 return;
3652 }
3653
3654 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
3655 even for negative values. */
3656 if (pix_x < 0)
3657 pix_x -= FONT_WIDTH (FRAME_FONT (f)) - 1;
3658 if (pix_y < 0)
3659 pix_y -= (f)->output_data.w32->line_height - 1;
3660
3661 pix_x = PIXEL_TO_CHAR_COL (f, pix_x);
3662 pix_y = PIXEL_TO_CHAR_ROW (f, pix_y);
3663
3664 if (bounds)
3665 {
3666 bounds->left = CHAR_TO_PIXEL_COL (f, pix_x);
3667 bounds->top = CHAR_TO_PIXEL_ROW (f, pix_y);
3668 bounds->right = bounds->left + FONT_WIDTH (FRAME_FONT (f)) - 1;
3669 bounds->bottom = bounds->top + f->output_data.w32->line_height - 1;
3670 }
3671
3672 if (!noclip)
3673 {
3674 if (pix_x < 0)
3675 pix_x = 0;
3676 else if (pix_x > FRAME_WINDOW_WIDTH (f))
3677 pix_x = FRAME_WINDOW_WIDTH (f);
3678
3679 if (pix_y < 0)
3680 pix_y = 0;
3681 else if (pix_y > f->height)
3682 pix_y = f->height;
3683 }
3684
3685 *x = pix_x;
3686 *y = pix_y;
3687 }
3688
3689
3690 /* Given HPOS/VPOS in the current matrix of W, return corresponding
3691 frame-relative pixel positions in *FRAME_X and *FRAME_Y. If we
3692 can't tell the positions because W's display is not up to date,
3693 return 0. */
3694
3695 int
3696 glyph_to_pixel_coords (w, hpos, vpos, frame_x, frame_y)
3697 struct window *w;
3698 int hpos, vpos;
3699 int *frame_x, *frame_y;
3700 {
3701 int success_p;
3702
3703 xassert (hpos >= 0 && hpos < w->current_matrix->matrix_w);
3704 xassert (vpos >= 0 && vpos < w->current_matrix->matrix_h);
3705
3706 if (display_completed)
3707 {
3708 struct glyph_row *row = MATRIX_ROW (w->current_matrix, vpos);
3709 struct glyph *glyph = row->glyphs[TEXT_AREA];
3710 struct glyph *end = glyph + min (hpos, row->used[TEXT_AREA]);
3711
3712 *frame_y = row->y;
3713 *frame_x = row->x;
3714 while (glyph < end)
3715 {
3716 *frame_x += glyph->pixel_width;
3717 ++glyph;
3718 }
3719
3720 success_p = 1;
3721 }
3722 else
3723 {
3724 *frame_y = *frame_x = 0;
3725 success_p = 0;
3726 }
3727
3728 *frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, *frame_y);
3729 *frame_x = WINDOW_TO_FRAME_PIXEL_X (w, *frame_x);
3730 return success_p;
3731 }
3732
3733 /* Parse a button MESSAGE. The button index is returned in PBUTTON, and
3734 the state in PUP. XBUTTON provides extra information for extended mouse
3735 button messages. Returns FALSE if unable to parse the message. */
3736 BOOL
3737 parse_button (message, xbutton, pbutton, pup)
3738 int message;
3739 int xbutton;
3740 int * pbutton;
3741 int * pup;
3742 {
3743 int button = 0;
3744 int up = 0;
3745
3746 switch (message)
3747 {
3748 case WM_LBUTTONDOWN:
3749 button = 0;
3750 up = 0;
3751 break;
3752 case WM_LBUTTONUP:
3753 button = 0;
3754 up = 1;
3755 break;
3756 case WM_MBUTTONDOWN:
3757 if (NILP (Vw32_swap_mouse_buttons))
3758 button = 1;
3759 else
3760 button = 2;
3761 up = 0;
3762 break;
3763 case WM_MBUTTONUP:
3764 if (NILP (Vw32_swap_mouse_buttons))
3765 button = 1;
3766 else
3767 button = 2;
3768 up = 1;
3769 break;
3770 case WM_RBUTTONDOWN:
3771 if (NILP (Vw32_swap_mouse_buttons))
3772 button = 2;
3773 else
3774 button = 1;
3775 up = 0;
3776 break;
3777 case WM_RBUTTONUP:
3778 if (NILP (Vw32_swap_mouse_buttons))
3779 button = 2;
3780 else
3781 button = 1;
3782 up = 1;
3783 break;
3784 case WM_XBUTTONDOWN:
3785 button = xbutton + 2;
3786 up = 0;
3787 break;
3788 case WM_XBUTTONUP:
3789 button = xbutton + 2;
3790 up = 1;
3791 break;
3792 default:
3793 return (FALSE);
3794 }
3795
3796 if (pup) *pup = up;
3797 if (pbutton) *pbutton = button;
3798
3799 return (TRUE);
3800 }
3801
3802
3803 /* Prepare a mouse-event in *RESULT for placement in the input queue.
3804
3805 If the event is a button press, then note that we have grabbed
3806 the mouse. */
3807
3808 static Lisp_Object
3809 construct_mouse_click (result, msg, f)
3810 struct input_event *result;
3811 W32Msg *msg;
3812 struct frame *f;
3813 {
3814 int button;
3815 int up;
3816
3817 parse_button (msg->msg.message, HIWORD (msg->msg.wParam),
3818 &button, &up);
3819
3820 /* Make the event type NO_EVENT; we'll change that when we decide
3821 otherwise. */
3822 result->kind = MOUSE_CLICK_EVENT;
3823 result->code = button;
3824 result->timestamp = msg->msg.time;
3825 result->modifiers = (msg->dwModifiers
3826 | (up
3827 ? up_modifier
3828 : down_modifier));
3829
3830 XSETINT (result->x, LOWORD (msg->msg.lParam));
3831 XSETINT (result->y, HIWORD (msg->msg.lParam));
3832 XSETFRAME (result->frame_or_window, f);
3833 result->arg = Qnil;
3834 return Qnil;
3835 }
3836
3837 static Lisp_Object
3838 construct_mouse_wheel (result, msg, f)
3839 struct input_event *result;
3840 W32Msg *msg;
3841 struct frame *f;
3842 {
3843 POINT p;
3844 result->kind = MOUSE_WHEEL_EVENT;
3845 result->code = (short) HIWORD (msg->msg.wParam);
3846 result->timestamp = msg->msg.time;
3847 result->modifiers = msg->dwModifiers;
3848 p.x = LOWORD (msg->msg.lParam);
3849 p.y = HIWORD (msg->msg.lParam);
3850 ScreenToClient (msg->msg.hwnd, &p);
3851 XSETINT (result->x, p.x);
3852 XSETINT (result->y, p.y);
3853 XSETFRAME (result->frame_or_window, f);
3854 result->arg = Qnil;
3855 return Qnil;
3856 }
3857
3858 static Lisp_Object
3859 construct_drag_n_drop (result, msg, f)
3860 struct input_event *result;
3861 W32Msg *msg;
3862 struct frame *f;
3863 {
3864 Lisp_Object files;
3865 Lisp_Object frame;
3866 HDROP hdrop;
3867 POINT p;
3868 WORD num_files;
3869 char *name;
3870 int i, len;
3871
3872 result->kind = DRAG_N_DROP_EVENT;
3873 result->code = 0;
3874 result->timestamp = msg->msg.time;
3875 result->modifiers = msg->dwModifiers;
3876
3877 hdrop = (HDROP) msg->msg.wParam;
3878 DragQueryPoint (hdrop, &p);
3879
3880 #if 0
3881 p.x = LOWORD (msg->msg.lParam);
3882 p.y = HIWORD (msg->msg.lParam);
3883 ScreenToClient (msg->msg.hwnd, &p);
3884 #endif
3885
3886 XSETINT (result->x, p.x);
3887 XSETINT (result->y, p.y);
3888
3889 num_files = DragQueryFile (hdrop, 0xFFFFFFFF, NULL, 0);
3890 files = Qnil;
3891
3892 for (i = 0; i < num_files; i++)
3893 {
3894 len = DragQueryFile (hdrop, i, NULL, 0);
3895 if (len <= 0)
3896 continue;
3897 name = alloca (len + 1);
3898 DragQueryFile (hdrop, i, name, len + 1);
3899 files = Fcons (DECODE_FILE (build_string (name)), files);
3900 }
3901
3902 DragFinish (hdrop);
3903
3904 XSETFRAME (frame, f);
3905 result->frame_or_window = Fcons (frame, files);
3906 result->arg = Qnil;
3907 return Qnil;
3908 }
3909
3910 \f
3911 /* Function to report a mouse movement to the mainstream Emacs code.
3912 The input handler calls this.
3913
3914 We have received a mouse movement event, which is given in *event.
3915 If the mouse is over a different glyph than it was last time, tell
3916 the mainstream emacs code by setting mouse_moved. If not, ask for
3917 another motion event, so we can check again the next time it moves. */
3918
3919 static MSG last_mouse_motion_event;
3920 static Lisp_Object last_mouse_motion_frame;
3921
3922 static void remember_mouse_glyph P_ ((struct frame *, int, int));
3923
3924 static void
3925 note_mouse_movement (frame, msg)
3926 FRAME_PTR frame;
3927 MSG *msg;
3928 {
3929 int mouse_x = LOWORD (msg->lParam);
3930 int mouse_y = HIWORD (msg->lParam);
3931
3932 last_mouse_movement_time = msg->time;
3933 memcpy (&last_mouse_motion_event, msg, sizeof (last_mouse_motion_event));
3934 XSETFRAME (last_mouse_motion_frame, frame);
3935
3936 if (msg->hwnd != FRAME_W32_WINDOW (frame))
3937 {
3938 frame->mouse_moved = 1;
3939 last_mouse_scroll_bar = Qnil;
3940 note_mouse_highlight (frame, -1, -1);
3941 }
3942
3943 /* Has the mouse moved off the glyph it was on at the last sighting? */
3944 else if (mouse_x < last_mouse_glyph.left
3945 || mouse_x > last_mouse_glyph.right
3946 || mouse_y < last_mouse_glyph.top
3947 || mouse_y > last_mouse_glyph.bottom)
3948 {
3949 frame->mouse_moved = 1;
3950 last_mouse_scroll_bar = Qnil;
3951 note_mouse_highlight (frame, mouse_x, mouse_y);
3952 /* Remember the mouse position here, as w32_mouse_position only
3953 gets called when mouse tracking is enabled but we also need
3954 to keep track of the mouse for help_echo and highlighting at
3955 other times. */
3956 remember_mouse_glyph (frame, mouse_x, mouse_y);
3957 }
3958 }
3959
3960 \f
3961 /************************************************************************
3962 Mouse Face
3963 ************************************************************************/
3964
3965 /* Find the glyph under window-relative coordinates X/Y in window W.
3966 Consider only glyphs from buffer text, i.e. no glyphs from overlay
3967 strings. Return in *HPOS and *VPOS the row and column number of
3968 the glyph found. Return in *AREA the glyph area containing X.
3969 Value is a pointer to the glyph found or null if X/Y is not on
3970 text, or we can't tell because W's current matrix is not up to
3971 date. */
3972
3973 static struct glyph *
3974 x_y_to_hpos_vpos (w, x, y, hpos, vpos, area, buffer_only_p)
3975 struct window *w;
3976 int x, y;
3977 int *hpos, *vpos, *area;
3978 int buffer_only_p;
3979 {
3980 struct glyph *glyph, *end;
3981 struct glyph_row *row = NULL;
3982 int x0, i, left_area_width;
3983
3984 /* Find row containing Y. Give up if some row is not enabled. */
3985 for (i = 0; i < w->current_matrix->nrows; ++i)
3986 {
3987 row = MATRIX_ROW (w->current_matrix, i);
3988 if (!row->enabled_p)
3989 return NULL;
3990 if (y >= row->y && y < MATRIX_ROW_BOTTOM_Y (row))
3991 break;
3992 }
3993
3994 *vpos = i;
3995 *hpos = 0;
3996
3997 /* Give up if Y is not in the window. */
3998 if (i == w->current_matrix->nrows)
3999 return NULL;
4000
4001 /* Get the glyph area containing X. */
4002 if (w->pseudo_window_p)
4003 {
4004 *area = TEXT_AREA;
4005 x0 = 0;
4006 }
4007 else
4008 {
4009 left_area_width = window_box_width (w, LEFT_MARGIN_AREA);
4010 if (x < left_area_width)
4011 {
4012 *area = LEFT_MARGIN_AREA;
4013 x0 = 0;
4014 }
4015 else if (x < left_area_width + window_box_width (w, TEXT_AREA))
4016 {
4017 *area = TEXT_AREA;
4018 x0 = row->x + left_area_width;
4019 }
4020 else
4021 {
4022 *area = RIGHT_MARGIN_AREA;
4023 x0 = left_area_width + window_box_width (w, TEXT_AREA);
4024 }
4025 }
4026
4027 /* Find glyph containing X. */
4028 glyph = row->glyphs[*area];
4029 end = glyph + row->used[*area];
4030 while (glyph < end)
4031 {
4032 if (x < x0 + glyph->pixel_width)
4033 {
4034 if (w->pseudo_window_p)
4035 break;
4036 else if (!buffer_only_p || BUFFERP (glyph->object))
4037 break;
4038 }
4039
4040 x0 += glyph->pixel_width;
4041 ++glyph;
4042 }
4043
4044 if (glyph == end)
4045 return NULL;
4046
4047 *hpos = glyph - row->glyphs[*area];
4048 return glyph;
4049 }
4050
4051
4052 /* Convert frame-relative x/y to coordinates relative to window W.
4053 Takes pseudo-windows into account. */
4054
4055 static void
4056 frame_to_window_pixel_xy (w, x, y)
4057 struct window *w;
4058 int *x, *y;
4059 {
4060 if (w->pseudo_window_p)
4061 {
4062 /* A pseudo-window is always full-width, and starts at the
4063 left edge of the frame, plus a frame border. */
4064 struct frame *f = XFRAME (w->frame);
4065 *x -= FRAME_INTERNAL_BORDER_WIDTH_SAFE (f);
4066 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
4067 }
4068 else
4069 {
4070 *x = FRAME_TO_WINDOW_PIXEL_X (w, *x);
4071 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
4072 }
4073 }
4074
4075
4076 /* Take proper action when mouse has moved to the mode or header line
4077 or marginal area of window W, x-position X and y-position Y. Area
4078 is 1, 3, 6 or 7 for the mode line, header line, left and right
4079 marginal area respectively. X is relative to the start of the text
4080 display area of W, so the width of bitmap areas and scroll bars
4081 must be subtracted to get a position relative to the start of the
4082 mode line. */
4083
4084 static void
4085 note_mode_line_or_margin_highlight (w, x, y, portion)
4086 struct window *w;
4087 int x, y, portion;
4088 {
4089 struct frame *f = XFRAME (w->frame);
4090 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
4091 Cursor cursor = dpyinfo->vertical_scroll_bar_cursor;
4092 int charpos;
4093 Lisp_Object string, help, map, pos;
4094
4095 if (portion == 1 || portion == 3)
4096 string = mode_line_string (w, x, y, portion == 1, &charpos);
4097 else
4098 string = marginal_area_string (w, x, y, portion, &charpos);
4099
4100 if (STRINGP (string))
4101 {
4102 pos = make_number (charpos);
4103
4104 /* If we're on a string with `help-echo' text property, arrange
4105 for the help to be displayed. This is done by setting the
4106 global variable help_echo to the help string. */
4107 help = Fget_text_property (pos, Qhelp_echo, string);
4108 if (!NILP (help))
4109 {
4110 help_echo = help;
4111 XSETWINDOW (help_echo_window, w);
4112 help_echo_object = string;
4113 help_echo_pos = charpos;
4114 }
4115
4116 /* Change the mouse pointer according to what is under X/Y. */
4117 map = Fget_text_property (pos, Qlocal_map, string);
4118 if (!KEYMAPP (map))
4119 map = Fget_text_property (pos, Qkeymap, string);
4120 if (KEYMAPP (map))
4121 cursor = f->output_data.w32->nontext_cursor;
4122 }
4123
4124 w32_define_cursor (FRAME_W32_WINDOW (f), cursor);
4125 }
4126
4127
4128 /* Take proper action when the mouse has moved to position X, Y on
4129 frame F as regards highlighting characters that have mouse-face
4130 properties. Also de-highlighting chars where the mouse was before.
4131 X and Y can be negative or out of range. */
4132
4133 static void
4134 note_mouse_highlight (f, x, y)
4135 struct frame *f;
4136 int x, y;
4137 {
4138 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
4139 int portion;
4140 Lisp_Object window;
4141 struct window *w;
4142 Cursor cursor = 0;
4143 struct buffer *b;
4144
4145 /* When a menu is active, don't highlight because this looks odd. */
4146 if (popup_activated ())
4147 return;
4148
4149 if (NILP (Vmouse_highlight)
4150 || !f->glyphs_initialized_p)
4151 return;
4152
4153 dpyinfo->mouse_face_mouse_x = x;
4154 dpyinfo->mouse_face_mouse_y = y;
4155 dpyinfo->mouse_face_mouse_frame = f;
4156
4157 if (dpyinfo->mouse_face_defer)
4158 return;
4159
4160 if (gc_in_progress)
4161 {
4162 dpyinfo->mouse_face_deferred_gc = 1;
4163 return;
4164 }
4165
4166 /* Which window is that in? */
4167 window = window_from_coordinates (f, x, y, &portion, 1);
4168
4169 /* If we were displaying active text in another window, clear that. */
4170 if (! EQ (window, dpyinfo->mouse_face_window))
4171 clear_mouse_face (dpyinfo);
4172
4173 /* Not on a window -> return. */
4174 if (!WINDOWP (window))
4175 return;
4176
4177 /* Reset help_echo. It will get recomputed below. */
4178 help_echo = Qnil;
4179
4180 /* Convert to window-relative pixel coordinates. */
4181 w = XWINDOW (window);
4182 frame_to_window_pixel_xy (w, &x, &y);
4183
4184 /* Handle tool-bar window differently since it doesn't display a
4185 buffer. */
4186 if (EQ (window, f->tool_bar_window))
4187 {
4188 note_tool_bar_highlight (f, x, y);
4189 return;
4190 }
4191
4192 /* Mouse is on the mode or header line? */
4193 if (portion == 1 || portion == 3 || portion == 6 || portion == 7)
4194 {
4195 note_mode_line_or_margin_highlight (w, x, y, portion);
4196 return;
4197 }
4198
4199 if (portion == 2)
4200 cursor = f->output_data.w32->horizontal_drag_cursor;
4201 else
4202 cursor = f->output_data.w32->text_cursor;
4203
4204 /* Are we in a window whose display is up to date?
4205 And verify the buffer's text has not changed. */
4206 b = XBUFFER (w->buffer);
4207 if (/* Within text portion of the window. */
4208 portion == 0
4209 && EQ (w->window_end_valid, w->buffer)
4210 && XFASTINT (w->last_modified) == BUF_MODIFF (b)
4211 && XFASTINT (w->last_overlay_modified) == BUF_OVERLAY_MODIFF (b))
4212 {
4213 int hpos, vpos, pos, i, area;
4214 struct glyph *glyph;
4215 Lisp_Object object;
4216 Lisp_Object mouse_face = Qnil, overlay = Qnil, position;
4217 Lisp_Object *overlay_vec = NULL;
4218 int len, noverlays;
4219 struct buffer *obuf;
4220 int obegv, ozv, same_region;
4221
4222 /* Find the glyph under X/Y. */
4223 glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, &area, 0);
4224
4225 /* Clear mouse face if X/Y not over text. */
4226 if (glyph == NULL
4227 || area != TEXT_AREA
4228 || !MATRIX_ROW (w->current_matrix, vpos)->displays_text_p)
4229 {
4230 clear_mouse_face (dpyinfo);
4231 cursor = f->output_data.w32->nontext_cursor;
4232 goto set_cursor;
4233 }
4234
4235 pos = glyph->charpos;
4236 object = glyph->object;
4237 if (!STRINGP (object) && !BUFFERP (object))
4238 goto set_cursor;
4239
4240 /* If we get an out-of-range value, return now; avoid an error. */
4241 if (BUFFERP (object) && pos > BUF_Z (b))
4242 goto set_cursor;
4243
4244 /* Make the window's buffer temporarily current for
4245 overlays_at and compute_char_face. */
4246 obuf = current_buffer;
4247 current_buffer = b;
4248 obegv = BEGV;
4249 ozv = ZV;
4250 BEGV = BEG;
4251 ZV = Z;
4252
4253 /* Is this char mouse-active or does it have help-echo? */
4254 position = make_number (pos);
4255
4256 if (BUFFERP (object))
4257 {
4258 /* Put all the overlays we want in a vector in overlay_vec.
4259 Store the length in len. If there are more than 10, make
4260 enough space for all, and try again. */
4261 len = 10;
4262 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
4263 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL, 0);
4264 if (noverlays > len)
4265 {
4266 len = noverlays;
4267 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
4268 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL,0);
4269 }
4270
4271 /* Sort overlays into increasing priority order. */
4272 noverlays = sort_overlays (overlay_vec, noverlays, w);
4273 }
4274 else
4275 noverlays = 0;
4276
4277 same_region = (EQ (window, dpyinfo->mouse_face_window)
4278 && vpos >= dpyinfo->mouse_face_beg_row
4279 && vpos <= dpyinfo->mouse_face_end_row
4280 && (vpos > dpyinfo->mouse_face_beg_row
4281 || hpos >= dpyinfo->mouse_face_beg_col)
4282 && (vpos < dpyinfo->mouse_face_end_row
4283 || hpos < dpyinfo->mouse_face_end_col
4284 || dpyinfo->mouse_face_past_end));
4285
4286 if (same_region)
4287 cursor = 0;
4288
4289 /* Check mouse-face highlighting. */
4290 if (! same_region
4291 /* If there exists an overlay with mouse-face overlapping
4292 the one we are currently highlighting, we have to
4293 check if we enter the overlapping overlay, and then
4294 highlight that. */
4295 || (OVERLAYP (dpyinfo->mouse_face_overlay)
4296 && mouse_face_overlay_overlaps (dpyinfo->mouse_face_overlay)))
4297 {
4298 /* Find the highest priority overlay that has a mouse-face
4299 property. */
4300 overlay = Qnil;
4301 for (i = noverlays - 1; i >= 0 && NILP (overlay); --i)
4302 {
4303 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
4304 if (!NILP (mouse_face))
4305 overlay = overlay_vec[i];
4306 }
4307
4308 /* If we're actually highlighting the same overlay as
4309 before, there's no need to do that again. */
4310 if (!NILP (overlay)
4311 && EQ (overlay, dpyinfo->mouse_face_overlay))
4312 goto check_help_echo;
4313
4314 dpyinfo->mouse_face_overlay = overlay;
4315
4316 /* Clear the display of the old active region, if any. */
4317 if (clear_mouse_face (dpyinfo))
4318 cursor = 0;
4319
4320 /* If no overlay applies, get a text property. */
4321 if (NILP (overlay))
4322 mouse_face = Fget_text_property (position, Qmouse_face, object);
4323
4324 /* Handle the overlay case. */
4325 if (!NILP (overlay))
4326 {
4327 /* Find the range of text around this char that
4328 should be active. */
4329 Lisp_Object before, after;
4330 int ignore;
4331
4332 before = Foverlay_start (overlay);
4333 after = Foverlay_end (overlay);
4334 /* Record this as the current active region. */
4335 fast_find_position (w, XFASTINT (before),
4336 &dpyinfo->mouse_face_beg_col,
4337 &dpyinfo->mouse_face_beg_row,
4338 &dpyinfo->mouse_face_beg_x,
4339 &dpyinfo->mouse_face_beg_y, Qnil);
4340
4341 dpyinfo->mouse_face_past_end
4342 = !fast_find_position (w, XFASTINT (after),
4343 &dpyinfo->mouse_face_end_col,
4344 &dpyinfo->mouse_face_end_row,
4345 &dpyinfo->mouse_face_end_x,
4346 &dpyinfo->mouse_face_end_y, Qnil);
4347 dpyinfo->mouse_face_window = window;
4348
4349 dpyinfo->mouse_face_face_id
4350 = face_at_buffer_position (w, pos, 0, 0,
4351 &ignore, pos + 1,
4352 !dpyinfo->mouse_face_hidden);
4353
4354 /* Display it as active. */
4355 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
4356 cursor = 0;
4357 }
4358 /* Handle the text property case. */
4359 else if (! NILP (mouse_face) && BUFFERP (object))
4360 {
4361 /* Find the range of text around this char that
4362 should be active. */
4363 Lisp_Object before, after, beginning, end;
4364 int ignore;
4365
4366 beginning = Fmarker_position (w->start);
4367 end = make_number (BUF_Z (XBUFFER (object))
4368 - XFASTINT (w->window_end_pos));
4369 before
4370 = Fprevious_single_property_change (make_number (pos + 1),
4371 Qmouse_face,
4372 object, beginning);
4373 after
4374 = Fnext_single_property_change (position, Qmouse_face,
4375 object, end);
4376
4377 /* Record this as the current active region. */
4378 fast_find_position (w, XFASTINT (before),
4379 &dpyinfo->mouse_face_beg_col,
4380 &dpyinfo->mouse_face_beg_row,
4381 &dpyinfo->mouse_face_beg_x,
4382 &dpyinfo->mouse_face_beg_y, Qnil);
4383 dpyinfo->mouse_face_past_end
4384 = !fast_find_position (w, XFASTINT (after),
4385 &dpyinfo->mouse_face_end_col,
4386 &dpyinfo->mouse_face_end_row,
4387 &dpyinfo->mouse_face_end_x,
4388 &dpyinfo->mouse_face_end_y, Qnil);
4389 dpyinfo->mouse_face_window = window;
4390
4391 if (BUFFERP (object))
4392 dpyinfo->mouse_face_face_id
4393 = face_at_buffer_position (w, pos, 0, 0,
4394 &ignore, pos + 1,
4395 !dpyinfo->mouse_face_hidden);
4396
4397 /* Display it as active. */
4398 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
4399 cursor = 0;
4400 }
4401 else if (!NILP (mouse_face) && STRINGP (object))
4402 {
4403 Lisp_Object b, e;
4404 int ignore;
4405
4406 b = Fprevious_single_property_change (make_number (pos + 1),
4407 Qmouse_face,
4408 object, Qnil);
4409 e = Fnext_single_property_change (position, Qmouse_face,
4410 object, Qnil);
4411 if (NILP (b))
4412 b = make_number (0);
4413 if (NILP (e))
4414 e = make_number (SCHARS (object) - 1);
4415 fast_find_string_pos (w, XINT (b), object,
4416 &dpyinfo->mouse_face_beg_col,
4417 &dpyinfo->mouse_face_beg_row,
4418 &dpyinfo->mouse_face_beg_x,
4419 &dpyinfo->mouse_face_beg_y, 0);
4420 fast_find_string_pos (w, XINT (e), object,
4421 &dpyinfo->mouse_face_end_col,
4422 &dpyinfo->mouse_face_end_row,
4423 &dpyinfo->mouse_face_end_x,
4424 &dpyinfo->mouse_face_end_y, 1);
4425 dpyinfo->mouse_face_past_end = 0;
4426 dpyinfo->mouse_face_window = window;
4427 dpyinfo->mouse_face_face_id
4428 = face_at_string_position (w, object, pos, 0, 0, 0, &ignore,
4429 glyph->face_id, 1);
4430 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
4431 cursor = 0;
4432 }
4433 else if (STRINGP (object) && NILP (mouse_face))
4434 {
4435 /* A string which doesn't have mouse-face, but
4436 the text ``under'' it might have. */
4437 struct glyph_row *r = MATRIX_ROW (w->current_matrix, vpos);
4438 int start = MATRIX_ROW_START_CHARPOS (r);
4439
4440 pos = string_buffer_position (w, object, start);
4441 if (pos > 0)
4442 mouse_face = get_char_property_and_overlay (make_number (pos),
4443 Qmouse_face,
4444 w->buffer,
4445 &overlay);
4446 if (!NILP (mouse_face) && !NILP (overlay))
4447 {
4448 Lisp_Object before = Foverlay_start (overlay);
4449 Lisp_Object after = Foverlay_end (overlay);
4450 int ignore;
4451
4452 /* Note that we might not be able to find position
4453 BEFORE in the glyph matrix if the overlay is
4454 entirely covered by a `display' property. In
4455 this case, we overshoot. So let's stop in
4456 the glyph matrix before glyphs for OBJECT. */
4457 fast_find_position (w, XFASTINT (before),
4458 &dpyinfo->mouse_face_beg_col,
4459 &dpyinfo->mouse_face_beg_row,
4460 &dpyinfo->mouse_face_beg_x,
4461 &dpyinfo->mouse_face_beg_y,
4462 object);
4463
4464 dpyinfo->mouse_face_past_end
4465 = !fast_find_position (w, XFASTINT (after),
4466 &dpyinfo->mouse_face_end_col,
4467 &dpyinfo->mouse_face_end_row,
4468 &dpyinfo->mouse_face_end_x,
4469 &dpyinfo->mouse_face_end_y,
4470 Qnil);
4471 dpyinfo->mouse_face_window = window;
4472 dpyinfo->mouse_face_face_id
4473 = face_at_buffer_position (w, pos, 0, 0,
4474 &ignore, pos + 1,
4475 !dpyinfo->mouse_face_hidden);
4476
4477 /* Display it as active. */
4478 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
4479 cursor = 0;
4480 }
4481 }
4482 }
4483
4484 check_help_echo:
4485
4486 /* Look for a `help-echo' property. */
4487 {
4488 Lisp_Object help, overlay;
4489
4490 /* Check overlays first. */
4491 help = overlay = Qnil;
4492 for (i = noverlays - 1; i >= 0 && NILP (help); --i)
4493 {
4494 overlay = overlay_vec[i];
4495 help = Foverlay_get (overlay, Qhelp_echo);
4496 }
4497
4498 if (!NILP (help))
4499 {
4500 help_echo = help;
4501 help_echo_window = window;
4502 help_echo_object = overlay;
4503 help_echo_pos = pos;
4504 }
4505 else
4506 {
4507 Lisp_Object object = glyph->object;
4508 int charpos = glyph->charpos;
4509
4510 /* Try text properties. */
4511 if (STRINGP (object)
4512 && charpos >= 0
4513 && charpos < SCHARS (object))
4514 {
4515 help = Fget_text_property (make_number (charpos),
4516 Qhelp_echo, object);
4517 if (NILP (help))
4518 {
4519 /* If the string itself doesn't specify a help-echo,
4520 see if the buffer text ``under'' it does. */
4521 struct glyph_row *r
4522 = MATRIX_ROW (w->current_matrix, vpos);
4523 int start = MATRIX_ROW_START_CHARPOS (r);
4524 int pos = string_buffer_position (w, object, start);
4525 if (pos > 0)
4526 {
4527 help = Fget_char_property (make_number (pos),
4528 Qhelp_echo, w->buffer);
4529 if (!NILP (help))
4530 {
4531 charpos = pos;
4532 object = w->buffer;
4533 }
4534 }
4535 }
4536 }
4537 else if (BUFFERP (object)
4538 && charpos >= BEGV
4539 && charpos < ZV)
4540 help = Fget_text_property (make_number (charpos), Qhelp_echo,
4541 object);
4542
4543 if (!NILP (help))
4544 {
4545 help_echo = help;
4546 help_echo_window = window;
4547 help_echo_object = object;
4548 help_echo_pos = charpos;
4549 }
4550 }
4551 }
4552
4553 BEGV = obegv;
4554 ZV = ozv;
4555 current_buffer = obuf;
4556 }
4557
4558 set_cursor:
4559 if (cursor)
4560 w32_define_cursor (FRAME_W32_WINDOW (f), cursor);
4561 }
4562
4563 static void
4564 redo_mouse_highlight ()
4565 {
4566 if (!NILP (last_mouse_motion_frame)
4567 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame)))
4568 note_mouse_highlight (XFRAME (last_mouse_motion_frame),
4569 LOWORD (last_mouse_motion_event.lParam),
4570 HIWORD (last_mouse_motion_event.lParam));
4571 }
4572
4573 void
4574 w32_define_cursor (window, cursor)
4575 Window window;
4576 Cursor cursor;
4577 {
4578 PostMessage (window, WM_EMACS_SETCURSOR, (WPARAM) cursor, 0);
4579 }
4580
4581 \f
4582 /***********************************************************************
4583 Tool-bars
4584 ***********************************************************************/
4585
4586 static int x_tool_bar_item P_ ((struct frame *, int, int,
4587 struct glyph **, int *, int *, int *));
4588
4589 /* Tool-bar item index of the item on which a mouse button was pressed
4590 or -1. */
4591
4592 static int last_tool_bar_item;
4593
4594
4595 /* Get information about the tool-bar item at position X/Y on frame F.
4596 Return in *GLYPH a pointer to the glyph of the tool-bar item in
4597 the current matrix of the tool-bar window of F, or NULL if not
4598 on a tool-bar item. Return in *PROP_IDX the index of the tool-bar
4599 item in F->tool_bar_items. Value is
4600
4601 -1 if X/Y is not on a tool-bar item
4602 0 if X/Y is on the same item that was highlighted before.
4603 1 otherwise. */
4604
4605 static int
4606 x_tool_bar_item (f, x, y, glyph, hpos, vpos, prop_idx)
4607 struct frame *f;
4608 int x, y;
4609 struct glyph **glyph;
4610 int *hpos, *vpos, *prop_idx;
4611 {
4612 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
4613 struct window *w = XWINDOW (f->tool_bar_window);
4614 int area;
4615
4616 /* Find the glyph under X/Y. */
4617 *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, &area, 0);
4618 if (*glyph == NULL)
4619 return -1;
4620
4621 /* Get the start of this tool-bar item's properties in
4622 f->tool_bar_items. */
4623 if (!tool_bar_item_info (f, *glyph, prop_idx))
4624 return -1;
4625
4626 /* Is mouse on the highlighted item? */
4627 if (EQ (f->tool_bar_window, dpyinfo->mouse_face_window)
4628 && *vpos >= dpyinfo->mouse_face_beg_row
4629 && *vpos <= dpyinfo->mouse_face_end_row
4630 && (*vpos > dpyinfo->mouse_face_beg_row
4631 || *hpos >= dpyinfo->mouse_face_beg_col)
4632 && (*vpos < dpyinfo->mouse_face_end_row
4633 || *hpos < dpyinfo->mouse_face_end_col
4634 || dpyinfo->mouse_face_past_end))
4635 return 0;
4636
4637 return 1;
4638 }
4639
4640
4641 /* Handle mouse button event on the tool-bar of frame F, at
4642 frame-relative coordinates X/Y. EVENT_TYPE is either ButtionPress
4643 or ButtonRelase. */
4644
4645 static void
4646 w32_handle_tool_bar_click (f, button_event)
4647 struct frame *f;
4648 struct input_event *button_event;
4649 {
4650 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
4651 struct window *w = XWINDOW (f->tool_bar_window);
4652 int hpos, vpos, prop_idx;
4653 struct glyph *glyph;
4654 Lisp_Object enabled_p;
4655 int x = XFASTINT (button_event->x);
4656 int y = XFASTINT (button_event->y);
4657
4658 /* If not on the highlighted tool-bar item, return. */
4659 frame_to_window_pixel_xy (w, &x, &y);
4660 if (x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx) != 0)
4661 return;
4662
4663 /* If item is disabled, do nothing. */
4664 enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
4665 if (NILP (enabled_p))
4666 return;
4667
4668 if (button_event->modifiers & down_modifier)
4669 {
4670 /* Show item in pressed state. */
4671 show_mouse_face (dpyinfo, DRAW_IMAGE_SUNKEN);
4672 dpyinfo->mouse_face_image_state = DRAW_IMAGE_SUNKEN;
4673 last_tool_bar_item = prop_idx;
4674 }
4675 else
4676 {
4677 Lisp_Object key, frame;
4678 struct input_event event;
4679
4680 /* Show item in released state. */
4681 show_mouse_face (dpyinfo, DRAW_IMAGE_RAISED);
4682 dpyinfo->mouse_face_image_state = DRAW_IMAGE_RAISED;
4683
4684 key = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_KEY);
4685
4686 XSETFRAME (frame, f);
4687 event.kind = TOOL_BAR_EVENT;
4688 event.frame_or_window = frame;
4689 event.arg = frame;
4690 kbd_buffer_store_event (&event);
4691
4692 event.kind = TOOL_BAR_EVENT;
4693 event.frame_or_window = frame;
4694 event.arg = key;
4695 /* The keyboard buffer doesn't like the up modifier being set. */
4696 event.modifiers = button_event->modifiers & ~up_modifier;
4697 kbd_buffer_store_event (&event);
4698 last_tool_bar_item = -1;
4699 }
4700 }
4701
4702
4703 /* Possibly highlight a tool-bar item on frame F when mouse moves to
4704 tool-bar window-relative coordinates X/Y. Called from
4705 note_mouse_highlight. */
4706
4707 static void
4708 note_tool_bar_highlight (f, x, y)
4709 struct frame *f;
4710 int x, y;
4711 {
4712 Lisp_Object window = f->tool_bar_window;
4713 struct window *w = XWINDOW (window);
4714 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
4715 int hpos, vpos;
4716 struct glyph *glyph;
4717 struct glyph_row *row;
4718 int i;
4719 Lisp_Object enabled_p;
4720 int prop_idx;
4721 enum draw_glyphs_face draw = DRAW_IMAGE_RAISED;
4722 int mouse_down_p, rc;
4723
4724 /* Function note_mouse_highlight is called with negative x(y
4725 values when mouse moves outside of the frame. */
4726 if (x <= 0 || y <= 0)
4727 {
4728 clear_mouse_face (dpyinfo);
4729 return;
4730 }
4731
4732 rc = x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx);
4733 if (rc < 0)
4734 {
4735 /* Not on tool-bar item. */
4736 clear_mouse_face (dpyinfo);
4737 return;
4738 }
4739 else if (rc == 0)
4740 /* On same tool-bar item as before. */
4741 goto set_help_echo;
4742
4743 clear_mouse_face (dpyinfo);
4744
4745 /* Mouse is down, but on different tool-bar item? */
4746 mouse_down_p = (dpyinfo->grabbed
4747 && f == last_mouse_frame
4748 && FRAME_LIVE_P (f));
4749 if (mouse_down_p
4750 && last_tool_bar_item != prop_idx)
4751 return;
4752
4753 dpyinfo->mouse_face_image_state = DRAW_NORMAL_TEXT;
4754 draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
4755
4756 /* If tool-bar item is not enabled, don't highlight it. */
4757 enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
4758 if (!NILP (enabled_p))
4759 {
4760 /* Compute the x-position of the glyph. In front and past the
4761 image is a space. We include this is the highlighted area. */
4762 row = MATRIX_ROW (w->current_matrix, vpos);
4763 for (i = x = 0; i < hpos; ++i)
4764 x += row->glyphs[TEXT_AREA][i].pixel_width;
4765
4766 /* Record this as the current active region. */
4767 dpyinfo->mouse_face_beg_col = hpos;
4768 dpyinfo->mouse_face_beg_row = vpos;
4769 dpyinfo->mouse_face_beg_x = x;
4770 dpyinfo->mouse_face_beg_y = row->y;
4771 dpyinfo->mouse_face_past_end = 0;
4772
4773 dpyinfo->mouse_face_end_col = hpos + 1;
4774 dpyinfo->mouse_face_end_row = vpos;
4775 dpyinfo->mouse_face_end_x = x + glyph->pixel_width;
4776 dpyinfo->mouse_face_end_y = row->y;
4777 dpyinfo->mouse_face_window = window;
4778 dpyinfo->mouse_face_face_id = TOOL_BAR_FACE_ID;
4779
4780 /* Display it as active. */
4781 show_mouse_face (dpyinfo, draw);
4782 dpyinfo->mouse_face_image_state = draw;
4783 }
4784
4785 set_help_echo:
4786
4787 /* Set help_echo to a help string.to display for this tool-bar item.
4788 w32_read_socket does the rest. */
4789 help_echo_object = help_echo_window = Qnil;
4790 help_echo_pos = -1;
4791 help_echo = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_HELP);
4792 if (NILP (help_echo))
4793 help_echo = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_CAPTION);
4794 }
4795
4796
4797 \f
4798 /* Find the glyph matrix position of buffer position CHARPOS in window
4799 *W. HPOS, *VPOS, *X, and *Y are set to the positions found. W's
4800 current glyphs must be up to date. If CHARPOS is above window
4801 start return (0, 0, 0, 0). If CHARPOS is after end of W, return end
4802 of last line in W. In the row containing CHARPOS, stop before glyphs
4803 having STOP as object. */
4804
4805 #if 0 /* This is a version of fast_find_position that's more correct
4806 in the presence of hscrolling, for example. I didn't install
4807 it right away because the problem fixed is minor, it failed
4808 in 20.x as well, and I think it's too risky to install
4809 so near the release of 21.1. 2001-09-25 gerd. */
4810
4811 static int
4812 fast_find_position (w, charpos, hpos, vpos, x, y, stop)
4813 struct window *w;
4814 int charpos;
4815 int *hpos, *vpos, *x, *y;
4816 Lisp_Object stop;
4817 {
4818 struct glyph_row *row, *first;
4819 struct glyph *glyph, *end;
4820 int i, past_end = 0;
4821
4822 first = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
4823 row = row_containing_pos (w, charpos, first, NULL, 0);
4824 if (row == NULL)
4825 {
4826 if (charpos < MATRIX_ROW_START_CHARPOS (first))
4827 {
4828 *x = *y = *hpos = *vpos = 0;
4829 return 0;
4830 }
4831 else
4832 {
4833 row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos));
4834 past_end = 1;
4835 }
4836 }
4837
4838 *x = row->x;
4839 *y = row->y;
4840 *vpos = MATRIX_ROW_VPOS (row, w->current_matrix);
4841
4842 glyph = row->glyphs[TEXT_AREA];
4843 end = glyph + row->used[TEXT_AREA];
4844
4845 /* Skip over glyphs not having an object at the start of the row.
4846 These are special glyphs like truncation marks on terminal
4847 frames. */
4848 if (row->displays_text_p)
4849 while (glyph < end
4850 && INTEGERP (glyph->object)
4851 && !EQ (stop, glyph->object)
4852 && glyph->charpos < 0)
4853 {
4854 *x += glyph->pixel_width;
4855 ++glyph;
4856 }
4857
4858 while (glyph < end
4859 && !INTEGERP (glyph->object)
4860 && !EQ (stop, glyph->object)
4861 && (!BUFFERP (glyph->object)
4862 || glyph->charpos < charpos))
4863 {
4864 *x += glyph->pixel_width;
4865 ++glyph;
4866 }
4867
4868 *hpos = glyph - row->glyphs[TEXT_AREA];
4869 return past_end;
4870 }
4871
4872 #else /* not 0 */
4873
4874 static int
4875 fast_find_position (w, pos, hpos, vpos, x, y, stop)
4876 struct window *w;
4877 int pos;
4878 int *hpos, *vpos, *x, *y;
4879 Lisp_Object stop;
4880 {
4881 int i;
4882 int lastcol;
4883 int maybe_next_line_p = 0;
4884 int line_start_position;
4885 int yb = window_text_bottom_y (w);
4886 struct glyph_row *row, *best_row;
4887 int row_vpos, best_row_vpos;
4888 int current_x;
4889
4890 row = best_row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
4891 row_vpos = best_row_vpos = MATRIX_ROW_VPOS (row, w->current_matrix);
4892
4893 while (row->y < yb)
4894 {
4895 if (row->used[TEXT_AREA])
4896 line_start_position = row->glyphs[TEXT_AREA]->charpos;
4897 else
4898 line_start_position = 0;
4899
4900 if (line_start_position > pos)
4901 break;
4902 /* If the position sought is the end of the buffer,
4903 don't include the blank lines at the bottom of the window. */
4904 else if (line_start_position == pos
4905 && pos == BUF_ZV (XBUFFER (w->buffer)))
4906 {
4907 maybe_next_line_p = 1;
4908 break;
4909 }
4910 else if (line_start_position > 0)
4911 {
4912 best_row = row;
4913 best_row_vpos = row_vpos;
4914 }
4915
4916 if (row->y + row->height >= yb)
4917 break;
4918
4919 ++row;
4920 ++row_vpos;
4921 }
4922
4923 /* Find the right column within BEST_ROW. */
4924 lastcol = 0;
4925 current_x = best_row->x;
4926 for (i = 0; i < best_row->used[TEXT_AREA]; i++)
4927 {
4928 struct glyph *glyph = best_row->glyphs[TEXT_AREA] + i;
4929 int charpos = glyph->charpos;
4930
4931 if (BUFFERP (glyph->object))
4932 {
4933 if (charpos == pos)
4934 {
4935 *hpos = i;
4936 *vpos = best_row_vpos;
4937 *x = current_x;
4938 *y = best_row->y;
4939 return 1;
4940 }
4941 else if (charpos > pos)
4942 break;
4943 }
4944 else if (EQ (glyph->object, stop))
4945 break;
4946
4947 if (charpos > 0)
4948 lastcol = i;
4949 current_x += glyph->pixel_width;
4950 }
4951
4952 /* If we're looking for the end of the buffer,
4953 and we didn't find it in the line we scanned,
4954 use the start of the following line. */
4955 if (maybe_next_line_p)
4956 {
4957 ++best_row;
4958 ++best_row_vpos;
4959 lastcol = 0;
4960 current_x = best_row->x;
4961 }
4962
4963 *vpos = best_row_vpos;
4964 *hpos = lastcol + 1;
4965 *x = current_x;
4966 *y = best_row->y;
4967 return 0;
4968 }
4969
4970 #endif /* not 0 */
4971
4972
4973 /* Find the position of the glyph for position POS in OBJECT in
4974 window W's current matrix, and return in *X/*Y the pixel
4975 coordinates, and return in *HPOS/*VPOS the column/row of the glyph.
4976
4977 RIGHT_P non-zero means return the position of the right edge of the
4978 glyph, RIGHT_P zero means return the left edge position.
4979
4980 If no glyph for POS exists in the matrix, return the position of
4981 the glyph with the next smaller position that is in the matrix, if
4982 RIGHT_P is zero. If RIGHT_P is non-zero, and no glyph for POS
4983 exists in the matrix, return the position of the glyph with the
4984 next larger position in OBJECT.
4985
4986 Value is non-zero if a glyph was found. */
4987
4988 static int
4989 fast_find_string_pos (w, pos, object, hpos, vpos, x, y, right_p)
4990 struct window *w;
4991 int pos;
4992 Lisp_Object object;
4993 int *hpos, *vpos, *x, *y;
4994 int right_p;
4995 {
4996 int yb = window_text_bottom_y (w);
4997 struct glyph_row *r;
4998 struct glyph *best_glyph = NULL;
4999 struct glyph_row *best_row = NULL;
5000 int best_x = 0;
5001
5002 for (r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
5003 r->enabled_p && r->y < yb;
5004 ++r)
5005 {
5006 struct glyph *g = r->glyphs[TEXT_AREA];
5007 struct glyph *e = g + r->used[TEXT_AREA];
5008 int gx;
5009
5010 for (gx = r->x; g < e; gx += g->pixel_width, ++g)
5011 if (EQ (g->object, object))
5012 {
5013 if (g->charpos == pos)
5014 {
5015 best_glyph = g;
5016 best_x = gx;
5017 best_row = r;
5018 goto found;
5019 }
5020 else if (best_glyph == NULL
5021 || ((abs (g->charpos - pos)
5022 < abs (best_glyph->charpos - pos))
5023 && (right_p
5024 ? g->charpos < pos
5025 : g->charpos > pos)))
5026 {
5027 best_glyph = g;
5028 best_x = gx;
5029 best_row = r;
5030 }
5031 }
5032 }
5033
5034 found:
5035
5036 if (best_glyph)
5037 {
5038 *x = best_x;
5039 *hpos = best_glyph - best_row->glyphs[TEXT_AREA];
5040
5041 if (right_p)
5042 {
5043 *x += best_glyph->pixel_width;
5044 ++*hpos;
5045 }
5046
5047 *y = best_row->y;
5048 *vpos = best_row - w->current_matrix->rows;
5049 }
5050
5051 return best_glyph != NULL;
5052 }
5053
5054
5055 /* Display the active region described by mouse_face_*
5056 in its mouse-face if HL > 0, in its normal face if HL = 0. */
5057
5058 static void
5059 show_mouse_face (dpyinfo, draw)
5060 struct w32_display_info *dpyinfo;
5061 enum draw_glyphs_face draw;
5062 {
5063 struct window *w = XWINDOW (dpyinfo->mouse_face_window);
5064 struct frame *f = XFRAME (WINDOW_FRAME (w));
5065
5066 if (/* If window is in the process of being destroyed, don't bother
5067 to do anything. */
5068 w->current_matrix != NULL
5069 /* Don't update mouse highlight if hidden */
5070 && (draw != DRAW_MOUSE_FACE || !dpyinfo->mouse_face_hidden)
5071 /* Recognize when we are called to operate on rows that don't exist
5072 anymore. This can happen when a window is split. */
5073 && dpyinfo->mouse_face_end_row < w->current_matrix->nrows)
5074 {
5075 int phys_cursor_on_p = w->phys_cursor_on_p;
5076 struct glyph_row *row, *first, *last;
5077
5078 first = MATRIX_ROW (w->current_matrix, dpyinfo->mouse_face_beg_row);
5079 last = MATRIX_ROW (w->current_matrix, dpyinfo->mouse_face_end_row);
5080
5081 for (row = first; row <= last && row->enabled_p; ++row)
5082 {
5083 int start_hpos, end_hpos, start_x;
5084
5085 /* For all but the first row, the highlight starts at column 0. */
5086 if (row == first)
5087 {
5088 start_hpos = dpyinfo->mouse_face_beg_col;
5089 start_x = dpyinfo->mouse_face_beg_x;
5090 }
5091 else
5092 {
5093 start_hpos = 0;
5094 start_x = 0;
5095 }
5096
5097 if (row == last)
5098 end_hpos = dpyinfo->mouse_face_end_col;
5099 else
5100 end_hpos = row->used[TEXT_AREA];
5101
5102 if (end_hpos > start_hpos)
5103 {
5104 x_draw_glyphs (w, start_x, row, TEXT_AREA,
5105 start_hpos, end_hpos, draw, 0);
5106
5107 row->mouse_face_p
5108 = draw == DRAW_MOUSE_FACE || draw == DRAW_IMAGE_RAISED;
5109 }
5110 }
5111
5112 /* When we've written over the cursor, arrange for it to
5113 be displayed again. */
5114 if (phys_cursor_on_p && !w->phys_cursor_on_p)
5115 x_display_cursor (w, 1,
5116 w->phys_cursor.hpos, w->phys_cursor.vpos,
5117 w->phys_cursor.x, w->phys_cursor.y);
5118 }
5119
5120 /* Change the mouse cursor. */
5121 if (draw == DRAW_NORMAL_TEXT)
5122 w32_define_cursor (FRAME_W32_WINDOW (f),
5123 f->output_data.w32->text_cursor);
5124 else if (draw == DRAW_MOUSE_FACE)
5125 w32_define_cursor (FRAME_W32_WINDOW (f),
5126 f->output_data.w32->hand_cursor);
5127 else
5128 w32_define_cursor (FRAME_W32_WINDOW (f),
5129 f->output_data.w32->nontext_cursor);
5130
5131 }
5132
5133 /* Clear out the mouse-highlighted active region.
5134 Redraw it un-highlighted first. */
5135
5136 static int
5137 clear_mouse_face (dpyinfo)
5138 struct w32_display_info *dpyinfo;
5139 {
5140 int cleared = 0;
5141
5142 if (! NILP (dpyinfo->mouse_face_window))
5143 {
5144 show_mouse_face (dpyinfo, DRAW_NORMAL_TEXT);
5145 cleared = 1;
5146 }
5147
5148 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
5149 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
5150 dpyinfo->mouse_face_window = Qnil;
5151 dpyinfo->mouse_face_overlay = Qnil;
5152 return cleared;
5153 }
5154
5155
5156 /* Clear any mouse-face on window W. This function is part of the
5157 redisplay interface, and is called from try_window_id and similar
5158 functions to ensure the mouse-highlight is off. */
5159
5160 static void
5161 x_clear_mouse_face (w)
5162 struct window *w;
5163 {
5164 struct w32_display_info *dpyinfo
5165 = FRAME_W32_DISPLAY_INFO (XFRAME (w->frame));
5166 Lisp_Object window;
5167
5168 BLOCK_INPUT;
5169 XSETWINDOW (window, w);
5170 if (EQ (window, dpyinfo->mouse_face_window))
5171 clear_mouse_face (dpyinfo);
5172 UNBLOCK_INPUT;
5173 }
5174
5175
5176 /* Just discard the mouse face information for frame F, if any.
5177 This is used when the size of F is changed. */
5178
5179 void
5180 cancel_mouse_face (f)
5181 FRAME_PTR f;
5182 {
5183 Lisp_Object window;
5184 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
5185
5186 window = dpyinfo->mouse_face_window;
5187 if (! NILP (window) && XFRAME (XWINDOW (window)->frame) == f)
5188 {
5189 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
5190 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
5191 dpyinfo->mouse_face_window = Qnil;
5192 }
5193 }
5194 \f
5195 static struct scroll_bar *x_window_to_scroll_bar ();
5196 static void x_scroll_bar_report_motion ();
5197 static void x_check_fullscreen P_ ((struct frame *));
5198 static void x_check_fullscreen_move P_ ((struct frame *));
5199 static int glyph_rect P_ ((struct frame *f, int, int, RECT *));
5200
5201
5202 /* Try to determine frame pixel position and size of the glyph under
5203 frame pixel coordinates X/Y on frame F . Return the position and
5204 size in *RECT. Value is non-zero if we could compute these
5205 values. */
5206
5207 static int
5208 glyph_rect (f, x, y, rect)
5209 struct frame *f;
5210 int x, y;
5211 RECT *rect;
5212 {
5213 Lisp_Object window;
5214 int part;
5215
5216 window = window_from_coordinates (f, x, y, &part, 0);
5217 if (!NILP (window))
5218 {
5219 struct window *w = XWINDOW (window);
5220 struct glyph_row *r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
5221 struct glyph_row *end = r + w->current_matrix->nrows - 1;
5222
5223 frame_to_window_pixel_xy (w, &x, &y);
5224
5225 for (; r < end && r->enabled_p; ++r)
5226 if (r->y <= y && r->y + r->height > y)
5227 {
5228 /* Found the row at y. */
5229 struct glyph *g = r->glyphs[TEXT_AREA];
5230 struct glyph *end = g + r->used[TEXT_AREA];
5231 int gx;
5232
5233 rect->top = WINDOW_TO_FRAME_PIXEL_Y (w, r->y);
5234 rect->bottom = rect->top + r->height;
5235
5236 if (x < r->x)
5237 {
5238 /* x is to the left of the first glyph in the row. */
5239 rect->left = XINT (w->left);
5240 rect->right = WINDOW_TO_FRAME_PIXEL_X (w, r->x);
5241 return 1;
5242 }
5243
5244 for (gx = r->x; g < end; gx += g->pixel_width, ++g)
5245 if (gx <= x && gx + g->pixel_width > x)
5246 {
5247 /* x is on a glyph. */
5248 rect->left = WINDOW_TO_FRAME_PIXEL_X (w, gx);
5249 rect->right = rect->left + g->pixel_width;
5250 return 1;
5251 }
5252
5253 /* x is to the right of the last glyph in the row. */
5254 rect->left = WINDOW_TO_FRAME_PIXEL_X (w, gx);
5255 rect->right = XINT (w->left) + XINT (w->width);
5256 return 1;
5257 }
5258 }
5259
5260 /* The y is not on any row. */
5261 return 0;
5262 }
5263
5264 /* Record the position of the mouse in last_mouse_glyph. */
5265 static void
5266 remember_mouse_glyph (f1, gx, gy)
5267 struct frame * f1;
5268 int gx, gy;
5269 {
5270 if (!glyph_rect (f1, gx, gy, &last_mouse_glyph))
5271 {
5272 int width = FRAME_SMALLEST_CHAR_WIDTH (f1);
5273 int height = FRAME_SMALLEST_FONT_HEIGHT (f1);
5274
5275 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to
5276 round down even for negative values. */
5277 if (gx < 0)
5278 gx -= width - 1;
5279 if (gy < 0)
5280 gy -= height - 1;
5281 #if 0
5282 /* This was the original code from XTmouse_position, but it seems
5283 to give the position of the glyph diagonally next to the one
5284 the mouse is over. */
5285 gx = (gx + width - 1) / width * width;
5286 gy = (gy + height - 1) / height * height;
5287 #else
5288 gx = gx / width * width;
5289 gy = gy / height * height;
5290 #endif
5291
5292 last_mouse_glyph.left = gx;
5293 last_mouse_glyph.top = gy;
5294 last_mouse_glyph.right = gx + width;
5295 last_mouse_glyph.bottom = gy + height;
5296 }
5297 }
5298
5299 /* Return the current position of the mouse.
5300 *fp should be a frame which indicates which display to ask about.
5301
5302 If the mouse movement started in a scroll bar, set *fp, *bar_window,
5303 and *part to the frame, window, and scroll bar part that the mouse
5304 is over. Set *x and *y to the portion and whole of the mouse's
5305 position on the scroll bar.
5306
5307 If the mouse movement started elsewhere, set *fp to the frame the
5308 mouse is on, *bar_window to nil, and *x and *y to the character cell
5309 the mouse is over.
5310
5311 Set *time to the server time-stamp for the time at which the mouse
5312 was at this position.
5313
5314 Don't store anything if we don't have a valid set of values to report.
5315
5316 This clears the mouse_moved flag, so we can wait for the next mouse
5317 movement. */
5318
5319 static void
5320 w32_mouse_position (fp, insist, bar_window, part, x, y, time)
5321 FRAME_PTR *fp;
5322 int insist;
5323 Lisp_Object *bar_window;
5324 enum scroll_bar_part *part;
5325 Lisp_Object *x, *y;
5326 unsigned long *time;
5327 {
5328 FRAME_PTR f1;
5329
5330 BLOCK_INPUT;
5331
5332 if (! NILP (last_mouse_scroll_bar) && insist == 0)
5333 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
5334 else
5335 {
5336 POINT pt;
5337
5338 Lisp_Object frame, tail;
5339
5340 /* Clear the mouse-moved flag for every frame on this display. */
5341 FOR_EACH_FRAME (tail, frame)
5342 XFRAME (frame)->mouse_moved = 0;
5343
5344 last_mouse_scroll_bar = Qnil;
5345
5346 GetCursorPos (&pt);
5347
5348 /* Now we have a position on the root; find the innermost window
5349 containing the pointer. */
5350 {
5351 if (FRAME_W32_DISPLAY_INFO (*fp)->grabbed && last_mouse_frame
5352 && FRAME_LIVE_P (last_mouse_frame))
5353 {
5354 /* If mouse was grabbed on a frame, give coords for that frame
5355 even if the mouse is now outside it. */
5356 f1 = last_mouse_frame;
5357 }
5358 else
5359 {
5360 /* Is window under mouse one of our frames? */
5361 f1 = x_any_window_to_frame (FRAME_W32_DISPLAY_INFO (*fp),
5362 WindowFromPoint (pt));
5363 }
5364
5365 /* If not, is it one of our scroll bars? */
5366 if (! f1)
5367 {
5368 struct scroll_bar *bar
5369 = x_window_to_scroll_bar (WindowFromPoint (pt));
5370
5371 if (bar)
5372 {
5373 f1 = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
5374 }
5375 }
5376
5377 if (f1 == 0 && insist > 0)
5378 f1 = SELECTED_FRAME ();
5379
5380 if (f1)
5381 {
5382 /* Ok, we found a frame. Store all the values.
5383 last_mouse_glyph is a rectangle used to reduce the
5384 generation of mouse events. To not miss any motion
5385 events, we must divide the frame into rectangles of the
5386 size of the smallest character that could be displayed
5387 on it, i.e. into the same rectangles that matrices on
5388 the frame are divided into. */
5389
5390 #if OLD_REDISPLAY_CODE
5391 int ignore1, ignore2;
5392
5393 ScreenToClient (FRAME_W32_WINDOW (f1), &pt);
5394
5395 pixel_to_glyph_coords (f1, pt.x, pt.y, &ignore1, &ignore2,
5396 &last_mouse_glyph,
5397 FRAME_W32_DISPLAY_INFO (f1)->grabbed
5398 || insist);
5399 #else
5400 ScreenToClient (FRAME_W32_WINDOW (f1), &pt);
5401 remember_mouse_glyph (f1, pt.x, pt.y);
5402 #endif
5403
5404 *bar_window = Qnil;
5405 *part = 0;
5406 *fp = f1;
5407 XSETINT (*x, pt.x);
5408 XSETINT (*y, pt.y);
5409 *time = last_mouse_movement_time;
5410 }
5411 }
5412 }
5413
5414 UNBLOCK_INPUT;
5415 }
5416
5417 \f
5418 /* Scroll bar support. */
5419
5420 /* Given a window ID, find the struct scroll_bar which manages it.
5421 This can be called in GC, so we have to make sure to strip off mark
5422 bits. */
5423
5424 static struct scroll_bar *
5425 x_window_to_scroll_bar (window_id)
5426 Window window_id;
5427 {
5428 Lisp_Object tail;
5429
5430 for (tail = Vframe_list;
5431 XGCTYPE (tail) == Lisp_Cons;
5432 tail = XCDR (tail))
5433 {
5434 Lisp_Object frame, bar, condemned;
5435
5436 frame = XCAR (tail);
5437 /* All elements of Vframe_list should be frames. */
5438 if (! GC_FRAMEP (frame))
5439 abort ();
5440
5441 /* Scan this frame's scroll bar list for a scroll bar with the
5442 right window ID. */
5443 condemned = FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame));
5444 for (bar = FRAME_SCROLL_BARS (XFRAME (frame));
5445 /* This trick allows us to search both the ordinary and
5446 condemned scroll bar lists with one loop. */
5447 ! GC_NILP (bar) || (bar = condemned,
5448 condemned = Qnil,
5449 ! GC_NILP (bar));
5450 bar = XSCROLL_BAR (bar)->next)
5451 if (SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar)) == window_id)
5452 return XSCROLL_BAR (bar);
5453 }
5454
5455 return 0;
5456 }
5457
5458
5459 \f
5460 /* Set the thumb size and position of scroll bar BAR. We are currently
5461 displaying PORTION out of a whole WHOLE, and our position POSITION. */
5462
5463 static void
5464 w32_set_scroll_bar_thumb (bar, portion, position, whole)
5465 struct scroll_bar *bar;
5466 int portion, position, whole;
5467 {
5468 Window w = SCROLL_BAR_W32_WINDOW (bar);
5469 double range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
5470 int sb_page, sb_pos;
5471 BOOL draggingp = !NILP (bar->dragging) ? TRUE : FALSE;
5472
5473 if (whole)
5474 {
5475 /* Position scroll bar at rock bottom if the bottom of the
5476 buffer is visible. This avoids shinking the thumb away
5477 to nothing if it is held at the bottom of the buffer. */
5478 if (position + portion >= whole)
5479 {
5480 sb_page = range * (whole - position) / whole
5481 + VERTICAL_SCROLL_BAR_MIN_HANDLE;
5482 sb_pos = range;
5483 }
5484
5485 sb_page = portion * range / whole + VERTICAL_SCROLL_BAR_MIN_HANDLE;
5486 sb_pos = position * range / whole;
5487 }
5488 else
5489 {
5490 sb_page = range;
5491 sb_pos = 0;
5492 }
5493
5494 BLOCK_INPUT;
5495
5496 if (pfnSetScrollInfo)
5497 {
5498 SCROLLINFO si;
5499
5500 si.cbSize = sizeof (si);
5501 /* Only update page size if currently dragging, to reduce
5502 flicker effects. */
5503 if (draggingp)
5504 si.fMask = SIF_PAGE;
5505 else
5506 si.fMask = SIF_PAGE | SIF_POS;
5507 si.nPage = sb_page;
5508 si.nPos = sb_pos;
5509
5510 pfnSetScrollInfo (w, SB_CTL, &si, !draggingp);
5511 }
5512 else
5513 SetScrollPos (w, SB_CTL, sb_pos, !draggingp);
5514
5515 UNBLOCK_INPUT;
5516 }
5517
5518 \f
5519 /************************************************************************
5520 Scroll bars, general
5521 ************************************************************************/
5522
5523 HWND
5524 my_create_scrollbar (f, bar)
5525 struct frame * f;
5526 struct scroll_bar * bar;
5527 {
5528 return (HWND) SendMessage (FRAME_W32_WINDOW (f),
5529 WM_EMACS_CREATESCROLLBAR, (WPARAM) f,
5530 (LPARAM) bar);
5531 }
5532
5533 /*#define ATTACH_THREADS*/
5534
5535 BOOL
5536 my_show_window (FRAME_PTR f, HWND hwnd, int how)
5537 {
5538 #ifndef ATTACH_THREADS
5539 return SendMessage (FRAME_W32_WINDOW (f), WM_EMACS_SHOWWINDOW,
5540 (WPARAM) hwnd, (LPARAM) how);
5541 #else
5542 return ShowWindow (hwnd, how);
5543 #endif
5544 }
5545
5546 void
5547 my_set_window_pos (HWND hwnd, HWND hwndAfter,
5548 int x, int y, int cx, int cy, UINT flags)
5549 {
5550 #ifndef ATTACH_THREADS
5551 WINDOWPOS pos;
5552 pos.hwndInsertAfter = hwndAfter;
5553 pos.x = x;
5554 pos.y = y;
5555 pos.cx = cx;
5556 pos.cy = cy;
5557 pos.flags = flags;
5558 SendMessage (hwnd, WM_EMACS_SETWINDOWPOS, (WPARAM) &pos, 0);
5559 #else
5560 SetWindowPos (hwnd, hwndAfter, x, y, cx, cy, flags);
5561 #endif
5562 }
5563
5564 void
5565 my_set_focus (f, hwnd)
5566 struct frame * f;
5567 HWND hwnd;
5568 {
5569 SendMessage (FRAME_W32_WINDOW (f), WM_EMACS_SETFOCUS,
5570 (WPARAM) hwnd, 0);
5571 }
5572
5573 void
5574 my_set_foreground_window (hwnd)
5575 HWND hwnd;
5576 {
5577 SendMessage (hwnd, WM_EMACS_SETFOREGROUND, (WPARAM) hwnd, 0);
5578 }
5579
5580 void
5581 my_destroy_window (f, hwnd)
5582 struct frame * f;
5583 HWND hwnd;
5584 {
5585 SendMessage (FRAME_W32_WINDOW (f), WM_EMACS_DESTROYWINDOW,
5586 (WPARAM) hwnd, 0);
5587 }
5588
5589 /* Create a scroll bar and return the scroll bar vector for it. W is
5590 the Emacs window on which to create the scroll bar. TOP, LEFT,
5591 WIDTH and HEIGHT are.the pixel coordinates and dimensions of the
5592 scroll bar. */
5593
5594 static struct scroll_bar *
5595 x_scroll_bar_create (w, top, left, width, height)
5596 struct window *w;
5597 int top, left, width, height;
5598 {
5599 struct frame *f = XFRAME (WINDOW_FRAME (w));
5600 HWND hwnd;
5601 struct scroll_bar *bar
5602 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
5603
5604 BLOCK_INPUT;
5605
5606 XSETWINDOW (bar->window, w);
5607 XSETINT (bar->top, top);
5608 XSETINT (bar->left, left);
5609 XSETINT (bar->width, width);
5610 XSETINT (bar->height, height);
5611 XSETINT (bar->start, 0);
5612 XSETINT (bar->end, 0);
5613 bar->dragging = Qnil;
5614
5615 /* Requires geometry to be set before call to create the real window */
5616
5617 hwnd = my_create_scrollbar (f, bar);
5618
5619 if (pfnSetScrollInfo)
5620 {
5621 SCROLLINFO si;
5622
5623 si.cbSize = sizeof (si);
5624 si.fMask = SIF_ALL;
5625 si.nMin = 0;
5626 si.nMax = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height)
5627 + VERTICAL_SCROLL_BAR_MIN_HANDLE;
5628 si.nPage = si.nMax;
5629 si.nPos = 0;
5630
5631 pfnSetScrollInfo (hwnd, SB_CTL, &si, FALSE);
5632 }
5633 else
5634 {
5635 SetScrollRange (hwnd, SB_CTL, 0,
5636 VERTICAL_SCROLL_BAR_TOP_RANGE (f, height), FALSE);
5637 SetScrollPos (hwnd, SB_CTL, 0, FALSE);
5638 }
5639
5640 SET_SCROLL_BAR_W32_WINDOW (bar, hwnd);
5641
5642 /* Add bar to its frame's list of scroll bars. */
5643 bar->next = FRAME_SCROLL_BARS (f);
5644 bar->prev = Qnil;
5645 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
5646 if (! NILP (bar->next))
5647 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
5648
5649 UNBLOCK_INPUT;
5650
5651 return bar;
5652 }
5653
5654
5655 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
5656 nil. */
5657
5658 static void
5659 x_scroll_bar_remove (bar)
5660 struct scroll_bar *bar;
5661 {
5662 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
5663
5664 BLOCK_INPUT;
5665
5666 /* Destroy the window. */
5667 my_destroy_window (f, SCROLL_BAR_W32_WINDOW (bar));
5668
5669 /* Disassociate this scroll bar from its window. */
5670 XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
5671
5672 UNBLOCK_INPUT;
5673 }
5674
5675 /* Set the handle of the vertical scroll bar for WINDOW to indicate
5676 that we are displaying PORTION characters out of a total of WHOLE
5677 characters, starting at POSITION. If WINDOW has no scroll bar,
5678 create one. */
5679 static void
5680 w32_set_vertical_scroll_bar (w, portion, whole, position)
5681 struct window *w;
5682 int portion, whole, position;
5683 {
5684 struct frame *f = XFRAME (w->frame);
5685 struct scroll_bar *bar;
5686 int top, height, left, sb_left, width, sb_width;
5687 int window_x, window_y, window_width, window_height;
5688
5689 /* Get window dimensions. */
5690 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
5691 top = window_y;
5692 width = FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f);
5693 height = window_height;
5694
5695 /* Compute the left edge of the scroll bar area. */
5696 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
5697 left = XINT (w->left) + XINT (w->width) - FRAME_SCROLL_BAR_COLS (f);
5698 else
5699 left = XFASTINT (w->left);
5700 left *= CANON_X_UNIT (f);
5701 left += FRAME_INTERNAL_BORDER_WIDTH (f);
5702
5703 /* Compute the width of the scroll bar which might be less than
5704 the width of the area reserved for the scroll bar. */
5705 if (FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0)
5706 sb_width = FRAME_SCROLL_BAR_PIXEL_WIDTH (f);
5707 else
5708 sb_width = width;
5709
5710 /* Compute the left edge of the scroll bar. */
5711 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
5712 sb_left = left + width - sb_width - (width - sb_width) / 2;
5713 else
5714 sb_left = left + (width - sb_width) / 2;
5715
5716 /* Does the scroll bar exist yet? */
5717 if (NILP (w->vertical_scroll_bar))
5718 {
5719 HDC hdc;
5720 BLOCK_INPUT;
5721 if (width > 0 && height > 0)
5722 {
5723 hdc = get_frame_dc (f);
5724 w32_clear_area (f, hdc, left, top, width, height);
5725 release_frame_dc (f, hdc);
5726 }
5727 UNBLOCK_INPUT;
5728
5729 bar = x_scroll_bar_create (w, top, sb_left, sb_width, height);
5730 }
5731 else
5732 {
5733 /* It may just need to be moved and resized. */
5734 HWND hwnd;
5735
5736 bar = XSCROLL_BAR (w->vertical_scroll_bar);
5737 hwnd = SCROLL_BAR_W32_WINDOW (bar);
5738
5739 /* If already correctly positioned, do nothing. */
5740 if ( XINT (bar->left) == sb_left
5741 && XINT (bar->top) == top
5742 && XINT (bar->width) == sb_width
5743 && XINT (bar->height) == height )
5744 {
5745 /* Redraw after clear_frame. */
5746 if (!my_show_window (f, hwnd, SW_NORMAL))
5747 InvalidateRect (hwnd, NULL, FALSE);
5748 }
5749 else
5750 {
5751 HDC hdc;
5752 BLOCK_INPUT;
5753 if (width && height)
5754 {
5755 hdc = get_frame_dc (f);
5756 /* Since Windows scroll bars are smaller than the space reserved
5757 for them on the frame, we have to clear "under" them. */
5758 w32_clear_area (f, hdc,
5759 left,
5760 top,
5761 width,
5762 height);
5763 release_frame_dc (f, hdc);
5764 }
5765 /* Make sure scroll bar is "visible" before moving, to ensure the
5766 area of the parent window now exposed will be refreshed. */
5767 my_show_window (f, hwnd, SW_HIDE);
5768 MoveWindow (hwnd, sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
5769 top, sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
5770 max (height, 1), TRUE);
5771 if (pfnSetScrollInfo)
5772 {
5773 SCROLLINFO si;
5774
5775 si.cbSize = sizeof (si);
5776 si.fMask = SIF_RANGE;
5777 si.nMin = 0;
5778 si.nMax = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height)
5779 + VERTICAL_SCROLL_BAR_MIN_HANDLE;
5780
5781 pfnSetScrollInfo (hwnd, SB_CTL, &si, FALSE);
5782 }
5783 else
5784 SetScrollRange (hwnd, SB_CTL, 0,
5785 VERTICAL_SCROLL_BAR_TOP_RANGE (f, height), FALSE);
5786 my_show_window (f, hwnd, SW_NORMAL);
5787 /* InvalidateRect (w, NULL, FALSE); */
5788
5789 /* Remember new settings. */
5790 XSETINT (bar->left, sb_left);
5791 XSETINT (bar->top, top);
5792 XSETINT (bar->width, sb_width);
5793 XSETINT (bar->height, height);
5794
5795 UNBLOCK_INPUT;
5796 }
5797 }
5798 w32_set_scroll_bar_thumb (bar, portion, position, whole);
5799
5800 XSETVECTOR (w->vertical_scroll_bar, bar);
5801 }
5802
5803
5804 /* The following three hooks are used when we're doing a thorough
5805 redisplay of the frame. We don't explicitly know which scroll bars
5806 are going to be deleted, because keeping track of when windows go
5807 away is a real pain - "Can you say set-window-configuration, boys
5808 and girls?" Instead, we just assert at the beginning of redisplay
5809 that *all* scroll bars are to be removed, and then save a scroll bar
5810 from the fiery pit when we actually redisplay its window. */
5811
5812 /* Arrange for all scroll bars on FRAME to be removed at the next call
5813 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
5814 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
5815
5816 static void
5817 w32_condemn_scroll_bars (frame)
5818 FRAME_PTR frame;
5819 {
5820 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
5821 while (! NILP (FRAME_SCROLL_BARS (frame)))
5822 {
5823 Lisp_Object bar;
5824 bar = FRAME_SCROLL_BARS (frame);
5825 FRAME_SCROLL_BARS (frame) = XSCROLL_BAR (bar)->next;
5826 XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
5827 XSCROLL_BAR (bar)->prev = Qnil;
5828 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
5829 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
5830 FRAME_CONDEMNED_SCROLL_BARS (frame) = bar;
5831 }
5832 }
5833
5834
5835 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
5836 Note that WINDOW isn't necessarily condemned at all. */
5837
5838 static void
5839 w32_redeem_scroll_bar (window)
5840 struct window *window;
5841 {
5842 struct scroll_bar *bar;
5843 struct frame *f;
5844
5845 /* We can't redeem this window's scroll bar if it doesn't have one. */
5846 if (NILP (window->vertical_scroll_bar))
5847 abort ();
5848
5849 bar = XSCROLL_BAR (window->vertical_scroll_bar);
5850
5851 /* Unlink it from the condemned list. */
5852 f = XFRAME (WINDOW_FRAME (window));
5853 if (NILP (bar->prev))
5854 {
5855 /* If the prev pointer is nil, it must be the first in one of
5856 the lists. */
5857 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
5858 /* It's not condemned. Everything's fine. */
5859 return;
5860 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
5861 window->vertical_scroll_bar))
5862 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
5863 else
5864 /* If its prev pointer is nil, it must be at the front of
5865 one or the other! */
5866 abort ();
5867 }
5868 else
5869 XSCROLL_BAR (bar->prev)->next = bar->next;
5870
5871 if (! NILP (bar->next))
5872 XSCROLL_BAR (bar->next)->prev = bar->prev;
5873
5874 bar->next = FRAME_SCROLL_BARS (f);
5875 bar->prev = Qnil;
5876 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
5877 if (! NILP (bar->next))
5878 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
5879 }
5880
5881 /* Remove all scroll bars on FRAME that haven't been saved since the
5882 last call to `*condemn_scroll_bars_hook'. */
5883
5884 static void
5885 w32_judge_scroll_bars (f)
5886 FRAME_PTR f;
5887 {
5888 Lisp_Object bar, next;
5889
5890 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
5891
5892 /* Clear out the condemned list now so we won't try to process any
5893 more events on the hapless scroll bars. */
5894 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
5895
5896 for (; ! NILP (bar); bar = next)
5897 {
5898 struct scroll_bar *b = XSCROLL_BAR (bar);
5899
5900 x_scroll_bar_remove (b);
5901
5902 next = b->next;
5903 b->next = b->prev = Qnil;
5904 }
5905
5906 /* Now there should be no references to the condemned scroll bars,
5907 and they should get garbage-collected. */
5908 }
5909
5910 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
5911 is set to something other than NO_EVENT, it is enqueued.
5912
5913 This may be called from a signal handler, so we have to ignore GC
5914 mark bits. */
5915
5916 static int
5917 w32_scroll_bar_handle_click (bar, msg, emacs_event)
5918 struct scroll_bar *bar;
5919 W32Msg *msg;
5920 struct input_event *emacs_event;
5921 {
5922 if (! GC_WINDOWP (bar->window))
5923 abort ();
5924
5925 emacs_event->kind = W32_SCROLL_BAR_CLICK_EVENT;
5926 emacs_event->code = 0;
5927 /* not really meaningful to distinguish up/down */
5928 emacs_event->modifiers = msg->dwModifiers;
5929 emacs_event->frame_or_window = bar->window;
5930 emacs_event->arg = Qnil;
5931 emacs_event->timestamp = msg->msg.time;
5932
5933 {
5934 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
5935 int y;
5936 int dragging = !NILP (bar->dragging);
5937
5938 if (pfnGetScrollInfo)
5939 {
5940 SCROLLINFO si;
5941
5942 si.cbSize = sizeof (si);
5943 si.fMask = SIF_POS;
5944
5945 pfnGetScrollInfo ((HWND) msg->msg.lParam, SB_CTL, &si);
5946 y = si.nPos;
5947 }
5948 else
5949 y = GetScrollPos ((HWND) msg->msg.lParam, SB_CTL);
5950
5951 bar->dragging = Qnil;
5952
5953
5954 last_mouse_scroll_bar_pos = msg->msg.wParam;
5955
5956 switch (LOWORD (msg->msg.wParam))
5957 {
5958 case SB_LINEDOWN:
5959 emacs_event->part = scroll_bar_down_arrow;
5960 break;
5961 case SB_LINEUP:
5962 emacs_event->part = scroll_bar_up_arrow;
5963 break;
5964 case SB_PAGEUP:
5965 emacs_event->part = scroll_bar_above_handle;
5966 break;
5967 case SB_PAGEDOWN:
5968 emacs_event->part = scroll_bar_below_handle;
5969 break;
5970 case SB_TOP:
5971 emacs_event->part = scroll_bar_handle;
5972 y = 0;
5973 break;
5974 case SB_BOTTOM:
5975 emacs_event->part = scroll_bar_handle;
5976 y = top_range;
5977 break;
5978 case SB_THUMBTRACK:
5979 case SB_THUMBPOSITION:
5980 if (VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height)) <= 0xffff)
5981 y = HIWORD (msg->msg.wParam);
5982 bar->dragging = Qt;
5983 emacs_event->part = scroll_bar_handle;
5984
5985 /* "Silently" update current position. */
5986 if (pfnSetScrollInfo)
5987 {
5988 SCROLLINFO si;
5989
5990 si.cbSize = sizeof (si);
5991 si.fMask = SIF_POS;
5992 si.nPos = y;
5993 /* Remember apparent position (we actually lag behind the real
5994 position, so don't set that directly. */
5995 last_scroll_bar_drag_pos = y;
5996
5997 pfnSetScrollInfo (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, &si, FALSE);
5998 }
5999 else
6000 SetScrollPos (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, y, FALSE);
6001 break;
6002 case SB_ENDSCROLL:
6003 /* If this is the end of a drag sequence, then reset the scroll
6004 handle size to normal and do a final redraw. Otherwise do
6005 nothing. */
6006 if (dragging)
6007 {
6008 if (pfnSetScrollInfo)
6009 {
6010 SCROLLINFO si;
6011 int start = XINT (bar->start);
6012 int end = XINT (bar->end);
6013
6014 si.cbSize = sizeof (si);
6015 si.fMask = SIF_PAGE | SIF_POS;
6016 si.nPage = end - start + VERTICAL_SCROLL_BAR_MIN_HANDLE;
6017 si.nPos = last_scroll_bar_drag_pos;
6018 pfnSetScrollInfo (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, &si, TRUE);
6019 }
6020 else
6021 SetScrollPos (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, y, TRUE);
6022 }
6023 /* fall through */
6024 default:
6025 emacs_event->kind = NO_EVENT;
6026 return FALSE;
6027 }
6028
6029 XSETINT (emacs_event->x, y);
6030 XSETINT (emacs_event->y, top_range);
6031
6032 return TRUE;
6033 }
6034 }
6035
6036 /* Return information to the user about the current position of the mouse
6037 on the scroll bar. */
6038
6039 static void
6040 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
6041 FRAME_PTR *fp;
6042 Lisp_Object *bar_window;
6043 enum scroll_bar_part *part;
6044 Lisp_Object *x, *y;
6045 unsigned long *time;
6046 {
6047 struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
6048 Window w = SCROLL_BAR_W32_WINDOW (bar);
6049 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
6050 int pos;
6051 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
6052
6053 BLOCK_INPUT;
6054
6055 *fp = f;
6056 *bar_window = bar->window;
6057
6058 if (pfnGetScrollInfo)
6059 {
6060 SCROLLINFO si;
6061
6062 si.cbSize = sizeof (si);
6063 si.fMask = SIF_POS | SIF_PAGE | SIF_RANGE;
6064
6065 pfnGetScrollInfo (w, SB_CTL, &si);
6066 pos = si.nPos;
6067 top_range = si.nMax - si.nPage + 1;
6068 }
6069 else
6070 pos = GetScrollPos (w, SB_CTL);
6071
6072 switch (LOWORD (last_mouse_scroll_bar_pos))
6073 {
6074 case SB_THUMBPOSITION:
6075 case SB_THUMBTRACK:
6076 *part = scroll_bar_handle;
6077 if (VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height)) <= 0xffff)
6078 pos = HIWORD (last_mouse_scroll_bar_pos);
6079 break;
6080 case SB_LINEDOWN:
6081 *part = scroll_bar_handle;
6082 pos++;
6083 break;
6084 default:
6085 *part = scroll_bar_handle;
6086 break;
6087 }
6088
6089 XSETINT (*x, pos);
6090 XSETINT (*y, top_range);
6091
6092 f->mouse_moved = 0;
6093 last_mouse_scroll_bar = Qnil;
6094
6095 *time = last_mouse_movement_time;
6096
6097 UNBLOCK_INPUT;
6098 }
6099
6100
6101 /* The screen has been cleared so we may have changed foreground or
6102 background colors, and the scroll bars may need to be redrawn.
6103 Clear out the scroll bars, and ask for expose events, so we can
6104 redraw them. */
6105
6106 void
6107 x_scroll_bar_clear (f)
6108 FRAME_PTR f;
6109 {
6110 Lisp_Object bar;
6111
6112 /* We can have scroll bars even if this is 0,
6113 if we just turned off scroll bar mode.
6114 But in that case we should not clear them. */
6115 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
6116 for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar);
6117 bar = XSCROLL_BAR (bar)->next)
6118 {
6119 HWND window = SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar));
6120 HDC hdc = GetDC (window);
6121 RECT rect;
6122
6123 /* Hide scroll bar until ready to repaint. x_scroll_bar_move
6124 arranges to refresh the scroll bar if hidden. */
6125 my_show_window (f, window, SW_HIDE);
6126
6127 GetClientRect (window, &rect);
6128 select_palette (f, hdc);
6129 w32_clear_rect (f, hdc, &rect);
6130 deselect_palette (f, hdc);
6131
6132 ReleaseDC (window, hdc);
6133 }
6134 }
6135
6136 \f
6137 /* The main W32 event-reading loop - w32_read_socket. */
6138
6139 /* Record the last 100 characters stored
6140 to help debug the loss-of-chars-during-GC problem. */
6141
6142 static int temp_index;
6143 static short temp_buffer[100];
6144
6145
6146 /* Read events coming from the W32 shell.
6147 This routine is called by the SIGIO handler.
6148 We return as soon as there are no more events to be read.
6149
6150 Events representing keys are stored in buffer BUFP,
6151 which can hold up to NUMCHARS characters.
6152 We return the number of characters stored into the buffer,
6153 thus pretending to be `read'.
6154
6155 EXPECTED is nonzero if the caller knows input is available.
6156
6157 Some of these messages are reposted back to the message queue since the
6158 system calls the windows proc directly in a context where we cannot return
6159 the data nor can we guarantee the state we are in. So if we dispatch them
6160 we will get into an infinite loop. To prevent this from ever happening we
6161 will set a variable to indicate we are in the read_socket call and indicate
6162 which message we are processing since the windows proc gets called
6163 recursively with different messages by the system.
6164 */
6165
6166 int
6167 w32_read_socket (sd, bufp, numchars, expected)
6168 register int sd;
6169 /* register */ struct input_event *bufp;
6170 /* register */ int numchars;
6171 int expected;
6172 {
6173 int count = 0;
6174 int check_visibility = 0;
6175 W32Msg msg;
6176 struct frame *f;
6177 struct w32_display_info *dpyinfo = &one_w32_display_info;
6178
6179 if (interrupt_input_blocked)
6180 {
6181 interrupt_input_pending = 1;
6182 return -1;
6183 }
6184
6185 interrupt_input_pending = 0;
6186 BLOCK_INPUT;
6187
6188 /* So people can tell when we have read the available input. */
6189 input_signal_count++;
6190
6191 if (numchars <= 0)
6192 abort (); /* Don't think this happens. */
6193
6194 /* TODO: tool-bars, ghostscript integration, mouse
6195 cursors. */
6196 while (get_next_msg (&msg, FALSE))
6197 {
6198 switch (msg.msg.message)
6199 {
6200 case WM_PAINT:
6201 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
6202
6203 if (f)
6204 {
6205 if (msg.rect.right == msg.rect.left ||
6206 msg.rect.bottom == msg.rect.top)
6207 {
6208 /* We may get paint messages even though the client
6209 area is clipped - these are not expose events. */
6210 DebPrint (("clipped frame %p (%s) got WM_PAINT - ignored\n", f,
6211 SDATA (f->name)));
6212 }
6213 else if (f->async_visible != 1)
6214 {
6215 /* Definitely not obscured, so mark as visible. */
6216 f->async_visible = 1;
6217 f->async_iconified = 0;
6218 SET_FRAME_GARBAGED (f);
6219 DebPrint (("frame %p (%s) reexposed by WM_PAINT\n", f,
6220 SDATA (f->name)));
6221
6222 /* WM_PAINT serves as MapNotify as well, so report
6223 visibility changes properly. */
6224 if (f->iconified)
6225 {
6226 bufp->kind = DEICONIFY_EVENT;
6227 XSETFRAME (bufp->frame_or_window, f);
6228 bufp->arg = Qnil;
6229 bufp++;
6230 count++;
6231 numchars--;
6232 }
6233 else if (! NILP (Vframe_list)
6234 && ! NILP (XCDR (Vframe_list)))
6235 /* Force a redisplay sooner or later to update the
6236 frame titles in case this is the second frame. */
6237 record_asynch_buffer_change ();
6238 }
6239 else
6240 {
6241 HDC hdc = get_frame_dc (f);
6242
6243 /* Erase background again for safety. */
6244 w32_clear_rect (f, hdc, &msg.rect);
6245 release_frame_dc (f, hdc);
6246 expose_frame (f,
6247 msg.rect.left,
6248 msg.rect.top,
6249 msg.rect.right - msg.rect.left,
6250 msg.rect.bottom - msg.rect.top);
6251 }
6252 }
6253 break;
6254
6255 case WM_INPUTLANGCHANGE:
6256 /* Generate a language change event. */
6257 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
6258
6259 if (f)
6260 {
6261 if (numchars == 0)
6262 abort ();
6263
6264 bufp->kind = LANGUAGE_CHANGE_EVENT;
6265 XSETFRAME (bufp->frame_or_window, f);
6266 bufp->arg = Qnil;
6267 bufp->code = msg.msg.wParam;
6268 bufp->modifiers = msg.msg.lParam & 0xffff;
6269 bufp++;
6270 count++;
6271 numchars--;
6272 }
6273 break;
6274
6275 case WM_KEYDOWN:
6276 case WM_SYSKEYDOWN:
6277 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
6278
6279 if (f && !f->iconified)
6280 {
6281 if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight))
6282 {
6283 dpyinfo->mouse_face_hidden = 1;
6284 clear_mouse_face (dpyinfo);
6285 }
6286
6287 if (temp_index == sizeof temp_buffer / sizeof (short))
6288 temp_index = 0;
6289 temp_buffer[temp_index++] = msg.msg.wParam;
6290 bufp->kind = NON_ASCII_KEYSTROKE_EVENT;
6291 bufp->code = msg.msg.wParam;
6292 bufp->modifiers = msg.dwModifiers;
6293 XSETFRAME (bufp->frame_or_window, f);
6294 bufp->arg = Qnil;
6295 bufp->timestamp = msg.msg.time;
6296 bufp++;
6297 numchars--;
6298 count++;
6299 }
6300 break;
6301
6302 case WM_SYSCHAR:
6303 case WM_CHAR:
6304 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
6305
6306 if (f && !f->iconified)
6307 {
6308 if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight))
6309 {
6310 dpyinfo->mouse_face_hidden = 1;
6311 clear_mouse_face (dpyinfo);
6312 }
6313
6314 if (temp_index == sizeof temp_buffer / sizeof (short))
6315 temp_index = 0;
6316 temp_buffer[temp_index++] = msg.msg.wParam;
6317 bufp->kind = ASCII_KEYSTROKE_EVENT;
6318 bufp->code = msg.msg.wParam;
6319 bufp->modifiers = msg.dwModifiers;
6320 XSETFRAME (bufp->frame_or_window, f);
6321 bufp->arg = Qnil;
6322 bufp->timestamp = msg.msg.time;
6323 bufp++;
6324 numchars--;
6325 count++;
6326 }
6327 break;
6328
6329 case WM_MOUSEMOVE:
6330 /* Ignore non-movement. */
6331 {
6332 int x = LOWORD (msg.msg.lParam);
6333 int y = HIWORD (msg.msg.lParam);
6334 if (x == last_mousemove_x && y == last_mousemove_y)
6335 break;
6336 last_mousemove_x = x;
6337 last_mousemove_y = y;
6338 }
6339
6340 previous_help_echo = help_echo;
6341
6342 if (dpyinfo->grabbed && last_mouse_frame
6343 && FRAME_LIVE_P (last_mouse_frame))
6344 f = last_mouse_frame;
6345 else
6346 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
6347
6348 if (dpyinfo->mouse_face_hidden)
6349 {
6350 dpyinfo->mouse_face_hidden = 0;
6351 clear_mouse_face (dpyinfo);
6352 }
6353
6354 if (f)
6355 {
6356 /* Generate SELECT_WINDOW_EVENTs when needed. */
6357 if (mouse_autoselect_window)
6358 {
6359 Lisp_Object window;
6360 int area;
6361 int x = LOWORD (msg.msg.lParam);
6362 int y = HIWORD (msg.msg.lParam);
6363
6364 window = window_from_coordinates (f,
6365 x, y,
6366 &area, 0);
6367
6368 /* Window will be selected only when it is not
6369 selected now and last mouse movement event was
6370 not in it. Minibuffer window will be selected
6371 iff it is active. */
6372 if (WINDOWP(window)
6373 && !EQ (window, last_window)
6374 && !EQ (window, selected_window)
6375 && numchars > 0)
6376 {
6377 bufp->kind = SELECT_WINDOW_EVENT;
6378 bufp->frame_or_window = window;
6379 bufp->arg = Qnil;
6380 ++bufp, ++count, --numchars;
6381 }
6382
6383 last_window=window;
6384 }
6385 note_mouse_movement (f, &msg.msg);
6386 }
6387 else
6388 {
6389 /* If we move outside the frame, then we're
6390 certainly no longer on any text in the frame. */
6391 clear_mouse_face (dpyinfo);
6392 }
6393
6394 /* If the contents of the global variable help_echo
6395 has changed, generate a HELP_EVENT. */
6396 if (help_echo != previous_help_echo ||
6397 (!NILP (help_echo) && !STRINGP (help_echo) && f->mouse_moved))
6398 {
6399 Lisp_Object frame;
6400 int n;
6401
6402 if (help_echo == Qnil)
6403 {
6404 help_echo_object = help_echo_window = Qnil;
6405 help_echo_pos = -1;
6406 }
6407
6408 if (f)
6409 XSETFRAME (frame, f);
6410 else
6411 frame = Qnil;
6412
6413 any_help_event_p = 1;
6414 n = gen_help_event (bufp, numchars, help_echo, frame,
6415 help_echo_window, help_echo_object,
6416 help_echo_pos);
6417 bufp += n, count += n, numchars -= n;
6418 }
6419 break;
6420
6421 case WM_LBUTTONDOWN:
6422 case WM_LBUTTONUP:
6423 case WM_MBUTTONDOWN:
6424 case WM_MBUTTONUP:
6425 case WM_RBUTTONDOWN:
6426 case WM_RBUTTONUP:
6427 case WM_XBUTTONDOWN:
6428 case WM_XBUTTONUP:
6429 {
6430 /* If we decide we want to generate an event to be seen
6431 by the rest of Emacs, we put it here. */
6432 struct input_event emacs_event;
6433 int tool_bar_p = 0;
6434 int button;
6435 int up;
6436
6437 emacs_event.kind = NO_EVENT;
6438
6439 if (dpyinfo->grabbed && last_mouse_frame
6440 && FRAME_LIVE_P (last_mouse_frame))
6441 f = last_mouse_frame;
6442 else
6443 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
6444
6445 if (f)
6446 {
6447 construct_mouse_click (&emacs_event, &msg, f);
6448
6449 /* Is this in the tool-bar? */
6450 if (WINDOWP (f->tool_bar_window)
6451 && XFASTINT (XWINDOW (f->tool_bar_window)->height))
6452 {
6453 Lisp_Object window;
6454 int p, x, y;
6455
6456 x = XFASTINT (emacs_event.x);
6457 y = XFASTINT (emacs_event.y);
6458
6459 /* Set x and y. */
6460 window = window_from_coordinates (f, x, y, &p, 1);
6461
6462 if (EQ (window, f->tool_bar_window))
6463 {
6464 w32_handle_tool_bar_click (f, &emacs_event);
6465 tool_bar_p = 1;
6466 }
6467 }
6468
6469 if (!tool_bar_p)
6470 if (!dpyinfo->w32_focus_frame
6471 || f == dpyinfo->w32_focus_frame
6472 && (numchars >= 1))
6473 {
6474 construct_mouse_click (bufp, &msg, f);
6475 bufp++;
6476 count++;
6477 numchars--;
6478 }
6479 }
6480
6481 parse_button (msg.msg.message, HIWORD (msg.msg.wParam),
6482 &button, &up);
6483
6484 if (up)
6485 {
6486 dpyinfo->grabbed &= ~ (1 << button);
6487 }
6488 else
6489 {
6490 dpyinfo->grabbed |= (1 << button);
6491 last_mouse_frame = f;
6492 /* Ignore any mouse motion that happened
6493 before this event; any subsequent mouse-movement
6494 Emacs events should reflect only motion after
6495 the ButtonPress. */
6496 if (f != 0)
6497 f->mouse_moved = 0;
6498
6499 if (!tool_bar_p)
6500 last_tool_bar_item = -1;
6501 }
6502 break;
6503 }
6504
6505 case WM_MOUSEWHEEL:
6506 if (dpyinfo->grabbed && last_mouse_frame
6507 && FRAME_LIVE_P (last_mouse_frame))
6508 f = last_mouse_frame;
6509 else
6510 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
6511
6512 if (f)
6513 {
6514 if ((!dpyinfo->w32_focus_frame
6515 || f == dpyinfo->w32_focus_frame)
6516 && (numchars >= 1))
6517 {
6518 construct_mouse_wheel (bufp, &msg, f);
6519 bufp++;
6520 count++;
6521 numchars--;
6522 }
6523 }
6524 break;
6525
6526 case WM_DROPFILES:
6527 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
6528
6529 if (f)
6530 {
6531 construct_drag_n_drop (bufp, &msg, f);
6532 bufp++;
6533 count++;
6534 numchars--;
6535 }
6536 break;
6537
6538 case WM_VSCROLL:
6539 {
6540 struct scroll_bar *bar =
6541 x_window_to_scroll_bar ((HWND)msg.msg.lParam);
6542
6543 if (bar && numchars >= 1)
6544 {
6545 if (w32_scroll_bar_handle_click (bar, &msg, bufp))
6546 {
6547 bufp++;
6548 count++;
6549 numchars--;
6550 }
6551 }
6552 break;
6553 }
6554
6555 case WM_WINDOWPOSCHANGED:
6556 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
6557 if (f)
6558 {
6559 x_check_fullscreen_move(f);
6560 if (f->output_data.w32->want_fullscreen & FULLSCREEN_WAIT)
6561 f->output_data.w32->want_fullscreen &=
6562 ~(FULLSCREEN_WAIT|FULLSCREEN_BOTH);
6563 }
6564 check_visibility = 1;
6565 break;
6566
6567 case WM_ACTIVATE:
6568 case WM_ACTIVATEAPP:
6569 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
6570 if (f)
6571 x_check_fullscreen (f);
6572 check_visibility = 1;
6573 break;
6574
6575 case WM_MOVE:
6576 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
6577
6578 if (f && !f->async_iconified)
6579 {
6580 int x, y;
6581
6582 x_real_positions (f, &x, &y);
6583 f->output_data.w32->left_pos = x;
6584 f->output_data.w32->top_pos = y;
6585 }
6586
6587 check_visibility = 1;
6588 break;
6589
6590 case WM_SHOWWINDOW:
6591 /* wParam non-zero means Window is about to be shown, 0 means
6592 about to be hidden. */
6593 /* Redo the mouse-highlight after the tooltip has gone. */
6594 if (!msg.msg.wParam && msg.msg.hwnd == tip_window)
6595 {
6596 tip_window = NULL;
6597 redo_mouse_highlight ();
6598 }
6599
6600 /* If window has been obscured or exposed by another window
6601 being maximised or minimised/restored, then recheck
6602 visibility of all frames. Direct changes to our own
6603 windows get handled by WM_SIZE. */
6604 #if 0
6605 if (msg.msg.lParam != 0)
6606 check_visibility = 1;
6607 else
6608 {
6609 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
6610 f->async_visible = msg.msg.wParam;
6611 }
6612 #endif
6613
6614 check_visibility = 1;
6615 break;
6616
6617 case WM_SIZE:
6618 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
6619
6620 /* Inform lisp of whether frame has been iconified etc. */
6621 if (f)
6622 {
6623 switch (msg.msg.wParam)
6624 {
6625 case SIZE_MINIMIZED:
6626 f->async_visible = 0;
6627 f->async_iconified = 1;
6628
6629 bufp->kind = ICONIFY_EVENT;
6630 XSETFRAME (bufp->frame_or_window, f);
6631 bufp->arg = Qnil;
6632 bufp++;
6633 count++;
6634 numchars--;
6635 break;
6636
6637 case SIZE_MAXIMIZED:
6638 case SIZE_RESTORED:
6639 f->async_visible = 1;
6640 f->async_iconified = 0;
6641
6642 /* wait_reading_process_input will notice this and update
6643 the frame's display structures. */
6644 SET_FRAME_GARBAGED (f);
6645
6646 if (f->iconified)
6647 {
6648 int x, y;
6649
6650 /* Reset top and left positions of the Window
6651 here since Windows sends a WM_MOVE message
6652 BEFORE telling us the Window is minimized
6653 when the Window is iconified, with 3000,3000
6654 as the co-ords. */
6655 x_real_positions (f, &x, &y);
6656 f->output_data.w32->left_pos = x;
6657 f->output_data.w32->top_pos = y;
6658
6659 bufp->kind = DEICONIFY_EVENT;
6660 XSETFRAME (bufp->frame_or_window, f);
6661 bufp->arg = Qnil;
6662 bufp++;
6663 count++;
6664 numchars--;
6665 }
6666 else if (! NILP (Vframe_list)
6667 && ! NILP (XCDR (Vframe_list)))
6668 /* Force a redisplay sooner or later
6669 to update the frame titles
6670 in case this is the second frame. */
6671 record_asynch_buffer_change ();
6672 break;
6673 }
6674 }
6675
6676 if (f && !f->async_iconified && msg.msg.wParam != SIZE_MINIMIZED)
6677 {
6678 RECT rect;
6679 int rows;
6680 int columns;
6681 int width;
6682 int height;
6683
6684 GetClientRect (msg.msg.hwnd, &rect);
6685
6686 height = rect.bottom - rect.top;
6687 width = rect.right - rect.left;
6688
6689 rows = PIXEL_TO_CHAR_HEIGHT (f, height);
6690 columns = PIXEL_TO_CHAR_WIDTH (f, width);
6691
6692 /* TODO: Clip size to the screen dimensions. */
6693
6694 /* Even if the number of character rows and columns has
6695 not changed, the font size may have changed, so we need
6696 to check the pixel dimensions as well. */
6697
6698 if (columns != f->width
6699 || rows != f->height
6700 || width != f->output_data.w32->pixel_width
6701 || height != f->output_data.w32->pixel_height)
6702 {
6703 change_frame_size (f, rows, columns, 0, 1, 0);
6704 SET_FRAME_GARBAGED (f);
6705 cancel_mouse_face (f);
6706 f->output_data.w32->pixel_width = width;
6707 f->output_data.w32->pixel_height = height;
6708 f->output_data.w32->win_gravity = NorthWestGravity;
6709 }
6710 }
6711
6712 check_visibility = 1;
6713 break;
6714
6715 case WM_MOUSELEAVE:
6716 f = x_any_window_to_frame (dpyinfo, msg.msg.hwnd);
6717 if (f)
6718 {
6719 if (f == dpyinfo->mouse_face_mouse_frame)
6720 {
6721 /* If we move outside the frame, then we're
6722 certainly no longer on any text in the frame. */
6723 clear_mouse_face (dpyinfo);
6724 dpyinfo->mouse_face_mouse_frame = 0;
6725 }
6726
6727 /* Generate a nil HELP_EVENT to cancel a help-echo.
6728 Do it only if there's something to cancel.
6729 Otherwise, the startup message is cleared when
6730 the mouse leaves the frame. */
6731 if (any_help_event_p)
6732 {
6733 Lisp_Object frame;
6734 int n;
6735
6736 XSETFRAME (frame, f);
6737 help_echo = Qnil;
6738 n = gen_help_event (bufp, numchars,
6739 Qnil, frame, Qnil, Qnil, 0);
6740 bufp += n, count += n, numchars -= n;
6741 }
6742 }
6743 break;
6744
6745 case WM_SETFOCUS:
6746 /* TODO: Port this change:
6747 2002-06-28 Jan D. <jan.h.d@swipnet.se>
6748 * xterm.h (struct x_output): Add focus_state.
6749 * xterm.c (x_focus_changed): New function.
6750 (x_detect_focus_change): New function.
6751 (XTread_socket): Call x_detect_focus_change for FocusIn/FocusOut
6752 EnterNotify and LeaveNotify to track X focus changes.
6753 */
6754 f = x_any_window_to_frame (dpyinfo, msg.msg.hwnd);
6755
6756 dpyinfo->w32_focus_event_frame = f;
6757
6758 if (f)
6759 x_new_focus_frame (dpyinfo, f);
6760
6761
6762 dpyinfo->grabbed = 0;
6763 check_visibility = 1;
6764 break;
6765
6766 case WM_KILLFOCUS:
6767 /* TODO: some of this belongs in MOUSE_LEAVE */
6768 f = x_top_window_to_frame (dpyinfo, msg.msg.hwnd);
6769
6770 if (f)
6771 {
6772 if (f == dpyinfo->w32_focus_event_frame)
6773 dpyinfo->w32_focus_event_frame = 0;
6774
6775 if (f == dpyinfo->w32_focus_frame)
6776 x_new_focus_frame (dpyinfo, 0);
6777
6778 if (f == dpyinfo->mouse_face_mouse_frame)
6779 {
6780 /* If we move outside the frame, then we're
6781 certainly no longer on any text in the frame. */
6782 clear_mouse_face (dpyinfo);
6783 dpyinfo->mouse_face_mouse_frame = 0;
6784 }
6785
6786 /* Generate a nil HELP_EVENT to cancel a help-echo.
6787 Do it only if there's something to cancel.
6788 Otherwise, the startup message is cleared when
6789 the mouse leaves the frame. */
6790 if (any_help_event_p)
6791 {
6792 Lisp_Object frame;
6793 int n;
6794
6795 XSETFRAME (frame, f);
6796 help_echo = Qnil;
6797 n = gen_help_event (bufp, numchars,
6798 Qnil, frame, Qnil, Qnil, 0);
6799 bufp += n, count += n, numchars -=n;
6800 }
6801 }
6802
6803 dpyinfo->grabbed = 0;
6804 check_visibility = 1;
6805 break;
6806
6807 case WM_CLOSE:
6808 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
6809
6810 if (f)
6811 {
6812 if (numchars == 0)
6813 abort ();
6814
6815 bufp->kind = DELETE_WINDOW_EVENT;
6816 XSETFRAME (bufp->frame_or_window, f);
6817 bufp->arg = Qnil;
6818 bufp++;
6819 count++;
6820 numchars--;
6821 }
6822 break;
6823
6824 case WM_INITMENU:
6825 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
6826
6827 if (f)
6828 {
6829 if (numchars == 0)
6830 abort ();
6831
6832 bufp->kind = MENU_BAR_ACTIVATE_EVENT;
6833 XSETFRAME (bufp->frame_or_window, f);
6834 bufp->arg = Qnil;
6835 bufp++;
6836 count++;
6837 numchars--;
6838 }
6839 break;
6840
6841 case WM_COMMAND:
6842 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
6843
6844 if (f)
6845 {
6846 extern void menubar_selection_callback
6847 (FRAME_PTR f, void * client_data);
6848 menubar_selection_callback (f, (void *)msg.msg.wParam);
6849 }
6850
6851 check_visibility = 1;
6852 break;
6853
6854 case WM_DISPLAYCHANGE:
6855 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
6856
6857 if (f)
6858 {
6859 dpyinfo->width = (short) LOWORD (msg.msg.lParam);
6860 dpyinfo->height = (short) HIWORD (msg.msg.lParam);
6861 dpyinfo->n_cbits = msg.msg.wParam;
6862 DebPrint (("display change: %d %d\n", dpyinfo->width,
6863 dpyinfo->height));
6864 }
6865
6866 check_visibility = 1;
6867 break;
6868
6869 default:
6870 /* Check for messages registered at runtime. */
6871 if (msg.msg.message == msh_mousewheel)
6872 {
6873 if (dpyinfo->grabbed && last_mouse_frame
6874 && FRAME_LIVE_P (last_mouse_frame))
6875 f = last_mouse_frame;
6876 else
6877 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
6878
6879 if (f)
6880 {
6881 if ((!dpyinfo->w32_focus_frame
6882 || f == dpyinfo->w32_focus_frame)
6883 && (numchars >= 1))
6884 {
6885 construct_mouse_wheel (bufp, &msg, f);
6886 bufp++;
6887 count++;
6888 numchars--;
6889 }
6890 }
6891 }
6892 break;
6893 }
6894 }
6895
6896 /* If the focus was just given to an autoraising frame,
6897 raise it now. */
6898 /* ??? This ought to be able to handle more than one such frame. */
6899 if (pending_autoraise_frame)
6900 {
6901 x_raise_frame (pending_autoraise_frame);
6902 pending_autoraise_frame = 0;
6903 }
6904
6905 /* Check which frames are still visisble, if we have enqueued any user
6906 events or been notified of events that may affect visibility. We
6907 do this here because there doesn't seem to be any direct
6908 notification from Windows that the visibility of a window has
6909 changed (at least, not in all cases). */
6910 if (count > 0 || check_visibility)
6911 {
6912 Lisp_Object tail, frame;
6913
6914 FOR_EACH_FRAME (tail, frame)
6915 {
6916 FRAME_PTR f = XFRAME (frame);
6917 /* The tooltip has been drawn already. Avoid the
6918 SET_FRAME_GARBAGED below. */
6919 if (EQ (frame, tip_frame))
6920 continue;
6921
6922 /* Check "visible" frames and mark each as obscured or not.
6923 Note that async_visible is nonzero for unobscured and
6924 obscured frames, but zero for hidden and iconified frames. */
6925 if (FRAME_W32_P (f) && f->async_visible)
6926 {
6927 RECT clipbox;
6928 HDC hdc;
6929
6930 enter_crit ();
6931 /* Query clipping rectangle for the entire window area
6932 (GetWindowDC), not just the client portion (GetDC).
6933 Otherwise, the scrollbars and menubar aren't counted as
6934 part of the visible area of the frame, and we may think
6935 the frame is obscured when really a scrollbar is still
6936 visible and gets WM_PAINT messages above. */
6937 hdc = GetWindowDC (FRAME_W32_WINDOW (f));
6938 GetClipBox (hdc, &clipbox);
6939 ReleaseDC (FRAME_W32_WINDOW (f), hdc);
6940 leave_crit ();
6941
6942 if (clipbox.right == clipbox.left
6943 || clipbox.bottom == clipbox.top)
6944 {
6945 /* Frame has become completely obscured so mark as
6946 such (we do this by setting async_visible to 2 so
6947 that FRAME_VISIBLE_P is still true, but redisplay
6948 will skip it). */
6949 f->async_visible = 2;
6950
6951 if (!FRAME_OBSCURED_P (f))
6952 {
6953 DebPrint (("frame %p (%s) obscured\n", f,
6954 SDATA (f->name)));
6955 }
6956 }
6957 else
6958 {
6959 /* Frame is not obscured, so mark it as such. */
6960 f->async_visible = 1;
6961
6962 if (FRAME_OBSCURED_P (f))
6963 {
6964 SET_FRAME_GARBAGED (f);
6965 DebPrint (("obscured frame %p (%s) found to be visible\n", f,
6966 SDATA (f->name)));
6967
6968 /* Force a redisplay sooner or later. */
6969 record_asynch_buffer_change ();
6970 }
6971 }
6972 }
6973 }
6974 }
6975
6976 UNBLOCK_INPUT;
6977 return count;
6978 }
6979
6980
6981
6982 \f
6983 /***********************************************************************
6984 Text Cursor
6985 ***********************************************************************/
6986
6987 /* Set clipping for output in glyph row ROW. W is the window in which
6988 we operate. GC is the graphics context to set clipping in.
6989 WHOLE_LINE_P non-zero means include the areas used for truncation
6990 mark display and alike in the clipping rectangle.
6991
6992 ROW may be a text row or, e.g., a mode line. Text rows must be
6993 clipped to the interior of the window dedicated to text display,
6994 mode lines must be clipped to the whole window. */
6995
6996 static void
6997 w32_clip_to_row (w, row, hdc, whole_line_p)
6998 struct window *w;
6999 struct glyph_row *row;
7000 HDC hdc;
7001 int whole_line_p;
7002 {
7003 struct frame *f = XFRAME (WINDOW_FRAME (w));
7004 RECT clip_rect;
7005 int window_x, window_y, window_width, window_height;
7006
7007 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
7008
7009 clip_rect.left = WINDOW_TO_FRAME_PIXEL_X (w, 0);
7010 clip_rect.top = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
7011 clip_rect.top = max (clip_rect.top, window_y);
7012 clip_rect.right = clip_rect.left + window_width;
7013 clip_rect.bottom = clip_rect.top + row->visible_height;
7014
7015 /* If clipping to the whole line, including trunc marks, extend
7016 the rectangle to the left and increase its width. */
7017 if (whole_line_p)
7018 {
7019 clip_rect.left -= FRAME_X_LEFT_FRINGE_WIDTH (f);
7020 clip_rect.right += FRAME_X_FRINGE_WIDTH (f);
7021 }
7022
7023 w32_set_clip_rectangle (hdc, &clip_rect);
7024 }
7025
7026
7027 /* Draw a hollow box cursor on window W in glyph row ROW. */
7028
7029 static void
7030 x_draw_hollow_cursor (w, row)
7031 struct window *w;
7032 struct glyph_row *row;
7033 {
7034 struct frame *f = XFRAME (WINDOW_FRAME (w));
7035 HDC hdc;
7036 RECT rect;
7037 int wd;
7038 struct glyph *cursor_glyph;
7039 HBRUSH hb = CreateSolidBrush (f->output_data.w32->cursor_pixel);
7040
7041 /* Compute frame-relative coordinates from window-relative
7042 coordinates. */
7043 rect.left = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
7044 rect.top = (WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y)
7045 + row->ascent - w->phys_cursor_ascent);
7046 rect.bottom = rect.top + row->height;
7047
7048 /* Get the glyph the cursor is on. If we can't tell because
7049 the current matrix is invalid or such, give up. */
7050 cursor_glyph = get_phys_cursor_glyph (w);
7051 if (cursor_glyph == NULL)
7052 return;
7053
7054 /* Compute the width of the rectangle to draw. If on a stretch
7055 glyph, and `x-stretch-block-cursor' is nil, don't draw a
7056 rectangle as wide as the glyph, but use a canonical character
7057 width instead. */
7058 wd = cursor_glyph->pixel_width;
7059 if (cursor_glyph->type == STRETCH_GLYPH
7060 && !x_stretch_cursor_p)
7061 wd = min (CANON_X_UNIT (f), wd);
7062 w->phys_cursor_width = wd;
7063
7064 rect.right = rect.left + wd;
7065 hdc = get_frame_dc (f);
7066 /* Set clipping, draw the rectangle, and reset clipping again. */
7067 w32_clip_to_row (w, row, hdc, 0);
7068 FrameRect (hdc, &rect, hb);
7069 DeleteObject (hb);
7070 w32_set_clip_rectangle (hdc, NULL);
7071 release_frame_dc (f, hdc);
7072 }
7073
7074
7075 /* Draw a bar cursor on window W in glyph row ROW.
7076
7077 Implementation note: One would like to draw a bar cursor with an
7078 angle equal to the one given by the font property XA_ITALIC_ANGLE.
7079 Unfortunately, I didn't find a font yet that has this property set.
7080 --gerd. */
7081
7082 static void
7083 x_draw_bar_cursor (w, row, width, kind)
7084 struct window *w;
7085 struct glyph_row *row;
7086 int width;
7087 enum text_cursor_kinds kind;
7088 {
7089 struct frame *f = XFRAME (w->frame);
7090 struct glyph *cursor_glyph;
7091 int x;
7092 HDC hdc;
7093
7094 /* If cursor is out of bounds, don't draw garbage. This can happen
7095 in mini-buffer windows when switching between echo area glyphs
7096 and mini-buffer. */
7097 cursor_glyph = get_phys_cursor_glyph (w);
7098 if (cursor_glyph == NULL)
7099 return;
7100
7101 /* If on an image, draw like a normal cursor. That's usually better
7102 visible than drawing a bar, esp. if the image is large so that
7103 the bar might not be in the window. */
7104 if (cursor_glyph->type == IMAGE_GLYPH)
7105 {
7106 struct glyph_row *row;
7107 row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
7108 x_draw_phys_cursor_glyph (w, row, DRAW_CURSOR);
7109 }
7110 else
7111 {
7112 COLORREF cursor_color = f->output_data.w32->cursor_pixel;
7113 struct face *face = FACE_FROM_ID (f, cursor_glyph->face_id);
7114
7115 /* If the glyph's background equals the color we normally draw
7116 the bar cursor in, the bar cursor in its normal color is
7117 invisible. Use the glyph's foreground color instead in this
7118 case, on the assumption that the glyph's colors are chosen so
7119 that the glyph is legible. */
7120 if (face->background == cursor_color)
7121 cursor_color = face->foreground;
7122
7123 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
7124
7125 if (width < 0)
7126 width = FRAME_CURSOR_WIDTH (f);
7127 width = min (cursor_glyph->pixel_width, width);
7128
7129 w->phys_cursor_width = width;
7130
7131
7132 hdc = get_frame_dc (f);
7133 w32_clip_to_row (w, row, hdc, 0);
7134
7135 if (kind == BAR_CURSOR)
7136 {
7137 w32_fill_area (f, hdc, cursor_color, x,
7138 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
7139 width, row->height);
7140 }
7141 else
7142 {
7143 w32_fill_area (f, hdc, cursor_color, x,
7144 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y +
7145 row->height - width),
7146 cursor_glyph->pixel_width, width);
7147 }
7148
7149 w32_set_clip_rectangle (hdc, NULL);
7150 release_frame_dc (f, hdc);
7151 }
7152 }
7153
7154
7155 /* Clear the cursor of window W to background color, and mark the
7156 cursor as not shown. This is used when the text where the cursor
7157 is is about to be rewritten. */
7158
7159 static void
7160 x_clear_cursor (w)
7161 struct window *w;
7162 {
7163 if (FRAME_VISIBLE_P (XFRAME (w->frame)) && w->phys_cursor_on_p)
7164 x_update_window_cursor (w, 0);
7165 }
7166
7167
7168 /* Draw the cursor glyph of window W in glyph row ROW. See the
7169 comment of x_draw_glyphs for the meaning of HL. */
7170
7171 static void
7172 x_draw_phys_cursor_glyph (w, row, hl)
7173 struct window *w;
7174 struct glyph_row *row;
7175 enum draw_glyphs_face hl;
7176 {
7177 /* If cursor hpos is out of bounds, don't draw garbage. This can
7178 happen in mini-buffer windows when switching between echo area
7179 glyphs and mini-buffer. */
7180 if (w->phys_cursor.hpos < row->used[TEXT_AREA])
7181 {
7182 int on_p = w->phys_cursor_on_p;
7183 int x1;
7184 x1 = x_draw_glyphs (w, w->phys_cursor.x, row, TEXT_AREA,
7185 w->phys_cursor.hpos, w->phys_cursor.hpos + 1,
7186 hl, 0);
7187 w->phys_cursor_on_p = on_p;
7188
7189 if (hl == DRAW_CURSOR)
7190 w->phys_cursor_width = x1 - w->phys_cursor.x;
7191
7192 /* When we erase the cursor, and ROW is overlapped by other
7193 rows, make sure that these overlapping parts of other rows
7194 are redrawn. */
7195 if (hl == DRAW_NORMAL_TEXT && row->overlapped_p)
7196 {
7197 if (row > w->current_matrix->rows
7198 && MATRIX_ROW_OVERLAPS_SUCC_P (row - 1))
7199 x_fix_overlapping_area (w, row - 1, TEXT_AREA);
7200
7201 if (MATRIX_ROW_BOTTOM_Y (row) < window_text_bottom_y (w)
7202 && MATRIX_ROW_OVERLAPS_PRED_P (row + 1))
7203 x_fix_overlapping_area (w, row + 1, TEXT_AREA);
7204 }
7205 }
7206 }
7207
7208
7209 /* Erase the image of a cursor of window W from the screen. */
7210
7211 static void
7212 x_erase_phys_cursor (w)
7213 struct window *w;
7214 {
7215 struct frame *f = XFRAME (w->frame);
7216 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
7217 int hpos = w->phys_cursor.hpos;
7218 int vpos = w->phys_cursor.vpos;
7219 int mouse_face_here_p = 0;
7220 struct glyph_matrix *active_glyphs = w->current_matrix;
7221 struct glyph_row *cursor_row;
7222 struct glyph *cursor_glyph;
7223 enum draw_glyphs_face hl;
7224
7225 /* No cursor displayed or row invalidated => nothing to do on the
7226 screen. */
7227 if (w->phys_cursor_type == NO_CURSOR)
7228 goto mark_cursor_off;
7229
7230 /* VPOS >= active_glyphs->nrows means that window has been resized.
7231 Don't bother to erase the cursor. */
7232 if (vpos >= active_glyphs->nrows)
7233 goto mark_cursor_off;
7234
7235 /* If row containing cursor is marked invalid, there is nothing we
7236 can do. */
7237 cursor_row = MATRIX_ROW (active_glyphs, vpos);
7238 if (!cursor_row->enabled_p)
7239 goto mark_cursor_off;
7240
7241 /* If row is completely invisible, don't attempt to delete a cursor which
7242 isn't there. This may happen if cursor is at top of window, and
7243 we switch to a buffer with a header line in that window. */
7244 if (cursor_row->visible_height <= 0)
7245 goto mark_cursor_off;
7246
7247 /* This can happen when the new row is shorter than the old one.
7248 In this case, either x_draw_glyphs or clear_end_of_line
7249 should have cleared the cursor. Note that we wouldn't be
7250 able to erase the cursor in this case because we don't have a
7251 cursor glyph at hand. */
7252 if (w->phys_cursor.hpos >= cursor_row->used[TEXT_AREA])
7253 goto mark_cursor_off;
7254
7255 /* If the cursor is in the mouse face area, redisplay that when
7256 we clear the cursor. */
7257 if (! NILP (dpyinfo->mouse_face_window)
7258 && w == XWINDOW (dpyinfo->mouse_face_window)
7259 && (vpos > dpyinfo->mouse_face_beg_row
7260 || (vpos == dpyinfo->mouse_face_beg_row
7261 && hpos >= dpyinfo->mouse_face_beg_col))
7262 && (vpos < dpyinfo->mouse_face_end_row
7263 || (vpos == dpyinfo->mouse_face_end_row
7264 && hpos < dpyinfo->mouse_face_end_col))
7265 /* Don't redraw the cursor's spot in mouse face if it is at the
7266 end of a line (on a newline). The cursor appears there, but
7267 mouse highlighting does not. */
7268 && cursor_row->used[TEXT_AREA] > hpos)
7269 mouse_face_here_p = 1;
7270
7271 /* Maybe clear the display under the cursor. */
7272 if (w->phys_cursor_type == HOLLOW_BOX_CURSOR)
7273 {
7274 int x;
7275 int header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
7276 HDC hdc;
7277
7278 cursor_glyph = get_phys_cursor_glyph (w);
7279 if (cursor_glyph == NULL)
7280 goto mark_cursor_off;
7281
7282 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
7283
7284 hdc = get_frame_dc (f);
7285 w32_clear_area (f, hdc, x,
7286 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
7287 cursor_row->y)),
7288 cursor_glyph->pixel_width,
7289 cursor_row->visible_height);
7290 release_frame_dc (f, hdc);
7291 }
7292
7293 /* Erase the cursor by redrawing the character underneath it. */
7294 if (mouse_face_here_p)
7295 hl = DRAW_MOUSE_FACE;
7296 else
7297 hl = DRAW_NORMAL_TEXT;
7298 x_draw_phys_cursor_glyph (w, cursor_row, hl);
7299
7300 mark_cursor_off:
7301 w->phys_cursor_on_p = 0;
7302 w->phys_cursor_type = NO_CURSOR;
7303 }
7304
7305
7306 /* Non-zero if physical cursor of window W is within mouse face. */
7307
7308 static int
7309 cursor_in_mouse_face_p (w)
7310 struct window *w;
7311 {
7312 struct w32_display_info *dpyinfo
7313 = FRAME_W32_DISPLAY_INFO (XFRAME (w->frame));
7314 int in_mouse_face = 0;
7315
7316 if (WINDOWP (dpyinfo->mouse_face_window)
7317 && XWINDOW (dpyinfo->mouse_face_window) == w)
7318 {
7319 int hpos = w->phys_cursor.hpos;
7320 int vpos = w->phys_cursor.vpos;
7321
7322 if (vpos >= dpyinfo->mouse_face_beg_row
7323 && vpos <= dpyinfo->mouse_face_end_row
7324 && (vpos > dpyinfo->mouse_face_beg_row
7325 || hpos >= dpyinfo->mouse_face_beg_col)
7326 && (vpos < dpyinfo->mouse_face_end_row
7327 || hpos < dpyinfo->mouse_face_end_col
7328 || dpyinfo->mouse_face_past_end))
7329 in_mouse_face = 1;
7330 }
7331
7332 return in_mouse_face;
7333 }
7334
7335
7336 /* Display or clear cursor of window W. If ON is zero, clear the
7337 cursor. If it is non-zero, display the cursor. If ON is nonzero,
7338 where to put the cursor is specified by HPOS, VPOS, X and Y. */
7339
7340 void
7341 x_display_and_set_cursor (w, on, hpos, vpos, x, y)
7342 struct window *w;
7343 int on, hpos, vpos, x, y;
7344 {
7345 struct frame *f = XFRAME (w->frame);
7346 int new_cursor_type;
7347 int new_cursor_width;
7348 int active_cursor;
7349 struct glyph_matrix *current_glyphs;
7350 struct glyph_row *glyph_row;
7351 struct glyph *glyph;
7352
7353 /* This is pointless on invisible frames, and dangerous on garbaged
7354 windows and frames; in the latter case, the frame or window may
7355 be in the midst of changing its size, and x and y may be off the
7356 window. */
7357 if (! FRAME_VISIBLE_P (f)
7358 || FRAME_GARBAGED_P (f)
7359 || vpos >= w->current_matrix->nrows
7360 || hpos >= w->current_matrix->matrix_w)
7361 return;
7362
7363 /* If cursor is off and we want it off, return quickly. */
7364 if (!on && !w->phys_cursor_on_p)
7365 return;
7366
7367 current_glyphs = w->current_matrix;
7368 glyph_row = MATRIX_ROW (current_glyphs, vpos);
7369 glyph = glyph_row->glyphs[TEXT_AREA] + hpos;
7370
7371 /* If cursor row is not enabled, we don't really know where to
7372 display the cursor. */
7373 if (!glyph_row->enabled_p)
7374 {
7375 w->phys_cursor_on_p = 0;
7376 return;
7377 }
7378
7379 xassert (interrupt_input_blocked);
7380
7381 /* Set new_cursor_type to the cursor we want to be displayed. */
7382 new_cursor_type = get_window_cursor_type (w, &new_cursor_width, &active_cursor);
7383
7384 /* If cursor is currently being shown and we don't want it to be or
7385 it is in the wrong place, or the cursor type is not what we want,
7386 erase it. */
7387 if (w->phys_cursor_on_p
7388 && (!on
7389 || w->phys_cursor.x != x
7390 || w->phys_cursor.y != y
7391 || new_cursor_type != w->phys_cursor_type
7392 || ((new_cursor_type == BAR_CURSOR || new_cursor_type == HBAR_CURSOR)
7393 && new_cursor_width != w->phys_cursor_width)))
7394 x_erase_phys_cursor (w);
7395
7396 /* Don't check phys_cursor_on_p here because that flag is only set
7397 to zero in some cases where we know that the cursor has been
7398 completely erased, to avoid the extra work of erasing the cursor
7399 twice. In other words, phys_cursor_on_p can be 1 and the cursor
7400 still not be visible, or it has only been partly erased. */
7401 if (on)
7402 {
7403 w->phys_cursor_ascent = glyph_row->ascent;
7404 w->phys_cursor_height = glyph_row->height;
7405
7406 /* Set phys_cursor_.* before x_draw_.* is called because some
7407 of them may need the information. */
7408 w->phys_cursor.x = x;
7409 w->phys_cursor.y = glyph_row->y;
7410 w->phys_cursor.hpos = hpos;
7411 w->phys_cursor.vpos = vpos;
7412
7413 /* If the user wants to use the system caret, make sure our own
7414 cursor remains invisible. */
7415 if (w32_use_visible_system_caret)
7416 {
7417 if (w->phys_cursor_type != NO_CURSOR)
7418 x_erase_phys_cursor (w);
7419
7420 new_cursor_type = w->phys_cursor_type = NO_CURSOR;
7421 w->phys_cursor_width = -1;
7422 }
7423 else
7424 {
7425 w->phys_cursor_type = new_cursor_type;
7426 }
7427
7428 w->phys_cursor_on_p = 1;
7429
7430 /* If this is the active cursor, we need to track it with the
7431 system caret, so third party software like screen magnifiers
7432 and speech synthesizers can follow the cursor. */
7433 if (active_cursor)
7434 {
7435 HWND hwnd = FRAME_W32_WINDOW (f);
7436
7437 w32_system_caret_x
7438 = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
7439 w32_system_caret_y
7440 = (WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y)
7441 + glyph_row->ascent - w->phys_cursor_ascent);
7442
7443 /* If the size of the active cursor changed, destroy the old
7444 system caret. */
7445 if (w32_system_caret_hwnd
7446 && (w32_system_caret_height != w->phys_cursor_height))
7447 PostMessage (hwnd, WM_EMACS_DESTROY_CARET, 0, 0);
7448
7449 w32_system_caret_height = w->phys_cursor_height;
7450
7451 /* Move the system caret. */
7452 PostMessage (hwnd, WM_EMACS_TRACK_CARET, 0, 0);
7453 }
7454
7455 switch (new_cursor_type)
7456 {
7457 case HOLLOW_BOX_CURSOR:
7458 x_draw_hollow_cursor (w, glyph_row);
7459 break;
7460
7461 case FILLED_BOX_CURSOR:
7462 x_draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
7463 break;
7464
7465 case BAR_CURSOR:
7466 x_draw_bar_cursor (w, glyph_row, new_cursor_width, BAR_CURSOR);
7467 break;
7468
7469 case HBAR_CURSOR:
7470 x_draw_bar_cursor (w, glyph_row, new_cursor_width, HBAR_CURSOR);
7471 break;
7472
7473 case NO_CURSOR:
7474 w->phys_cursor_width = 0;
7475 break;
7476
7477 default:
7478 abort ();
7479 }
7480 }
7481 }
7482
7483
7484 /* Display the cursor on window W, or clear it. X and Y are window
7485 relative pixel coordinates. HPOS and VPOS are glyph matrix
7486 positions. If W is not the selected window, display a hollow
7487 cursor. ON non-zero means display the cursor at X, Y which
7488 correspond to HPOS, VPOS, otherwise it is cleared. */
7489
7490 void
7491 x_display_cursor (w, on, hpos, vpos, x, y)
7492 struct window *w;
7493 int on, hpos, vpos, x, y;
7494 {
7495 BLOCK_INPUT;
7496 x_display_and_set_cursor (w, on, hpos, vpos, x, y);
7497 UNBLOCK_INPUT;
7498 }
7499
7500
7501 /* Display the cursor on window W, or clear it, according to ON_P.
7502 Don't change the cursor's position. */
7503
7504 void
7505 x_update_cursor (f, on_p)
7506 struct frame *f;
7507 int on_p;
7508 {
7509 x_update_cursor_in_window_tree (XWINDOW (f->root_window), on_p);
7510 }
7511
7512
7513 /* Call x_update_window_cursor with parameter ON_P on all leaf windows
7514 in the window tree rooted at W. */
7515
7516 static void
7517 x_update_cursor_in_window_tree (w, on_p)
7518 struct window *w;
7519 int on_p;
7520 {
7521 while (w)
7522 {
7523 if (!NILP (w->hchild))
7524 x_update_cursor_in_window_tree (XWINDOW (w->hchild), on_p);
7525 else if (!NILP (w->vchild))
7526 x_update_cursor_in_window_tree (XWINDOW (w->vchild), on_p);
7527 else
7528 x_update_window_cursor (w, on_p);
7529
7530 w = NILP (w->next) ? 0 : XWINDOW (w->next);
7531 }
7532 }
7533
7534
7535 /* Switch the display of W's cursor on or off, according to the value
7536 of ON. */
7537
7538 static void
7539 x_update_window_cursor (w, on)
7540 struct window *w;
7541 int on;
7542 {
7543 /* Don't update cursor in windows whose frame is in the process
7544 of being deleted. */
7545 if (w->current_matrix)
7546 {
7547 BLOCK_INPUT;
7548 x_display_and_set_cursor (w, on, w->phys_cursor.hpos,
7549 w->phys_cursor.vpos, w->phys_cursor.x,
7550 w->phys_cursor.y);
7551 UNBLOCK_INPUT;
7552 }
7553 }
7554
7555
7556
7557 \f
7558 /* Icons. */
7559
7560 int
7561 x_bitmap_icon (f, icon)
7562 struct frame *f;
7563 Lisp_Object icon;
7564 {
7565 HANDLE hicon;
7566
7567 if (FRAME_W32_WINDOW (f) == 0)
7568 return 1;
7569
7570 if (NILP (icon))
7571 hicon = LoadIcon (hinst, EMACS_CLASS);
7572 else if (STRINGP (icon))
7573 hicon = LoadImage (NULL, (LPCTSTR) SDATA (icon), IMAGE_ICON, 0, 0,
7574 LR_DEFAULTSIZE | LR_LOADFROMFILE);
7575 else if (SYMBOLP (icon))
7576 {
7577 LPCTSTR name;
7578
7579 if (EQ (icon, intern ("application")))
7580 name = (LPCTSTR) IDI_APPLICATION;
7581 else if (EQ (icon, intern ("hand")))
7582 name = (LPCTSTR) IDI_HAND;
7583 else if (EQ (icon, intern ("question")))
7584 name = (LPCTSTR) IDI_QUESTION;
7585 else if (EQ (icon, intern ("exclamation")))
7586 name = (LPCTSTR) IDI_EXCLAMATION;
7587 else if (EQ (icon, intern ("asterisk")))
7588 name = (LPCTSTR) IDI_ASTERISK;
7589 else if (EQ (icon, intern ("winlogo")))
7590 name = (LPCTSTR) IDI_WINLOGO;
7591 else
7592 return 1;
7593
7594 hicon = LoadIcon (NULL, name);
7595 }
7596 else
7597 return 1;
7598
7599 if (hicon == NULL)
7600 return 1;
7601
7602 PostMessage (FRAME_W32_WINDOW (f), WM_SETICON, (WPARAM) ICON_BIG,
7603 (LPARAM) hicon);
7604
7605 return 0;
7606 }
7607
7608 \f
7609 /************************************************************************
7610 Handling X errors
7611 ************************************************************************/
7612
7613 /* Display Error Handling functions not used on W32. Listing them here
7614 helps diff stay in step when comparing w32term.c with xterm.c.
7615
7616 x_error_catcher (display, error)
7617 x_catch_errors (dpy)
7618 x_catch_errors_unwind (old_val)
7619 x_check_errors (dpy, format)
7620 x_had_errors_p (dpy)
7621 x_clear_errors (dpy)
7622 x_uncatch_errors (dpy, count)
7623 x_trace_wire ()
7624 x_connection_signal (signalnum)
7625 x_connection_closed (dpy, error_message)
7626 x_error_quitter (display, error)
7627 x_error_handler (display, error)
7628 x_io_error_quitter (display)
7629
7630 */
7631
7632 \f
7633 /* Changing the font of the frame. */
7634
7635 /* Give frame F the font named FONTNAME as its default font, and
7636 return the full name of that font. FONTNAME may be a wildcard
7637 pattern; in that case, we choose some font that fits the pattern.
7638 The return value shows which font we chose. */
7639
7640 Lisp_Object
7641 x_new_font (f, fontname)
7642 struct frame *f;
7643 register char *fontname;
7644 {
7645 struct font_info *fontp
7646 = FS_LOAD_FONT (f, 0, fontname, -1);
7647
7648 if (!fontp)
7649 return Qnil;
7650
7651 FRAME_FONT (f) = (XFontStruct *) (fontp->font);
7652 FRAME_BASELINE_OFFSET (f) = fontp->baseline_offset;
7653 FRAME_FONTSET (f) = -1;
7654
7655 /* Compute the scroll bar width in character columns. */
7656 if (f->scroll_bar_pixel_width > 0)
7657 {
7658 int wid = FONT_WIDTH (FRAME_FONT (f));
7659 f->scroll_bar_cols = (f->scroll_bar_pixel_width + wid-1) / wid;
7660 }
7661 else
7662 {
7663 int wid = FONT_WIDTH (FRAME_FONT (f));
7664 f->scroll_bar_cols = (14 + wid - 1) / wid;
7665 }
7666
7667 /* Now make the frame display the given font. */
7668 if (FRAME_W32_WINDOW (f) != 0)
7669 {
7670 frame_update_line_height (f);
7671 if (NILP (tip_frame) || XFRAME (tip_frame) != f)
7672 x_set_window_size (f, 0, f->width, f->height);
7673 }
7674 else
7675 /* If we are setting a new frame's font for the first time,
7676 there are no faces yet, so this font's height is the line height. */
7677 f->output_data.w32->line_height = FONT_HEIGHT (FRAME_FONT (f));
7678
7679 return build_string (fontp->full_name);
7680 }
7681 \f
7682 /* Give frame F the fontset named FONTSETNAME as its default font, and
7683 return the full name of that fontset. FONTSETNAME may be a wildcard
7684 pattern; in that case, we choose some fontset that fits the pattern.
7685 The return value shows which fontset we chose. */
7686
7687 Lisp_Object
7688 x_new_fontset (f, fontsetname)
7689 struct frame *f;
7690 char *fontsetname;
7691 {
7692 int fontset = fs_query_fontset (build_string (fontsetname), 0);
7693 Lisp_Object result;
7694
7695 if (fontset < 0)
7696 return Qnil;
7697
7698 if (FRAME_FONTSET (f) == fontset)
7699 /* This fontset is already set in frame F. There's nothing more
7700 to do. */
7701 return fontset_name (fontset);
7702
7703 result = x_new_font (f, (SDATA (fontset_ascii (fontset))));
7704
7705 if (!STRINGP (result))
7706 /* Can't load ASCII font. */
7707 return Qnil;
7708
7709 /* Since x_new_font doesn't update any fontset information, do it now. */
7710 FRAME_FONTSET(f) = fontset;
7711
7712 return build_string (fontsetname);
7713 }
7714
7715 \f
7716 /***********************************************************************
7717 TODO: W32 Input Methods
7718 ***********************************************************************/
7719 /* Listing missing functions from xterm.c helps diff stay in step.
7720
7721 xim_destroy_callback (xim, client_data, call_data)
7722 xim_open_dpy (dpyinfo, resource_name)
7723 struct xim_inst_t
7724 xim_instantiate_callback (display, client_data, call_data)
7725 xim_initialize (dpyinfo, resource_name)
7726 xim_close_dpy (dpyinfo)
7727
7728 */
7729
7730 \f
7731 /* Calculate the absolute position in frame F
7732 from its current recorded position values and gravity. */
7733
7734 void
7735 x_calc_absolute_position (f)
7736 struct frame *f;
7737 {
7738 POINT pt;
7739 int flags = f->output_data.w32->size_hint_flags;
7740
7741 pt.x = pt.y = 0;
7742
7743 /* Find the position of the outside upper-left corner of
7744 the inner window, with respect to the outer window.
7745 But do this only if we will need the results. */
7746 if (f->output_data.w32->parent_desc != FRAME_W32_DISPLAY_INFO (f)->root_window)
7747 {
7748 BLOCK_INPUT;
7749 MapWindowPoints (FRAME_W32_WINDOW (f),
7750 f->output_data.w32->parent_desc,
7751 &pt, 1);
7752 UNBLOCK_INPUT;
7753 }
7754
7755 {
7756 RECT rt;
7757 rt.left = rt.right = rt.top = rt.bottom = 0;
7758
7759 BLOCK_INPUT;
7760 AdjustWindowRect(&rt, f->output_data.w32->dwStyle,
7761 FRAME_EXTERNAL_MENU_BAR (f));
7762 UNBLOCK_INPUT;
7763
7764 pt.x += (rt.right - rt.left);
7765 pt.y += (rt.bottom - rt.top);
7766 }
7767
7768 /* Treat negative positions as relative to the leftmost bottommost
7769 position that fits on the screen. */
7770 if (flags & XNegative)
7771 f->output_data.w32->left_pos = (FRAME_W32_DISPLAY_INFO (f)->width
7772 - 2 * f->output_data.w32->border_width - pt.x
7773 - PIXEL_WIDTH (f)
7774 + f->output_data.w32->left_pos);
7775
7776 if (flags & YNegative)
7777 f->output_data.w32->top_pos = (FRAME_W32_DISPLAY_INFO (f)->height
7778 - 2 * f->output_data.w32->border_width - pt.y
7779 - PIXEL_HEIGHT (f)
7780 + f->output_data.w32->top_pos);
7781 /* The left_pos and top_pos
7782 are now relative to the top and left screen edges,
7783 so the flags should correspond. */
7784 f->output_data.w32->size_hint_flags &= ~ (XNegative | YNegative);
7785 }
7786
7787 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
7788 to really change the position, and 0 when calling from
7789 x_make_frame_visible (in that case, XOFF and YOFF are the current
7790 position values). It is -1 when calling from x_set_frame_parameters,
7791 which means, do adjust for borders but don't change the gravity. */
7792
7793 void
7794 x_set_offset (f, xoff, yoff, change_gravity)
7795 struct frame *f;
7796 register int xoff, yoff;
7797 int change_gravity;
7798 {
7799 int modified_top, modified_left;
7800
7801 if (change_gravity > 0)
7802 {
7803 f->output_data.w32->top_pos = yoff;
7804 f->output_data.w32->left_pos = xoff;
7805 f->output_data.w32->size_hint_flags &= ~ (XNegative | YNegative);
7806 if (xoff < 0)
7807 f->output_data.w32->size_hint_flags |= XNegative;
7808 if (yoff < 0)
7809 f->output_data.w32->size_hint_flags |= YNegative;
7810 f->output_data.w32->win_gravity = NorthWestGravity;
7811 }
7812 x_calc_absolute_position (f);
7813
7814 BLOCK_INPUT;
7815 x_wm_set_size_hint (f, (long) 0, 0);
7816
7817 modified_left = f->output_data.w32->left_pos;
7818 modified_top = f->output_data.w32->top_pos;
7819
7820 my_set_window_pos (FRAME_W32_WINDOW (f),
7821 NULL,
7822 modified_left, modified_top,
7823 0, 0,
7824 SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
7825 UNBLOCK_INPUT;
7826 }
7827
7828
7829 /* Check if we need to resize the frame due to a fullscreen request.
7830 If so needed, resize the frame. */
7831 static void
7832 x_check_fullscreen (f)
7833 struct frame *f;
7834 {
7835 if (f->output_data.w32->want_fullscreen & FULLSCREEN_BOTH)
7836 {
7837 int width, height, ign;
7838
7839 x_real_positions (f, &f->output_data.w32->left_pos,
7840 &f->output_data.w32->top_pos);
7841
7842 x_fullscreen_adjust (f, &width, &height, &ign, &ign);
7843
7844 /* We do not need to move the window, it shall be taken care of
7845 when setting WM manager hints.
7846 If the frame is visible already, the position is checked by
7847 x_check_fullscreen_move. */
7848 if (f->width != width || f->height != height)
7849 {
7850 change_frame_size (f, height, width, 0, 1, 0);
7851 SET_FRAME_GARBAGED (f);
7852 cancel_mouse_face (f);
7853
7854 /* Wait for the change of frame size to occur */
7855 f->output_data.w32->want_fullscreen |= FULLSCREEN_WAIT;
7856 }
7857 }
7858 }
7859
7860 /* If frame parameters are set after the frame is mapped, we need to move
7861 the window. This is done in xfns.c.
7862 Some window managers moves the window to the right position, some
7863 moves the outer window manager window to the specified position.
7864 Here we check that we are in the right spot. If not, make a second
7865 move, assuming we are dealing with the second kind of window manager. */
7866 static void
7867 x_check_fullscreen_move (f)
7868 struct frame *f;
7869 {
7870 if (f->output_data.w32->want_fullscreen & FULLSCREEN_MOVE_WAIT)
7871 {
7872 int expect_top = f->output_data.w32->top_pos;
7873 int expect_left = f->output_data.w32->left_pos;
7874
7875 if (f->output_data.w32->want_fullscreen & FULLSCREEN_HEIGHT)
7876 expect_top = 0;
7877 if (f->output_data.w32->want_fullscreen & FULLSCREEN_WIDTH)
7878 expect_left = 0;
7879
7880 if (expect_top != f->output_data.w32->top_pos
7881 || expect_left != f->output_data.w32->left_pos)
7882 x_set_offset (f, expect_left, expect_top, 1);
7883
7884 /* Just do this once */
7885 f->output_data.w32->want_fullscreen &= ~FULLSCREEN_MOVE_WAIT;
7886 }
7887 }
7888
7889
7890 /* Calculate fullscreen size. Return in *TOP_POS and *LEFT_POS the
7891 wanted positions of the WM window (not emacs window).
7892 Return in *WIDTH and *HEIGHT the wanted width and height of Emacs
7893 window (FRAME_X_WINDOW).
7894 */
7895 void
7896 x_fullscreen_adjust (f, width, height, top_pos, left_pos)
7897 struct frame *f;
7898 int *width;
7899 int *height;
7900 int *top_pos;
7901 int *left_pos;
7902 {
7903 int newwidth = f->width, newheight = f->height;
7904
7905 *top_pos = f->output_data.w32->top_pos;
7906 *left_pos = f->output_data.w32->left_pos;
7907
7908 if (f->output_data.w32->want_fullscreen & FULLSCREEN_HEIGHT)
7909 {
7910 int ph;
7911
7912 ph = FRAME_X_DISPLAY_INFO (f)->height;
7913 newheight = PIXEL_TO_CHAR_HEIGHT (f, ph);
7914 ph = CHAR_TO_PIXEL_HEIGHT (f, newheight)
7915 - f->output_data.w32->y_pixels_diff;
7916 newheight = PIXEL_TO_CHAR_HEIGHT (f, ph);
7917 *top_pos = 0;
7918 }
7919
7920 if (f->output_data.w32->want_fullscreen & FULLSCREEN_WIDTH)
7921 {
7922 int pw;
7923
7924 pw = FRAME_X_DISPLAY_INFO (f)->width;
7925 newwidth = PIXEL_TO_CHAR_WIDTH (f, pw);
7926 pw = CHAR_TO_PIXEL_WIDTH (f, newwidth)
7927 - f->output_data.w32->x_pixels_diff;
7928 newwidth = PIXEL_TO_CHAR_WIDTH (f, pw);
7929 *left_pos = 0;
7930 }
7931
7932 *width = newwidth;
7933 *height = newheight;
7934 }
7935
7936
7937 /* Call this to change the size of frame F's x-window.
7938 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
7939 for this size change and subsequent size changes.
7940 Otherwise we leave the window gravity unchanged. */
7941
7942 void
7943 x_set_window_size (f, change_gravity, cols, rows)
7944 struct frame *f;
7945 int change_gravity;
7946 int cols, rows;
7947 {
7948 int pixelwidth, pixelheight;
7949
7950 BLOCK_INPUT;
7951
7952 check_frame_size (f, &rows, &cols);
7953 f->output_data.w32->vertical_scroll_bar_extra
7954 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
7955 ? 0
7956 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.w32->font)));
7957
7958 compute_fringe_widths (f, 0);
7959
7960 pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols);
7961 pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows);
7962
7963 f->output_data.w32->win_gravity = NorthWestGravity;
7964 x_wm_set_size_hint (f, (long) 0, 0);
7965
7966 {
7967 RECT rect;
7968
7969 rect.left = rect.top = 0;
7970 rect.right = pixelwidth;
7971 rect.bottom = pixelheight;
7972
7973 AdjustWindowRect(&rect, f->output_data.w32->dwStyle,
7974 FRAME_EXTERNAL_MENU_BAR (f));
7975
7976 my_set_window_pos (FRAME_W32_WINDOW (f),
7977 NULL,
7978 0, 0,
7979 rect.right - rect.left,
7980 rect.bottom - rect.top,
7981 SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE);
7982 }
7983
7984 /* Now, strictly speaking, we can't be sure that this is accurate,
7985 but the window manager will get around to dealing with the size
7986 change request eventually, and we'll hear how it went when the
7987 ConfigureNotify event gets here.
7988
7989 We could just not bother storing any of this information here,
7990 and let the ConfigureNotify event set everything up, but that
7991 might be kind of confusing to the Lisp code, since size changes
7992 wouldn't be reported in the frame parameters until some random
7993 point in the future when the ConfigureNotify event arrives.
7994
7995 We pass 1 for DELAY since we can't run Lisp code inside of
7996 a BLOCK_INPUT. */
7997 change_frame_size (f, rows, cols, 0, 1, 0);
7998 PIXEL_WIDTH (f) = pixelwidth;
7999 PIXEL_HEIGHT (f) = pixelheight;
8000
8001 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
8002 receive in the ConfigureNotify event; if we get what we asked
8003 for, then the event won't cause the screen to become garbaged, so
8004 we have to make sure to do it here. */
8005 SET_FRAME_GARBAGED (f);
8006
8007 /* If cursor was outside the new size, mark it as off. */
8008 mark_window_cursors_off (XWINDOW (f->root_window));
8009
8010 /* Clear out any recollection of where the mouse highlighting was,
8011 since it might be in a place that's outside the new frame size.
8012 Actually checking whether it is outside is a pain in the neck,
8013 so don't try--just let the highlighting be done afresh with new size. */
8014 cancel_mouse_face (f);
8015
8016 UNBLOCK_INPUT;
8017 }
8018 \f
8019 /* Mouse warping. */
8020
8021 void x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y);
8022
8023 void
8024 x_set_mouse_position (f, x, y)
8025 struct frame *f;
8026 int x, y;
8027 {
8028 int pix_x, pix_y;
8029
8030 pix_x = CHAR_TO_PIXEL_COL (f, x) + FONT_WIDTH (f->output_data.w32->font) / 2;
8031 pix_y = CHAR_TO_PIXEL_ROW (f, y) + f->output_data.w32->line_height / 2;
8032
8033 if (pix_x < 0) pix_x = 0;
8034 if (pix_x > PIXEL_WIDTH (f)) pix_x = PIXEL_WIDTH (f);
8035
8036 if (pix_y < 0) pix_y = 0;
8037 if (pix_y > PIXEL_HEIGHT (f)) pix_y = PIXEL_HEIGHT (f);
8038
8039 x_set_mouse_pixel_position (f, pix_x, pix_y);
8040 }
8041
8042 void
8043 x_set_mouse_pixel_position (f, pix_x, pix_y)
8044 struct frame *f;
8045 int pix_x, pix_y;
8046 {
8047 RECT rect;
8048 POINT pt;
8049
8050 BLOCK_INPUT;
8051
8052 GetClientRect (FRAME_W32_WINDOW (f), &rect);
8053 pt.x = rect.left + pix_x;
8054 pt.y = rect.top + pix_y;
8055 ClientToScreen (FRAME_W32_WINDOW (f), &pt);
8056
8057 SetCursorPos (pt.x, pt.y);
8058
8059 UNBLOCK_INPUT;
8060 }
8061
8062 \f
8063 /* focus shifting, raising and lowering. */
8064
8065 void
8066 x_focus_on_frame (f)
8067 struct frame *f;
8068 {
8069 struct w32_display_info *dpyinfo = &one_w32_display_info;
8070
8071 /* Give input focus to frame. */
8072 BLOCK_INPUT;
8073 #if 0
8074 /* Try not to change its Z-order if possible. */
8075 if (x_window_to_frame (dpyinfo, GetForegroundWindow ()))
8076 my_set_focus (f, FRAME_W32_WINDOW (f));
8077 else
8078 #endif
8079 my_set_foreground_window (FRAME_W32_WINDOW (f));
8080 UNBLOCK_INPUT;
8081 }
8082
8083 void
8084 x_unfocus_frame (f)
8085 struct frame *f;
8086 {
8087 }
8088
8089 /* Raise frame F. */
8090 void
8091 x_raise_frame (f)
8092 struct frame *f;
8093 {
8094 BLOCK_INPUT;
8095
8096 /* Strictly speaking, raise-frame should only change the frame's Z
8097 order, leaving input focus unchanged. This is reasonable behaviour
8098 on X where the usual policy is point-to-focus. However, this
8099 behaviour would be very odd on Windows where the usual policy is
8100 click-to-focus.
8101
8102 On X, if the mouse happens to be over the raised frame, it gets
8103 input focus anyway (so the window with focus will never be
8104 completely obscured) - if not, then just moving the mouse over it
8105 is sufficient to give it focus. On Windows, the user must actually
8106 click on the frame (preferrably the title bar so as not to move
8107 point), which is more awkward. Also, no other Windows program
8108 raises a window to the top but leaves another window (possibly now
8109 completely obscured) with input focus.
8110
8111 Because there is a system setting on Windows that allows the user
8112 to choose the point to focus policy, we make the strict semantics
8113 optional, but by default we grab focus when raising. */
8114
8115 if (NILP (Vw32_grab_focus_on_raise))
8116 {
8117 /* The obvious call to my_set_window_pos doesn't work if Emacs is
8118 not already the foreground application: the frame is raised
8119 above all other frames belonging to us, but not above the
8120 current top window. To achieve that, we have to resort to this
8121 more cumbersome method. */
8122
8123 HDWP handle = BeginDeferWindowPos (2);
8124 if (handle)
8125 {
8126 DeferWindowPos (handle,
8127 FRAME_W32_WINDOW (f),
8128 HWND_TOP,
8129 0, 0, 0, 0,
8130 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
8131
8132 DeferWindowPos (handle,
8133 GetForegroundWindow (),
8134 FRAME_W32_WINDOW (f),
8135 0, 0, 0, 0,
8136 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
8137
8138 EndDeferWindowPos (handle);
8139 }
8140 }
8141 else
8142 {
8143 my_set_foreground_window (FRAME_W32_WINDOW (f));
8144 }
8145
8146 UNBLOCK_INPUT;
8147 }
8148
8149 /* Lower frame F. */
8150 void
8151 x_lower_frame (f)
8152 struct frame *f;
8153 {
8154 BLOCK_INPUT;
8155 my_set_window_pos (FRAME_W32_WINDOW (f),
8156 HWND_BOTTOM,
8157 0, 0, 0, 0,
8158 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
8159 UNBLOCK_INPUT;
8160 }
8161
8162 static void
8163 w32_frame_raise_lower (f, raise_flag)
8164 FRAME_PTR f;
8165 int raise_flag;
8166 {
8167 if (! FRAME_W32_P (f))
8168 return;
8169
8170 if (raise_flag)
8171 x_raise_frame (f);
8172 else
8173 x_lower_frame (f);
8174 }
8175 \f
8176 /* Change of visibility. */
8177
8178 /* This tries to wait until the frame is really visible.
8179 However, if the window manager asks the user where to position
8180 the frame, this will return before the user finishes doing that.
8181 The frame will not actually be visible at that time,
8182 but it will become visible later when the window manager
8183 finishes with it. */
8184
8185 void
8186 x_make_frame_visible (f)
8187 struct frame *f;
8188 {
8189 Lisp_Object type;
8190
8191 BLOCK_INPUT;
8192
8193 type = x_icon_type (f);
8194 if (!NILP (type))
8195 x_bitmap_icon (f, type);
8196
8197 if (! FRAME_VISIBLE_P (f))
8198 {
8199 /* We test FRAME_GARBAGED_P here to make sure we don't
8200 call x_set_offset a second time
8201 if we get to x_make_frame_visible a second time
8202 before the window gets really visible. */
8203 if (! FRAME_ICONIFIED_P (f)
8204 && ! f->output_data.w32->asked_for_visible)
8205 x_set_offset (f, f->output_data.w32->left_pos, f->output_data.w32->top_pos, 0);
8206
8207 f->output_data.w32->asked_for_visible = 1;
8208
8209 /* my_show_window (f, FRAME_W32_WINDOW (f), f->async_iconified ? SW_RESTORE : SW_SHOW); */
8210 my_show_window (f, FRAME_W32_WINDOW (f), SW_SHOWNORMAL);
8211 }
8212
8213 /* Synchronize to ensure Emacs knows the frame is visible
8214 before we do anything else. We do this loop with input not blocked
8215 so that incoming events are handled. */
8216 {
8217 Lisp_Object frame;
8218 int count;
8219
8220 /* This must come after we set COUNT. */
8221 UNBLOCK_INPUT;
8222
8223 XSETFRAME (frame, f);
8224
8225 /* Wait until the frame is visible. Process X events until a
8226 MapNotify event has been seen, or until we think we won't get a
8227 MapNotify at all.. */
8228 for (count = input_signal_count + 10;
8229 input_signal_count < count && !FRAME_VISIBLE_P (f);)
8230 {
8231 /* Force processing of queued events. */
8232 /* TODO: x_sync equivalent? */
8233
8234 /* Machines that do polling rather than SIGIO have been observed
8235 to go into a busy-wait here. So we'll fake an alarm signal
8236 to let the handler know that there's something to be read.
8237 We used to raise a real alarm, but it seems that the handler
8238 isn't always enabled here. This is probably a bug. */
8239 if (input_polling_used ())
8240 {
8241 /* It could be confusing if a real alarm arrives while processing
8242 the fake one. Turn it off and let the handler reset it. */
8243 int old_poll_suppress_count = poll_suppress_count;
8244 poll_suppress_count = 1;
8245 poll_for_input_1 ();
8246 poll_suppress_count = old_poll_suppress_count;
8247 }
8248 }
8249 FRAME_SAMPLE_VISIBILITY (f);
8250 }
8251 }
8252
8253 /* Change from mapped state to withdrawn state. */
8254
8255 /* Make the frame visible (mapped and not iconified). */
8256
8257 x_make_frame_invisible (f)
8258 struct frame *f;
8259 {
8260 /* Don't keep the highlight on an invisible frame. */
8261 if (FRAME_W32_DISPLAY_INFO (f)->x_highlight_frame == f)
8262 FRAME_W32_DISPLAY_INFO (f)->x_highlight_frame = 0;
8263
8264 BLOCK_INPUT;
8265
8266 my_show_window (f, FRAME_W32_WINDOW (f), SW_HIDE);
8267
8268 /* We can't distinguish this from iconification
8269 just by the event that we get from the server.
8270 So we can't win using the usual strategy of letting
8271 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
8272 and synchronize with the server to make sure we agree. */
8273 f->visible = 0;
8274 FRAME_ICONIFIED_P (f) = 0;
8275 f->async_visible = 0;
8276 f->async_iconified = 0;
8277
8278 UNBLOCK_INPUT;
8279 }
8280
8281 /* Change window state from mapped to iconified. */
8282
8283 void
8284 x_iconify_frame (f)
8285 struct frame *f;
8286 {
8287 Lisp_Object type;
8288
8289 /* Don't keep the highlight on an invisible frame. */
8290 if (FRAME_W32_DISPLAY_INFO (f)->x_highlight_frame == f)
8291 FRAME_W32_DISPLAY_INFO (f)->x_highlight_frame = 0;
8292
8293 if (f->async_iconified)
8294 return;
8295
8296 BLOCK_INPUT;
8297
8298 type = x_icon_type (f);
8299 if (!NILP (type))
8300 x_bitmap_icon (f, type);
8301
8302 /* Simulate the user minimizing the frame. */
8303 SendMessage (FRAME_W32_WINDOW (f), WM_SYSCOMMAND, SC_MINIMIZE, 0);
8304
8305 UNBLOCK_INPUT;
8306 }
8307
8308 \f
8309 /* Free X resources of frame F. */
8310
8311 void
8312 x_free_frame_resources (f)
8313 struct frame *f;
8314 {
8315 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
8316
8317 BLOCK_INPUT;
8318
8319 if (FRAME_W32_WINDOW (f))
8320 my_destroy_window (f, FRAME_W32_WINDOW (f));
8321
8322 free_frame_menubar (f);
8323
8324 unload_color (f, f->output_data.x->foreground_pixel);
8325 unload_color (f, f->output_data.x->background_pixel);
8326 unload_color (f, f->output_data.w32->cursor_pixel);
8327 unload_color (f, f->output_data.w32->cursor_foreground_pixel);
8328 unload_color (f, f->output_data.w32->border_pixel);
8329 unload_color (f, f->output_data.w32->mouse_pixel);
8330 if (f->output_data.w32->white_relief.allocated_p)
8331 unload_color (f, f->output_data.w32->white_relief.pixel);
8332 if (f->output_data.w32->black_relief.allocated_p)
8333 unload_color (f, f->output_data.w32->black_relief.pixel);
8334
8335 if (FRAME_FACE_CACHE (f))
8336 free_frame_faces (f);
8337
8338 xfree (f->output_data.w32);
8339 f->output_data.w32 = NULL;
8340
8341 if (f == dpyinfo->w32_focus_frame)
8342 dpyinfo->w32_focus_frame = 0;
8343 if (f == dpyinfo->w32_focus_event_frame)
8344 dpyinfo->w32_focus_event_frame = 0;
8345 if (f == dpyinfo->x_highlight_frame)
8346 dpyinfo->x_highlight_frame = 0;
8347
8348 if (f == dpyinfo->mouse_face_mouse_frame)
8349 {
8350 dpyinfo->mouse_face_beg_row
8351 = dpyinfo->mouse_face_beg_col = -1;
8352 dpyinfo->mouse_face_end_row
8353 = dpyinfo->mouse_face_end_col = -1;
8354 dpyinfo->mouse_face_window = Qnil;
8355 dpyinfo->mouse_face_deferred_gc = 0;
8356 dpyinfo->mouse_face_mouse_frame = 0;
8357 }
8358
8359 UNBLOCK_INPUT;
8360 }
8361
8362
8363 /* Destroy the window of frame F. */
8364
8365 x_destroy_window (f)
8366 struct frame *f;
8367 {
8368 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
8369
8370 x_free_frame_resources (f);
8371
8372 dpyinfo->reference_count--;
8373 }
8374
8375 \f
8376 /* Setting window manager hints. */
8377
8378 /* Set the normal size hints for the window manager, for frame F.
8379 FLAGS is the flags word to use--or 0 meaning preserve the flags
8380 that the window now has.
8381 If USER_POSITION is nonzero, we set the USPosition
8382 flag (this is useful when FLAGS is 0). */
8383 void
8384 x_wm_set_size_hint (f, flags, user_position)
8385 struct frame *f;
8386 long flags;
8387 int user_position;
8388 {
8389 Window window = FRAME_W32_WINDOW (f);
8390
8391 enter_crit ();
8392
8393 SetWindowLong (window, WND_FONTWIDTH_INDEX, FONT_WIDTH (f->output_data.w32->font));
8394 SetWindowLong (window, WND_LINEHEIGHT_INDEX, f->output_data.w32->line_height);
8395 SetWindowLong (window, WND_BORDER_INDEX, f->output_data.w32->internal_border_width);
8396 SetWindowLong (window, WND_SCROLLBAR_INDEX, f->output_data.w32->vertical_scroll_bar_extra);
8397
8398 leave_crit ();
8399 }
8400
8401 /* Window manager things */
8402 x_wm_set_icon_position (f, icon_x, icon_y)
8403 struct frame *f;
8404 int icon_x, icon_y;
8405 {
8406 #if 0
8407 Window window = FRAME_W32_WINDOW (f);
8408
8409 f->display.x->wm_hints.flags |= IconPositionHint;
8410 f->display.x->wm_hints.icon_x = icon_x;
8411 f->display.x->wm_hints.icon_y = icon_y;
8412
8413 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->display.x->wm_hints);
8414 #endif
8415 }
8416
8417 \f
8418 /***********************************************************************
8419 Fonts
8420 ***********************************************************************/
8421
8422 /* The following functions are listed here to help diff stay in step
8423 with xterm.c. See w32fns.c for definitions.
8424
8425 x_get_font_info (f, font_idx)
8426 x_list_fonts (f, pattern, size, maxnames)
8427
8428 */
8429
8430 #if GLYPH_DEBUG
8431
8432 /* Check that FONT is valid on frame F. It is if it can be found in F's
8433 font table. */
8434
8435 static void
8436 x_check_font (f, font)
8437 struct frame *f;
8438 XFontStruct *font;
8439 {
8440 int i;
8441 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
8442
8443 xassert (font != NULL);
8444
8445 for (i = 0; i < dpyinfo->n_fonts; i++)
8446 if (dpyinfo->font_table[i].name
8447 && font == dpyinfo->font_table[i].font)
8448 break;
8449
8450 xassert (i < dpyinfo->n_fonts);
8451 }
8452
8453 #endif /* GLYPH_DEBUG != 0 */
8454
8455 /* Set *W to the minimum width, *H to the minimum font height of FONT.
8456 Note: There are (broken) X fonts out there with invalid XFontStruct
8457 min_bounds contents. For example, handa@etl.go.jp reports that
8458 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
8459 have font->min_bounds.width == 0. */
8460
8461 static INLINE void
8462 x_font_min_bounds (font, w, h)
8463 XFontStruct *font;
8464 int *w, *h;
8465 {
8466 /*
8467 * TODO: Windows does not appear to offer min bound, only
8468 * average and maximum width, and maximum height.
8469 */
8470 *h = FONT_HEIGHT (font);
8471 *w = FONT_WIDTH (font);
8472 }
8473
8474
8475 /* Compute the smallest character width and smallest font height over
8476 all fonts available on frame F. Set the members smallest_char_width
8477 and smallest_font_height in F's x_display_info structure to
8478 the values computed. Value is non-zero if smallest_font_height or
8479 smallest_char_width become smaller than they were before. */
8480
8481 int
8482 x_compute_min_glyph_bounds (f)
8483 struct frame *f;
8484 {
8485 int i;
8486 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
8487 XFontStruct *font;
8488 int old_width = dpyinfo->smallest_char_width;
8489 int old_height = dpyinfo->smallest_font_height;
8490
8491 dpyinfo->smallest_font_height = 100000;
8492 dpyinfo->smallest_char_width = 100000;
8493
8494 for (i = 0; i < dpyinfo->n_fonts; ++i)
8495 if (dpyinfo->font_table[i].name)
8496 {
8497 struct font_info *fontp = dpyinfo->font_table + i;
8498 int w, h;
8499
8500 font = (XFontStruct *) fontp->font;
8501 xassert (font != (XFontStruct *) ~0);
8502 x_font_min_bounds (font, &w, &h);
8503
8504 dpyinfo->smallest_font_height = min (dpyinfo->smallest_font_height, h);
8505 dpyinfo->smallest_char_width = min (dpyinfo->smallest_char_width, w);
8506 }
8507
8508 xassert (dpyinfo->smallest_char_width > 0
8509 && dpyinfo->smallest_font_height > 0);
8510
8511 return (dpyinfo->n_fonts == 1
8512 || dpyinfo->smallest_char_width < old_width
8513 || dpyinfo->smallest_font_height < old_height);
8514 }
8515
8516 /* The following functions are listed here to help diff stay in step
8517 with xterm.c. See w32fns.c for definitions.
8518
8519 x_load_font (f, fontname, size)
8520 x_query_font (f, fontname)
8521 x_find_ccl_program (fontp)
8522
8523 */
8524 \f
8525 /***********************************************************************
8526 Initialization
8527 ***********************************************************************/
8528
8529 static int w32_initialized = 0;
8530
8531 void
8532 w32_initialize_display_info (display_name)
8533 Lisp_Object display_name;
8534 {
8535 struct w32_display_info *dpyinfo = &one_w32_display_info;
8536
8537 bzero (dpyinfo, sizeof (*dpyinfo));
8538
8539 /* Put it on w32_display_name_list. */
8540 w32_display_name_list = Fcons (Fcons (display_name, Qnil),
8541 w32_display_name_list);
8542 dpyinfo->name_list_element = XCAR (w32_display_name_list);
8543
8544 dpyinfo->w32_id_name
8545 = (char *) xmalloc (SCHARS (Vinvocation_name)
8546 + SCHARS (Vsystem_name)
8547 + 2);
8548 sprintf (dpyinfo->w32_id_name, "%s@%s",
8549 SDATA (Vinvocation_name), SDATA (Vsystem_name));
8550
8551 /* Default Console mode values - overridden when running in GUI mode
8552 with values obtained from system metrics. */
8553 dpyinfo->resx = 1;
8554 dpyinfo->resy = 1;
8555 dpyinfo->height_in = 1;
8556 dpyinfo->width_in = 1;
8557 dpyinfo->n_planes = 1;
8558 dpyinfo->n_cbits = 4;
8559 dpyinfo->n_fonts = 0;
8560 dpyinfo->smallest_font_height = 1;
8561 dpyinfo->smallest_char_width = 1;
8562
8563 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
8564 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
8565 dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
8566 dpyinfo->mouse_face_window = Qnil;
8567 dpyinfo->mouse_face_overlay = Qnil;
8568 dpyinfo->mouse_face_hidden = 0;
8569
8570 dpyinfo->vertical_scroll_bar_cursor = w32_load_cursor (IDC_ARROW);
8571 /* TODO: dpyinfo->gray */
8572
8573 }
8574
8575 /* Create an xrdb-style database of resources to supercede registry settings.
8576 The database is just a concatenation of C strings, finished by an additional
8577 \0. The string are submitted to some basic normalization, so
8578
8579 [ *]option[ *]:[ *]value...
8580
8581 becomes
8582
8583 option:value...
8584
8585 but any whitespace following value is not removed. */
8586
8587 static char *
8588 w32_make_rdb (xrm_option)
8589 char *xrm_option;
8590 {
8591 char *buffer = xmalloc (strlen (xrm_option) + 2);
8592 char *current = buffer;
8593 char ch;
8594 int in_option = 1;
8595 int before_value = 0;
8596
8597 do {
8598 ch = *xrm_option++;
8599
8600 if (ch == '\n')
8601 {
8602 *current++ = '\0';
8603 in_option = 1;
8604 before_value = 0;
8605 }
8606 else if (ch != ' ')
8607 {
8608 *current++ = ch;
8609 if (in_option && (ch == ':'))
8610 {
8611 in_option = 0;
8612 before_value = 1;
8613 }
8614 else if (before_value)
8615 {
8616 before_value = 0;
8617 }
8618 }
8619 else if (!(in_option || before_value))
8620 {
8621 *current++ = ch;
8622 }
8623 } while (ch);
8624
8625 *current = '\0';
8626
8627 return buffer;
8628 }
8629
8630 struct w32_display_info *
8631 w32_term_init (display_name, xrm_option, resource_name)
8632 Lisp_Object display_name;
8633 char *xrm_option;
8634 char *resource_name;
8635 {
8636 struct w32_display_info *dpyinfo;
8637 HDC hdc;
8638
8639 BLOCK_INPUT;
8640
8641 if (!w32_initialized)
8642 {
8643 w32_initialize ();
8644 w32_initialized = 1;
8645 }
8646
8647 w32_initialize_display_info (display_name);
8648
8649 dpyinfo = &one_w32_display_info;
8650
8651 dpyinfo->xrdb = xrm_option ? w32_make_rdb (xrm_option) : NULL;
8652
8653 /* Put this display on the chain. */
8654 dpyinfo->next = x_display_list;
8655 x_display_list = dpyinfo;
8656
8657 hdc = GetDC (GetDesktopWindow ());
8658
8659 dpyinfo->height = GetDeviceCaps (hdc, VERTRES);
8660 dpyinfo->width = GetDeviceCaps (hdc, HORZRES);
8661 dpyinfo->root_window = GetDesktopWindow ();
8662 dpyinfo->n_planes = GetDeviceCaps (hdc, PLANES);
8663 dpyinfo->n_cbits = GetDeviceCaps (hdc, BITSPIXEL);
8664 dpyinfo->resx = GetDeviceCaps (hdc, LOGPIXELSX);
8665 dpyinfo->resy = GetDeviceCaps (hdc, LOGPIXELSY);
8666 dpyinfo->has_palette = GetDeviceCaps (hdc, RASTERCAPS) & RC_PALETTE;
8667 dpyinfo->image_cache = make_image_cache ();
8668 dpyinfo->height_in = dpyinfo->height / dpyinfo->resx;
8669 dpyinfo->width_in = dpyinfo->width / dpyinfo->resy;
8670 ReleaseDC (GetDesktopWindow (), hdc);
8671
8672 /* initialise palette with white and black */
8673 {
8674 XColor color;
8675 w32_defined_color (0, "white", &color, 1);
8676 w32_defined_color (0, "black", &color, 1);
8677 }
8678
8679 /* Create Fringe Bitmaps and store them for later use.
8680
8681 On W32, bitmaps are all unsigned short, as Windows requires
8682 bitmap data to be Word aligned. For some reason they are
8683 horizontally reflected compared to how they appear on X, so we
8684 need to bitswap and convert to unsigned shorts before creating
8685 the bitmaps. */
8686 {
8687 int i, j;
8688
8689 for (i = NO_FRINGE_BITMAP + 1; i < MAX_FRINGE_BITMAPS; i++)
8690 {
8691 int h = fringe_bitmaps[i].height;
8692 int wd = fringe_bitmaps[i].width;
8693 unsigned short *w32bits
8694 = (unsigned short *)alloca (h * sizeof (unsigned short));
8695 unsigned short *wb = w32bits;
8696 unsigned char *bits = fringe_bitmaps[i].bits;
8697 for (j = 0; j < h; j++)
8698 {
8699 static unsigned char swap_nibble[16]
8700 = { 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */
8701 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */
8702 0x1, 0x9, 0x5, 0xd, /* 0001 1001 0101 1101 */
8703 0x3, 0xb, 0x7, 0xf }; /* 0011 1011 0111 1111 */
8704
8705 unsigned char b = *bits++;
8706 *wb++ = (unsigned short)((swap_nibble[b & 0xf]<<4)
8707 | (swap_nibble[(b>>4) & 0xf]));
8708 }
8709 fringe_bmp[i] = CreateBitmap (wd, h, 1, 1, w32bits);
8710 }
8711 }
8712
8713 #ifndef F_SETOWN_BUG
8714 #ifdef F_SETOWN
8715 #ifdef F_SETOWN_SOCK_NEG
8716 /* stdin is a socket here */
8717 fcntl (connection, F_SETOWN, -getpid ());
8718 #else /* ! defined (F_SETOWN_SOCK_NEG) */
8719 fcntl (connection, F_SETOWN, getpid ());
8720 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
8721 #endif /* ! defined (F_SETOWN) */
8722 #endif /* F_SETOWN_BUG */
8723
8724 #ifdef SIGIO
8725 if (interrupt_input)
8726 init_sigio (connection);
8727 #endif /* ! defined (SIGIO) */
8728
8729 UNBLOCK_INPUT;
8730
8731 return dpyinfo;
8732 }
8733 \f
8734 /* Get rid of display DPYINFO, assuming all frames are already gone. */
8735
8736 void
8737 x_delete_display (dpyinfo)
8738 struct w32_display_info *dpyinfo;
8739 {
8740 /* Discard this display from w32_display_name_list and w32_display_list.
8741 We can't use Fdelq because that can quit. */
8742 if (! NILP (w32_display_name_list)
8743 && EQ (XCAR (w32_display_name_list), dpyinfo->name_list_element))
8744 w32_display_name_list = XCDR (w32_display_name_list);
8745 else
8746 {
8747 Lisp_Object tail;
8748
8749 tail = w32_display_name_list;
8750 while (CONSP (tail) && CONSP (XCDR (tail)))
8751 {
8752 if (EQ (XCAR (XCDR (tail)), dpyinfo->name_list_element))
8753 {
8754 XSETCDR (tail, XCDR (XCDR (tail)));
8755 break;
8756 }
8757 tail = XCDR (tail);
8758 }
8759 }
8760
8761 /* free palette table */
8762 {
8763 struct w32_palette_entry * plist;
8764
8765 plist = dpyinfo->color_list;
8766 while (plist)
8767 {
8768 struct w32_palette_entry * pentry = plist;
8769 plist = plist->next;
8770 xfree (pentry);
8771 }
8772 dpyinfo->color_list = NULL;
8773 if (dpyinfo->palette)
8774 DeleteObject(dpyinfo->palette);
8775 }
8776 xfree (dpyinfo->font_table);
8777 xfree (dpyinfo->w32_id_name);
8778
8779 /* Destroy row bitmaps. */
8780 {
8781 int i;
8782
8783 for (i = NO_FRINGE_BITMAP + 1; i < MAX_FRINGE_BITMAPS; i++)
8784 DeleteObject (fringe_bmp[i]);
8785 }
8786 }
8787 \f
8788 /* Set up use of W32. */
8789
8790 DWORD w32_msg_worker ();
8791
8792 void
8793 x_flush (struct frame * f)
8794 { /* Nothing to do */ }
8795
8796 static struct redisplay_interface w32_redisplay_interface =
8797 {
8798 x_produce_glyphs,
8799 x_write_glyphs,
8800 x_insert_glyphs,
8801 x_clear_end_of_line,
8802 x_scroll_run,
8803 x_after_update_window_line,
8804 x_update_window_begin,
8805 x_update_window_end,
8806 w32_cursor_to,
8807 x_flush,
8808 x_clear_mouse_face,
8809 w32_get_glyph_overhangs,
8810 x_fix_overlapping_area,
8811 w32_draw_fringe_bitmap,
8812 w32_per_char_metric,
8813 w32_encode_char,
8814 NULL, /* w32_compute_glyph_string_overhangs */
8815 x_draw_glyph_string
8816 };
8817
8818 void
8819 w32_initialize ()
8820 {
8821 rif = &w32_redisplay_interface;
8822
8823 /* MSVC does not type K&R functions with no arguments correctly, and
8824 so we must explicitly cast them. */
8825 clear_frame_hook = (void (*)(void)) x_clear_frame;
8826 ring_bell_hook = (void (*)(void)) w32_ring_bell;
8827 update_begin_hook = x_update_begin;
8828 update_end_hook = x_update_end;
8829
8830 read_socket_hook = w32_read_socket;
8831
8832 frame_up_to_date_hook = w32_frame_up_to_date;
8833
8834 mouse_position_hook = w32_mouse_position;
8835 frame_rehighlight_hook = w32_frame_rehighlight;
8836 frame_raise_lower_hook = w32_frame_raise_lower;
8837 set_vertical_scroll_bar_hook = w32_set_vertical_scroll_bar;
8838 condemn_scroll_bars_hook = w32_condemn_scroll_bars;
8839 redeem_scroll_bar_hook = w32_redeem_scroll_bar;
8840 judge_scroll_bars_hook = w32_judge_scroll_bars;
8841 estimate_mode_line_height_hook = x_estimate_mode_line_height;
8842
8843 scroll_region_ok = 1; /* we'll scroll partial frames */
8844 char_ins_del_ok = 1;
8845 line_ins_del_ok = 1; /* we'll just blt 'em */
8846 fast_clear_end_of_line = 1; /* X does this well */
8847 memory_below_frame = 0; /* we don't remember what scrolls
8848 off the bottom */
8849 baud_rate = 19200;
8850
8851 w32_system_caret_hwnd = NULL;
8852 w32_system_caret_height = 0;
8853 w32_system_caret_x = 0;
8854 w32_system_caret_y = 0;
8855
8856 last_tool_bar_item = -1;
8857 any_help_event_p = 0;
8858
8859 /* Initialize input mode: interrupt_input off, no flow control, allow
8860 8 bit character input, standard quit char. */
8861 Fset_input_mode (Qnil, Qnil, make_number (2), Qnil);
8862
8863 /* Create the window thread - it will terminate itself or when the app terminates */
8864
8865 init_crit ();
8866
8867 dwMainThreadId = GetCurrentThreadId ();
8868 DuplicateHandle (GetCurrentProcess (), GetCurrentThread (),
8869 GetCurrentProcess (), &hMainThread, 0, TRUE, DUPLICATE_SAME_ACCESS);
8870
8871 /* Wait for thread to start */
8872
8873 {
8874 MSG msg;
8875
8876 PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE);
8877
8878 hWindowsThread = CreateThread (NULL, 0,
8879 (LPTHREAD_START_ROUTINE) w32_msg_worker,
8880 0, 0, &dwWindowsThreadId);
8881
8882 GetMessage (&msg, NULL, WM_EMACS_DONE, WM_EMACS_DONE);
8883 }
8884
8885 /* It is desirable that mainThread should have the same notion of
8886 focus window and active window as windowsThread. Unfortunately, the
8887 following call to AttachThreadInput, which should do precisely what
8888 we need, causes major problems when Emacs is linked as a console
8889 program. Unfortunately, we have good reasons for doing that, so
8890 instead we need to send messages to windowsThread to make some API
8891 calls for us (ones that affect, or depend on, the active/focus
8892 window state. */
8893 #ifdef ATTACH_THREADS
8894 AttachThreadInput (dwMainThreadId, dwWindowsThreadId, TRUE);
8895 #endif
8896
8897 /* Dynamically link to optional system components. */
8898 {
8899 HANDLE user_lib = LoadLibrary ("user32.dll");
8900
8901 #define LOAD_PROC(fn) pfn##fn = (void *) GetProcAddress (user_lib, #fn)
8902
8903 /* New proportional scroll bar functions. */
8904 LOAD_PROC (SetScrollInfo);
8905 LOAD_PROC (GetScrollInfo);
8906
8907 #undef LOAD_PROC
8908
8909 FreeLibrary (user_lib);
8910
8911 /* If using proportional scroll bars, ensure handle is at least 5 pixels;
8912 otherwise use the fixed height. */
8913 vertical_scroll_bar_min_handle = (pfnSetScrollInfo != NULL) ? 5 :
8914 GetSystemMetrics (SM_CYVTHUMB);
8915
8916 /* For either kind of scroll bar, take account of the arrows; these
8917 effectively form the border of the main scroll bar range. */
8918 vertical_scroll_bar_top_border = vertical_scroll_bar_bottom_border
8919 = GetSystemMetrics (SM_CYVSCROLL);
8920 }
8921 }
8922
8923 void
8924 syms_of_w32term ()
8925 {
8926 staticpro (&w32_display_name_list);
8927 w32_display_name_list = Qnil;
8928
8929 staticpro (&last_mouse_scroll_bar);
8930 last_mouse_scroll_bar = Qnil;
8931
8932 staticpro (&Qvendor_specific_keysyms);
8933 Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
8934
8935 DEFVAR_INT ("w32-num-mouse-buttons",
8936 &Vw32_num_mouse_buttons,
8937 doc: /* Number of physical mouse buttons. */);
8938 Vw32_num_mouse_buttons = Qnil;
8939
8940 DEFVAR_LISP ("w32-swap-mouse-buttons",
8941 &Vw32_swap_mouse_buttons,
8942 doc: /* Swap the mapping of middle and right mouse buttons.
8943 When nil, middle button is mouse-2 and right button is mouse-3. */);
8944 Vw32_swap_mouse_buttons = Qnil;
8945
8946 DEFVAR_LISP ("w32-grab-focus-on-raise",
8947 &Vw32_grab_focus_on_raise,
8948 doc: /* Raised frame grabs input focus.
8949 When t, `raise-frame' grabs input focus as well. This fits well
8950 with the normal Windows click-to-focus policy, but might not be
8951 desirable when using a point-to-focus policy. */);
8952 Vw32_grab_focus_on_raise = Qt;
8953
8954 DEFVAR_LISP ("w32-capslock-is-shiftlock",
8955 &Vw32_capslock_is_shiftlock,
8956 doc: /* Apply CapsLock state to non character input keys.
8957 When nil, CapsLock only affects normal character input keys. */);
8958 Vw32_capslock_is_shiftlock = Qnil;
8959
8960 DEFVAR_LISP ("w32-recognize-altgr",
8961 &Vw32_recognize_altgr,
8962 doc: /* Recognize right-alt and left-ctrl as AltGr.
8963 When nil, the right-alt and left-ctrl key combination is
8964 interpreted normally. */);
8965 Vw32_recognize_altgr = Qt;
8966
8967 DEFVAR_BOOL ("w32-enable-unicode-output",
8968 &w32_enable_unicode_output,
8969 doc: /* Enable the use of Unicode for text output if non-nil.
8970 Unicode output may prevent some third party applications for displaying
8971 Far-East Languages on Windows 95/98 from working properly.
8972 NT uses Unicode internally anyway, so this flag will probably have no
8973 affect on NT machines. */);
8974 w32_enable_unicode_output = 1;
8975
8976 help_echo = Qnil;
8977 staticpro (&help_echo);
8978 help_echo_object = Qnil;
8979 staticpro (&help_echo_object);
8980 help_echo_window = Qnil;
8981 staticpro (&help_echo_window);
8982 previous_help_echo = Qnil;
8983 staticpro (&previous_help_echo);
8984 help_echo_pos = -1;
8985
8986 DEFVAR_BOOL ("mouse-autoselect-window", &mouse_autoselect_window,
8987 doc: /* *Non-nil means autoselect window with mouse pointer. */);
8988 mouse_autoselect_window = 0;
8989
8990 DEFVAR_BOOL ("w32-use-visible-system-caret",
8991 &w32_use_visible_system_caret,
8992 doc: /* Flag to make the system caret visible.
8993 When this is non-nil, Emacs will indicate the position of point by
8994 using the system caret instead of drawing its own cursor. Some screen
8995 reader software does not track the system cursor properly when it is
8996 invisible, and gets confused by Emacs drawing its own cursor, so this
8997 variable is initialized to t when Emacs detects that screen reader
8998 software is running as it starts up.
8999
9000 When this variable is set, other variables affecting the appearance of
9001 the cursor have no effect. */);
9002
9003 /* Initialize w32_use_visible_system_caret based on whether a screen
9004 reader is in use. */
9005 if (!SystemParametersInfo (SPI_GETSCREENREADER, 0,
9006 &w32_use_visible_system_caret, 0))
9007 w32_use_visible_system_caret = 0;
9008
9009 DEFVAR_BOOL ("x-stretch-cursor", &x_stretch_cursor_p,
9010 doc: /* *Non-nil means draw block cursor as wide as the glyph under it.
9011 For example, if a block cursor is over a tab, it will be drawn as
9012 wide as that tab on the display. */);
9013 x_stretch_cursor_p = 0;
9014
9015 DEFVAR_BOOL ("x-use-underline-position-properties",
9016 &x_use_underline_position_properties,
9017 doc: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
9018 nil means ignore them. If you encounter fonts with bogus
9019 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
9020 to 4.1, set this to nil. */);
9021 x_use_underline_position_properties = 1;
9022
9023 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,
9024 doc: /* If not nil, Emacs uses toolkit scroll bars. */);
9025 Vx_toolkit_scroll_bars = Qt;
9026
9027 staticpro (&last_mouse_motion_frame);
9028 last_mouse_motion_frame = Qnil;
9029 }