Merge from emacs-23
[bpt/emacs.git] / src / w32term.c
1 /* Implementation of GUI terminal on the Microsoft W32 API.
2 Copyright (C) 1989, 1993, 1994, 1995, 1996, 1997, 1998,
3 1999, 2000, 2001, 2002, 2003, 2004, 2005,
4 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
5
6 This file is part of GNU Emacs.
7
8 GNU Emacs is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
12
13 GNU Emacs is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
20
21 #include <config.h>
22 #include <signal.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <setjmp.h>
26 #include "lisp.h"
27 #include "blockinput.h"
28 #include "w32term.h"
29
30 #include "systty.h"
31 #include "systime.h"
32
33 #include <ctype.h>
34 #include <errno.h>
35 #include <sys/stat.h>
36 #include <imm.h>
37
38 #include "charset.h"
39 #include "character.h"
40 #include "coding.h"
41 #include "ccl.h"
42 #include "frame.h"
43 #include "dispextern.h"
44 #include "fontset.h"
45 #include "termhooks.h"
46 #include "termopts.h"
47 #include "termchar.h"
48 #include "disptab.h"
49 #include "buffer.h"
50 #include "window.h"
51 #include "keyboard.h"
52 #include "intervals.h"
53 #include "process.h"
54 #include "atimer.h"
55 #include "keymap.h"
56
57 #include "w32heap.h"
58 #include <shellapi.h>
59
60 #include "font.h"
61 #include "w32font.h"
62 \f
63 /* Fringe bitmaps. */
64
65 static int max_fringe_bmp = 0;
66 static HBITMAP *fringe_bmp = 0;
67
68 /* Non-nil means Emacs uses toolkit scroll bars. */
69
70 Lisp_Object Vx_toolkit_scroll_bars;
71
72 /* Temporary variables for w32_read_socket. */
73
74 static int last_mousemove_x = 0;
75 static int last_mousemove_y = 0;
76
77 /* Define GET_WHEEL_DELTA_WPARAM macro if system headers don't. */
78 #ifndef GET_WHEEL_DELTA_WPARAM
79 #define GET_WHEEL_DELTA_WPARAM(wparam) ((short)HIWORD (wparam))
80 #endif
81
82 /* Non-zero means that a HELP_EVENT has been generated since Emacs
83 start. */
84
85 static int any_help_event_p;
86
87 /* Last window where we saw the mouse. Used by mouse-autoselect-window. */
88 static Lisp_Object last_window;
89
90 /* Non-zero means make use of UNDERLINE_POSITION font properties. */
91 int x_use_underline_position_properties;
92
93 /* Non-zero means to draw the underline at the same place as the descent line. */
94
95 int x_underline_at_descent_line;
96
97 extern unsigned int msh_mousewheel;
98
99 extern void free_frame_menubar ();
100
101 extern int w32_codepage_for_font (char *fontname);
102 extern Cursor w32_load_cursor (LPCTSTR name);
103
104 extern Lisp_Object Vwindow_system;
105
106 #define x_any_window_to_frame x_window_to_frame
107 #define x_top_window_to_frame x_window_to_frame
108
109 \f
110 /* This is display since w32 does not support multiple ones. */
111 struct w32_display_info one_w32_display_info;
112 struct w32_display_info *x_display_list;
113
114 /* This is a list of cons cells, each of the form (NAME . FONT-LIST-CACHE),
115 one for each element of w32_display_list and in the same order.
116 NAME is the name of the frame.
117 FONT-LIST-CACHE records previous values returned by x-list-fonts. */
118 Lisp_Object w32_display_name_list;
119
120
121 #ifndef GLYPHSET
122 /* Pre Windows 2000, this was not available, but define it here so
123 that Emacs compiled on such a platform will run on newer versions. */
124
125 typedef struct tagWCRANGE
126 {
127 WCHAR wcLow;
128 USHORT cGlyphs;
129 } WCRANGE;
130
131 typedef struct tagGLYPHSET
132 {
133 DWORD cbThis;
134 DWORD flAccel;
135 DWORD cGlyphsSupported;
136 DWORD cRanges;
137 WCRANGE ranges[1];
138 } GLYPHSET;
139
140 #endif
141
142 /* Dynamic linking to SetLayeredWindowAttribute (only since 2000). */
143 BOOL (WINAPI *pfnSetLayeredWindowAttributes) (HWND, COLORREF, BYTE, DWORD);
144
145 #ifndef LWA_ALPHA
146 #define LWA_ALPHA 0x02
147 #endif
148 /* WS_EX_LAYERED is defined unconditionally by MingW, but only for W2K and
149 later targets by MSVC headers. */
150 #ifndef WS_EX_LAYERED
151 #define WS_EX_LAYERED 0x80000
152 #endif
153
154 /* Frame being updated by update_frame. This is declared in term.c.
155 This is set by update_begin and looked at by all the
156 w32 functions. It is zero while not inside an update.
157 In that case, the w32 functions assume that `SELECTED_FRAME ()'
158 is the frame to apply to. */
159 extern struct frame *updating_frame;
160
161 /* This is a frame waiting to be autoraised, within w32_read_socket. */
162 struct frame *pending_autoraise_frame;
163
164 /* The handle of the frame that currently owns the system caret. */
165 HWND w32_system_caret_hwnd;
166 int w32_system_caret_height;
167 int w32_system_caret_x;
168 int w32_system_caret_y;
169 int w32_use_visible_system_caret;
170
171 DWORD dwWindowsThreadId = 0;
172 HANDLE hWindowsThread = NULL;
173 DWORD dwMainThreadId = 0;
174 HANDLE hMainThread = NULL;
175
176 int vertical_scroll_bar_min_handle;
177 int vertical_scroll_bar_top_border;
178 int vertical_scroll_bar_bottom_border;
179
180 int last_scroll_bar_drag_pos;
181
182 /* Mouse movement. */
183
184 /* Where the mouse was last time we reported a mouse event. */
185 static RECT last_mouse_glyph;
186 static FRAME_PTR last_mouse_glyph_frame;
187 static Lisp_Object last_mouse_press_frame;
188
189 int w32_num_mouse_buttons;
190
191 Lisp_Object Vw32_swap_mouse_buttons;
192
193 /* Control whether x_raise_frame also sets input focus. */
194 Lisp_Object Vw32_grab_focus_on_raise;
195
196 /* Control whether Caps Lock affects non-ascii characters. */
197 Lisp_Object Vw32_capslock_is_shiftlock;
198
199 /* Control whether right-alt and left-ctrl should be recognized as AltGr. */
200 Lisp_Object Vw32_recognize_altgr;
201
202 /* The scroll bar in which the last motion event occurred.
203
204 If the last motion event occurred in a scroll bar, we set this
205 so w32_mouse_position can know whether to report a scroll bar motion or
206 an ordinary motion.
207
208 If the last motion event didn't occur in a scroll bar, we set this
209 to Qnil, to tell w32_mouse_position to return an ordinary motion event. */
210 static Lisp_Object last_mouse_scroll_bar;
211 static int last_mouse_scroll_bar_pos;
212
213 /* This is a hack. We would really prefer that w32_mouse_position would
214 return the time associated with the position it returns, but there
215 doesn't seem to be any way to wrest the time-stamp from the server
216 along with the position query. So, we just keep track of the time
217 of the last movement we received, and return that in hopes that
218 it's somewhat accurate. */
219 static Time last_mouse_movement_time;
220
221 /* Incremented by w32_read_socket whenever it really tries to read
222 events. */
223 #ifdef __STDC__
224 static int volatile input_signal_count;
225 #else
226 static int input_signal_count;
227 #endif
228
229 extern Lisp_Object Vcommand_line_args, Vsystem_name;
230
231 /* A mask of extra modifier bits to put into every keyboard char. */
232 extern EMACS_INT extra_keyboard_modifiers;
233
234 /* Keyboard code page - may be changed by language-change events. */
235 static int keyboard_codepage;
236
237 static void x_update_window_end P_ ((struct window *, int, int));
238 static void w32_handle_tool_bar_click P_ ((struct frame *,
239 struct input_event *));
240 static void w32_define_cursor P_ ((Window, Cursor));
241
242 void x_lower_frame P_ ((struct frame *));
243 void x_scroll_bar_clear P_ ((struct frame *));
244 void x_wm_set_size_hint P_ ((struct frame *, long, int));
245 void x_raise_frame P_ ((struct frame *));
246 void x_set_window_size P_ ((struct frame *, int, int, int));
247 void x_wm_set_window_state P_ ((struct frame *, int));
248 void x_wm_set_icon_pixmap P_ ((struct frame *, int));
249 static void w32_initialize P_ ((void));
250 static void x_update_end P_ ((struct frame *));
251 static void w32_frame_up_to_date P_ ((struct frame *));
252 static void w32_set_terminal_modes P_ ((struct terminal *));
253 static void w32_reset_terminal_modes P_ ((struct terminal *));
254 static void x_clear_frame P_ ((struct frame *));
255 static void frame_highlight P_ ((struct frame *));
256 static void frame_unhighlight P_ ((struct frame *));
257 static void x_new_focus_frame P_ ((struct w32_display_info *,
258 struct frame *));
259 static void x_focus_changed P_ ((int, int, struct w32_display_info *,
260 struct frame *, struct input_event *));
261 static void w32_detect_focus_change P_ ((struct w32_display_info *,
262 W32Msg *, struct input_event *));
263 static void w32_frame_rehighlight P_ ((struct frame *));
264 static void x_frame_rehighlight P_ ((struct w32_display_info *));
265 static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *));
266 static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int,
267 enum text_cursor_kinds));
268 static void w32_clip_to_row P_ ((struct window *, struct glyph_row *, int, HDC));
269 static BOOL my_show_window P_ ((struct frame *, HWND, int));
270 static void my_set_window_pos P_ ((HWND, HWND, int, int, int, int, UINT));
271 static void my_set_focus P_ ((struct frame *, HWND));
272 static void my_set_foreground_window P_ ((HWND));
273 static void my_destroy_window P_ ((struct frame *, HWND));
274
275 static Lisp_Object Qvendor_specific_keysyms;
276
277 \f
278 /***********************************************************************
279 Debugging
280 ***********************************************************************/
281
282 #if 0
283
284 /* This is a function useful for recording debugging information about
285 the sequence of occurrences in this file. */
286
287 struct record
288 {
289 char *locus;
290 int type;
291 };
292
293 struct record event_record[100];
294
295 int event_record_index;
296
297 record_event (locus, type)
298 char *locus;
299 int type;
300 {
301 if (event_record_index == sizeof (event_record) / sizeof (struct record))
302 event_record_index = 0;
303
304 event_record[event_record_index].locus = locus;
305 event_record[event_record_index].type = type;
306 event_record_index++;
307 }
308
309 #endif /* 0 */
310 \f
311
312 void
313 XChangeGC (void * ignore, XGCValues* gc, unsigned long mask,
314 XGCValues *xgcv)
315 {
316 if (mask & GCForeground)
317 gc->foreground = xgcv->foreground;
318 if (mask & GCBackground)
319 gc->background = xgcv->background;
320 if (mask & GCFont)
321 gc->font = xgcv->font;
322 }
323
324 XGCValues *XCreateGC (void * ignore, Window window, unsigned long mask,
325 XGCValues *xgcv)
326 {
327 XGCValues *gc = (XGCValues *) xmalloc (sizeof (XGCValues));
328 bzero (gc, sizeof (XGCValues));
329
330 XChangeGC (ignore, gc, mask, xgcv);
331
332 return gc;
333 }
334
335 void
336 XGetGCValues (void* ignore, XGCValues *gc,
337 unsigned long mask, XGCValues *xgcv)
338 {
339 XChangeGC (ignore, xgcv, mask, gc);
340 }
341
342 static void
343 w32_set_clip_rectangle (HDC hdc, RECT *rect)
344 {
345 if (rect)
346 {
347 HRGN clip_region = CreateRectRgnIndirect (rect);
348 SelectClipRgn (hdc, clip_region);
349 DeleteObject (clip_region);
350 }
351 else
352 SelectClipRgn (hdc, NULL);
353 }
354
355
356 /* Draw a hollow rectangle at the specified position. */
357 void
358 w32_draw_rectangle (HDC hdc, XGCValues *gc, int x, int y,
359 int width, int height)
360 {
361 HBRUSH hb, oldhb;
362 HPEN hp, oldhp;
363
364 hb = CreateSolidBrush (gc->background);
365 hp = CreatePen (PS_SOLID, 0, gc->foreground);
366 oldhb = SelectObject (hdc, hb);
367 oldhp = SelectObject (hdc, hp);
368
369 Rectangle (hdc, x, y, x + width, y + height);
370
371 SelectObject (hdc, oldhb);
372 SelectObject (hdc, oldhp);
373 DeleteObject (hb);
374 DeleteObject (hp);
375 }
376
377 /* Draw a filled rectangle at the specified position. */
378 void
379 w32_fill_rect (f, hdc, pix, lprect)
380 FRAME_PTR f;
381 HDC hdc;
382 COLORREF pix;
383 RECT * lprect;
384 {
385 HBRUSH hb;
386
387 hb = CreateSolidBrush (pix);
388 FillRect (hdc, lprect, hb);
389 DeleteObject (hb);
390 }
391
392 void
393 w32_clear_window (f)
394 FRAME_PTR f;
395 {
396 RECT rect;
397 HDC hdc = get_frame_dc (f);
398
399 /* Under certain conditions, this can be called at startup with
400 a console frame pointer before the GUI frame is created. An HDC
401 of 0 indicates this. */
402 if (hdc)
403 {
404 GetClientRect (FRAME_W32_WINDOW (f), &rect);
405 w32_clear_rect (f, hdc, &rect);
406 }
407
408 release_frame_dc (f, hdc);
409 }
410
411 #define OPAQUE_FRAME 255
412
413 void
414 x_set_frame_alpha (f)
415 struct frame *f;
416 {
417 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
418 double alpha = 1.0;
419 double alpha_min = 1.0;
420 BYTE opac;
421 LONG ex_style;
422 HWND window = FRAME_W32_WINDOW (f);
423
424 /* Older versions of Windows do not support transparency. */
425 if (!pfnSetLayeredWindowAttributes)
426 return;
427
428 if (dpyinfo->x_highlight_frame == f)
429 alpha = f->alpha[0];
430 else
431 alpha = f->alpha[1];
432
433 if (FLOATP (Vframe_alpha_lower_limit))
434 alpha_min = XFLOAT_DATA (Vframe_alpha_lower_limit);
435 else if (INTEGERP (Vframe_alpha_lower_limit))
436 alpha_min = (XINT (Vframe_alpha_lower_limit)) / 100.0;
437
438 if (alpha < 0.0)
439 return;
440 else if (alpha > 1.0)
441 alpha = 1.0;
442 else if (alpha < alpha_min && alpha_min <= 1.0)
443 alpha = alpha_min;
444
445 opac = alpha * OPAQUE_FRAME;
446
447 ex_style = GetWindowLong (window, GWL_EXSTYLE);
448
449 if (opac == OPAQUE_FRAME)
450 ex_style &= ~WS_EX_LAYERED;
451 else
452 ex_style |= WS_EX_LAYERED;
453
454 SetWindowLong (window, GWL_EXSTYLE, ex_style);
455
456 if (opac != OPAQUE_FRAME)
457 pfnSetLayeredWindowAttributes (window, 0, opac, LWA_ALPHA);
458 }
459
460 int
461 x_display_pixel_height (dpyinfo)
462 struct w32_display_info *dpyinfo;
463 {
464 HDC dc = GetDC (NULL);
465 int pixels = GetDeviceCaps (dc, VERTRES);
466 ReleaseDC (NULL, dc);
467 return pixels;
468 }
469
470 int
471 x_display_pixel_width (dpyinfo)
472 struct w32_display_info *dpyinfo;
473 {
474 HDC dc = GetDC (NULL);
475 int pixels = GetDeviceCaps (dc, HORZRES);
476 ReleaseDC (NULL, dc);
477 return pixels;
478 }
479
480 \f
481 /***********************************************************************
482 Starting and ending an update
483 ***********************************************************************/
484
485 /* Start an update of frame F. This function is installed as a hook
486 for update_begin, i.e. it is called when update_begin is called.
487 This function is called prior to calls to x_update_window_begin for
488 each window being updated. */
489
490 static void
491 x_update_begin (f)
492 struct frame *f;
493 {
494 struct w32_display_info *display_info = FRAME_W32_DISPLAY_INFO (f);
495
496 if (! FRAME_W32_P (f))
497 return;
498
499 /* Regenerate display palette before drawing if list of requested
500 colors has changed. */
501 if (display_info->regen_palette)
502 {
503 w32_regenerate_palette (f);
504 display_info->regen_palette = FALSE;
505 }
506 }
507
508
509 /* Start update of window W. Set the global variable updated_window
510 to the window being updated and set output_cursor to the cursor
511 position of W. */
512
513 static void
514 x_update_window_begin (w)
515 struct window *w;
516 {
517 struct frame *f = XFRAME (WINDOW_FRAME (w));
518 struct w32_display_info *display_info = FRAME_W32_DISPLAY_INFO (f);
519
520 /* Hide the system caret during an update. */
521 if (w32_use_visible_system_caret && w32_system_caret_hwnd)
522 {
523 SendMessage (w32_system_caret_hwnd, WM_EMACS_HIDE_CARET, 0, 0);
524 }
525
526 updated_window = w;
527 set_output_cursor (&w->cursor);
528
529 BLOCK_INPUT;
530
531 if (f == display_info->mouse_face_mouse_frame)
532 {
533 /* Don't do highlighting for mouse motion during the update. */
534 display_info->mouse_face_defer = 1;
535
536 /* If F needs to be redrawn, simply forget about any prior mouse
537 highlighting. */
538 if (FRAME_GARBAGED_P (f))
539 display_info->mouse_face_window = Qnil;
540
541 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
542 their mouse_face_p flag set, which means that they are always
543 unequal to rows in a desired matrix which never have that
544 flag set. So, rows containing mouse-face glyphs are never
545 scrolled, and we don't have to switch the mouse highlight off
546 here to prevent it from being scrolled. */
547
548 /* Can we tell that this update does not affect the window
549 where the mouse highlight is? If so, no need to turn off.
550 Likewise, don't do anything if the frame is garbaged;
551 in that case, the frame's current matrix that we would use
552 is all wrong, and we will redisplay that line anyway. */
553 if (!NILP (display_info->mouse_face_window)
554 && w == XWINDOW (display_info->mouse_face_window))
555 {
556 int i;
557
558 for (i = 0; i < w->desired_matrix->nrows; ++i)
559 if (MATRIX_ROW_ENABLED_P (w->desired_matrix, i))
560 break;
561
562 if (i < w->desired_matrix->nrows)
563 clear_mouse_face (display_info);
564 }
565 #endif /* 0 */
566 }
567
568 UNBLOCK_INPUT;
569 }
570
571 /* Draw a vertical window border from (x,y0) to (x,y1) */
572
573 static void
574 w32_draw_vertical_window_border (w, x, y0, y1)
575 struct window *w;
576 int x, y0, y1;
577 {
578 struct frame *f = XFRAME (WINDOW_FRAME (w));
579 RECT r;
580 HDC hdc;
581 struct face *face;
582
583 r.left = x;
584 r.right = x + 1;
585 r.top = y0;
586 r.bottom = y1;
587
588 hdc = get_frame_dc (f);
589 face = FACE_FROM_ID (f, VERTICAL_BORDER_FACE_ID);
590 if (face)
591 w32_fill_rect (f, hdc, face->foreground, &r);
592 else
593 w32_fill_rect (f, hdc, FRAME_FOREGROUND_PIXEL (f), &r);
594
595 release_frame_dc (f, hdc);
596 }
597
598
599 /* End update of window W (which is equal to updated_window).
600
601 Draw vertical borders between horizontally adjacent windows, and
602 display W's cursor if CURSOR_ON_P is non-zero.
603
604 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
605 glyphs in mouse-face were overwritten. In that case we have to
606 make sure that the mouse-highlight is properly redrawn.
607
608 W may be a menu bar pseudo-window in case we don't have X toolkit
609 support. Such windows don't have a cursor, so don't display it
610 here. */
611
612 static void
613 x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p)
614 struct window *w;
615 int cursor_on_p, mouse_face_overwritten_p;
616 {
617 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (XFRAME (w->frame));
618
619 if (!w->pseudo_window_p)
620 {
621 BLOCK_INPUT;
622
623 if (cursor_on_p)
624 display_and_set_cursor (w, 1, output_cursor.hpos,
625 output_cursor.vpos,
626 output_cursor.x, output_cursor.y);
627
628 if (draw_window_fringes (w, 1))
629 x_draw_vertical_border (w);
630
631 UNBLOCK_INPUT;
632 }
633
634 /* If a row with mouse-face was overwritten, arrange for
635 XTframe_up_to_date to redisplay the mouse highlight. */
636 if (mouse_face_overwritten_p)
637 {
638 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
639 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
640 dpyinfo->mouse_face_window = Qnil;
641 }
642
643 /* Unhide the caret. This won't actually show the cursor, unless it
644 was visible before the corresponding call to HideCaret in
645 x_update_window_begin. */
646 if (w32_use_visible_system_caret && w32_system_caret_hwnd)
647 {
648 SendMessage (w32_system_caret_hwnd, WM_EMACS_SHOW_CARET, 0, 0);
649 }
650
651 updated_window = NULL;
652 }
653
654
655 /* End update of frame F. This function is installed as a hook in
656 update_end. */
657
658 static void
659 x_update_end (f)
660 struct frame *f;
661 {
662 if (! FRAME_W32_P (f))
663 return;
664
665 /* Mouse highlight may be displayed again. */
666 FRAME_W32_DISPLAY_INFO (f)->mouse_face_defer = 0;
667 }
668
669
670 /* This function is called from various places in xdisp.c whenever a
671 complete update has been performed. The global variable
672 updated_window is not available here. */
673
674 static void
675 w32_frame_up_to_date (f)
676 struct frame *f;
677 {
678 if (FRAME_W32_P (f))
679 {
680 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
681
682 if (dpyinfo->mouse_face_deferred_gc
683 || f == dpyinfo->mouse_face_mouse_frame)
684 {
685 BLOCK_INPUT;
686 if (dpyinfo->mouse_face_mouse_frame)
687 note_mouse_highlight (dpyinfo->mouse_face_mouse_frame,
688 dpyinfo->mouse_face_mouse_x,
689 dpyinfo->mouse_face_mouse_y);
690 dpyinfo->mouse_face_deferred_gc = 0;
691 UNBLOCK_INPUT;
692 }
693 }
694 }
695
696
697 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
698 arrow bitmaps, or clear the fringes if no bitmaps are required
699 before DESIRED_ROW is made current. The window being updated is
700 found in updated_window. This function is called from
701 update_window_line only if it is known that there are differences
702 between bitmaps to be drawn between current row and DESIRED_ROW. */
703
704 static void
705 x_after_update_window_line (desired_row)
706 struct glyph_row *desired_row;
707 {
708 struct window *w = updated_window;
709 struct frame *f;
710 int width, height;
711
712 xassert (w);
713
714 if (!desired_row->mode_line_p && !w->pseudo_window_p)
715 desired_row->redraw_fringe_bitmaps_p = 1;
716
717 /* When a window has disappeared, make sure that no rest of
718 full-width rows stays visible in the internal border. Could
719 check here if updated_window is the leftmost/rightmost window,
720 but I guess it's not worth doing since vertically split windows
721 are almost never used, internal border is rarely set, and the
722 overhead is very small. */
723 if (windows_or_buffers_changed
724 && desired_row->full_width_p
725 && (f = XFRAME (w->frame),
726 width = FRAME_INTERNAL_BORDER_WIDTH (f),
727 width != 0)
728 && (height = desired_row->visible_height,
729 height > 0))
730 {
731 int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
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, FRAME_PIXEL_WIDTH (f) - 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 int rowY;
761
762 hdc = get_frame_dc (f);
763
764 if (!p->overlay_p)
765 {
766 int bx = p->bx, by = p->by, nx = p->nx, ny = p->ny;
767
768 /* If the fringe is adjacent to the left (right) scroll bar of a
769 leftmost (rightmost, respectively) window, then extend its
770 background to the gap between the fringe and the bar. */
771 if ((WINDOW_LEFTMOST_P (w)
772 && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w))
773 || (WINDOW_RIGHTMOST_P (w)
774 && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w)))
775 {
776 int sb_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
777
778 if (sb_width > 0)
779 {
780 int left = WINDOW_SCROLL_BAR_AREA_X (w);
781 int width = (WINDOW_CONFIG_SCROLL_BAR_COLS (w)
782 * FRAME_COLUMN_WIDTH (f));
783
784 if (bx < 0)
785 {
786 /* Bitmap fills the fringe. */
787 if (left + width == p->x)
788 bx = left + sb_width;
789 else if (p->x + p->wd == left)
790 bx = left;
791 if (bx >= 0)
792 {
793 int header_line_height = WINDOW_HEADER_LINE_HEIGHT (w);
794
795 nx = width - sb_width;
796 by = WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
797 row->y));
798 ny = row->visible_height;
799 }
800 }
801 else
802 {
803 if (left + width == bx)
804 {
805 bx = left + sb_width;
806 nx += width - sb_width;
807 }
808 else if (bx + nx == left)
809 nx += width - sb_width;
810 }
811 }
812 }
813
814 if (bx >= 0 && nx > 0)
815 w32_fill_area (f, hdc, face->background, bx, by, nx, ny);
816 }
817
818 /* Must clip because of partially visible lines. */
819 rowY = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
820 if (p->y < rowY)
821 {
822 /* Adjust position of "bottom aligned" bitmap on partially
823 visible last row. */
824 int oldY = row->y;
825 int oldVH = row->visible_height;
826 row->visible_height = p->h;
827 row->y -= rowY - p->y;
828 w32_clip_to_row (w, row, -1, hdc);
829 row->y = oldY;
830 row->visible_height = oldVH;
831 }
832 else
833 w32_clip_to_row (w, row, -1, hdc);
834
835 if (p->which && p->which < max_fringe_bmp)
836 {
837 HBITMAP pixmap = fringe_bmp[p->which];
838 HDC compat_hdc;
839 HANDLE horig_obj;
840
841 compat_hdc = CreateCompatibleDC (hdc);
842
843 SaveDC (hdc);
844
845 horig_obj = SelectObject (compat_hdc, pixmap);
846
847 /* Paint overlays transparently. */
848 if (p->overlay_p)
849 {
850 HBRUSH h_brush, h_orig_brush;
851
852 SetTextColor (hdc, BLACK_PIX_DEFAULT (f));
853 SetBkColor (hdc, WHITE_PIX_DEFAULT (f));
854 h_brush = CreateSolidBrush (face->foreground);
855 h_orig_brush = SelectObject (hdc, h_brush);
856
857 BitBlt (hdc, p->x, p->y, p->wd, p->h,
858 compat_hdc, 0, p->dh,
859 DSTINVERT);
860 BitBlt (hdc, p->x, p->y, p->wd, p->h,
861 compat_hdc, 0, p->dh,
862 0x2E064A);
863 BitBlt (hdc, p->x, p->y, p->wd, p->h,
864 compat_hdc, 0, p->dh,
865 DSTINVERT);
866
867 SelectObject (hdc, h_orig_brush);
868 DeleteObject (h_brush);
869 }
870 else
871 {
872 SetTextColor (hdc, face->background);
873 SetBkColor (hdc, (p->cursor_p
874 ? f->output_data.w32->cursor_pixel
875 : face->foreground));
876
877 BitBlt (hdc, p->x, p->y, p->wd, p->h,
878 compat_hdc, 0, p->dh,
879 SRCCOPY);
880 }
881
882 SelectObject (compat_hdc, horig_obj);
883 DeleteDC (compat_hdc);
884 RestoreDC (hdc, -1);
885 }
886
887 w32_set_clip_rectangle (hdc, NULL);
888
889 release_frame_dc (f, hdc);
890 }
891
892 static void
893 w32_define_fringe_bitmap (which, bits, h, wd)
894 int which;
895 unsigned short *bits;
896 int h, wd;
897 {
898 if (which >= max_fringe_bmp)
899 {
900 int i = max_fringe_bmp;
901 max_fringe_bmp = which + 20;
902 fringe_bmp = (HBITMAP *) xrealloc (fringe_bmp, max_fringe_bmp * sizeof (HBITMAP));
903 while (i < max_fringe_bmp)
904 fringe_bmp[i++] = 0;
905 }
906
907 fringe_bmp[which] = CreateBitmap (wd, h, 1, 1, bits);
908 }
909
910 static void
911 w32_destroy_fringe_bitmap (which)
912 int which;
913 {
914 if (which >= max_fringe_bmp)
915 return;
916
917 if (fringe_bmp[which])
918 DeleteObject (fringe_bmp[which]);
919 fringe_bmp[which] = 0;
920 }
921
922
923 \f
924 /* This is called when starting Emacs and when restarting after
925 suspend. When starting Emacs, no window is mapped. And nothing
926 must be done to Emacs's own window if it is suspended (though that
927 rarely happens). */
928
929 static void
930 w32_set_terminal_modes (struct terminal *term)
931 {
932 }
933
934 /* This is called when exiting or suspending Emacs. Exiting will make
935 the W32 windows go away, and suspending requires no action. */
936
937 static void
938 w32_reset_terminal_modes (struct terminal *term)
939 {
940 }
941
942
943 \f
944 /***********************************************************************
945 Display Iterator
946 ***********************************************************************/
947
948 /* Function prototypes of this page. */
949
950 static void x_set_glyph_string_clipping P_ ((struct glyph_string *));
951 static void x_set_glyph_string_gc P_ ((struct glyph_string *));
952 static void x_draw_glyph_string_background P_ ((struct glyph_string *,
953 int));
954 static void x_draw_glyph_string_foreground P_ ((struct glyph_string *));
955 static void x_draw_composite_glyph_string_foreground P_ ((struct glyph_string *));
956 static void x_draw_glyph_string_box P_ ((struct glyph_string *));
957 static void x_draw_glyph_string P_ ((struct glyph_string *));
958 static void x_set_cursor_gc P_ ((struct glyph_string *));
959 static void x_set_mode_line_face_gc P_ ((struct glyph_string *));
960 static void x_set_mouse_face_gc P_ ((struct glyph_string *));
961 static int w32_alloc_lighter_color (struct frame *, COLORREF *, double, int);
962 static void w32_setup_relief_color P_ ((struct frame *, struct relief *,
963 double, int, COLORREF));
964 static void x_setup_relief_colors P_ ((struct glyph_string *));
965 static void x_draw_image_glyph_string P_ ((struct glyph_string *));
966 static void x_draw_image_relief P_ ((struct glyph_string *));
967 static void x_draw_image_foreground P_ ((struct glyph_string *));
968 static void w32_draw_image_foreground_1 P_ ((struct glyph_string *, HBITMAP));
969 static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int,
970 int, int, int));
971 static void w32_draw_relief_rect P_ ((struct frame *, int, int, int, int,
972 int, int, int, int, int, int,
973 RECT *));
974 static void w32_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,
975 int, int, int, RECT *));
976
977
978 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
979 face. */
980
981 static void
982 x_set_cursor_gc (s)
983 struct glyph_string *s;
984 {
985 if (s->font == FRAME_FONT (s->f)
986 && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
987 && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
988 && !s->cmp)
989 s->gc = s->f->output_data.w32->cursor_gc;
990 else
991 {
992 /* Cursor on non-default face: must merge. */
993 XGCValues xgcv;
994 unsigned long mask;
995
996 xgcv.background = s->f->output_data.w32->cursor_pixel;
997 xgcv.foreground = s->face->background;
998
999 /* If the glyph would be invisible, try a different foreground. */
1000 if (xgcv.foreground == xgcv.background)
1001 xgcv.foreground = s->face->foreground;
1002 if (xgcv.foreground == xgcv.background)
1003 xgcv.foreground = s->f->output_data.w32->cursor_foreground_pixel;
1004 if (xgcv.foreground == xgcv.background)
1005 xgcv.foreground = s->face->foreground;
1006
1007 /* Make sure the cursor is distinct from text in this face. */
1008 if (xgcv.background == s->face->background
1009 && xgcv.foreground == s->face->foreground)
1010 {
1011 xgcv.background = s->face->foreground;
1012 xgcv.foreground = s->face->background;
1013 }
1014
1015 IF_DEBUG (x_check_font (s->f, s->font));
1016 xgcv.font = s->font;
1017 mask = GCForeground | GCBackground | GCFont;
1018
1019 if (FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc)
1020 XChangeGC (NULL, FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc,
1021 mask, &xgcv);
1022 else
1023 FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc
1024 = XCreateGC (NULL, s->window, mask, &xgcv);
1025
1026 s->gc = FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc;
1027 }
1028 }
1029
1030
1031 /* Set up S->gc of glyph string S for drawing text in mouse face. */
1032
1033 static void
1034 x_set_mouse_face_gc (s)
1035 struct glyph_string *s;
1036 {
1037 int face_id;
1038 struct face *face;
1039
1040 /* What face has to be used last for the mouse face? */
1041 face_id = FRAME_W32_DISPLAY_INFO (s->f)->mouse_face_face_id;
1042 face = FACE_FROM_ID (s->f, face_id);
1043 if (face == NULL)
1044 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
1045
1046 if (s->first_glyph->type == CHAR_GLYPH)
1047 face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch, -1, Qnil);
1048 else
1049 face_id = FACE_FOR_CHAR (s->f, face, 0, -1, Qnil);
1050 s->face = FACE_FROM_ID (s->f, face_id);
1051 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
1052
1053 /* If font in this face is same as S->font, use it. */
1054 if (s->font == s->face->font)
1055 s->gc = s->face->gc;
1056 else
1057 {
1058 /* Otherwise construct scratch_cursor_gc with values from FACE
1059 but font FONT. */
1060 XGCValues xgcv;
1061 unsigned long mask;
1062
1063 xgcv.background = s->face->background;
1064 xgcv.foreground = s->face->foreground;
1065 IF_DEBUG (x_check_font (s->f, s->font));
1066 xgcv.font = s->font;
1067 mask = GCForeground | GCBackground | GCFont;
1068
1069 if (FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc)
1070 XChangeGC (NULL, FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc,
1071 mask, &xgcv);
1072 else
1073 FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc
1074 = XCreateGC (NULL, s->window, mask, &xgcv);
1075
1076 s->gc = FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc;
1077 }
1078
1079 xassert (s->gc != 0);
1080 }
1081
1082
1083 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
1084 Faces to use in the mode line have already been computed when the
1085 matrix was built, so there isn't much to do, here. */
1086
1087 static INLINE void
1088 x_set_mode_line_face_gc (s)
1089 struct glyph_string *s;
1090 {
1091 s->gc = s->face->gc;
1092 }
1093
1094
1095 /* Set S->gc of glyph string S for drawing that glyph string. Set
1096 S->stippled_p to a non-zero value if the face of S has a stipple
1097 pattern. */
1098
1099 static INLINE void
1100 x_set_glyph_string_gc (s)
1101 struct glyph_string *s;
1102 {
1103 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
1104
1105 if (s->hl == DRAW_NORMAL_TEXT)
1106 {
1107 s->gc = s->face->gc;
1108 s->stippled_p = s->face->stipple != 0;
1109 }
1110 else if (s->hl == DRAW_INVERSE_VIDEO)
1111 {
1112 x_set_mode_line_face_gc (s);
1113 s->stippled_p = s->face->stipple != 0;
1114 }
1115 else if (s->hl == DRAW_CURSOR)
1116 {
1117 x_set_cursor_gc (s);
1118 s->stippled_p = 0;
1119 }
1120 else if (s->hl == DRAW_MOUSE_FACE)
1121 {
1122 x_set_mouse_face_gc (s);
1123 s->stippled_p = s->face->stipple != 0;
1124 }
1125 else if (s->hl == DRAW_IMAGE_RAISED
1126 || s->hl == DRAW_IMAGE_SUNKEN)
1127 {
1128 s->gc = s->face->gc;
1129 s->stippled_p = s->face->stipple != 0;
1130 }
1131 else
1132 {
1133 s->gc = s->face->gc;
1134 s->stippled_p = s->face->stipple != 0;
1135 }
1136
1137 /* GC must have been set. */
1138 xassert (s->gc != 0);
1139 }
1140
1141
1142 /* Set clipping for output of glyph string S. S may be part of a mode
1143 line or menu if we don't have X toolkit support. */
1144
1145 static INLINE void
1146 x_set_glyph_string_clipping (s)
1147 struct glyph_string *s;
1148 {
1149 RECT *r = s->clip;
1150 int n = get_glyph_string_clip_rects (s, r, 2);
1151
1152 if (n == 1)
1153 w32_set_clip_rectangle (s->hdc, r);
1154 else if (n > 1)
1155 {
1156 HRGN full_clip, clip1, clip2;
1157 clip1 = CreateRectRgnIndirect (r);
1158 clip2 = CreateRectRgnIndirect (r + 1);
1159 if (CombineRgn (full_clip, clip1, clip2, RGN_OR) != ERROR)
1160 {
1161 SelectClipRgn (s->hdc, full_clip);
1162 }
1163 DeleteObject (clip1);
1164 DeleteObject (clip2);
1165 DeleteObject (full_clip);
1166 }
1167 s->num_clips = n;
1168 }
1169
1170 /* Set SRC's clipping for output of glyph string DST. This is called
1171 when we are drawing DST's left_overhang or right_overhang only in
1172 the area of SRC. */
1173
1174 static void
1175 x_set_glyph_string_clipping_exactly (src, dst)
1176 struct glyph_string *src, *dst;
1177 {
1178 RECT r;
1179
1180 r.left = src->x;
1181 r.right = r.left + src->width;
1182 r.top = src->y;
1183 r.bottom = r.top + src->height;
1184 dst->clip[0] = r;
1185 dst->num_clips = 1;
1186 w32_set_clip_rectangle (dst->hdc, &r);
1187 }
1188
1189 /* RIF:
1190 Compute left and right overhang of glyph string S. */
1191
1192 static void
1193 w32_compute_glyph_string_overhangs (s)
1194 struct glyph_string *s;
1195 {
1196 if (s->cmp == NULL
1197 && s->first_glyph->type == CHAR_GLYPH
1198 && !s->font_not_found_p)
1199 {
1200 unsigned *code = alloca (sizeof (unsigned) * s->nchars);
1201 struct font *font = s->font;
1202 struct font_metrics metrics;
1203 int i;
1204
1205 for (i = 0; i < s->nchars; i++)
1206 code[i] = s->char2b[i];
1207 font->driver->text_extents (font, code, s->nchars, &metrics);
1208 s->right_overhang = (metrics.rbearing > metrics.width
1209 ? metrics.rbearing - metrics.width : 0);
1210 s->left_overhang = metrics.lbearing < 0 ? -metrics.lbearing : 0;
1211 }
1212 else if (s->cmp)
1213 {
1214 s->right_overhang = s->cmp->rbearing - s->cmp->pixel_width;
1215 s->left_overhang = -s->cmp->lbearing;
1216 }
1217 }
1218
1219 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
1220
1221 static INLINE void
1222 x_clear_glyph_string_rect (s, x, y, w, h)
1223 struct glyph_string *s;
1224 int x, y, w, h;
1225 {
1226 int real_x = x;
1227 int real_y = y;
1228 int real_w = w;
1229 int real_h = h;
1230 #if 0
1231 /* Take clipping into account. */
1232 if (s->gc->clip_mask == Rect)
1233 {
1234 real_x = max (real_x, s->gc->clip_rectangle.left);
1235 real_y = max (real_y, s->gc->clip_rectangle.top);
1236 real_w = min (real_w, s->gc->clip_rectangle.right
1237 - s->gc->clip_rectangle.left);
1238 real_h = min (real_h, s->gc->clip_rectangle.bottom
1239 - s->gc->clip_rectangle.top);
1240 }
1241 #endif
1242 w32_fill_area (s->f, s->hdc, s->gc->background, real_x, real_y,
1243 real_w, real_h);
1244 }
1245
1246
1247 /* Draw the background of glyph_string S. If S->background_filled_p
1248 is non-zero don't draw it. FORCE_P non-zero means draw the
1249 background even if it wouldn't be drawn normally. This is used
1250 when a string preceding S draws into the background of S, or S
1251 contains the first component of a composition. */
1252
1253 static void
1254 x_draw_glyph_string_background (s, force_p)
1255 struct glyph_string *s;
1256 int force_p;
1257 {
1258 /* Nothing to do if background has already been drawn or if it
1259 shouldn't be drawn in the first place. */
1260 if (!s->background_filled_p)
1261 {
1262 int box_line_width = max (s->face->box_line_width, 0);
1263
1264 #if 0 /* TODO: stipple */
1265 if (s->stippled_p)
1266 {
1267 /* Fill background with a stipple pattern. */
1268 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
1269 XFillRectangle (s->display, s->window, s->gc, s->x,
1270 s->y + box_line_width,
1271 s->background_width,
1272 s->height - 2 * box_line_width);
1273 XSetFillStyle (s->display, s->gc, FillSolid);
1274 s->background_filled_p = 1;
1275 }
1276 else
1277 #endif
1278 if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
1279 || s->font_not_found_p
1280 || s->extends_to_end_of_line_p
1281 || force_p)
1282 {
1283 x_clear_glyph_string_rect (s, s->x, s->y + box_line_width,
1284 s->background_width,
1285 s->height - 2 * box_line_width);
1286 s->background_filled_p = 1;
1287 }
1288 }
1289 }
1290
1291
1292 /* Draw the foreground of glyph string S. */
1293
1294 static void
1295 x_draw_glyph_string_foreground (s)
1296 struct glyph_string *s;
1297 {
1298 int i, x;
1299
1300 /* If first glyph of S has a left box line, start drawing the text
1301 of S to the right of that box line. */
1302 if (s->face->box != FACE_NO_BOX
1303 && s->first_glyph->left_box_line_p)
1304 x = s->x + eabs (s->face->box_line_width);
1305 else
1306 x = s->x;
1307
1308 SetTextColor (s->hdc, s->gc->foreground);
1309 SetBkColor (s->hdc, s->gc->background);
1310 SetTextAlign (s->hdc, TA_BASELINE | TA_LEFT);
1311
1312 /* Draw characters of S as rectangles if S's font could not be
1313 loaded. */
1314 if (s->font_not_found_p)
1315 {
1316 for (i = 0; i < s->nchars; ++i)
1317 {
1318 struct glyph *g = s->first_glyph + i;
1319
1320 w32_draw_rectangle (s->hdc, s->gc, x, s->y, g->pixel_width - 1,
1321 s->height - 1);
1322 x += g->pixel_width;
1323 }
1324 }
1325 else
1326 {
1327 struct font *font = s->font;
1328 int boff = font->baseline_offset;
1329 int y;
1330 HFONT old_font;
1331
1332 old_font = SelectObject (s->hdc, FONT_HANDLE (font));
1333
1334 if (font->vertical_centering)
1335 boff = VCENTER_BASELINE_OFFSET (font, s->f) - boff;
1336
1337 y = s->ybase - boff;
1338 if (s->for_overlaps
1339 || (s->background_filled_p && s->hl != DRAW_CURSOR))
1340 font->driver->draw (s, 0, s->nchars, x, y, 0);
1341 else
1342 font->driver->draw (s, 0, s->nchars, x, y, 1);
1343 if (s->face->overstrike)
1344 font->driver->draw (s, 0, s->nchars, x + 1, y, 0);
1345
1346 SelectObject (s->hdc, old_font);
1347 }
1348 }
1349
1350 /* Draw the foreground of composite glyph string S. */
1351
1352 static void
1353 x_draw_composite_glyph_string_foreground (s)
1354 struct glyph_string *s;
1355 {
1356 int i, j, x;
1357 struct font *font = s->font;
1358
1359 /* If first glyph of S has a left box line, start drawing the text
1360 of S to the right of that box line. */
1361 if (s->face && s->face->box != FACE_NO_BOX
1362 && s->first_glyph->left_box_line_p)
1363 x = s->x + eabs (s->face->box_line_width);
1364 else
1365 x = s->x;
1366
1367 /* S is a glyph string for a composition. S->cmp_from is the index
1368 of the first character drawn for glyphs of this composition.
1369 S->cmp_from == 0 means we are drawing the very first character of
1370 this composition. */
1371
1372 SetTextColor (s->hdc, s->gc->foreground);
1373 SetBkColor (s->hdc, s->gc->background);
1374 SetTextAlign (s->hdc, TA_BASELINE | TA_LEFT);
1375
1376 /* Draw a rectangle for the composition if the font for the very
1377 first character of the composition could not be loaded. */
1378 if (s->font_not_found_p)
1379 {
1380 if (s->cmp_from == 0)
1381 w32_draw_rectangle (s->hdc, s->gc, x, s->y, s->width - 1,
1382 s->height - 1);
1383 }
1384 else if (! s->first_glyph->u.cmp.automatic)
1385 {
1386 int y = s->ybase;
1387 int width = 0;
1388 HFONT old_font;
1389
1390 old_font = SelectObject (s->hdc, FONT_HANDLE (font));
1391
1392 for (i = 0, j = s->cmp_from; i < s->nchars; i++, j++)
1393 if (COMPOSITION_GLYPH (s->cmp, j) != '\t')
1394 {
1395 int xx = x + s->cmp->offsets[j * 2];
1396 int yy = y - s->cmp->offsets[j * 2 + 1];
1397
1398 font->driver->draw (s, j, j + 1, xx, yy, 0);
1399 if (s->face->overstrike)
1400 font->driver->draw (s, j, j + 1, xx + 1, yy, 0);
1401 }
1402 SelectObject (s->hdc, old_font);
1403 }
1404 else
1405 {
1406 Lisp_Object gstring = composition_gstring_from_id (s->cmp_id);
1407 Lisp_Object glyph;
1408 int y = s->ybase;
1409 int width = 0;
1410 HFONT old_font;
1411
1412 old_font = SelectObject (s->hdc, FONT_HANDLE (font));
1413
1414 for (i = j = s->cmp_from; i < s->cmp_to; i++)
1415 {
1416 glyph = LGSTRING_GLYPH (gstring, i);
1417 if (NILP (LGLYPH_ADJUSTMENT (glyph)))
1418 width += LGLYPH_WIDTH (glyph);
1419 else
1420 {
1421 int xoff, yoff, wadjust;
1422
1423 if (j < i)
1424 {
1425 font->driver->draw (s, j, i, x, y, 0);
1426 x += width;
1427 }
1428 xoff = LGLYPH_XOFF (glyph);
1429 yoff = LGLYPH_YOFF (glyph);
1430 wadjust = LGLYPH_WADJUST (glyph);
1431 font->driver->draw (s, i, i + 1, x + xoff, y + yoff, 0);
1432 x += wadjust;
1433 j = i + 1;
1434 width = 0;
1435 }
1436 }
1437 if (j < i)
1438 font->driver->draw (s, j, i, x, y, 0);
1439
1440 SelectObject (s->hdc, old_font);
1441 }
1442 }
1443
1444
1445 /* Brightness beyond which a color won't have its highlight brightness
1446 boosted.
1447
1448 Nominally, highlight colors for `3d' faces are calculated by
1449 brightening an object's color by a constant scale factor, but this
1450 doesn't yield good results for dark colors, so for colors who's
1451 brightness is less than this value (on a scale of 0-255) have to
1452 use an additional additive factor.
1453
1454 The value here is set so that the default menu-bar/mode-line color
1455 (grey75) will not have its highlights changed at all. */
1456 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 187
1457
1458
1459 /* Allocate a color which is lighter or darker than *COLOR by FACTOR
1460 or DELTA. Try a color with RGB values multiplied by FACTOR first.
1461 If this produces the same color as COLOR, try a color where all RGB
1462 values have DELTA added. Return the allocated color in *COLOR.
1463 DISPLAY is the X display, CMAP is the colormap to operate on.
1464 Value is non-zero if successful. */
1465
1466 static int
1467 w32_alloc_lighter_color (f, color, factor, delta)
1468 struct frame *f;
1469 COLORREF *color;
1470 double factor;
1471 int delta;
1472 {
1473 COLORREF new;
1474 long bright;
1475
1476 /* On Windows, RGB values are 0-255, not 0-65535, so scale delta. */
1477 delta /= 256;
1478
1479 /* Change RGB values by specified FACTOR. Avoid overflow! */
1480 xassert (factor >= 0);
1481 new = PALETTERGB (min (0xff, factor * GetRValue (*color)),
1482 min (0xff, factor * GetGValue (*color)),
1483 min (0xff, factor * GetBValue (*color)));
1484
1485 /* Calculate brightness of COLOR. */
1486 bright = (2 * GetRValue (*color) + 3 * GetGValue (*color)
1487 + GetBValue (*color)) / 6;
1488
1489 /* We only boost colors that are darker than
1490 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
1491 if (bright < HIGHLIGHT_COLOR_DARK_BOOST_LIMIT)
1492 /* Make an additive adjustment to NEW, because it's dark enough so
1493 that scaling by FACTOR alone isn't enough. */
1494 {
1495 /* How far below the limit this color is (0 - 1, 1 being darker). */
1496 double dimness = 1 - (double)bright / HIGHLIGHT_COLOR_DARK_BOOST_LIMIT;
1497 /* The additive adjustment. */
1498 int min_delta = delta * dimness * factor / 2;
1499
1500 if (factor < 1)
1501 new = PALETTERGB (max (0, min (0xff, min_delta - GetRValue (*color))),
1502 max (0, min (0xff, min_delta - GetGValue (*color))),
1503 max (0, min (0xff, min_delta - GetBValue (*color))));
1504 else
1505 new = PALETTERGB (max (0, min (0xff, min_delta + GetRValue (*color))),
1506 max (0, min (0xff, min_delta + GetGValue (*color))),
1507 max (0, min (0xff, min_delta + GetBValue (*color))));
1508 }
1509
1510 if (new == *color)
1511 new = PALETTERGB (max (0, min (0xff, delta + GetRValue (*color))),
1512 max (0, min (0xff, delta + GetGValue (*color))),
1513 max (0, min (0xff, delta + GetBValue (*color))));
1514
1515 /* TODO: Map to palette and retry with delta if same? */
1516 /* TODO: Free colors (if using palette)? */
1517
1518 if (new == *color)
1519 return 0;
1520
1521 *color = new;
1522
1523 return 1;
1524 }
1525
1526 /* On frame F, translate pixel colors to RGB values for the NCOLORS
1527 colors in COLORS. On W32, we no longer try to map colors to
1528 a palette. */
1529 void
1530 x_query_colors (f, colors, ncolors)
1531 struct frame *f;
1532 XColor *colors;
1533 int ncolors;
1534 {
1535 int i;
1536
1537 for (i = 0; i < ncolors; i++)
1538 {
1539 DWORD pixel = colors[i].pixel;
1540 /* Convert to a 16 bit value in range 0 - 0xffff. */
1541 colors[i].red = GetRValue (pixel) * 257;
1542 colors[i].green = GetGValue (pixel) * 257;
1543 colors[i].blue = GetBValue (pixel) * 257;
1544 }
1545 }
1546
1547 void
1548 x_query_color (f, color)
1549 struct frame *f;
1550 XColor *color;
1551 {
1552 x_query_colors (f, color, 1);
1553 }
1554
1555
1556 /* Set up the foreground color for drawing relief lines of glyph
1557 string S. RELIEF is a pointer to a struct relief containing the GC
1558 with which lines will be drawn. Use a color that is FACTOR or
1559 DELTA lighter or darker than the relief's background which is found
1560 in S->f->output_data.x->relief_background. If such a color cannot
1561 be allocated, use DEFAULT_PIXEL, instead. */
1562
1563 static void
1564 w32_setup_relief_color (f, relief, factor, delta, default_pixel)
1565 struct frame *f;
1566 struct relief *relief;
1567 double factor;
1568 int delta;
1569 COLORREF default_pixel;
1570 {
1571 XGCValues xgcv;
1572 struct w32_output *di = f->output_data.w32;
1573 unsigned long mask = GCForeground;
1574 COLORREF pixel;
1575 COLORREF background = di->relief_background;
1576 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
1577
1578 /* TODO: Free colors (if using palette)? */
1579
1580 /* Allocate new color. */
1581 xgcv.foreground = default_pixel;
1582 pixel = background;
1583 if (w32_alloc_lighter_color (f, &pixel, factor, delta))
1584 {
1585 relief->allocated_p = 1;
1586 xgcv.foreground = relief->pixel = pixel;
1587 }
1588
1589 if (relief->gc == 0)
1590 {
1591 #if 0 /* TODO: stipple */
1592 xgcv.stipple = dpyinfo->gray;
1593 mask |= GCStipple;
1594 #endif
1595 relief->gc = XCreateGC (NULL, FRAME_W32_WINDOW (f), mask, &xgcv);
1596 }
1597 else
1598 XChangeGC (NULL, relief->gc, mask, &xgcv);
1599 }
1600
1601
1602 /* Set up colors for the relief lines around glyph string S. */
1603
1604 static void
1605 x_setup_relief_colors (s)
1606 struct glyph_string *s;
1607 {
1608 struct w32_output *di = s->f->output_data.w32;
1609 COLORREF color;
1610
1611 if (s->face->use_box_color_for_shadows_p)
1612 color = s->face->box_color;
1613 else if (s->first_glyph->type == IMAGE_GLYPH
1614 && s->img->pixmap
1615 && !IMAGE_BACKGROUND_TRANSPARENT (s->img, s->f, 0))
1616 color = IMAGE_BACKGROUND (s->img, s->f, 0);
1617 else
1618 color = s->gc->background;
1619
1620 if (di->white_relief.gc == 0
1621 || color != di->relief_background)
1622 {
1623 di->relief_background = color;
1624 w32_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
1625 WHITE_PIX_DEFAULT (s->f));
1626 w32_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
1627 BLACK_PIX_DEFAULT (s->f));
1628 }
1629 }
1630
1631
1632 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
1633 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
1634 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
1635 relief. LEFT_P non-zero means draw a relief on the left side of
1636 the rectangle. RIGHT_P non-zero means draw a relief on the right
1637 side of the rectangle. CLIP_RECT is the clipping rectangle to use
1638 when drawing. */
1639
1640 static void
1641 w32_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
1642 raised_p, top_p, bot_p, left_p, right_p, clip_rect)
1643 struct frame *f;
1644 int left_x, top_y, right_x, bottom_y, width;
1645 int top_p, bot_p, left_p, right_p, raised_p;
1646 RECT *clip_rect;
1647 {
1648 int i;
1649 XGCValues gc;
1650 HDC hdc = get_frame_dc (f);
1651
1652 if (raised_p)
1653 gc.foreground = f->output_data.w32->white_relief.gc->foreground;
1654 else
1655 gc.foreground = f->output_data.w32->black_relief.gc->foreground;
1656
1657 w32_set_clip_rectangle (hdc, clip_rect);
1658
1659 /* Top. */
1660 if (top_p)
1661 for (i = 0; i < width; ++i)
1662 w32_fill_area (f, hdc, gc.foreground,
1663 left_x + i * left_p, top_y + i,
1664 right_x - left_x - i * (left_p + right_p ) + 1, 1);
1665
1666 /* Left. */
1667 if (left_p)
1668 for (i = 0; i < width; ++i)
1669 w32_fill_area (f, hdc, gc.foreground,
1670 left_x + i, top_y + i, 1,
1671 bottom_y - top_y - 2 * i + 1);
1672
1673 if (raised_p)
1674 gc.foreground = f->output_data.w32->black_relief.gc->foreground;
1675 else
1676 gc.foreground = f->output_data.w32->white_relief.gc->foreground;
1677
1678 /* Bottom. */
1679 if (bot_p)
1680 for (i = 0; i < width; ++i)
1681 w32_fill_area (f, hdc, gc.foreground,
1682 left_x + i * left_p, bottom_y - i,
1683 right_x - left_x - i * (left_p + right_p) + 1, 1);
1684
1685 /* Right. */
1686 if (right_p)
1687 for (i = 0; i < width; ++i)
1688 w32_fill_area (f, hdc, gc.foreground,
1689 right_x - i, top_y + i + 1, 1,
1690 bottom_y - top_y - 2 * i - 1);
1691
1692 w32_set_clip_rectangle (hdc, NULL);
1693
1694 release_frame_dc (f, hdc);
1695 }
1696
1697
1698 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
1699 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
1700 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
1701 left side of the rectangle. RIGHT_P non-zero means draw a line
1702 on the right side of the rectangle. CLIP_RECT is the clipping
1703 rectangle to use when drawing. */
1704
1705 static void
1706 w32_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
1707 left_p, right_p, clip_rect)
1708 struct glyph_string *s;
1709 int left_x, top_y, right_x, bottom_y, width, left_p, right_p;
1710 RECT *clip_rect;
1711 {
1712 w32_set_clip_rectangle (s->hdc, clip_rect);
1713
1714 /* Top. */
1715 w32_fill_area (s->f, s->hdc, s->face->box_color,
1716 left_x, top_y, right_x - left_x + 1, width);
1717
1718 /* Left. */
1719 if (left_p)
1720 {
1721 w32_fill_area (s->f, s->hdc, s->face->box_color,
1722 left_x, top_y, width, bottom_y - top_y + 1);
1723 }
1724
1725 /* Bottom. */
1726 w32_fill_area (s->f, s->hdc, s->face->box_color,
1727 left_x, bottom_y - width + 1, right_x - left_x + 1, width);
1728
1729 /* Right. */
1730 if (right_p)
1731 {
1732 w32_fill_area (s->f, s->hdc, s->face->box_color,
1733 right_x - width + 1, top_y, width, bottom_y - top_y + 1);
1734 }
1735
1736 w32_set_clip_rectangle (s->hdc, NULL);
1737 }
1738
1739
1740 /* Draw a box around glyph string S. */
1741
1742 static void
1743 x_draw_glyph_string_box (s)
1744 struct glyph_string *s;
1745 {
1746 int width, left_x, right_x, top_y, bottom_y, last_x, raised_p;
1747 int left_p, right_p;
1748 struct glyph *last_glyph;
1749 RECT clip_rect;
1750
1751 last_x = ((s->row->full_width_p && !s->w->pseudo_window_p)
1752 ? WINDOW_RIGHT_EDGE_X (s->w)
1753 : window_box_right (s->w, s->area));
1754
1755 /* The glyph that may have a right box line. */
1756 last_glyph = (s->cmp || s->img
1757 ? s->first_glyph
1758 : s->first_glyph + s->nchars - 1);
1759
1760 width = eabs (s->face->box_line_width);
1761 raised_p = s->face->box == FACE_RAISED_BOX;
1762 left_x = s->x;
1763 right_x = ((s->row->full_width_p && s->extends_to_end_of_line_p
1764 ? last_x - 1
1765 : min (last_x, s->x + s->background_width) - 1));
1766 top_y = s->y;
1767 bottom_y = top_y + s->height - 1;
1768
1769 left_p = (s->first_glyph->left_box_line_p
1770 || (s->hl == DRAW_MOUSE_FACE
1771 && (s->prev == NULL
1772 || s->prev->hl != s->hl)));
1773 right_p = (last_glyph->right_box_line_p
1774 || (s->hl == DRAW_MOUSE_FACE
1775 && (s->next == NULL
1776 || s->next->hl != s->hl)));
1777
1778 get_glyph_string_clip_rect (s, &clip_rect);
1779
1780 if (s->face->box == FACE_SIMPLE_BOX)
1781 w32_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
1782 left_p, right_p, &clip_rect);
1783 else
1784 {
1785 x_setup_relief_colors (s);
1786 w32_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
1787 width, raised_p, 1, 1, left_p, right_p, &clip_rect);
1788 }
1789 }
1790
1791
1792 /* Draw foreground of image glyph string S. */
1793
1794 static void
1795 x_draw_image_foreground (s)
1796 struct glyph_string *s;
1797 {
1798 int x = s->x;
1799 int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
1800
1801 /* If first glyph of S has a left box line, start drawing it to the
1802 right of that line. */
1803 if (s->face->box != FACE_NO_BOX
1804 && s->first_glyph->left_box_line_p
1805 && s->slice.x == 0)
1806 x += eabs (s->face->box_line_width);
1807
1808 /* If there is a margin around the image, adjust x- and y-position
1809 by that margin. */
1810 if (s->slice.x == 0)
1811 x += s->img->hmargin;
1812 if (s->slice.y == 0)
1813 y += s->img->vmargin;
1814
1815 SaveDC (s->hdc);
1816
1817 if (s->img->pixmap)
1818 {
1819 HDC compat_hdc = CreateCompatibleDC (s->hdc);
1820 HBRUSH fg_brush = CreateSolidBrush (s->gc->foreground);
1821 HBRUSH orig_brush = SelectObject (s->hdc, fg_brush);
1822 HGDIOBJ orig_obj = SelectObject (compat_hdc, s->img->pixmap);
1823 SetBkColor (compat_hdc, RGB (255, 255, 255));
1824 SetTextColor (s->hdc, RGB (0, 0, 0));
1825 x_set_glyph_string_clipping (s);
1826
1827 if (s->img->mask)
1828 {
1829 HDC mask_dc = CreateCompatibleDC (s->hdc);
1830 HGDIOBJ mask_orig_obj = SelectObject (mask_dc, s->img->mask);
1831
1832 SetTextColor (s->hdc, RGB (255, 255, 255));
1833 SetBkColor (s->hdc, RGB (0, 0, 0));
1834
1835 BitBlt (s->hdc, x, y, s->slice.width, s->slice.height,
1836 compat_hdc, s->slice.x, s->slice.y, SRCINVERT);
1837 BitBlt (s->hdc, x, y, s->slice.width, s->slice.height,
1838 mask_dc, s->slice.x, s->slice.y, SRCAND);
1839 BitBlt (s->hdc, x, y, s->slice.width, s->slice.height,
1840 compat_hdc, s->slice.x, s->slice.y, SRCINVERT);
1841
1842 SelectObject (mask_dc, mask_orig_obj);
1843 DeleteDC (mask_dc);
1844 }
1845 else
1846 {
1847 SetTextColor (s->hdc, s->gc->foreground);
1848 SetBkColor (s->hdc, s->gc->background);
1849
1850 BitBlt (s->hdc, x, y, s->slice.width, s->slice.height,
1851 compat_hdc, s->slice.x, s->slice.y, SRCCOPY);
1852
1853 /* When the image has a mask, we can expect that at
1854 least part of a mouse highlight or a block cursor will
1855 be visible. If the image doesn't have a mask, make
1856 a block cursor visible by drawing a rectangle around
1857 the image. I believe it's looking better if we do
1858 nothing here for mouse-face. */
1859 if (s->hl == DRAW_CURSOR)
1860 {
1861 int r = s->img->relief;
1862 if (r < 0) r = -r;
1863 w32_draw_rectangle (s->hdc, s->gc, x - r, y - r ,
1864 s->slice.width + r*2 - 1,
1865 s->slice.height + r*2 - 1);
1866 }
1867 }
1868
1869 w32_set_clip_rectangle (s->hdc, NULL);
1870 SelectObject (s->hdc, orig_brush);
1871 DeleteObject (fg_brush);
1872 SelectObject (compat_hdc, orig_obj);
1873 DeleteDC (compat_hdc);
1874 }
1875 else
1876 w32_draw_rectangle (s->hdc, s->gc, x, y,
1877 s->slice.width - 1, s->slice.height - 1);
1878
1879 RestoreDC (s->hdc ,-1);
1880 }
1881
1882
1883 /* Draw a relief around the image glyph string S. */
1884
1885 static void
1886 x_draw_image_relief (s)
1887 struct glyph_string *s;
1888 {
1889 int x0, y0, x1, y1, thick, raised_p;
1890 RECT r;
1891 int x = s->x;
1892 int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
1893
1894 /* If first glyph of S has a left box line, start drawing it to the
1895 right of that line. */
1896 if (s->face->box != FACE_NO_BOX
1897 && s->first_glyph->left_box_line_p
1898 && s->slice.x == 0)
1899 x += eabs (s->face->box_line_width);
1900
1901 /* If there is a margin around the image, adjust x- and y-position
1902 by that margin. */
1903 if (s->slice.x == 0)
1904 x += s->img->hmargin;
1905 if (s->slice.y == 0)
1906 y += s->img->vmargin;
1907
1908 if (s->hl == DRAW_IMAGE_SUNKEN
1909 || s->hl == DRAW_IMAGE_RAISED)
1910 {
1911 thick = tool_bar_button_relief >= 0 ? tool_bar_button_relief : DEFAULT_TOOL_BAR_BUTTON_RELIEF;
1912 raised_p = s->hl == DRAW_IMAGE_RAISED;
1913 }
1914 else
1915 {
1916 thick = eabs (s->img->relief);
1917 raised_p = s->img->relief > 0;
1918 }
1919
1920 x0 = x - thick;
1921 y0 = y - thick;
1922 x1 = x + s->slice.width + thick - 1;
1923 y1 = y + s->slice.height + thick - 1;
1924
1925 x_setup_relief_colors (s);
1926 get_glyph_string_clip_rect (s, &r);
1927 w32_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p,
1928 s->slice.y == 0,
1929 s->slice.y + s->slice.height == s->img->height,
1930 s->slice.x == 0,
1931 s->slice.x + s->slice.width == s->img->width,
1932 &r);
1933 }
1934
1935
1936 /* Draw the foreground of image glyph string S to PIXMAP. */
1937
1938 static void
1939 w32_draw_image_foreground_1 (s, pixmap)
1940 struct glyph_string *s;
1941 HBITMAP pixmap;
1942 {
1943 HDC hdc = CreateCompatibleDC (s->hdc);
1944 HGDIOBJ orig_hdc_obj = SelectObject (hdc, pixmap);
1945 int x = 0;
1946 int y = s->ybase - s->y - image_ascent (s->img, s->face, &s->slice);
1947
1948 /* If first glyph of S has a left box line, start drawing it to the
1949 right of that line. */
1950 if (s->face->box != FACE_NO_BOX
1951 && s->first_glyph->left_box_line_p
1952 && s->slice.x == 0)
1953 x += eabs (s->face->box_line_width);
1954
1955 /* If there is a margin around the image, adjust x- and y-position
1956 by that margin. */
1957 if (s->slice.x == 0)
1958 x += s->img->hmargin;
1959 if (s->slice.y == 0)
1960 y += s->img->vmargin;
1961
1962 if (s->img->pixmap)
1963 {
1964 HDC compat_hdc = CreateCompatibleDC (hdc);
1965 HBRUSH fg_brush = CreateSolidBrush (s->gc->foreground);
1966 HBRUSH orig_brush = SelectObject (hdc, fg_brush);
1967 HGDIOBJ orig_obj = SelectObject (compat_hdc, s->img->pixmap);
1968
1969 if (s->img->mask)
1970 {
1971 HDC mask_dc = CreateCompatibleDC (hdc);
1972 HGDIOBJ mask_orig_obj = SelectObject (mask_dc, s->img->mask);
1973
1974 SetTextColor (hdc, RGB (0, 0, 0));
1975 SetBkColor (hdc, RGB (255, 255, 255));
1976 BitBlt (hdc, x, y, s->slice.width, s->slice.height,
1977 compat_hdc, s->slice.x, s->slice.y, SRCINVERT);
1978 BitBlt (hdc, x, y, s->slice.width, s->slice.height,
1979 mask_dc, s->slice.x, s->slice.y, SRCAND);
1980 BitBlt (hdc, x, y, s->slice.width, s->slice.height,
1981 compat_hdc, s->slice.x, s->slice.y, SRCINVERT);
1982
1983 SelectObject (mask_dc, mask_orig_obj);
1984 DeleteDC (mask_dc);
1985 }
1986 else
1987 {
1988 SetTextColor (hdc, s->gc->foreground);
1989 SetBkColor (hdc, s->gc->background);
1990
1991 BitBlt (hdc, x, y, s->slice.width, s->slice.height,
1992 compat_hdc, s->slice.x, s->slice.y, SRCCOPY);
1993
1994 /* When the image has a mask, we can expect that at
1995 least part of a mouse highlight or a block cursor will
1996 be visible. If the image doesn't have a mask, make
1997 a block cursor visible by drawing a rectangle around
1998 the image. I believe it's looking better if we do
1999 nothing here for mouse-face. */
2000 if (s->hl == DRAW_CURSOR)
2001 {
2002 int r = s->img->relief;
2003 if (r < 0) r = -r;
2004 w32_draw_rectangle (hdc, s->gc, x - r, y - r,
2005 s->slice.width + r*2 - 1,
2006 s->slice.height + r*2 - 1);
2007 }
2008 }
2009
2010 SelectObject (hdc, orig_brush);
2011 DeleteObject (fg_brush);
2012 SelectObject (compat_hdc, orig_obj);
2013 DeleteDC (compat_hdc);
2014 }
2015 else
2016 w32_draw_rectangle (hdc, s->gc, x, y,
2017 s->slice.width - 1, s->slice.height - 1);
2018
2019 SelectObject (hdc, orig_hdc_obj);
2020 DeleteDC (hdc);
2021 }
2022
2023
2024 /* Draw part of the background of glyph string S. X, Y, W, and H
2025 give the rectangle to draw. */
2026
2027 static void
2028 x_draw_glyph_string_bg_rect (s, x, y, w, h)
2029 struct glyph_string *s;
2030 int x, y, w, h;
2031 {
2032 #if 0 /* TODO: stipple */
2033 if (s->stippled_p)
2034 {
2035 /* Fill background with a stipple pattern. */
2036 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
2037 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
2038 XSetFillStyle (s->display, s->gc, FillSolid);
2039 }
2040 else
2041 #endif
2042 x_clear_glyph_string_rect (s, x, y, w, h);
2043 }
2044
2045
2046 /* Draw image glyph string S.
2047
2048 s->y
2049 s->x +-------------------------
2050 | s->face->box
2051 |
2052 | +-------------------------
2053 | | s->img->vmargin
2054 | |
2055 | | +-------------------
2056 | | | the image
2057
2058 */
2059
2060 static void
2061 x_draw_image_glyph_string (s)
2062 struct glyph_string *s;
2063 {
2064 int x, y;
2065 int box_line_hwidth = eabs (s->face->box_line_width);
2066 int box_line_vwidth = max (s->face->box_line_width, 0);
2067 int height;
2068 HBITMAP pixmap = 0;
2069
2070 height = s->height - 2 * box_line_vwidth;
2071
2072 /* Fill background with face under the image. Do it only if row is
2073 taller than image or if image has a clip mask to reduce
2074 flickering. */
2075 s->stippled_p = s->face->stipple != 0;
2076 if (height > s->slice.height
2077 || s->img->hmargin
2078 || s->img->vmargin
2079 || s->img->mask
2080 || s->img->pixmap == 0
2081 || s->width != s->background_width)
2082 {
2083 x = s->x;
2084 if (s->first_glyph->left_box_line_p
2085 && s->slice.x == 0)
2086 x += box_line_hwidth;
2087
2088 y = s->y;
2089 if (s->slice.y == 0)
2090 y += box_line_vwidth;
2091
2092 #if 0 /* TODO: figure out if we need to do this on Windows. */
2093 if (s->img->mask)
2094 {
2095 /* Create a pixmap as large as the glyph string. Fill it
2096 with the background color. Copy the image to it, using
2097 its mask. Copy the temporary pixmap to the display. */
2098 Screen *screen = FRAME_X_SCREEN (s->f);
2099 int depth = DefaultDepthOfScreen (screen);
2100
2101 /* Create a pixmap as large as the glyph string. */
2102 pixmap = XCreatePixmap (s->display, s->window,
2103 s->background_width,
2104 s->height, depth);
2105
2106 /* Don't clip in the following because we're working on the
2107 pixmap. */
2108 XSetClipMask (s->display, s->gc, None);
2109
2110 /* Fill the pixmap with the background color/stipple. */
2111 if (s->stippled_p)
2112 {
2113 /* Fill background with a stipple pattern. */
2114 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
2115 XFillRectangle (s->display, pixmap, s->gc,
2116 0, 0, s->background_width, s->height);
2117 XSetFillStyle (s->display, s->gc, FillSolid);
2118 }
2119 else
2120 {
2121 XGCValues xgcv;
2122 XGetGCValues (s->display, s->gc, GCForeground | GCBackground,
2123 &xgcv);
2124 XSetForeground (s->display, s->gc, xgcv.background);
2125 XFillRectangle (s->display, pixmap, s->gc,
2126 0, 0, s->background_width, s->height);
2127 XSetForeground (s->display, s->gc, xgcv.foreground);
2128 }
2129 }
2130 else
2131 #endif
2132 x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
2133
2134 s->background_filled_p = 1;
2135 }
2136
2137 /* Draw the foreground. */
2138 if (pixmap != 0)
2139 {
2140 w32_draw_image_foreground_1 (s, pixmap);
2141 x_set_glyph_string_clipping (s);
2142 {
2143 HDC compat_hdc = CreateCompatibleDC (s->hdc);
2144 HBRUSH fg_brush = CreateSolidBrush (s->gc->foreground);
2145 HBRUSH orig_brush = SelectObject (s->hdc, fg_brush);
2146 HGDIOBJ orig_obj = SelectObject (compat_hdc, pixmap);
2147
2148 SetTextColor (s->hdc, s->gc->foreground);
2149 SetBkColor (s->hdc, s->gc->background);
2150 BitBlt (s->hdc, s->x, s->y, s->background_width, s->height,
2151 compat_hdc, 0, 0, SRCCOPY);
2152
2153 SelectObject (s->hdc, orig_brush);
2154 DeleteObject (fg_brush);
2155 SelectObject (compat_hdc, orig_obj);
2156 DeleteDC (compat_hdc);
2157 }
2158 DeleteObject (pixmap);
2159 pixmap = 0;
2160 }
2161 else
2162 x_draw_image_foreground (s);
2163
2164 /* If we must draw a relief around the image, do it. */
2165 if (s->img->relief
2166 || s->hl == DRAW_IMAGE_RAISED
2167 || s->hl == DRAW_IMAGE_SUNKEN)
2168 x_draw_image_relief (s);
2169 }
2170
2171
2172 /* Draw stretch glyph string S. */
2173
2174 static void
2175 x_draw_stretch_glyph_string (s)
2176 struct glyph_string *s;
2177 {
2178 xassert (s->first_glyph->type == STRETCH_GLYPH);
2179
2180 if (s->hl == DRAW_CURSOR
2181 && !x_stretch_cursor_p)
2182 {
2183 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
2184 as wide as the stretch glyph. */
2185 int width, background_width = s->background_width;
2186 int x = s->x, left_x = window_box_left_offset (s->w, TEXT_AREA);
2187
2188 if (x < left_x)
2189 {
2190 background_width -= left_x - x;
2191 x = left_x;
2192 }
2193 width = min (FRAME_COLUMN_WIDTH (s->f), background_width);
2194
2195 /* Draw cursor. */
2196 x_draw_glyph_string_bg_rect (s, x, s->y, width, s->height);
2197
2198 /* Clear rest using the GC of the original non-cursor face. */
2199 if (width < background_width)
2200 {
2201 XGCValues *gc = s->face->gc;
2202 int y = s->y;
2203 int w = background_width - width, h = s->height;
2204 RECT r;
2205 HDC hdc = s->hdc;
2206
2207 x += width;
2208 if (s->row->mouse_face_p
2209 && cursor_in_mouse_face_p (s->w))
2210 {
2211 x_set_mouse_face_gc (s);
2212 gc = s->gc;
2213 }
2214 else
2215 gc = s->face->gc;
2216
2217 get_glyph_string_clip_rect (s, &r);
2218 w32_set_clip_rectangle (hdc, &r);
2219
2220 #if 0 /* TODO: stipple */
2221 if (s->face->stipple)
2222 {
2223 /* Fill background with a stipple pattern. */
2224 XSetFillStyle (s->display, gc, FillOpaqueStippled);
2225 XFillRectangle (s->display, s->window, gc, x, y, w, h);
2226 XSetFillStyle (s->display, gc, FillSolid);
2227 }
2228 else
2229 #endif
2230 {
2231 w32_fill_area (s->f, s->hdc, gc->background, x, y, w, h);
2232 }
2233 }
2234 }
2235 else if (!s->background_filled_p)
2236 {
2237 int background_width = s->background_width;
2238 int x = s->x, left_x = window_box_left_offset (s->w, TEXT_AREA);
2239
2240 /* Don't draw into left margin, fringe or scrollbar area
2241 except for header line and mode line. */
2242 if (x < left_x && !s->row->mode_line_p)
2243 {
2244 background_width -= left_x - x;
2245 x = left_x;
2246 }
2247 if (background_width > 0)
2248 x_draw_glyph_string_bg_rect (s, x, s->y, background_width, s->height);
2249 }
2250
2251 s->background_filled_p = 1;
2252 }
2253
2254
2255 /* Draw glyph string S. */
2256
2257 static void
2258 x_draw_glyph_string (s)
2259 struct glyph_string *s;
2260 {
2261 int relief_drawn_p = 0;
2262
2263 /* If S draws into the background of its successor, draw the
2264 background of the successor first so that S can draw into it.
2265 This makes S->next use XDrawString instead of XDrawImageString. */
2266 if (s->next && s->right_overhang && !s->for_overlaps)
2267 {
2268 int width;
2269 struct glyph_string *next;
2270 for (width = 0, next = s->next;
2271 next && width < s->right_overhang;
2272 width += next->width, next = next->next)
2273 if (next->first_glyph->type != IMAGE_GLYPH)
2274 {
2275 x_set_glyph_string_gc (next);
2276 x_set_glyph_string_clipping (next);
2277 if (next->first_glyph->type == STRETCH_GLYPH)
2278 x_draw_stretch_glyph_string (next);
2279 else
2280 x_draw_glyph_string_background (next, 1);
2281 next->num_clips = 0;
2282 }
2283 }
2284
2285 /* Set up S->gc, set clipping and draw S. */
2286 x_set_glyph_string_gc (s);
2287
2288 /* Draw relief (if any) in advance for char/composition so that the
2289 glyph string can be drawn over it. */
2290 if (!s->for_overlaps
2291 && s->face->box != FACE_NO_BOX
2292 && (s->first_glyph->type == CHAR_GLYPH
2293 || s->first_glyph->type == COMPOSITE_GLYPH))
2294
2295 {
2296 x_set_glyph_string_clipping (s);
2297 x_draw_glyph_string_background (s, 1);
2298 x_draw_glyph_string_box (s);
2299 x_set_glyph_string_clipping (s);
2300 relief_drawn_p = 1;
2301 }
2302 else if (!s->clip_head /* draw_glyphs didn't specify a clip mask. */
2303 && !s->clip_tail
2304 && ((s->prev && s->prev->hl != s->hl && s->left_overhang)
2305 || (s->next && s->next->hl != s->hl && s->right_overhang)))
2306 /* We must clip just this glyph. left_overhang part has already
2307 drawn when s->prev was drawn, and right_overhang part will be
2308 drawn later when s->next is drawn. */
2309 x_set_glyph_string_clipping_exactly (s, s);
2310 else
2311 x_set_glyph_string_clipping (s);
2312
2313 switch (s->first_glyph->type)
2314 {
2315 case IMAGE_GLYPH:
2316 x_draw_image_glyph_string (s);
2317 break;
2318
2319 case STRETCH_GLYPH:
2320 x_draw_stretch_glyph_string (s);
2321 break;
2322
2323 case CHAR_GLYPH:
2324 if (s->for_overlaps)
2325 s->background_filled_p = 1;
2326 else
2327 x_draw_glyph_string_background (s, 0);
2328 x_draw_glyph_string_foreground (s);
2329 break;
2330
2331 case COMPOSITE_GLYPH:
2332 if (s->for_overlaps || (s->cmp_from > 0
2333 && ! s->first_glyph->u.cmp.automatic))
2334 s->background_filled_p = 1;
2335 else
2336 x_draw_glyph_string_background (s, 1);
2337 x_draw_composite_glyph_string_foreground (s);
2338 break;
2339
2340 default:
2341 abort ();
2342 }
2343
2344 if (!s->for_overlaps)
2345 {
2346 /* Draw underline. */
2347 if (s->face->underline_p)
2348 {
2349 unsigned long thickness, position;
2350 int y;
2351
2352 if (s->prev && s->prev->face->underline_p)
2353 {
2354 /* We use the same underline style as the previous one. */
2355 thickness = s->prev->underline_thickness;
2356 position = s->prev->underline_position;
2357 }
2358 else
2359 {
2360 /* Get the underline thickness. Default is 1 pixel. */
2361 if (s->font && s->font->underline_thickness > 0)
2362 thickness = s->font->underline_thickness;
2363 else
2364 thickness = 1;
2365 if (x_underline_at_descent_line)
2366 position = (s->height - thickness) - (s->ybase - s->y);
2367 else
2368 {
2369 /* Get the underline position. This is the recommended
2370 vertical offset in pixels from the baseline to the top of
2371 the underline. This is a signed value according to the
2372 specs, and its default is
2373
2374 ROUND ((maximum_descent) / 2), with
2375 ROUND (x) = floor (x + 0.5) */
2376
2377 if (x_use_underline_position_properties
2378 && s->font && s->font->underline_position >= 0)
2379 position = s->font->underline_position;
2380 else if (s->font)
2381 position = (s->font->descent + 1) / 2;
2382 }
2383 position = max (position, underline_minimum_offset);
2384 }
2385 /* Check the sanity of thickness and position. We should
2386 avoid drawing underline out of the current line area. */
2387 if (s->y + s->height <= s->ybase + position)
2388 position = (s->height - 1) - (s->ybase - s->y);
2389 if (s->y + s->height < s->ybase + position + thickness)
2390 thickness = (s->y + s->height) - (s->ybase + position);
2391 s->underline_thickness = thickness;
2392 s->underline_position =position;
2393 y = s->ybase + position;
2394 if (s->face->underline_defaulted_p)
2395 {
2396 w32_fill_area (s->f, s->hdc, s->gc->foreground, s->x,
2397 y, s->width, 1);
2398 }
2399 else
2400 {
2401 w32_fill_area (s->f, s->hdc, s->face->underline_color, s->x,
2402 y, s->width, 1);
2403 }
2404 }
2405 /* Draw overline. */
2406 if (s->face->overline_p)
2407 {
2408 unsigned long dy = 0, h = 1;
2409
2410 if (s->face->overline_color_defaulted_p)
2411 {
2412 w32_fill_area (s->f, s->hdc, s->gc->foreground, s->x,
2413 s->y + dy, s->width, h);
2414 }
2415 else
2416 {
2417 w32_fill_area (s->f, s->hdc, s->face->overline_color, s->x,
2418 s->y + dy, s->width, h);
2419 }
2420 }
2421
2422 /* Draw strike-through. */
2423 if (s->face->strike_through_p
2424 && !FONT_TEXTMETRIC(s->font).tmStruckOut)
2425 {
2426 unsigned long h = 1;
2427 unsigned long dy = (s->height - h) / 2;
2428
2429 if (s->face->strike_through_color_defaulted_p)
2430 {
2431 w32_fill_area (s->f, s->hdc, s->gc->foreground, s->x, s->y + dy,
2432 s->width, h);
2433 }
2434 else
2435 {
2436 w32_fill_area (s->f, s->hdc, s->face->strike_through_color, s->x,
2437 s->y + dy, s->width, h);
2438 }
2439 }
2440
2441 /* Draw relief if not yet drawn. */
2442 if (!relief_drawn_p && s->face->box != FACE_NO_BOX)
2443 x_draw_glyph_string_box (s);
2444
2445 if (s->prev)
2446 {
2447 struct glyph_string *prev;
2448
2449 for (prev = s->prev; prev; prev = prev->prev)
2450 if (prev->hl != s->hl
2451 && prev->x + prev->width + prev->right_overhang > s->x)
2452 {
2453 /* As prev was drawn while clipped to its own area, we
2454 must draw the right_overhang part using s->hl now. */
2455 enum draw_glyphs_face save = prev->hl;
2456
2457 prev->hl = s->hl;
2458 x_set_glyph_string_gc (prev);
2459 x_set_glyph_string_clipping_exactly (s, prev);
2460 if (prev->first_glyph->type == CHAR_GLYPH)
2461 x_draw_glyph_string_foreground (prev);
2462 else
2463 x_draw_composite_glyph_string_foreground (prev);
2464 w32_set_clip_rectangle (prev->hdc, NULL);
2465 prev->hl = save;
2466 prev->num_clips = 0;
2467 }
2468 }
2469
2470 if (s->next)
2471 {
2472 struct glyph_string *next;
2473
2474 for (next = s->next; next; next = next->next)
2475 if (next->hl != s->hl
2476 && next->x - next->left_overhang < s->x + s->width)
2477 {
2478 /* As next will be drawn while clipped to its own area,
2479 we must draw the left_overhang part using s->hl now. */
2480 enum draw_glyphs_face save = next->hl;
2481
2482 next->hl = s->hl;
2483 x_set_glyph_string_gc (next);
2484 x_set_glyph_string_clipping_exactly (s, next);
2485 if (next->first_glyph->type == CHAR_GLYPH)
2486 x_draw_glyph_string_foreground (next);
2487 else
2488 x_draw_composite_glyph_string_foreground (next);
2489 w32_set_clip_rectangle (next->hdc, NULL);
2490 next->hl = save;
2491 next->num_clips = 0;
2492 }
2493 }
2494 }
2495
2496 /* Reset clipping. */
2497 w32_set_clip_rectangle (s->hdc, NULL);
2498 s->num_clips = 0;
2499 }
2500
2501
2502 /* Shift display to make room for inserted glyphs. */
2503
2504 void
2505 w32_shift_glyphs_for_insert (f, x, y, width, height, shift_by)
2506 struct frame *f;
2507 int x, y, width, height, shift_by;
2508 {
2509 HDC hdc;
2510
2511 hdc = get_frame_dc (f);
2512 BitBlt (hdc, x + shift_by, y, width, height,
2513 hdc, x, y, SRCCOPY);
2514
2515 release_frame_dc (f, hdc);
2516 }
2517
2518
2519 /* Delete N glyphs at the nominal cursor position. Not implemented
2520 for X frames. */
2521
2522 static void
2523 x_delete_glyphs (f, n)
2524 struct frame *f;
2525 register int n;
2526 {
2527 if (! FRAME_W32_P (f))
2528 return;
2529
2530 abort ();
2531 }
2532
2533
2534 /* Clear entire frame. If updating_frame is non-null, clear that
2535 frame. Otherwise clear the selected frame. */
2536
2537 static void
2538 x_clear_frame (struct frame *f)
2539 {
2540 if (! FRAME_W32_P (f))
2541 return;
2542
2543 /* Clearing the frame will erase any cursor, so mark them all as no
2544 longer visible. */
2545 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
2546 output_cursor.hpos = output_cursor.vpos = 0;
2547 output_cursor.x = -1;
2548
2549 /* We don't set the output cursor here because there will always
2550 follow an explicit cursor_to. */
2551 BLOCK_INPUT;
2552
2553 w32_clear_window (f);
2554
2555 /* We have to clear the scroll bars, too. If we have changed
2556 colors or something like that, then they should be notified. */
2557 x_scroll_bar_clear (f);
2558
2559 UNBLOCK_INPUT;
2560 }
2561
2562 \f
2563 /* Make audible bell. */
2564
2565 static void
2566 w32_ring_bell (struct frame *f)
2567 {
2568 BLOCK_INPUT;
2569
2570 if (FRAME_W32_P (f) && visible_bell)
2571 {
2572 int i;
2573 HWND hwnd = FRAME_W32_WINDOW (f);
2574
2575 for (i = 0; i < 5; i++)
2576 {
2577 FlashWindow (hwnd, TRUE);
2578 Sleep (10);
2579 }
2580 FlashWindow (hwnd, FALSE);
2581 }
2582 else
2583 w32_sys_ring_bell (f);
2584
2585 UNBLOCK_INPUT;
2586 }
2587
2588 \f
2589 /* Specify how many text lines, from the top of the window,
2590 should be affected by insert-lines and delete-lines operations.
2591 This, and those operations, are used only within an update
2592 that is bounded by calls to x_update_begin and x_update_end. */
2593
2594 static void
2595 w32_set_terminal_window (n)
2596 register int n;
2597 {
2598 /* This function intentionally left blank. */
2599 }
2600
2601 \f
2602 /***********************************************************************
2603 Line Dance
2604 ***********************************************************************/
2605
2606 /* Perform an insert-lines or delete-lines operation, inserting N
2607 lines or deleting -N lines at vertical position VPOS. */
2608
2609 static void
2610 x_ins_del_lines (f, vpos, n)
2611 struct frame *f;
2612 int vpos, n;
2613 {
2614 if (! FRAME_W32_P (f))
2615 return;
2616
2617 abort ();
2618 }
2619
2620
2621 /* Scroll part of the display as described by RUN. */
2622
2623 static void
2624 x_scroll_run (w, run)
2625 struct window *w;
2626 struct run *run;
2627 {
2628 struct frame *f = XFRAME (w->frame);
2629 int x, y, width, height, from_y, to_y, bottom_y;
2630 HWND hwnd = FRAME_W32_WINDOW (f);
2631 HRGN expect_dirty;
2632
2633 /* Get frame-relative bounding box of the text display area of W,
2634 without mode lines. Include in this box the left and right
2635 fringes of W. */
2636 window_box (w, -1, &x, &y, &width, &height);
2637
2638 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
2639 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
2640 bottom_y = y + height;
2641
2642 if (to_y < from_y)
2643 {
2644 /* Scrolling up. Make sure we don't copy part of the mode
2645 line at the bottom. */
2646 if (from_y + run->height > bottom_y)
2647 height = bottom_y - from_y;
2648 else
2649 height = run->height;
2650 expect_dirty = CreateRectRgn (x, y + height, x + width, bottom_y);
2651 }
2652 else
2653 {
2654 /* Scolling down. Make sure we don't copy over the mode line.
2655 at the bottom. */
2656 if (to_y + run->height > bottom_y)
2657 height = bottom_y - to_y;
2658 else
2659 height = run->height;
2660 expect_dirty = CreateRectRgn (x, y, x + width, to_y);
2661 }
2662
2663 BLOCK_INPUT;
2664
2665 /* Cursor off. Will be switched on again in x_update_window_end. */
2666 updated_window = w;
2667 x_clear_cursor (w);
2668
2669 {
2670 RECT from;
2671 RECT to;
2672 HRGN dirty = CreateRectRgn (0, 0, 0, 0);
2673 HRGN combined = CreateRectRgn (0, 0, 0, 0);
2674
2675 from.left = to.left = x;
2676 from.right = to.right = x + width;
2677 from.top = from_y;
2678 from.bottom = from_y + height;
2679 to.top = y;
2680 to.bottom = bottom_y;
2681
2682 ScrollWindowEx (hwnd, 0, to_y - from_y, &from, &to, dirty,
2683 NULL, SW_INVALIDATE);
2684
2685 /* Combine this with what we expect to be dirty. This covers the
2686 case where not all of the region we expect is actually dirty. */
2687 CombineRgn (combined, dirty, expect_dirty, RGN_OR);
2688
2689 /* If the dirty region is not what we expected, redraw the entire frame. */
2690 if (!EqualRgn (combined, expect_dirty))
2691 SET_FRAME_GARBAGED (f);
2692
2693 DeleteObject (dirty);
2694 DeleteObject (combined);
2695 }
2696
2697 UNBLOCK_INPUT;
2698 DeleteObject (expect_dirty);
2699 }
2700
2701
2702 \f
2703 /***********************************************************************
2704 Exposure Events
2705 ***********************************************************************/
2706
2707 static void
2708 frame_highlight (f)
2709 struct frame *f;
2710 {
2711 x_update_cursor (f, 1);
2712 x_set_frame_alpha (f);
2713 }
2714
2715 static void
2716 frame_unhighlight (f)
2717 struct frame *f;
2718 {
2719 x_update_cursor (f, 1);
2720 x_set_frame_alpha (f);
2721 }
2722
2723 /* The focus has changed. Update the frames as necessary to reflect
2724 the new situation. Note that we can't change the selected frame
2725 here, because the Lisp code we are interrupting might become confused.
2726 Each event gets marked with the frame in which it occurred, so the
2727 Lisp code can tell when the switch took place by examining the events. */
2728
2729 static void
2730 x_new_focus_frame (dpyinfo, frame)
2731 struct w32_display_info *dpyinfo;
2732 struct frame *frame;
2733 {
2734 struct frame *old_focus = dpyinfo->w32_focus_frame;
2735
2736 if (frame != dpyinfo->w32_focus_frame)
2737 {
2738 /* Set this before calling other routines, so that they see
2739 the correct value of w32_focus_frame. */
2740 dpyinfo->w32_focus_frame = frame;
2741
2742 if (old_focus && old_focus->auto_lower)
2743 x_lower_frame (old_focus);
2744
2745 if (dpyinfo->w32_focus_frame && dpyinfo->w32_focus_frame->auto_raise)
2746 pending_autoraise_frame = dpyinfo->w32_focus_frame;
2747 else
2748 pending_autoraise_frame = 0;
2749 }
2750
2751 x_frame_rehighlight (dpyinfo);
2752 }
2753
2754
2755 /* Handle FocusIn and FocusOut state changes for FRAME.
2756 If FRAME has focus and there exists more than one frame, puts
2757 a FOCUS_IN_EVENT into *BUFP. */
2758
2759 static void
2760 x_focus_changed (type, state, dpyinfo, frame, bufp)
2761 int type;
2762 int state;
2763 struct w32_display_info *dpyinfo;
2764 struct frame *frame;
2765 struct input_event *bufp;
2766 {
2767 if (type == WM_SETFOCUS)
2768 {
2769 if (dpyinfo->w32_focus_event_frame != frame)
2770 {
2771 x_new_focus_frame (dpyinfo, frame);
2772 dpyinfo->w32_focus_event_frame = frame;
2773
2774 /* Don't stop displaying the initial startup message
2775 for a switch-frame event we don't need. */
2776 if (NILP (Vterminal_frame)
2777 && CONSP (Vframe_list)
2778 && !NILP (XCDR (Vframe_list)))
2779 {
2780 bufp->kind = FOCUS_IN_EVENT;
2781 XSETFRAME (bufp->frame_or_window, frame);
2782 }
2783 }
2784
2785 frame->output_data.x->focus_state |= state;
2786
2787 /* TODO: IME focus? */
2788 }
2789 else if (type == WM_KILLFOCUS)
2790 {
2791 frame->output_data.x->focus_state &= ~state;
2792
2793 if (dpyinfo->w32_focus_event_frame == frame)
2794 {
2795 dpyinfo->w32_focus_event_frame = 0;
2796 x_new_focus_frame (dpyinfo, 0);
2797 }
2798
2799 /* TODO: IME focus? */
2800 }
2801 }
2802
2803
2804 /* The focus may have changed. Figure out if it is a real focus change,
2805 by checking both FocusIn/Out and Enter/LeaveNotify events.
2806
2807 Returns FOCUS_IN_EVENT event in *BUFP. */
2808
2809 static void
2810 w32_detect_focus_change (dpyinfo, event, bufp)
2811 struct w32_display_info *dpyinfo;
2812 W32Msg *event;
2813 struct input_event *bufp;
2814 {
2815 struct frame *frame;
2816
2817 frame = x_any_window_to_frame (dpyinfo, event->msg.hwnd);
2818 if (! frame)
2819 return;
2820
2821 /* On w32, this is only called from focus events, so no switch needed. */
2822 x_focus_changed (event->msg.message,
2823 (event->msg.message == WM_KILLFOCUS ?
2824 FOCUS_IMPLICIT : FOCUS_EXPLICIT),
2825 dpyinfo, frame, bufp);
2826 }
2827
2828
2829 /* Handle an event saying the mouse has moved out of an Emacs frame. */
2830
2831 void
2832 x_mouse_leave (dpyinfo)
2833 struct w32_display_info *dpyinfo;
2834 {
2835 x_new_focus_frame (dpyinfo, dpyinfo->w32_focus_event_frame);
2836 }
2837
2838 /* The focus has changed, or we have redirected a frame's focus to
2839 another frame (this happens when a frame uses a surrogate
2840 mini-buffer frame). Shift the highlight as appropriate.
2841
2842 The FRAME argument doesn't necessarily have anything to do with which
2843 frame is being highlighted or un-highlighted; we only use it to find
2844 the appropriate X display info. */
2845
2846 static void
2847 w32_frame_rehighlight (frame)
2848 struct frame *frame;
2849 {
2850 if (! FRAME_W32_P (frame))
2851 return;
2852 x_frame_rehighlight (FRAME_W32_DISPLAY_INFO (frame));
2853 }
2854
2855 static void
2856 x_frame_rehighlight (dpyinfo)
2857 struct w32_display_info *dpyinfo;
2858 {
2859 struct frame *old_highlight = dpyinfo->x_highlight_frame;
2860
2861 if (dpyinfo->w32_focus_frame)
2862 {
2863 dpyinfo->x_highlight_frame
2864 = ((FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->w32_focus_frame)))
2865 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->w32_focus_frame))
2866 : dpyinfo->w32_focus_frame);
2867 if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame))
2868 {
2869 FRAME_FOCUS_FRAME (dpyinfo->w32_focus_frame) = Qnil;
2870 dpyinfo->x_highlight_frame = dpyinfo->w32_focus_frame;
2871 }
2872 }
2873 else
2874 dpyinfo->x_highlight_frame = 0;
2875
2876 if (dpyinfo->x_highlight_frame != old_highlight)
2877 {
2878 if (old_highlight)
2879 frame_unhighlight (old_highlight);
2880 if (dpyinfo->x_highlight_frame)
2881 frame_highlight (dpyinfo->x_highlight_frame);
2882 }
2883 }
2884 \f
2885 /* Keyboard processing - modifier keys, etc. */
2886
2887 /* Convert a keysym to its name. */
2888
2889 char *
2890 x_get_keysym_name (keysym)
2891 int keysym;
2892 {
2893 /* Make static so we can always return it */
2894 static char value[100];
2895
2896 BLOCK_INPUT;
2897 GetKeyNameText (keysym, value, 100);
2898 UNBLOCK_INPUT;
2899
2900 return value;
2901 }
2902
2903 static int codepage_for_locale(LCID locale)
2904 {
2905 char cp[20];
2906
2907 if (GetLocaleInfo (locale, LOCALE_IDEFAULTANSICODEPAGE, cp, 20) > 0)
2908 return atoi (cp);
2909 else
2910 return CP_ACP;
2911 }
2912
2913 \f
2914 /* Mouse clicks and mouse movement. Rah. */
2915
2916 /* Parse a button MESSAGE. The button index is returned in PBUTTON, and
2917 the state in PUP. XBUTTON provides extra information for extended mouse
2918 button messages. Returns FALSE if unable to parse the message. */
2919 BOOL
2920 parse_button (message, xbutton, pbutton, pup)
2921 int message;
2922 int xbutton;
2923 int * pbutton;
2924 int * pup;
2925 {
2926 int button = 0;
2927 int up = 0;
2928
2929 switch (message)
2930 {
2931 case WM_LBUTTONDOWN:
2932 button = 0;
2933 up = 0;
2934 break;
2935 case WM_LBUTTONUP:
2936 button = 0;
2937 up = 1;
2938 break;
2939 case WM_MBUTTONDOWN:
2940 if (NILP (Vw32_swap_mouse_buttons))
2941 button = 1;
2942 else
2943 button = 2;
2944 up = 0;
2945 break;
2946 case WM_MBUTTONUP:
2947 if (NILP (Vw32_swap_mouse_buttons))
2948 button = 1;
2949 else
2950 button = 2;
2951 up = 1;
2952 break;
2953 case WM_RBUTTONDOWN:
2954 if (NILP (Vw32_swap_mouse_buttons))
2955 button = 2;
2956 else
2957 button = 1;
2958 up = 0;
2959 break;
2960 case WM_RBUTTONUP:
2961 if (NILP (Vw32_swap_mouse_buttons))
2962 button = 2;
2963 else
2964 button = 1;
2965 up = 1;
2966 break;
2967 case WM_XBUTTONDOWN:
2968 button = xbutton + 2;
2969 up = 0;
2970 break;
2971 case WM_XBUTTONUP:
2972 button = xbutton + 2;
2973 up = 1;
2974 break;
2975 default:
2976 return (FALSE);
2977 }
2978
2979 if (pup) *pup = up;
2980 if (pbutton) *pbutton = button;
2981
2982 return (TRUE);
2983 }
2984
2985
2986 /* Prepare a mouse-event in *RESULT for placement in the input queue.
2987
2988 If the event is a button press, then note that we have grabbed
2989 the mouse. */
2990
2991 static Lisp_Object
2992 construct_mouse_click (result, msg, f)
2993 struct input_event *result;
2994 W32Msg *msg;
2995 struct frame *f;
2996 {
2997 int button;
2998 int up;
2999
3000 parse_button (msg->msg.message, HIWORD (msg->msg.wParam),
3001 &button, &up);
3002
3003 /* Make the event type NO_EVENT; we'll change that when we decide
3004 otherwise. */
3005 result->kind = MOUSE_CLICK_EVENT;
3006 result->code = button;
3007 result->timestamp = msg->msg.time;
3008 result->modifiers = (msg->dwModifiers
3009 | (up
3010 ? up_modifier
3011 : down_modifier));
3012
3013 XSETINT (result->x, LOWORD (msg->msg.lParam));
3014 XSETINT (result->y, HIWORD (msg->msg.lParam));
3015 XSETFRAME (result->frame_or_window, f);
3016 result->arg = Qnil;
3017 return Qnil;
3018 }
3019
3020 static Lisp_Object
3021 construct_mouse_wheel (result, msg, f)
3022 struct input_event *result;
3023 W32Msg *msg;
3024 struct frame *f;
3025 {
3026 POINT p;
3027 int delta;
3028
3029 result->kind = msg->msg.message == WM_MOUSEHWHEEL ? HORIZ_WHEEL_EVENT
3030 : WHEEL_EVENT;
3031 result->code = 0;
3032 result->timestamp = msg->msg.time;
3033
3034 /* A WHEEL_DELTA positive value indicates that the wheel was rotated
3035 forward, away from the user (up); a negative value indicates that
3036 the wheel was rotated backward, toward the user (down). */
3037 delta = GET_WHEEL_DELTA_WPARAM (msg->msg.wParam);
3038
3039 /* The up and down modifiers indicate if the wheel was rotated up or
3040 down based on WHEEL_DELTA value. */
3041 result->modifiers = (msg->dwModifiers
3042 | ((delta < 0 ) ? down_modifier : up_modifier));
3043
3044 /* With multiple monitors, we can legitimately get negative
3045 coordinates, so cast to short to interpret them correctly. */
3046 p.x = (short) LOWORD (msg->msg.lParam);
3047 p.y = (short) HIWORD (msg->msg.lParam);
3048 ScreenToClient (msg->msg.hwnd, &p);
3049 XSETINT (result->x, p.x);
3050 XSETINT (result->y, p.y);
3051 XSETFRAME (result->frame_or_window, f);
3052 result->arg = Qnil;
3053 return Qnil;
3054 }
3055
3056 static Lisp_Object
3057 construct_drag_n_drop (result, msg, f)
3058 struct input_event *result;
3059 W32Msg *msg;
3060 struct frame *f;
3061 {
3062 Lisp_Object files;
3063 Lisp_Object frame;
3064 HDROP hdrop;
3065 POINT p;
3066 WORD num_files;
3067 char *name;
3068 int i, len;
3069
3070 result->kind = DRAG_N_DROP_EVENT;
3071 result->code = 0;
3072 result->timestamp = msg->msg.time;
3073 result->modifiers = msg->dwModifiers;
3074
3075 hdrop = (HDROP) msg->msg.wParam;
3076 DragQueryPoint (hdrop, &p);
3077
3078 #if 0
3079 p.x = LOWORD (msg->msg.lParam);
3080 p.y = HIWORD (msg->msg.lParam);
3081 ScreenToClient (msg->msg.hwnd, &p);
3082 #endif
3083
3084 XSETINT (result->x, p.x);
3085 XSETINT (result->y, p.y);
3086
3087 num_files = DragQueryFile (hdrop, 0xFFFFFFFF, NULL, 0);
3088 files = Qnil;
3089
3090 for (i = 0; i < num_files; i++)
3091 {
3092 len = DragQueryFile (hdrop, i, NULL, 0);
3093 if (len <= 0)
3094 continue;
3095 name = alloca (len + 1);
3096 DragQueryFile (hdrop, i, name, len + 1);
3097 files = Fcons (DECODE_FILE (build_string (name)), files);
3098 }
3099
3100 DragFinish (hdrop);
3101
3102 XSETFRAME (frame, f);
3103 result->frame_or_window = frame;
3104 result->arg = files;
3105 return Qnil;
3106 }
3107
3108 \f
3109 /* Function to report a mouse movement to the mainstream Emacs code.
3110 The input handler calls this.
3111
3112 We have received a mouse movement event, which is given in *event.
3113 If the mouse is over a different glyph than it was last time, tell
3114 the mainstream emacs code by setting mouse_moved. If not, ask for
3115 another motion event, so we can check again the next time it moves. */
3116
3117 static MSG last_mouse_motion_event;
3118 static Lisp_Object last_mouse_motion_frame;
3119
3120 static int
3121 note_mouse_movement (frame, msg)
3122 FRAME_PTR frame;
3123 MSG *msg;
3124 {
3125 int mouse_x = LOWORD (msg->lParam);
3126 int mouse_y = HIWORD (msg->lParam);
3127
3128 last_mouse_movement_time = msg->time;
3129 memcpy (&last_mouse_motion_event, msg, sizeof (last_mouse_motion_event));
3130 XSETFRAME (last_mouse_motion_frame, frame);
3131
3132 if (!FRAME_X_OUTPUT (frame))
3133 return 0;
3134
3135 if (msg->hwnd != FRAME_W32_WINDOW (frame))
3136 {
3137 frame->mouse_moved = 1;
3138 last_mouse_scroll_bar = Qnil;
3139 note_mouse_highlight (frame, -1, -1);
3140 last_mouse_glyph_frame = 0;
3141 return 1;
3142 }
3143
3144 /* Has the mouse moved off the glyph it was on at the last sighting? */
3145 if (frame != last_mouse_glyph_frame
3146 || mouse_x < last_mouse_glyph.left
3147 || mouse_x >= last_mouse_glyph.right
3148 || mouse_y < last_mouse_glyph.top
3149 || mouse_y >= last_mouse_glyph.bottom)
3150 {
3151 frame->mouse_moved = 1;
3152 last_mouse_scroll_bar = Qnil;
3153 note_mouse_highlight (frame, mouse_x, mouse_y);
3154 /* Remember the mouse position here, as w32_mouse_position only
3155 gets called when mouse tracking is enabled but we also need
3156 to keep track of the mouse for help_echo and highlighting at
3157 other times. */
3158 remember_mouse_glyph (frame, mouse_x, mouse_y, &last_mouse_glyph);
3159 last_mouse_glyph_frame = frame;
3160 return 1;
3161 }
3162
3163 return 0;
3164 }
3165
3166 \f
3167 /************************************************************************
3168 Mouse Face
3169 ************************************************************************/
3170
3171 static struct scroll_bar *x_window_to_scroll_bar ();
3172 static void x_scroll_bar_report_motion ();
3173 static void x_check_fullscreen P_ ((struct frame *));
3174
3175 static void
3176 redo_mouse_highlight ()
3177 {
3178 if (!NILP (last_mouse_motion_frame)
3179 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame)))
3180 note_mouse_highlight (XFRAME (last_mouse_motion_frame),
3181 LOWORD (last_mouse_motion_event.lParam),
3182 HIWORD (last_mouse_motion_event.lParam));
3183 }
3184
3185 static void
3186 w32_define_cursor (window, cursor)
3187 Window window;
3188 Cursor cursor;
3189 {
3190 PostMessage (window, WM_EMACS_SETCURSOR, (WPARAM) cursor, 0);
3191 }
3192 /* Return the current position of the mouse.
3193 *fp should be a frame which indicates which display to ask about.
3194
3195 If the mouse movement started in a scroll bar, set *fp, *bar_window,
3196 and *part to the frame, window, and scroll bar part that the mouse
3197 is over. Set *x and *y to the portion and whole of the mouse's
3198 position on the scroll bar.
3199
3200 If the mouse movement started elsewhere, set *fp to the frame the
3201 mouse is on, *bar_window to nil, and *x and *y to the character cell
3202 the mouse is over.
3203
3204 Set *time to the server time-stamp for the time at which the mouse
3205 was at this position.
3206
3207 Don't store anything if we don't have a valid set of values to report.
3208
3209 This clears the mouse_moved flag, so we can wait for the next mouse
3210 movement. */
3211
3212 static void
3213 w32_mouse_position (fp, insist, bar_window, part, x, y, time)
3214 FRAME_PTR *fp;
3215 int insist;
3216 Lisp_Object *bar_window;
3217 enum scroll_bar_part *part;
3218 Lisp_Object *x, *y;
3219 unsigned long *time;
3220 {
3221 FRAME_PTR f1;
3222
3223 BLOCK_INPUT;
3224
3225 if (! NILP (last_mouse_scroll_bar) && insist == 0)
3226 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
3227 else
3228 {
3229 POINT pt;
3230
3231 Lisp_Object frame, tail;
3232
3233 /* Clear the mouse-moved flag for every frame on this display. */
3234 FOR_EACH_FRAME (tail, frame)
3235 XFRAME (frame)->mouse_moved = 0;
3236
3237 last_mouse_scroll_bar = Qnil;
3238
3239 GetCursorPos (&pt);
3240
3241 /* Now we have a position on the root; find the innermost window
3242 containing the pointer. */
3243 {
3244 if (FRAME_W32_DISPLAY_INFO (*fp)->grabbed && last_mouse_frame
3245 && FRAME_LIVE_P (last_mouse_frame))
3246 {
3247 /* If mouse was grabbed on a frame, give coords for that frame
3248 even if the mouse is now outside it. */
3249 f1 = last_mouse_frame;
3250 }
3251 else
3252 {
3253 /* Is window under mouse one of our frames? */
3254 f1 = x_any_window_to_frame (FRAME_W32_DISPLAY_INFO (*fp),
3255 WindowFromPoint (pt));
3256 }
3257
3258 /* If not, is it one of our scroll bars? */
3259 if (! f1)
3260 {
3261 struct scroll_bar *bar
3262 = x_window_to_scroll_bar (WindowFromPoint (pt));
3263
3264 if (bar)
3265 {
3266 f1 = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
3267 }
3268 }
3269
3270 if (f1 == 0 && insist > 0)
3271 f1 = SELECTED_FRAME ();
3272
3273 if (f1)
3274 {
3275 /* Ok, we found a frame. Store all the values.
3276 last_mouse_glyph is a rectangle used to reduce the
3277 generation of mouse events. To not miss any motion
3278 events, we must divide the frame into rectangles of the
3279 size of the smallest character that could be displayed
3280 on it, i.e. into the same rectangles that matrices on
3281 the frame are divided into. */
3282
3283 ScreenToClient (FRAME_W32_WINDOW (f1), &pt);
3284 remember_mouse_glyph (f1, pt.x, pt.y, &last_mouse_glyph);
3285 last_mouse_glyph_frame = f1;
3286
3287 *bar_window = Qnil;
3288 *part = 0;
3289 *fp = f1;
3290 XSETINT (*x, pt.x);
3291 XSETINT (*y, pt.y);
3292 *time = last_mouse_movement_time;
3293 }
3294 }
3295 }
3296
3297 UNBLOCK_INPUT;
3298 }
3299
3300 \f
3301 /***********************************************************************
3302 Tool-bars
3303 ***********************************************************************/
3304
3305 /* Handle mouse button event on the tool-bar of frame F, at
3306 frame-relative coordinates X/Y. EVENT_TYPE is either ButtionPress
3307 or ButtonRelase. */
3308
3309 static void
3310 w32_handle_tool_bar_click (f, button_event)
3311 struct frame *f;
3312 struct input_event *button_event;
3313 {
3314 int x = XFASTINT (button_event->x);
3315 int y = XFASTINT (button_event->y);
3316
3317 if (button_event->modifiers & down_modifier)
3318 handle_tool_bar_click (f, x, y, 1, 0);
3319 else
3320 handle_tool_bar_click (f, x, y, 0,
3321 button_event->modifiers & ~up_modifier);
3322 }
3323
3324
3325 \f
3326 /***********************************************************************
3327 Scroll bars
3328 ***********************************************************************/
3329
3330 /* Scroll bar support. */
3331
3332 /* Given a window ID, find the struct scroll_bar which manages it.
3333 This can be called in GC, so we have to make sure to strip off mark
3334 bits. */
3335
3336 static struct scroll_bar *
3337 x_window_to_scroll_bar (window_id)
3338 Window window_id;
3339 {
3340 Lisp_Object tail;
3341
3342 for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
3343 {
3344 Lisp_Object frame, bar, condemned;
3345
3346 frame = XCAR (tail);
3347 /* All elements of Vframe_list should be frames. */
3348 if (! FRAMEP (frame))
3349 abort ();
3350
3351 /* Scan this frame's scroll bar list for a scroll bar with the
3352 right window ID. */
3353 condemned = FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame));
3354 for (bar = FRAME_SCROLL_BARS (XFRAME (frame));
3355 /* This trick allows us to search both the ordinary and
3356 condemned scroll bar lists with one loop. */
3357 ! NILP (bar) || (bar = condemned,
3358 condemned = Qnil,
3359 ! NILP (bar));
3360 bar = XSCROLL_BAR (bar)->next)
3361 if (SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar)) == window_id)
3362 return XSCROLL_BAR (bar);
3363 }
3364
3365 return 0;
3366 }
3367
3368
3369 \f
3370 /* Set the thumb size and position of scroll bar BAR. We are currently
3371 displaying PORTION out of a whole WHOLE, and our position POSITION. */
3372
3373 static void
3374 w32_set_scroll_bar_thumb (bar, portion, position, whole)
3375 struct scroll_bar *bar;
3376 int portion, position, whole;
3377 {
3378 Window w = SCROLL_BAR_W32_WINDOW (bar);
3379 /* We use the whole scroll-bar height in the calculations below, to
3380 avoid strange effects like scrolling backwards when just clicking
3381 on the handle (without moving it). */
3382 double range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height))
3383 + VERTICAL_SCROLL_BAR_MIN_HANDLE;
3384 int sb_page, sb_pos;
3385 BOOL draggingp = !NILP (bar->dragging) ? TRUE : FALSE;
3386 SCROLLINFO si;
3387
3388 /* We used to change the nPage setting while dragging the handle,
3389 but that had very strange effects (such as scrolling backwards
3390 while dragging downwards).
3391
3392 Now, we don't change the nPage setting while dragging unless we
3393 get near to the end of the buffer, in which case we often have to
3394 resize the handle to "go all the way". */
3395
3396 if (draggingp)
3397 {
3398 int near_bottom_p;
3399 BLOCK_INPUT;
3400 si.cbSize = sizeof (si);
3401 si.fMask = SIF_POS | SIF_PAGE;
3402 GetScrollInfo(w, SB_CTL, &si);
3403 near_bottom_p = si.nPos + si.nPage >= range;
3404 UNBLOCK_INPUT;
3405 if (!near_bottom_p)
3406 return;
3407 }
3408
3409 if (whole)
3410 {
3411 /* Position scroll bar at rock bottom if the bottom of the
3412 buffer is visible. This avoids shinking the thumb away
3413 to nothing if it is held at the bottom of the buffer. */
3414 if (position + portion >= whole && !draggingp)
3415 {
3416 sb_page = range * (whole - position) / whole;
3417 sb_pos = range;
3418 }
3419 else
3420 {
3421 sb_pos = position * range / whole;
3422 sb_page = (min (portion, (whole - position)) * range) / whole;
3423 }
3424 }
3425 else
3426 {
3427 sb_page = range;
3428 sb_pos = 0;
3429 }
3430
3431 sb_page = max (sb_page, VERTICAL_SCROLL_BAR_MIN_HANDLE);
3432
3433 BLOCK_INPUT;
3434
3435 si.cbSize = sizeof (si);
3436 si.fMask = SIF_PAGE | SIF_POS;
3437 si.nPage = sb_page;
3438 si.nPos = sb_pos;
3439
3440 SetScrollInfo (w, SB_CTL, &si, TRUE);
3441
3442 UNBLOCK_INPUT;
3443 }
3444
3445 \f
3446 /************************************************************************
3447 Scroll bars, general
3448 ************************************************************************/
3449
3450 static HWND
3451 my_create_scrollbar (f, bar)
3452 struct frame * f;
3453 struct scroll_bar * bar;
3454 {
3455 return (HWND) SendMessage (FRAME_W32_WINDOW (f),
3456 WM_EMACS_CREATESCROLLBAR, (WPARAM) f,
3457 (LPARAM) bar);
3458 }
3459
3460 /*#define ATTACH_THREADS*/
3461
3462 static BOOL
3463 my_show_window (FRAME_PTR f, HWND hwnd, int how)
3464 {
3465 #ifndef ATTACH_THREADS
3466 return SendMessage (FRAME_W32_WINDOW (f), WM_EMACS_SHOWWINDOW,
3467 (WPARAM) hwnd, (LPARAM) how);
3468 #else
3469 return ShowWindow (hwnd, how);
3470 #endif
3471 }
3472
3473 static void
3474 my_set_window_pos (HWND hwnd, HWND hwndAfter,
3475 int x, int y, int cx, int cy, UINT flags)
3476 {
3477 #ifndef ATTACH_THREADS
3478 WINDOWPOS pos;
3479 pos.hwndInsertAfter = hwndAfter;
3480 pos.x = x;
3481 pos.y = y;
3482 pos.cx = cx;
3483 pos.cy = cy;
3484 pos.flags = flags;
3485 SendMessage (hwnd, WM_EMACS_SETWINDOWPOS, (WPARAM) &pos, 0);
3486 #else
3487 SetWindowPos (hwnd, hwndAfter, x, y, cx, cy, flags);
3488 #endif
3489 }
3490
3491 static void
3492 my_set_focus (f, hwnd)
3493 struct frame * f;
3494 HWND hwnd;
3495 {
3496 SendMessage (FRAME_W32_WINDOW (f), WM_EMACS_SETFOCUS,
3497 (WPARAM) hwnd, 0);
3498 }
3499
3500 static void
3501 my_set_foreground_window (hwnd)
3502 HWND hwnd;
3503 {
3504 SendMessage (hwnd, WM_EMACS_SETFOREGROUND, (WPARAM) hwnd, 0);
3505 }
3506
3507
3508 static void
3509 my_destroy_window (f, hwnd)
3510 struct frame * f;
3511 HWND hwnd;
3512 {
3513 SendMessage (FRAME_W32_WINDOW (f), WM_EMACS_DESTROYWINDOW,
3514 (WPARAM) hwnd, 0);
3515 }
3516
3517 /* Create a scroll bar and return the scroll bar vector for it. W is
3518 the Emacs window on which to create the scroll bar. TOP, LEFT,
3519 WIDTH and HEIGHT are.the pixel coordinates and dimensions of the
3520 scroll bar. */
3521
3522 static struct scroll_bar *
3523 x_scroll_bar_create (w, top, left, width, height)
3524 struct window *w;
3525 int top, left, width, height;
3526 {
3527 struct frame *f = XFRAME (WINDOW_FRAME (w));
3528 HWND hwnd;
3529 SCROLLINFO si;
3530 struct scroll_bar *bar
3531 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
3532
3533 BLOCK_INPUT;
3534
3535 XSETWINDOW (bar->window, w);
3536 XSETINT (bar->top, top);
3537 XSETINT (bar->left, left);
3538 XSETINT (bar->width, width);
3539 XSETINT (bar->height, height);
3540 XSETINT (bar->start, 0);
3541 XSETINT (bar->end, 0);
3542 bar->dragging = Qnil;
3543 bar->fringe_extended_p = Qnil;
3544
3545 /* Requires geometry to be set before call to create the real window */
3546
3547 hwnd = my_create_scrollbar (f, bar);
3548
3549 si.cbSize = sizeof (si);
3550 si.fMask = SIF_ALL;
3551 si.nMin = 0;
3552 si.nMax = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height)
3553 + VERTICAL_SCROLL_BAR_MIN_HANDLE;
3554 si.nPage = si.nMax;
3555 si.nPos = 0;
3556
3557 SetScrollInfo (hwnd, SB_CTL, &si, FALSE);
3558
3559 SET_SCROLL_BAR_W32_WINDOW (bar, hwnd);
3560
3561 /* Add bar to its frame's list of scroll bars. */
3562 bar->next = FRAME_SCROLL_BARS (f);
3563 bar->prev = Qnil;
3564 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
3565 if (! NILP (bar->next))
3566 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
3567
3568 UNBLOCK_INPUT;
3569
3570 return bar;
3571 }
3572
3573
3574 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
3575 nil. */
3576
3577 static void
3578 x_scroll_bar_remove (bar)
3579 struct scroll_bar *bar;
3580 {
3581 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
3582
3583 BLOCK_INPUT;
3584
3585 /* Destroy the window. */
3586 my_destroy_window (f, SCROLL_BAR_W32_WINDOW (bar));
3587
3588 /* Disassociate this scroll bar from its window. */
3589 XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
3590
3591 UNBLOCK_INPUT;
3592 }
3593
3594 /* Set the handle of the vertical scroll bar for WINDOW to indicate
3595 that we are displaying PORTION characters out of a total of WHOLE
3596 characters, starting at POSITION. If WINDOW has no scroll bar,
3597 create one. */
3598 static void
3599 w32_set_vertical_scroll_bar (w, portion, whole, position)
3600 struct window *w;
3601 int portion, whole, position;
3602 {
3603 struct frame *f = XFRAME (w->frame);
3604 struct scroll_bar *bar;
3605 int top, height, left, sb_left, width, sb_width;
3606 int window_y, window_height;
3607 int fringe_extended_p;
3608
3609 /* Get window dimensions. */
3610 window_box (w, -1, 0, &window_y, 0, &window_height);
3611 top = window_y;
3612 width = WINDOW_CONFIG_SCROLL_BAR_COLS (w) * FRAME_COLUMN_WIDTH (f);
3613 height = window_height;
3614
3615 /* Compute the left edge of the scroll bar area. */
3616 left = WINDOW_SCROLL_BAR_AREA_X (w);
3617
3618 /* Compute the width of the scroll bar which might be less than
3619 the width of the area reserved for the scroll bar. */
3620 if (WINDOW_CONFIG_SCROLL_BAR_WIDTH (w) > 0)
3621 sb_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
3622 else
3623 sb_width = width;
3624
3625 /* Compute the left edge of the scroll bar. */
3626 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w))
3627 sb_left = left + (WINDOW_RIGHTMOST_P (w) ? width - sb_width : 0);
3628 else
3629 sb_left = left + (WINDOW_LEFTMOST_P (w) ? 0 : width - sb_width);
3630
3631 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w))
3632 fringe_extended_p = (WINDOW_LEFTMOST_P (w)
3633 && WINDOW_LEFT_FRINGE_WIDTH (w)
3634 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
3635 || WINDOW_LEFT_MARGIN_COLS (w) == 0));
3636 else
3637 fringe_extended_p = (WINDOW_RIGHTMOST_P (w)
3638 && WINDOW_RIGHT_FRINGE_WIDTH (w)
3639 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
3640 || WINDOW_RIGHT_MARGIN_COLS (w) == 0));
3641
3642 /* Does the scroll bar exist yet? */
3643 if (NILP (w->vertical_scroll_bar))
3644 {
3645 HDC hdc;
3646 BLOCK_INPUT;
3647 if (width > 0 && height > 0)
3648 {
3649 hdc = get_frame_dc (f);
3650 if (fringe_extended_p)
3651 w32_clear_area (f, hdc, sb_left, top, sb_width, height);
3652 else
3653 w32_clear_area (f, hdc, left, top, width, height);
3654 release_frame_dc (f, hdc);
3655 }
3656 UNBLOCK_INPUT;
3657
3658 bar = x_scroll_bar_create (w, top, sb_left, sb_width, height);
3659 }
3660 else
3661 {
3662 /* It may just need to be moved and resized. */
3663 HWND hwnd;
3664
3665 bar = XSCROLL_BAR (w->vertical_scroll_bar);
3666 hwnd = SCROLL_BAR_W32_WINDOW (bar);
3667
3668 /* If already correctly positioned, do nothing. */
3669 if ( XINT (bar->left) == sb_left
3670 && XINT (bar->top) == top
3671 && XINT (bar->width) == sb_width
3672 && XINT (bar->height) == height
3673 && !NILP (bar->fringe_extended_p) == fringe_extended_p )
3674 {
3675 /* Redraw after clear_frame. */
3676 if (!my_show_window (f, hwnd, SW_NORMAL))
3677 InvalidateRect (hwnd, NULL, FALSE);
3678 }
3679 else
3680 {
3681 HDC hdc;
3682 SCROLLINFO si;
3683
3684 BLOCK_INPUT;
3685 if (width && height)
3686 {
3687 hdc = get_frame_dc (f);
3688 /* Since Windows scroll bars are smaller than the space reserved
3689 for them on the frame, we have to clear "under" them. */
3690 if (fringe_extended_p)
3691 w32_clear_area (f, hdc, sb_left, top, sb_width, height);
3692 else
3693 w32_clear_area (f, hdc, left, top, width, height);
3694 release_frame_dc (f, hdc);
3695 }
3696 /* Make sure scroll bar is "visible" before moving, to ensure the
3697 area of the parent window now exposed will be refreshed. */
3698 my_show_window (f, hwnd, SW_HIDE);
3699 MoveWindow (hwnd, sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
3700 top, sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
3701 max (height, 1), TRUE);
3702
3703 si.cbSize = sizeof (si);
3704 si.fMask = SIF_RANGE;
3705 si.nMin = 0;
3706 si.nMax = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height)
3707 + VERTICAL_SCROLL_BAR_MIN_HANDLE;
3708
3709 SetScrollInfo (hwnd, SB_CTL, &si, FALSE);
3710
3711 my_show_window (f, hwnd, SW_NORMAL);
3712 /* InvalidateRect (w, NULL, FALSE); */
3713
3714 /* Remember new settings. */
3715 XSETINT (bar->left, sb_left);
3716 XSETINT (bar->top, top);
3717 XSETINT (bar->width, sb_width);
3718 XSETINT (bar->height, height);
3719
3720 UNBLOCK_INPUT;
3721 }
3722 }
3723 bar->fringe_extended_p = fringe_extended_p ? Qt : Qnil;
3724
3725 w32_set_scroll_bar_thumb (bar, portion, position, whole);
3726
3727 XSETVECTOR (w->vertical_scroll_bar, bar);
3728 }
3729
3730
3731 /* The following three hooks are used when we're doing a thorough
3732 redisplay of the frame. We don't explicitly know which scroll bars
3733 are going to be deleted, because keeping track of when windows go
3734 away is a real pain - "Can you say set-window-configuration, boys
3735 and girls?" Instead, we just assert at the beginning of redisplay
3736 that *all* scroll bars are to be removed, and then save a scroll bar
3737 from the fiery pit when we actually redisplay its window. */
3738
3739 /* Arrange for all scroll bars on FRAME to be removed at the next call
3740 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
3741 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
3742
3743 static void
3744 w32_condemn_scroll_bars (frame)
3745 FRAME_PTR frame;
3746 {
3747 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
3748 while (! NILP (FRAME_SCROLL_BARS (frame)))
3749 {
3750 Lisp_Object bar;
3751 bar = FRAME_SCROLL_BARS (frame);
3752 FRAME_SCROLL_BARS (frame) = XSCROLL_BAR (bar)->next;
3753 XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
3754 XSCROLL_BAR (bar)->prev = Qnil;
3755 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
3756 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
3757 FRAME_CONDEMNED_SCROLL_BARS (frame) = bar;
3758 }
3759 }
3760
3761
3762 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
3763 Note that WINDOW isn't necessarily condemned at all. */
3764
3765 static void
3766 w32_redeem_scroll_bar (window)
3767 struct window *window;
3768 {
3769 struct scroll_bar *bar;
3770 struct frame *f;
3771
3772 /* We can't redeem this window's scroll bar if it doesn't have one. */
3773 if (NILP (window->vertical_scroll_bar))
3774 abort ();
3775
3776 bar = XSCROLL_BAR (window->vertical_scroll_bar);
3777
3778 /* Unlink it from the condemned list. */
3779 f = XFRAME (WINDOW_FRAME (window));
3780 if (NILP (bar->prev))
3781 {
3782 /* If the prev pointer is nil, it must be the first in one of
3783 the lists. */
3784 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
3785 /* It's not condemned. Everything's fine. */
3786 return;
3787 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
3788 window->vertical_scroll_bar))
3789 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
3790 else
3791 /* If its prev pointer is nil, it must be at the front of
3792 one or the other! */
3793 abort ();
3794 }
3795 else
3796 XSCROLL_BAR (bar->prev)->next = bar->next;
3797
3798 if (! NILP (bar->next))
3799 XSCROLL_BAR (bar->next)->prev = bar->prev;
3800
3801 bar->next = FRAME_SCROLL_BARS (f);
3802 bar->prev = Qnil;
3803 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
3804 if (! NILP (bar->next))
3805 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
3806 }
3807
3808 /* Remove all scroll bars on FRAME that haven't been saved since the
3809 last call to `*condemn_scroll_bars_hook'. */
3810
3811 static void
3812 w32_judge_scroll_bars (f)
3813 FRAME_PTR f;
3814 {
3815 Lisp_Object bar, next;
3816
3817 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
3818
3819 /* Clear out the condemned list now so we won't try to process any
3820 more events on the hapless scroll bars. */
3821 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
3822
3823 for (; ! NILP (bar); bar = next)
3824 {
3825 struct scroll_bar *b = XSCROLL_BAR (bar);
3826
3827 x_scroll_bar_remove (b);
3828
3829 next = b->next;
3830 b->next = b->prev = Qnil;
3831 }
3832
3833 /* Now there should be no references to the condemned scroll bars,
3834 and they should get garbage-collected. */
3835 }
3836
3837 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
3838 is set to something other than NO_EVENT, it is enqueued.
3839
3840 This may be called from a signal handler, so we have to ignore GC
3841 mark bits. */
3842
3843 static int
3844 w32_scroll_bar_handle_click (bar, msg, emacs_event)
3845 struct scroll_bar *bar;
3846 W32Msg *msg;
3847 struct input_event *emacs_event;
3848 {
3849 if (! WINDOWP (bar->window))
3850 abort ();
3851
3852 emacs_event->kind = SCROLL_BAR_CLICK_EVENT;
3853 emacs_event->code = 0;
3854 /* not really meaningful to distinguish up/down */
3855 emacs_event->modifiers = msg->dwModifiers;
3856 emacs_event->frame_or_window = bar->window;
3857 emacs_event->arg = Qnil;
3858 emacs_event->timestamp = msg->msg.time;
3859
3860 {
3861 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
3862 int y;
3863 int dragging = !NILP (bar->dragging);
3864 SCROLLINFO si;
3865
3866 si.cbSize = sizeof (si);
3867 si.fMask = SIF_POS;
3868
3869 GetScrollInfo ((HWND) msg->msg.lParam, SB_CTL, &si);
3870 y = si.nPos;
3871
3872 bar->dragging = Qnil;
3873
3874
3875 last_mouse_scroll_bar_pos = msg->msg.wParam;
3876
3877 switch (LOWORD (msg->msg.wParam))
3878 {
3879 case SB_LINEDOWN:
3880 emacs_event->part = scroll_bar_down_arrow;
3881 break;
3882 case SB_LINEUP:
3883 emacs_event->part = scroll_bar_up_arrow;
3884 break;
3885 case SB_PAGEUP:
3886 emacs_event->part = scroll_bar_above_handle;
3887 break;
3888 case SB_PAGEDOWN:
3889 emacs_event->part = scroll_bar_below_handle;
3890 break;
3891 case SB_TOP:
3892 emacs_event->part = scroll_bar_handle;
3893 y = 0;
3894 break;
3895 case SB_BOTTOM:
3896 emacs_event->part = scroll_bar_handle;
3897 y = top_range;
3898 break;
3899 case SB_THUMBTRACK:
3900 case SB_THUMBPOSITION:
3901 if (VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height)) <= 0xffff)
3902 y = HIWORD (msg->msg.wParam);
3903 bar->dragging = Qt;
3904 emacs_event->part = scroll_bar_handle;
3905
3906 /* "Silently" update current position. */
3907 {
3908 SCROLLINFO si;
3909
3910 si.cbSize = sizeof (si);
3911 si.fMask = SIF_POS;
3912 si.nPos = y;
3913 /* Remember apparent position (we actually lag behind the real
3914 position, so don't set that directly. */
3915 last_scroll_bar_drag_pos = y;
3916
3917 SetScrollInfo (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, &si, FALSE);
3918 }
3919 break;
3920 case SB_ENDSCROLL:
3921 /* If this is the end of a drag sequence, then reset the scroll
3922 handle size to normal and do a final redraw. Otherwise do
3923 nothing. */
3924 if (dragging)
3925 {
3926 SCROLLINFO si;
3927 int start = XINT (bar->start);
3928 int end = XINT (bar->end);
3929
3930 si.cbSize = sizeof (si);
3931 si.fMask = SIF_PAGE | SIF_POS;
3932 si.nPage = end - start + VERTICAL_SCROLL_BAR_MIN_HANDLE;
3933 si.nPos = last_scroll_bar_drag_pos;
3934 SetScrollInfo (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, &si, TRUE);
3935 }
3936 /* fall through */
3937 default:
3938 emacs_event->kind = NO_EVENT;
3939 return FALSE;
3940 }
3941
3942 XSETINT (emacs_event->x, y);
3943 XSETINT (emacs_event->y, top_range);
3944
3945 return TRUE;
3946 }
3947 }
3948
3949 /* Return information to the user about the current position of the mouse
3950 on the scroll bar. */
3951
3952 static void
3953 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
3954 FRAME_PTR *fp;
3955 Lisp_Object *bar_window;
3956 enum scroll_bar_part *part;
3957 Lisp_Object *x, *y;
3958 unsigned long *time;
3959 {
3960 struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
3961 Window w = SCROLL_BAR_W32_WINDOW (bar);
3962 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
3963 int pos;
3964 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
3965 SCROLLINFO si;
3966
3967 BLOCK_INPUT;
3968
3969 *fp = f;
3970 *bar_window = bar->window;
3971
3972 si.cbSize = sizeof (si);
3973 si.fMask = SIF_POS | SIF_PAGE | SIF_RANGE;
3974
3975 GetScrollInfo (w, SB_CTL, &si);
3976 pos = si.nPos;
3977 top_range = si.nMax - si.nPage + 1;
3978
3979 switch (LOWORD (last_mouse_scroll_bar_pos))
3980 {
3981 case SB_THUMBPOSITION:
3982 case SB_THUMBTRACK:
3983 *part = scroll_bar_handle;
3984 if (VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height)) <= 0xffff)
3985 pos = HIWORD (last_mouse_scroll_bar_pos);
3986 break;
3987 case SB_LINEDOWN:
3988 *part = scroll_bar_handle;
3989 pos++;
3990 break;
3991 default:
3992 *part = scroll_bar_handle;
3993 break;
3994 }
3995
3996 XSETINT (*x, pos);
3997 XSETINT (*y, top_range);
3998
3999 f->mouse_moved = 0;
4000 last_mouse_scroll_bar = Qnil;
4001
4002 *time = last_mouse_movement_time;
4003
4004 UNBLOCK_INPUT;
4005 }
4006
4007
4008 /* The screen has been cleared so we may have changed foreground or
4009 background colors, and the scroll bars may need to be redrawn.
4010 Clear out the scroll bars, and ask for expose events, so we can
4011 redraw them. */
4012
4013 void
4014 x_scroll_bar_clear (f)
4015 FRAME_PTR f;
4016 {
4017 Lisp_Object bar;
4018
4019 /* We can have scroll bars even if this is 0,
4020 if we just turned off scroll bar mode.
4021 But in that case we should not clear them. */
4022 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
4023 for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar);
4024 bar = XSCROLL_BAR (bar)->next)
4025 {
4026 HWND window = SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar));
4027 HDC hdc = GetDC (window);
4028 RECT rect;
4029
4030 /* Hide scroll bar until ready to repaint. x_scroll_bar_move
4031 arranges to refresh the scroll bar if hidden. */
4032 my_show_window (f, window, SW_HIDE);
4033
4034 GetClientRect (window, &rect);
4035 select_palette (f, hdc);
4036 w32_clear_rect (f, hdc, &rect);
4037 deselect_palette (f, hdc);
4038
4039 ReleaseDC (window, hdc);
4040 }
4041 }
4042
4043 \f
4044 /* The main W32 event-reading loop - w32_read_socket. */
4045
4046 /* Record the last 100 characters stored
4047 to help debug the loss-of-chars-during-GC problem. */
4048
4049 static int temp_index;
4050 static short temp_buffer[100];
4051
4052 /* Temporarily store lead byte of DBCS input sequences. */
4053 static char dbcs_lead = 0;
4054
4055 /* Read events coming from the W32 shell.
4056 This routine is called by the SIGIO handler.
4057 We return as soon as there are no more events to be read.
4058
4059 We return the number of characters stored into the buffer,
4060 thus pretending to be `read'.
4061
4062 EXPECTED is nonzero if the caller knows input is available.
4063
4064 Some of these messages are reposted back to the message queue since the
4065 system calls the windows proc directly in a context where we cannot return
4066 the data nor can we guarantee the state we are in. So if we dispatch them
4067 we will get into an infinite loop. To prevent this from ever happening we
4068 will set a variable to indicate we are in the read_socket call and indicate
4069 which message we are processing since the windows proc gets called
4070 recursively with different messages by the system.
4071 */
4072
4073 int
4074 w32_read_socket (sd, expected, hold_quit)
4075 register int sd;
4076 int expected;
4077 struct input_event *hold_quit;
4078 {
4079 int count = 0;
4080 int check_visibility = 0;
4081 W32Msg msg;
4082 struct frame *f;
4083 struct w32_display_info *dpyinfo = &one_w32_display_info;
4084
4085 if (interrupt_input_blocked)
4086 {
4087 interrupt_input_pending = 1;
4088 return -1;
4089 }
4090
4091 interrupt_input_pending = 0;
4092 BLOCK_INPUT;
4093
4094 /* So people can tell when we have read the available input. */
4095 input_signal_count++;
4096
4097 /* TODO: ghostscript integration. */
4098 while (get_next_msg (&msg, FALSE))
4099 {
4100 struct input_event inev;
4101 int do_help = 0;
4102
4103 EVENT_INIT (inev);
4104 inev.kind = NO_EVENT;
4105 inev.arg = Qnil;
4106
4107 switch (msg.msg.message)
4108 {
4109 case WM_EMACS_PAINT:
4110 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4111
4112 if (f)
4113 {
4114 if (msg.rect.right == msg.rect.left ||
4115 msg.rect.bottom == msg.rect.top)
4116 {
4117 /* We may get paint messages even though the client
4118 area is clipped - these are not expose events. */
4119 DebPrint (("clipped frame %p (%s) got WM_PAINT - ignored\n", f,
4120 SDATA (f->name)));
4121 }
4122 else if (f->async_visible != 1)
4123 {
4124 /* Definitely not obscured, so mark as visible. */
4125 f->async_visible = 1;
4126 f->async_iconified = 0;
4127 SET_FRAME_GARBAGED (f);
4128 DebPrint (("frame %p (%s) reexposed by WM_PAINT\n", f,
4129 SDATA (f->name)));
4130
4131 /* WM_PAINT serves as MapNotify as well, so report
4132 visibility changes properly. */
4133 if (f->iconified)
4134 {
4135 inev.kind = DEICONIFY_EVENT;
4136 XSETFRAME (inev.frame_or_window, f);
4137 }
4138 else if (! NILP (Vframe_list)
4139 && ! NILP (XCDR (Vframe_list)))
4140 /* Force a redisplay sooner or later to update the
4141 frame titles in case this is the second frame. */
4142 record_asynch_buffer_change ();
4143 }
4144 else
4145 {
4146 HDC hdc = get_frame_dc (f);
4147
4148 /* Erase background again for safety. */
4149 w32_clear_rect (f, hdc, &msg.rect);
4150 release_frame_dc (f, hdc);
4151 expose_frame (f,
4152 msg.rect.left,
4153 msg.rect.top,
4154 msg.rect.right - msg.rect.left,
4155 msg.rect.bottom - msg.rect.top);
4156 }
4157 }
4158 break;
4159
4160 case WM_INPUTLANGCHANGE:
4161 /* Generate a language change event. */
4162 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4163
4164 /* lParam contains the input lang ID. Use it to update our
4165 record of the keyboard codepage. */
4166 keyboard_codepage = codepage_for_locale ((LCID)(msg.msg.lParam
4167 & 0xffff));
4168
4169 if (f)
4170 {
4171 inev.kind = LANGUAGE_CHANGE_EVENT;
4172 XSETFRAME (inev.frame_or_window, f);
4173 inev.code = msg.msg.wParam;
4174 inev.modifiers = msg.msg.lParam & 0xffff;
4175 }
4176 break;
4177
4178 case WM_KEYDOWN:
4179 case WM_SYSKEYDOWN:
4180 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4181
4182 if (f && !f->iconified)
4183 {
4184 if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight)
4185 && !EQ (f->tool_bar_window, dpyinfo->mouse_face_window))
4186 {
4187 clear_mouse_face (dpyinfo);
4188 dpyinfo->mouse_face_hidden = 1;
4189 }
4190
4191 if (temp_index == sizeof temp_buffer / sizeof (short))
4192 temp_index = 0;
4193 temp_buffer[temp_index++] = msg.msg.wParam;
4194 inev.kind = NON_ASCII_KEYSTROKE_EVENT;
4195 inev.code = msg.msg.wParam;
4196 inev.modifiers = msg.dwModifiers;
4197 XSETFRAME (inev.frame_or_window, f);
4198 inev.timestamp = msg.msg.time;
4199 }
4200 break;
4201
4202 case WM_UNICHAR:
4203 case WM_SYSCHAR:
4204 case WM_CHAR:
4205 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4206
4207 if (f && !f->iconified)
4208 {
4209 if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight)
4210 && !EQ (f->tool_bar_window, dpyinfo->mouse_face_window))
4211 {
4212 clear_mouse_face (dpyinfo);
4213 dpyinfo->mouse_face_hidden = 1;
4214 }
4215
4216 if (temp_index == sizeof temp_buffer / sizeof (short))
4217 temp_index = 0;
4218 temp_buffer[temp_index++] = msg.msg.wParam;
4219
4220 inev.modifiers = msg.dwModifiers;
4221 XSETFRAME (inev.frame_or_window, f);
4222 inev.timestamp = msg.msg.time;
4223
4224 if (msg.msg.message == WM_UNICHAR)
4225 {
4226 inev.code = msg.msg.wParam;
4227 }
4228 else if (msg.msg.wParam < 256)
4229 {
4230 wchar_t code;
4231 char dbcs[2];
4232 dbcs[0] = 0;
4233 dbcs[1] = (char) msg.msg.wParam;
4234
4235 if (dbcs_lead)
4236 {
4237 dbcs[0] = dbcs_lead;
4238 dbcs_lead = 0;
4239 if (!MultiByteToWideChar (keyboard_codepage, 0,
4240 dbcs, 2, &code, 1))
4241 {
4242 /* Garbage */
4243 DebPrint (("Invalid DBCS sequence: %d %d\n",
4244 dbcs[0], dbcs[1]));
4245 inev.kind = NO_EVENT;
4246 break;
4247 }
4248 }
4249 else if (IsDBCSLeadByteEx (keyboard_codepage,
4250 (BYTE) msg.msg.wParam))
4251 {
4252 dbcs_lead = (char) msg.msg.wParam;
4253 inev.kind = NO_EVENT;
4254 break;
4255 }
4256 else
4257 {
4258 if (!MultiByteToWideChar (keyboard_codepage, 0,
4259 &dbcs[1], 1, &code, 1))
4260 {
4261 /* What to do with garbage? */
4262 DebPrint (("Invalid character: %d\n", dbcs[1]));
4263 inev.kind = NO_EVENT;
4264 break;
4265 }
4266 }
4267 inev.code = code;
4268 }
4269 else
4270 {
4271 /* Windows shouldn't generate WM_CHAR events above 0xFF
4272 in non-Unicode message handlers. */
4273 DebPrint (("Non-byte WM_CHAR: %d\n", msg.msg.wParam));
4274 inev.kind = NO_EVENT;
4275 break;
4276 }
4277 inev.kind = inev.code < 128 ? ASCII_KEYSTROKE_EVENT
4278 : MULTIBYTE_CHAR_KEYSTROKE_EVENT;
4279 }
4280 break;
4281
4282 case WM_APPCOMMAND:
4283 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4284
4285 if (f && !f->iconified)
4286 {
4287 if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight)
4288 && !EQ (f->tool_bar_window, dpyinfo->mouse_face_window))
4289 {
4290 clear_mouse_face (dpyinfo);
4291 dpyinfo->mouse_face_hidden = 1;
4292 }
4293
4294 if (temp_index == sizeof temp_buffer / sizeof (short))
4295 temp_index = 0;
4296 temp_buffer[temp_index++] = msg.msg.wParam;
4297 inev.kind = MULTIMEDIA_KEY_EVENT;
4298 inev.code = GET_APPCOMMAND_LPARAM(msg.msg.lParam);
4299 inev.modifiers = msg.dwModifiers;
4300 XSETFRAME (inev.frame_or_window, f);
4301 inev.timestamp = msg.msg.time;
4302 }
4303 break;
4304
4305 case WM_MOUSEMOVE:
4306 /* Ignore non-movement. */
4307 {
4308 int x = LOWORD (msg.msg.lParam);
4309 int y = HIWORD (msg.msg.lParam);
4310 if (x == last_mousemove_x && y == last_mousemove_y)
4311 break;
4312 last_mousemove_x = x;
4313 last_mousemove_y = y;
4314 }
4315
4316 previous_help_echo_string = help_echo_string;
4317 help_echo_string = Qnil;
4318
4319 if (dpyinfo->grabbed && last_mouse_frame
4320 && FRAME_LIVE_P (last_mouse_frame))
4321 f = last_mouse_frame;
4322 else
4323 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4324
4325 if (dpyinfo->mouse_face_hidden)
4326 {
4327 dpyinfo->mouse_face_hidden = 0;
4328 clear_mouse_face (dpyinfo);
4329 }
4330
4331 if (f)
4332 {
4333 /* Generate SELECT_WINDOW_EVENTs when needed. */
4334 if (!NILP (Vmouse_autoselect_window))
4335 {
4336 Lisp_Object window;
4337 int x = LOWORD (msg.msg.lParam);
4338 int y = HIWORD (msg.msg.lParam);
4339
4340 window = window_from_coordinates (f, x, y, 0, 0, 0, 0);
4341
4342 /* Window will be selected only when it is not
4343 selected now and last mouse movement event was
4344 not in it. Minibuffer window will be selected
4345 only when it is active. */
4346 if (WINDOWP(window)
4347 && !EQ (window, last_window)
4348 && !EQ (window, selected_window)
4349 /* For click-to-focus window managers
4350 create event iff we don't leave the
4351 selected frame. */
4352 && (focus_follows_mouse
4353 || (EQ (XWINDOW (window)->frame,
4354 XWINDOW (selected_window)->frame))))
4355 {
4356 inev.kind = SELECT_WINDOW_EVENT;
4357 inev.frame_or_window = window;
4358 }
4359
4360 last_window=window;
4361 }
4362 if (!note_mouse_movement (f, &msg.msg))
4363 help_echo_string = previous_help_echo_string;
4364 }
4365 else
4366 {
4367 /* If we move outside the frame, then we're
4368 certainly no longer on any text in the frame. */
4369 clear_mouse_face (dpyinfo);
4370 }
4371
4372 /* If the contents of the global variable help_echo_string
4373 has changed, generate a HELP_EVENT. */
4374 #if 0 /* The below is an invalid comparison when USE_LISP_UNION_TYPE.
4375 But it was originally changed to this to fix a bug, so I have
4376 not removed it completely in case the bug is still there. */
4377 if (help_echo_string != previous_help_echo_string ||
4378 (!NILP (help_echo_string) && !STRINGP (help_echo_string) && f->mouse_moved))
4379 #else /* This is what xterm.c does. */
4380 if (!NILP (help_echo_string)
4381 || !NILP (previous_help_echo_string))
4382 do_help = 1;
4383 #endif
4384 break;
4385
4386 case WM_LBUTTONDOWN:
4387 case WM_LBUTTONUP:
4388 case WM_MBUTTONDOWN:
4389 case WM_MBUTTONUP:
4390 case WM_RBUTTONDOWN:
4391 case WM_RBUTTONUP:
4392 case WM_XBUTTONDOWN:
4393 case WM_XBUTTONUP:
4394 {
4395 /* If we decide we want to generate an event to be seen
4396 by the rest of Emacs, we put it here. */
4397 int tool_bar_p = 0;
4398 int button;
4399 int up;
4400
4401 if (dpyinfo->grabbed && last_mouse_frame
4402 && FRAME_LIVE_P (last_mouse_frame))
4403 f = last_mouse_frame;
4404 else
4405 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4406
4407 if (f)
4408 {
4409 construct_mouse_click (&inev, &msg, f);
4410
4411 /* Is this in the tool-bar? */
4412 if (WINDOWP (f->tool_bar_window)
4413 && WINDOW_TOTAL_LINES (XWINDOW (f->tool_bar_window)))
4414 {
4415 Lisp_Object window;
4416 int x = XFASTINT (inev.x);
4417 int y = XFASTINT (inev.y);
4418
4419 window = window_from_coordinates (f, x, y, 0, 0, 0, 1);
4420
4421 if (EQ (window, f->tool_bar_window))
4422 {
4423 w32_handle_tool_bar_click (f, &inev);
4424 tool_bar_p = 1;
4425 }
4426 }
4427
4428 if (tool_bar_p
4429 || (dpyinfo->w32_focus_frame
4430 && f != dpyinfo->w32_focus_frame))
4431 inev.kind = NO_EVENT;
4432 }
4433
4434 parse_button (msg.msg.message, HIWORD (msg.msg.wParam),
4435 &button, &up);
4436
4437 if (up)
4438 {
4439 dpyinfo->grabbed &= ~ (1 << button);
4440 }
4441 else
4442 {
4443 dpyinfo->grabbed |= (1 << button);
4444 last_mouse_frame = f;
4445 /* Ignore any mouse motion that happened
4446 before this event; any subsequent mouse-movement
4447 Emacs events should reflect only motion after
4448 the ButtonPress. */
4449 if (f != 0)
4450 f->mouse_moved = 0;
4451
4452 if (!tool_bar_p)
4453 last_tool_bar_item = -1;
4454 }
4455 break;
4456 }
4457
4458 case WM_MOUSEWHEEL:
4459 case WM_MOUSEHWHEEL:
4460 {
4461 if (dpyinfo->grabbed && last_mouse_frame
4462 && FRAME_LIVE_P (last_mouse_frame))
4463 f = last_mouse_frame;
4464 else
4465 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4466
4467 if (f)
4468 {
4469
4470 if (!dpyinfo->w32_focus_frame
4471 || f == dpyinfo->w32_focus_frame)
4472 {
4473 /* Emit an Emacs wheel-up/down event. */
4474 construct_mouse_wheel (&inev, &msg, f);
4475 }
4476 /* Ignore any mouse motion that happened before this
4477 event; any subsequent mouse-movement Emacs events
4478 should reflect only motion after the
4479 ButtonPress. */
4480 f->mouse_moved = 0;
4481 }
4482 last_mouse_frame = f;
4483 last_tool_bar_item = -1;
4484 }
4485 break;
4486
4487 case WM_DROPFILES:
4488 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4489
4490 if (f)
4491 construct_drag_n_drop (&inev, &msg, f);
4492 break;
4493
4494 case WM_VSCROLL:
4495 {
4496 struct scroll_bar *bar =
4497 x_window_to_scroll_bar ((HWND)msg.msg.lParam);
4498
4499 if (bar)
4500 w32_scroll_bar_handle_click (bar, &msg, &inev);
4501 break;
4502 }
4503
4504 case WM_WINDOWPOSCHANGED:
4505 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4506 if (f)
4507 {
4508 if (f->want_fullscreen & FULLSCREEN_WAIT)
4509 f->want_fullscreen &= ~(FULLSCREEN_WAIT|FULLSCREEN_BOTH);
4510 }
4511 check_visibility = 1;
4512 break;
4513
4514 case WM_ACTIVATE:
4515 case WM_ACTIVATEAPP:
4516 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4517 if (f)
4518 x_check_fullscreen (f);
4519 check_visibility = 1;
4520 break;
4521
4522 case WM_MOVE:
4523 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4524
4525 if (f && !f->async_iconified)
4526 {
4527 int x, y;
4528
4529 x_real_positions (f, &x, &y);
4530 f->left_pos = x;
4531 f->top_pos = y;
4532 }
4533
4534 check_visibility = 1;
4535 break;
4536
4537 case WM_SHOWWINDOW:
4538 /* wParam non-zero means Window is about to be shown, 0 means
4539 about to be hidden. */
4540 /* Redo the mouse-highlight after the tooltip has gone. */
4541 if (!msg.msg.wParam && msg.msg.hwnd == tip_window)
4542 {
4543 tip_window = NULL;
4544 redo_mouse_highlight ();
4545 }
4546
4547 /* If window has been obscured or exposed by another window
4548 being maximised or minimised/restored, then recheck
4549 visibility of all frames. Direct changes to our own
4550 windows get handled by WM_SIZE. */
4551 #if 0
4552 if (msg.msg.lParam != 0)
4553 check_visibility = 1;
4554 else
4555 {
4556 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4557 f->async_visible = msg.msg.wParam;
4558 }
4559 #endif
4560
4561 check_visibility = 1;
4562 break;
4563
4564 case WM_SIZE:
4565 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4566
4567 /* Inform lisp of whether frame has been iconified etc. */
4568 if (f)
4569 {
4570 switch (msg.msg.wParam)
4571 {
4572 case SIZE_MINIMIZED:
4573 f->async_visible = 0;
4574 f->async_iconified = 1;
4575
4576 inev.kind = ICONIFY_EVENT;
4577 XSETFRAME (inev.frame_or_window, f);
4578 break;
4579
4580 case SIZE_MAXIMIZED:
4581 case SIZE_RESTORED:
4582 f->async_visible = 1;
4583 f->async_iconified = 0;
4584
4585 /* wait_reading_process_output will notice this and update
4586 the frame's display structures. */
4587 SET_FRAME_GARBAGED (f);
4588
4589 if (f->iconified)
4590 {
4591 int x, y;
4592
4593 /* Reset top and left positions of the Window
4594 here since Windows sends a WM_MOVE message
4595 BEFORE telling us the Window is minimized
4596 when the Window is iconified, with 3000,3000
4597 as the co-ords. */
4598 x_real_positions (f, &x, &y);
4599 f->left_pos = x;
4600 f->top_pos = y;
4601
4602 inev.kind = DEICONIFY_EVENT;
4603 XSETFRAME (inev.frame_or_window, f);
4604 }
4605 else if (! NILP (Vframe_list)
4606 && ! NILP (XCDR (Vframe_list)))
4607 /* Force a redisplay sooner or later
4608 to update the frame titles
4609 in case this is the second frame. */
4610 record_asynch_buffer_change ();
4611 break;
4612 }
4613 }
4614
4615 if (f && !f->async_iconified && msg.msg.wParam != SIZE_MINIMIZED)
4616 {
4617 RECT rect;
4618 int rows;
4619 int columns;
4620 int width;
4621 int height;
4622
4623 GetClientRect (msg.msg.hwnd, &rect);
4624
4625 height = rect.bottom - rect.top;
4626 width = rect.right - rect.left;
4627
4628 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, height);
4629 columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, width);
4630
4631 /* TODO: Clip size to the screen dimensions. */
4632
4633 /* Even if the number of character rows and columns has
4634 not changed, the font size may have changed, so we need
4635 to check the pixel dimensions as well. */
4636
4637 if (columns != FRAME_COLS (f)
4638 || rows != FRAME_LINES (f)
4639 || width != FRAME_PIXEL_WIDTH (f)
4640 || height != FRAME_PIXEL_HEIGHT (f))
4641 {
4642 change_frame_size (f, rows, columns, 0, 1, 0);
4643 SET_FRAME_GARBAGED (f);
4644 cancel_mouse_face (f);
4645 FRAME_PIXEL_WIDTH (f) = width;
4646 FRAME_PIXEL_HEIGHT (f) = height;
4647 f->win_gravity = NorthWestGravity;
4648 }
4649 }
4650
4651 check_visibility = 1;
4652 break;
4653
4654 case WM_MOUSELEAVE:
4655 f = x_any_window_to_frame (dpyinfo, msg.msg.hwnd);
4656 if (f)
4657 {
4658 if (f == dpyinfo->mouse_face_mouse_frame)
4659 {
4660 /* If we move outside the frame, then we're
4661 certainly no longer on any text in the frame. */
4662 clear_mouse_face (dpyinfo);
4663 dpyinfo->mouse_face_mouse_frame = 0;
4664 }
4665
4666 /* Generate a nil HELP_EVENT to cancel a help-echo.
4667 Do it only if there's something to cancel.
4668 Otherwise, the startup message is cleared when
4669 the mouse leaves the frame. */
4670 if (any_help_event_p)
4671 do_help = -1;
4672 }
4673 break;
4674
4675 case WM_SETFOCUS:
4676 w32_detect_focus_change (dpyinfo, &msg, &inev);
4677
4678 dpyinfo->grabbed = 0;
4679 check_visibility = 1;
4680 break;
4681
4682 case WM_KILLFOCUS:
4683 f = x_top_window_to_frame (dpyinfo, msg.msg.hwnd);
4684
4685 if (f)
4686 {
4687 if (f == dpyinfo->w32_focus_event_frame)
4688 dpyinfo->w32_focus_event_frame = 0;
4689
4690 if (f == dpyinfo->w32_focus_frame)
4691 x_new_focus_frame (dpyinfo, 0);
4692
4693 if (f == dpyinfo->mouse_face_mouse_frame)
4694 {
4695 /* If we move outside the frame, then we're
4696 certainly no longer on any text in the frame. */
4697 clear_mouse_face (dpyinfo);
4698 dpyinfo->mouse_face_mouse_frame = 0;
4699 }
4700
4701 /* Generate a nil HELP_EVENT to cancel a help-echo.
4702 Do it only if there's something to cancel.
4703 Otherwise, the startup message is cleared when
4704 the mouse leaves the frame. */
4705 if (any_help_event_p)
4706 do_help = -1;
4707 }
4708
4709 dpyinfo->grabbed = 0;
4710 check_visibility = 1;
4711 break;
4712
4713 case WM_CLOSE:
4714 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4715
4716 if (f)
4717 {
4718 inev.kind = DELETE_WINDOW_EVENT;
4719 XSETFRAME (inev.frame_or_window, f);
4720 }
4721 break;
4722
4723 case WM_INITMENU:
4724 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4725
4726 if (f)
4727 {
4728 inev.kind = MENU_BAR_ACTIVATE_EVENT;
4729 XSETFRAME (inev.frame_or_window, f);
4730 }
4731 break;
4732
4733 case WM_COMMAND:
4734 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4735
4736 if (f)
4737 {
4738 extern void menubar_selection_callback
4739 (FRAME_PTR f, void * client_data);
4740 menubar_selection_callback (f, (void *)msg.msg.wParam);
4741 }
4742
4743 check_visibility = 1;
4744 break;
4745
4746 case WM_DISPLAYCHANGE:
4747 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4748
4749 if (f)
4750 {
4751 dpyinfo->n_cbits = msg.msg.wParam;
4752 DebPrint (("display change: %d %d\n",
4753 (short) LOWORD (msg.msg.lParam),
4754 (short) HIWORD (msg.msg.lParam)));
4755 }
4756
4757 check_visibility = 1;
4758 break;
4759
4760 default:
4761 /* Check for messages registered at runtime. */
4762 if (msg.msg.message == msh_mousewheel)
4763 {
4764 /* Forward MSH_MOUSEWHEEL as WM_MOUSEWHEEL. */
4765 msg.msg.message = WM_MOUSEWHEEL;
4766 prepend_msg (&msg);
4767 }
4768 break;
4769 }
4770
4771 if (inev.kind != NO_EVENT)
4772 {
4773 kbd_buffer_store_event_hold (&inev, hold_quit);
4774 count++;
4775 }
4776
4777 if (do_help
4778 && !(hold_quit && hold_quit->kind != NO_EVENT))
4779 {
4780 Lisp_Object frame;
4781
4782 if (f)
4783 XSETFRAME (frame, f);
4784 else
4785 frame = Qnil;
4786
4787 if (do_help > 0)
4788 {
4789 if (NILP (help_echo_string))
4790 {
4791 help_echo_object = help_echo_window = Qnil;
4792 help_echo_pos = -1;
4793 }
4794
4795 any_help_event_p = 1;
4796 gen_help_event (help_echo_string, frame, help_echo_window,
4797 help_echo_object, help_echo_pos);
4798 }
4799 else
4800 {
4801 help_echo_string = Qnil;
4802 gen_help_event (Qnil, frame, Qnil, Qnil, 0);
4803 }
4804 count++;
4805 }
4806 }
4807
4808 /* If the focus was just given to an autoraising frame,
4809 raise it now. */
4810 /* ??? This ought to be able to handle more than one such frame. */
4811 if (pending_autoraise_frame)
4812 {
4813 x_raise_frame (pending_autoraise_frame);
4814 pending_autoraise_frame = 0;
4815 }
4816
4817 /* Check which frames are still visisble, if we have enqueued any user
4818 events or been notified of events that may affect visibility. We
4819 do this here because there doesn't seem to be any direct
4820 notification from Windows that the visibility of a window has
4821 changed (at least, not in all cases). */
4822 if (count > 0 || check_visibility)
4823 {
4824 Lisp_Object tail, frame;
4825
4826 FOR_EACH_FRAME (tail, frame)
4827 {
4828 FRAME_PTR f = XFRAME (frame);
4829 /* The tooltip has been drawn already. Avoid the
4830 SET_FRAME_GARBAGED below. */
4831 if (EQ (frame, tip_frame))
4832 continue;
4833
4834 /* Check "visible" frames and mark each as obscured or not.
4835 Note that async_visible is nonzero for unobscured and
4836 obscured frames, but zero for hidden and iconified frames. */
4837 if (FRAME_W32_P (f) && f->async_visible)
4838 {
4839 RECT clipbox;
4840 HDC hdc;
4841
4842 enter_crit ();
4843 /* Query clipping rectangle for the entire window area
4844 (GetWindowDC), not just the client portion (GetDC).
4845 Otherwise, the scrollbars and menubar aren't counted as
4846 part of the visible area of the frame, and we may think
4847 the frame is obscured when really a scrollbar is still
4848 visible and gets WM_PAINT messages above. */
4849 hdc = GetWindowDC (FRAME_W32_WINDOW (f));
4850 GetClipBox (hdc, &clipbox);
4851 ReleaseDC (FRAME_W32_WINDOW (f), hdc);
4852 leave_crit ();
4853
4854 if (clipbox.right == clipbox.left
4855 || clipbox.bottom == clipbox.top)
4856 {
4857 /* Frame has become completely obscured so mark as
4858 such (we do this by setting async_visible to 2 so
4859 that FRAME_VISIBLE_P is still true, but redisplay
4860 will skip it). */
4861 f->async_visible = 2;
4862
4863 if (!FRAME_OBSCURED_P (f))
4864 {
4865 DebPrint (("frame %p (%s) obscured\n", f,
4866 SDATA (f->name)));
4867 }
4868 }
4869 else
4870 {
4871 /* Frame is not obscured, so mark it as such. */
4872 f->async_visible = 1;
4873
4874 if (FRAME_OBSCURED_P (f))
4875 {
4876 SET_FRAME_GARBAGED (f);
4877 DebPrint (("obscured frame %p (%s) found to be visible\n", f,
4878 SDATA (f->name)));
4879
4880 /* Force a redisplay sooner or later. */
4881 record_asynch_buffer_change ();
4882 }
4883 }
4884 }
4885 }
4886 }
4887
4888 UNBLOCK_INPUT;
4889 return count;
4890 }
4891
4892
4893 \f
4894 /***********************************************************************
4895 Text Cursor
4896 ***********************************************************************/
4897
4898 /* Set clipping for output in glyph row ROW. W is the window in which
4899 we operate. GC is the graphics context to set clipping in.
4900
4901 ROW may be a text row or, e.g., a mode line. Text rows must be
4902 clipped to the interior of the window dedicated to text display,
4903 mode lines must be clipped to the whole window. */
4904
4905 static void
4906 w32_clip_to_row (w, row, area, hdc)
4907 struct window *w;
4908 struct glyph_row *row;
4909 int area;
4910 HDC hdc;
4911 {
4912 struct frame *f = XFRAME (WINDOW_FRAME (w));
4913 RECT clip_rect;
4914 int window_x, window_y, window_width;
4915
4916 window_box (w, area, &window_x, &window_y, &window_width, 0);
4917
4918 clip_rect.left = window_x;
4919 clip_rect.top = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
4920 clip_rect.top = max (clip_rect.top, window_y);
4921 clip_rect.right = clip_rect.left + window_width;
4922 clip_rect.bottom = clip_rect.top + row->visible_height;
4923
4924 w32_set_clip_rectangle (hdc, &clip_rect);
4925 }
4926
4927
4928 /* Draw a hollow box cursor on window W in glyph row ROW. */
4929
4930 static void
4931 x_draw_hollow_cursor (w, row)
4932 struct window *w;
4933 struct glyph_row *row;
4934 {
4935 struct frame *f = XFRAME (WINDOW_FRAME (w));
4936 HDC hdc;
4937 RECT rect;
4938 int left, top, h;
4939 struct glyph *cursor_glyph;
4940 HBRUSH hb = CreateSolidBrush (f->output_data.w32->cursor_pixel);
4941
4942 /* Get the glyph the cursor is on. If we can't tell because
4943 the current matrix is invalid or such, give up. */
4944 cursor_glyph = get_phys_cursor_glyph (w);
4945 if (cursor_glyph == NULL)
4946 return;
4947
4948 /* Compute frame-relative coordinates for phys cursor. */
4949 get_phys_cursor_geometry (w, row, cursor_glyph, &left, &top, &h);
4950 rect.left = left;
4951 rect.top = top;
4952 rect.bottom = rect.top + h;
4953 rect.right = rect.left + w->phys_cursor_width;
4954
4955 hdc = get_frame_dc (f);
4956 /* Set clipping, draw the rectangle, and reset clipping again. */
4957 w32_clip_to_row (w, row, TEXT_AREA, hdc);
4958 FrameRect (hdc, &rect, hb);
4959 DeleteObject (hb);
4960 w32_set_clip_rectangle (hdc, NULL);
4961 release_frame_dc (f, hdc);
4962 }
4963
4964
4965 /* Draw a bar cursor on window W in glyph row ROW.
4966
4967 Implementation note: One would like to draw a bar cursor with an
4968 angle equal to the one given by the font property XA_ITALIC_ANGLE.
4969 Unfortunately, I didn't find a font yet that has this property set.
4970 --gerd. */
4971
4972 static void
4973 x_draw_bar_cursor (w, row, width, kind)
4974 struct window *w;
4975 struct glyph_row *row;
4976 int width;
4977 enum text_cursor_kinds kind;
4978 {
4979 struct frame *f = XFRAME (w->frame);
4980 struct glyph *cursor_glyph;
4981
4982 /* If cursor is out of bounds, don't draw garbage. This can happen
4983 in mini-buffer windows when switching between echo area glyphs
4984 and mini-buffer. */
4985 cursor_glyph = get_phys_cursor_glyph (w);
4986 if (cursor_glyph == NULL)
4987 return;
4988
4989 /* If on an image, draw like a normal cursor. That's usually better
4990 visible than drawing a bar, esp. if the image is large so that
4991 the bar might not be in the window. */
4992 if (cursor_glyph->type == IMAGE_GLYPH)
4993 {
4994 struct glyph_row *row;
4995 row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
4996 draw_phys_cursor_glyph (w, row, DRAW_CURSOR);
4997 }
4998 else
4999 {
5000 COLORREF cursor_color = f->output_data.w32->cursor_pixel;
5001 struct face *face = FACE_FROM_ID (f, cursor_glyph->face_id);
5002 int x;
5003 HDC hdc;
5004
5005 /* If the glyph's background equals the color we normally draw
5006 the bar cursor in, the bar cursor in its normal color is
5007 invisible. Use the glyph's foreground color instead in this
5008 case, on the assumption that the glyph's colors are chosen so
5009 that the glyph is legible. */
5010 if (face->background == cursor_color)
5011 cursor_color = face->foreground;
5012
5013 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
5014
5015 hdc = get_frame_dc (f);
5016 w32_clip_to_row (w, row, TEXT_AREA, hdc);
5017
5018 if (kind == BAR_CURSOR)
5019 {
5020 if (width < 0)
5021 width = FRAME_CURSOR_WIDTH (f);
5022 width = min (cursor_glyph->pixel_width, width);
5023
5024 w->phys_cursor_width = width;
5025
5026 w32_fill_area (f, hdc, cursor_color, x,
5027 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
5028 width, row->height);
5029 }
5030 else
5031 {
5032 int dummy_x, dummy_y, dummy_h;
5033
5034 if (width < 0)
5035 width = row->height;
5036
5037 width = min (row->height, width);
5038
5039 get_phys_cursor_geometry (w, row, cursor_glyph, &dummy_x,
5040 &dummy_y, &dummy_h);
5041 w32_fill_area (f, hdc, cursor_color, x,
5042 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y +
5043 row->height - width),
5044 w->phys_cursor_width, width);
5045 }
5046
5047 w32_set_clip_rectangle (hdc, NULL);
5048 release_frame_dc (f, hdc);
5049 }
5050 }
5051
5052
5053 /* RIF: Define cursor CURSOR on frame F. */
5054
5055 static void
5056 w32_define_frame_cursor (f, cursor)
5057 struct frame *f;
5058 Cursor cursor;
5059 {
5060 w32_define_cursor (FRAME_W32_WINDOW (f), cursor);
5061 }
5062
5063
5064 /* RIF: Clear area on frame F. */
5065
5066 static void
5067 w32_clear_frame_area (f, x, y, width, height)
5068 struct frame *f;
5069 int x, y, width, height;
5070 {
5071 HDC hdc;
5072
5073 hdc = get_frame_dc (f);
5074 w32_clear_area (f, hdc, x, y, width, height);
5075 release_frame_dc (f, hdc);
5076 }
5077
5078 /* RIF: Draw or clear cursor on window W. */
5079
5080 static void
5081 w32_draw_window_cursor (w, glyph_row, x, y, cursor_type, cursor_width, on_p, active_p)
5082 struct window *w;
5083 struct glyph_row *glyph_row;
5084 int x, y;
5085 int cursor_type, cursor_width;
5086 int on_p, active_p;
5087 {
5088 if (on_p)
5089 {
5090 /* If the user wants to use the system caret, make sure our own
5091 cursor remains invisible. */
5092 if (w32_use_visible_system_caret)
5093 {
5094 /* Call to erase_phys_cursor here seems to use the
5095 wrong values of w->phys_cursor, as they have been
5096 overwritten before this function was called. */
5097 if (w->phys_cursor_type != NO_CURSOR)
5098 erase_phys_cursor (w);
5099
5100 cursor_type = w->phys_cursor_type = NO_CURSOR;
5101 w->phys_cursor_width = -1;
5102 }
5103 else
5104 {
5105 w->phys_cursor_type = cursor_type;
5106 }
5107
5108 w->phys_cursor_on_p = 1;
5109
5110 /* If this is the active cursor, we need to track it with the
5111 system caret, so third party software like screen magnifiers
5112 and speech synthesizers can follow the cursor. */
5113 if (active_p)
5114 {
5115 struct frame *f = XFRAME (WINDOW_FRAME (w));
5116 HWND hwnd = FRAME_W32_WINDOW (f);
5117
5118 w32_system_caret_x
5119 = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
5120 w32_system_caret_y
5121 = (WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y)
5122 + glyph_row->ascent - w->phys_cursor_ascent);
5123
5124 PostMessage (hwnd, WM_IME_STARTCOMPOSITION, 0, 0);
5125
5126 /* If the size of the active cursor changed, destroy the old
5127 system caret. */
5128 if (w32_system_caret_hwnd
5129 && (w32_system_caret_height != w->phys_cursor_height))
5130 PostMessage (hwnd, WM_EMACS_DESTROY_CARET, 0, 0);
5131
5132 w32_system_caret_height = w->phys_cursor_height;
5133
5134 /* Move the system caret. */
5135 PostMessage (hwnd, WM_EMACS_TRACK_CARET, 0, 0);
5136 }
5137
5138 if (glyph_row->exact_window_width_line_p
5139 && w->phys_cursor.hpos >= glyph_row->used[TEXT_AREA])
5140 {
5141 glyph_row->cursor_in_fringe_p = 1;
5142 draw_fringe_bitmap (w, glyph_row, 0);
5143 return;
5144 }
5145
5146 switch (cursor_type)
5147 {
5148 case HOLLOW_BOX_CURSOR:
5149 x_draw_hollow_cursor (w, glyph_row);
5150 break;
5151
5152 case FILLED_BOX_CURSOR:
5153 draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
5154 break;
5155
5156 case BAR_CURSOR:
5157 x_draw_bar_cursor (w, glyph_row, cursor_width, BAR_CURSOR);
5158 break;
5159
5160 case HBAR_CURSOR:
5161 x_draw_bar_cursor (w, glyph_row, cursor_width, HBAR_CURSOR);
5162 break;
5163
5164 case NO_CURSOR:
5165 w->phys_cursor_width = 0;
5166 break;
5167
5168 default:
5169 abort ();
5170 }
5171 }
5172 }
5173
5174
5175 \f
5176 /* Icons. */
5177
5178 int
5179 x_bitmap_icon (f, icon)
5180 struct frame *f;
5181 Lisp_Object icon;
5182 {
5183 HANDLE main_icon;
5184 HANDLE small_icon = NULL;
5185
5186 if (FRAME_W32_WINDOW (f) == 0)
5187 return 1;
5188
5189 if (NILP (icon))
5190 main_icon = LoadIcon (hinst, EMACS_CLASS);
5191 else if (STRINGP (icon))
5192 {
5193 /* Load the main icon from the named file. */
5194 main_icon = LoadImage (NULL, (LPCTSTR) SDATA (icon), IMAGE_ICON, 0, 0,
5195 LR_DEFAULTSIZE | LR_LOADFROMFILE);
5196 /* Try to load a small icon to go with it. */
5197 small_icon = LoadImage (NULL, (LPCSTR) SDATA (icon), IMAGE_ICON,
5198 GetSystemMetrics (SM_CXSMICON),
5199 GetSystemMetrics (SM_CYSMICON),
5200 LR_LOADFROMFILE);
5201 }
5202 else if (SYMBOLP (icon))
5203 {
5204 LPCTSTR name;
5205
5206 if (EQ (icon, intern ("application")))
5207 name = (LPCTSTR) IDI_APPLICATION;
5208 else if (EQ (icon, intern ("hand")))
5209 name = (LPCTSTR) IDI_HAND;
5210 else if (EQ (icon, intern ("question")))
5211 name = (LPCTSTR) IDI_QUESTION;
5212 else if (EQ (icon, intern ("exclamation")))
5213 name = (LPCTSTR) IDI_EXCLAMATION;
5214 else if (EQ (icon, intern ("asterisk")))
5215 name = (LPCTSTR) IDI_ASTERISK;
5216 else if (EQ (icon, intern ("winlogo")))
5217 name = (LPCTSTR) IDI_WINLOGO;
5218 else
5219 return 1;
5220
5221 main_icon = LoadIcon (NULL, name);
5222 }
5223 else
5224 return 1;
5225
5226 if (main_icon == NULL)
5227 return 1;
5228
5229 PostMessage (FRAME_W32_WINDOW (f), WM_SETICON, (WPARAM) ICON_BIG,
5230 (LPARAM) main_icon);
5231
5232 /* If there is a small icon that goes with it, set that too. */
5233 if (small_icon)
5234 PostMessage (FRAME_W32_WINDOW (f), WM_SETICON, (WPARAM) ICON_SMALL,
5235 (LPARAM) small_icon);
5236
5237 return 0;
5238 }
5239
5240 \f
5241 /************************************************************************
5242 Handling X errors
5243 ************************************************************************/
5244
5245 /* Display Error Handling functions not used on W32. Listing them here
5246 helps diff stay in step when comparing w32term.c with xterm.c.
5247
5248 x_error_catcher (display, error)
5249 x_catch_errors (dpy)
5250 x_catch_errors_unwind (old_val)
5251 x_check_errors (dpy, format)
5252 x_fully_uncatch_errors ()
5253 x_catching_errors ()
5254 x_had_errors_p (dpy)
5255 x_clear_errors (dpy)
5256 x_uncatch_errors (dpy, count)
5257 x_trace_wire ()
5258 x_connection_signal (signalnum)
5259 x_connection_closed (dpy, error_message)
5260 x_error_quitter (display, error)
5261 x_error_handler (display, error)
5262 x_io_error_quitter (display)
5263
5264 */
5265
5266 \f
5267 /* Changing the font of the frame. */
5268
5269 Lisp_Object
5270 x_new_font (f, font_object, fontset)
5271 struct frame *f;
5272 Lisp_Object font_object;
5273 int fontset;
5274 {
5275 struct font *font = XFONT_OBJECT (font_object);
5276
5277 if (fontset < 0)
5278 fontset = fontset_from_font (font_object);
5279 FRAME_FONTSET (f) = fontset;
5280 if (FRAME_FONT (f) == font)
5281 /* This font is already set in frame F. There's nothing more to
5282 do. */
5283 return font_object;
5284
5285 FRAME_FONT (f) = font;
5286 FRAME_BASELINE_OFFSET (f) = font->baseline_offset;
5287 FRAME_COLUMN_WIDTH (f) = font->average_width;
5288 FRAME_SPACE_WIDTH (f) = font->space_width;
5289 FRAME_LINE_HEIGHT (f) = font->height;
5290
5291 compute_fringe_widths (f, 1);
5292
5293 /* Compute the scroll bar width in character columns. */
5294 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0)
5295 {
5296 int wid = FRAME_COLUMN_WIDTH (f);
5297 FRAME_CONFIG_SCROLL_BAR_COLS (f)
5298 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + wid - 1) / wid;
5299 }
5300 else
5301 {
5302 int wid = FRAME_COLUMN_WIDTH (f);
5303 FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid;
5304 }
5305
5306 /* Now make the frame display the given font. */
5307 if (FRAME_X_WINDOW (f) != 0)
5308 {
5309 /* Don't change the size of a tip frame; there's no point in
5310 doing it because it's done in Fx_show_tip, and it leads to
5311 problems because the tip frame has no widget. */
5312 if (NILP (tip_frame) || XFRAME (tip_frame) != f)
5313 x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
5314 }
5315
5316 /* X version sets font of input methods here also. */
5317
5318 return font_object;
5319 }
5320
5321 \f
5322 /***********************************************************************
5323 TODO: W32 Input Methods
5324 ***********************************************************************/
5325 /* Listing missing functions from xterm.c helps diff stay in step.
5326
5327 xim_destroy_callback (xim, client_data, call_data)
5328 xim_open_dpy (dpyinfo, resource_name)
5329 struct xim_inst_t
5330 xim_instantiate_callback (display, client_data, call_data)
5331 xim_initialize (dpyinfo, resource_name)
5332 xim_close_dpy (dpyinfo)
5333
5334 */
5335
5336 \f
5337 /* Calculate the absolute position in frame F
5338 from its current recorded position values and gravity. */
5339
5340 void
5341 x_calc_absolute_position (f)
5342 struct frame *f;
5343 {
5344 int flags = f->size_hint_flags;
5345
5346 /* The sum of the widths of the frame's left and right borders, and
5347 the sum of the heights of the frame's top and bottom borders (in
5348 pixels) drawn by Windows. */
5349 unsigned int left_right_borders_width, top_bottom_borders_height;
5350
5351 /* Try to get the actual values of these two variables. We compute
5352 the border width (height) by subtracting the width (height) of
5353 the frame's client area from the width (height) of the frame's
5354 entire window. */
5355 WINDOWPLACEMENT wp = { 0 };
5356 RECT client_rect = { 0 };
5357
5358 if (GetWindowPlacement (FRAME_W32_WINDOW (f), &wp)
5359 && GetClientRect (FRAME_W32_WINDOW (f), &client_rect))
5360 {
5361 left_right_borders_width =
5362 (wp.rcNormalPosition.right - wp.rcNormalPosition.left) -
5363 (client_rect.right - client_rect.left);
5364
5365 top_bottom_borders_height =
5366 (wp.rcNormalPosition.bottom - wp.rcNormalPosition.top) -
5367 (client_rect.bottom - client_rect.top);
5368 }
5369 else
5370 {
5371 /* Use sensible default values. */
5372 left_right_borders_width = 8;
5373 top_bottom_borders_height = 32;
5374 }
5375
5376 /* Treat negative positions as relative to the rightmost bottommost
5377 position that fits on the screen. */
5378 if (flags & XNegative)
5379 f->left_pos = (x_display_pixel_width (FRAME_W32_DISPLAY_INFO (f))
5380 - FRAME_PIXEL_WIDTH (f)
5381 + f->left_pos
5382 - (left_right_borders_width - 1));
5383
5384 if (flags & YNegative)
5385 f->top_pos = (x_display_pixel_height (FRAME_W32_DISPLAY_INFO (f))
5386 - FRAME_PIXEL_HEIGHT (f)
5387 + f->top_pos
5388 - (top_bottom_borders_height - 1));
5389
5390 /* The left_pos and top_pos are now relative to the top and left
5391 screen edges, so the flags should correspond. */
5392 f->size_hint_flags &= ~ (XNegative | YNegative);
5393 }
5394
5395 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
5396 to really change the position, and 0 when calling from
5397 x_make_frame_visible (in that case, XOFF and YOFF are the current
5398 position values). It is -1 when calling from x_set_frame_parameters,
5399 which means, do adjust for borders but don't change the gravity. */
5400
5401 void
5402 x_set_offset (f, xoff, yoff, change_gravity)
5403 struct frame *f;
5404 register int xoff, yoff;
5405 int change_gravity;
5406 {
5407 int modified_top, modified_left;
5408
5409 if (change_gravity > 0)
5410 {
5411 f->top_pos = yoff;
5412 f->left_pos = xoff;
5413 f->size_hint_flags &= ~ (XNegative | YNegative);
5414 if (xoff < 0)
5415 f->size_hint_flags |= XNegative;
5416 if (yoff < 0)
5417 f->size_hint_flags |= YNegative;
5418 f->win_gravity = NorthWestGravity;
5419 }
5420 x_calc_absolute_position (f);
5421
5422 BLOCK_INPUT;
5423 x_wm_set_size_hint (f, (long) 0, 0);
5424
5425 modified_left = f->left_pos;
5426 modified_top = f->top_pos;
5427
5428 my_set_window_pos (FRAME_W32_WINDOW (f),
5429 NULL,
5430 modified_left, modified_top,
5431 0, 0,
5432 SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
5433 UNBLOCK_INPUT;
5434 }
5435
5436
5437 /* Check if we need to resize the frame due to a fullscreen request.
5438 If so needed, resize the frame. */
5439 static void
5440 x_check_fullscreen (f)
5441 struct frame *f;
5442 {
5443 if (f->want_fullscreen & FULLSCREEN_BOTH)
5444 {
5445 int width, height, ign;
5446
5447 x_real_positions (f, &f->left_pos, &f->top_pos);
5448
5449 x_fullscreen_adjust (f, &width, &height, &ign, &ign);
5450
5451 /* We do not need to move the window, it shall be taken care of
5452 when setting WM manager hints. */
5453 if (FRAME_COLS (f) != width || FRAME_LINES (f) != height)
5454 {
5455 change_frame_size (f, height, width, 0, 1, 0);
5456 SET_FRAME_GARBAGED (f);
5457 cancel_mouse_face (f);
5458
5459 /* Wait for the change of frame size to occur */
5460 f->want_fullscreen |= FULLSCREEN_WAIT;
5461 }
5462 }
5463 }
5464
5465 /* Call this to change the size of frame F's x-window.
5466 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
5467 for this size change and subsequent size changes.
5468 Otherwise we leave the window gravity unchanged. */
5469
5470 void
5471 x_set_window_size (f, change_gravity, cols, rows)
5472 struct frame *f;
5473 int change_gravity;
5474 int cols, rows;
5475 {
5476 int pixelwidth, pixelheight;
5477
5478 BLOCK_INPUT;
5479
5480 check_frame_size (f, &rows, &cols);
5481 f->scroll_bar_actual_width
5482 = FRAME_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f);
5483
5484 compute_fringe_widths (f, 0);
5485
5486 pixelwidth = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, cols);
5487 pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
5488
5489 f->win_gravity = NorthWestGravity;
5490 x_wm_set_size_hint (f, (long) 0, 0);
5491
5492 {
5493 RECT rect;
5494
5495 rect.left = rect.top = 0;
5496 rect.right = pixelwidth;
5497 rect.bottom = pixelheight;
5498
5499 AdjustWindowRect(&rect, f->output_data.w32->dwStyle,
5500 FRAME_EXTERNAL_MENU_BAR (f));
5501
5502 my_set_window_pos (FRAME_W32_WINDOW (f),
5503 NULL,
5504 0, 0,
5505 rect.right - rect.left,
5506 rect.bottom - rect.top,
5507 SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE);
5508 }
5509
5510 #if 0
5511 /* The following mirrors what is done in xterm.c. It appears to be
5512 for informing lisp of the new size immediately, while the actual
5513 resize will happen asynchronously. But on Windows, the menu bar
5514 automatically wraps when the frame is too narrow to contain it,
5515 and that causes any calculations made here to come out wrong. The
5516 end is some nasty buggy behavior, including the potential loss
5517 of the minibuffer.
5518
5519 Disabling this code is either not sufficient to fix the problems
5520 completely, or it causes fresh problems, but at least it removes
5521 the most problematic symptom of the minibuffer becoming unusable.
5522
5523 -----------------------------------------------------------------
5524
5525 Now, strictly speaking, we can't be sure that this is accurate,
5526 but the window manager will get around to dealing with the size
5527 change request eventually, and we'll hear how it went when the
5528 ConfigureNotify event gets here.
5529
5530 We could just not bother storing any of this information here,
5531 and let the ConfigureNotify event set everything up, but that
5532 might be kind of confusing to the Lisp code, since size changes
5533 wouldn't be reported in the frame parameters until some random
5534 point in the future when the ConfigureNotify event arrives.
5535
5536 We pass 1 for DELAY since we can't run Lisp code inside of
5537 a BLOCK_INPUT. */
5538 change_frame_size (f, rows, cols, 0, 1, 0);
5539 FRAME_PIXEL_WIDTH (f) = pixelwidth;
5540 FRAME_PIXEL_HEIGHT (f) = pixelheight;
5541
5542 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
5543 receive in the ConfigureNotify event; if we get what we asked
5544 for, then the event won't cause the screen to become garbaged, so
5545 we have to make sure to do it here. */
5546 SET_FRAME_GARBAGED (f);
5547
5548 /* If cursor was outside the new size, mark it as off. */
5549 mark_window_cursors_off (XWINDOW (f->root_window));
5550
5551 /* Clear out any recollection of where the mouse highlighting was,
5552 since it might be in a place that's outside the new frame size.
5553 Actually checking whether it is outside is a pain in the neck,
5554 so don't try--just let the highlighting be done afresh with new size. */
5555 cancel_mouse_face (f);
5556 #endif
5557
5558 UNBLOCK_INPUT;
5559 }
5560 \f
5561 /* Mouse warping. */
5562
5563 void x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y);
5564
5565 void
5566 x_set_mouse_position (f, x, y)
5567 struct frame *f;
5568 int x, y;
5569 {
5570 int pix_x, pix_y;
5571
5572 pix_x = FRAME_COL_TO_PIXEL_X (f, x) + FRAME_COLUMN_WIDTH (f) / 2;
5573 pix_y = FRAME_LINE_TO_PIXEL_Y (f, y) + FRAME_LINE_HEIGHT (f) / 2;
5574
5575 if (pix_x < 0) pix_x = 0;
5576 if (pix_x > FRAME_PIXEL_WIDTH (f)) pix_x = FRAME_PIXEL_WIDTH (f);
5577
5578 if (pix_y < 0) pix_y = 0;
5579 if (pix_y > FRAME_PIXEL_HEIGHT (f)) pix_y = FRAME_PIXEL_HEIGHT (f);
5580
5581 x_set_mouse_pixel_position (f, pix_x, pix_y);
5582 }
5583
5584 void
5585 x_set_mouse_pixel_position (f, pix_x, pix_y)
5586 struct frame *f;
5587 int pix_x, pix_y;
5588 {
5589 RECT rect;
5590 POINT pt;
5591
5592 BLOCK_INPUT;
5593
5594 GetClientRect (FRAME_W32_WINDOW (f), &rect);
5595 pt.x = rect.left + pix_x;
5596 pt.y = rect.top + pix_y;
5597 ClientToScreen (FRAME_W32_WINDOW (f), &pt);
5598
5599 SetCursorPos (pt.x, pt.y);
5600
5601 UNBLOCK_INPUT;
5602 }
5603
5604 \f
5605 /* focus shifting, raising and lowering. */
5606
5607 void
5608 x_focus_on_frame (f)
5609 struct frame *f;
5610 {
5611 struct w32_display_info *dpyinfo = &one_w32_display_info;
5612
5613 /* Give input focus to frame. */
5614 BLOCK_INPUT;
5615 #if 0
5616 /* Try not to change its Z-order if possible. */
5617 if (x_window_to_frame (dpyinfo, GetForegroundWindow ()))
5618 my_set_focus (f, FRAME_W32_WINDOW (f));
5619 else
5620 #endif
5621 my_set_foreground_window (FRAME_W32_WINDOW (f));
5622 UNBLOCK_INPUT;
5623 }
5624
5625 void
5626 x_unfocus_frame (f)
5627 struct frame *f;
5628 {
5629 }
5630
5631 /* Raise frame F. */
5632 void
5633 x_raise_frame (f)
5634 struct frame *f;
5635 {
5636 BLOCK_INPUT;
5637
5638 /* Strictly speaking, raise-frame should only change the frame's Z
5639 order, leaving input focus unchanged. This is reasonable behavior
5640 on X where the usual policy is point-to-focus. However, this
5641 behavior would be very odd on Windows where the usual policy is
5642 click-to-focus.
5643
5644 On X, if the mouse happens to be over the raised frame, it gets
5645 input focus anyway (so the window with focus will never be
5646 completely obscured) - if not, then just moving the mouse over it
5647 is sufficient to give it focus. On Windows, the user must actually
5648 click on the frame (preferrably the title bar so as not to move
5649 point), which is more awkward. Also, no other Windows program
5650 raises a window to the top but leaves another window (possibly now
5651 completely obscured) with input focus.
5652
5653 Because there is a system setting on Windows that allows the user
5654 to choose the point to focus policy, we make the strict semantics
5655 optional, but by default we grab focus when raising. */
5656
5657 if (NILP (Vw32_grab_focus_on_raise))
5658 {
5659 /* The obvious call to my_set_window_pos doesn't work if Emacs is
5660 not already the foreground application: the frame is raised
5661 above all other frames belonging to us, but not above the
5662 current top window. To achieve that, we have to resort to this
5663 more cumbersome method. */
5664
5665 HDWP handle = BeginDeferWindowPos (2);
5666 if (handle)
5667 {
5668 DeferWindowPos (handle,
5669 FRAME_W32_WINDOW (f),
5670 HWND_TOP,
5671 0, 0, 0, 0,
5672 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
5673
5674 DeferWindowPos (handle,
5675 GetForegroundWindow (),
5676 FRAME_W32_WINDOW (f),
5677 0, 0, 0, 0,
5678 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
5679
5680 EndDeferWindowPos (handle);
5681 }
5682 }
5683 else
5684 {
5685 my_set_foreground_window (FRAME_W32_WINDOW (f));
5686 }
5687
5688 UNBLOCK_INPUT;
5689 }
5690
5691 /* Lower frame F. */
5692 void
5693 x_lower_frame (f)
5694 struct frame *f;
5695 {
5696 BLOCK_INPUT;
5697 my_set_window_pos (FRAME_W32_WINDOW (f),
5698 HWND_BOTTOM,
5699 0, 0, 0, 0,
5700 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
5701 UNBLOCK_INPUT;
5702 }
5703
5704 static void
5705 w32_frame_raise_lower (f, raise_flag)
5706 FRAME_PTR f;
5707 int raise_flag;
5708 {
5709 if (! FRAME_W32_P (f))
5710 return;
5711
5712 if (raise_flag)
5713 x_raise_frame (f);
5714 else
5715 x_lower_frame (f);
5716 }
5717 \f
5718 /* Change of visibility. */
5719
5720 /* This tries to wait until the frame is really visible.
5721 However, if the window manager asks the user where to position
5722 the frame, this will return before the user finishes doing that.
5723 The frame will not actually be visible at that time,
5724 but it will become visible later when the window manager
5725 finishes with it. */
5726
5727 void
5728 x_make_frame_visible (f)
5729 struct frame *f;
5730 {
5731 Lisp_Object type;
5732
5733 BLOCK_INPUT;
5734
5735 type = x_icon_type (f);
5736 if (!NILP (type))
5737 x_bitmap_icon (f, type);
5738
5739 if (! FRAME_VISIBLE_P (f))
5740 {
5741 /* We test FRAME_GARBAGED_P here to make sure we don't
5742 call x_set_offset a second time
5743 if we get to x_make_frame_visible a second time
5744 before the window gets really visible. */
5745 if (! FRAME_ICONIFIED_P (f)
5746 && ! f->output_data.w32->asked_for_visible)
5747 {
5748 RECT workarea_rect;
5749 RECT window_rect;
5750
5751 /* Adjust vertical window position in order to avoid being
5752 covered by a task bar placed at the bottom of the desktop. */
5753 SystemParametersInfo(SPI_GETWORKAREA, 0, &workarea_rect, 0);
5754 GetWindowRect(FRAME_W32_WINDOW(f), &window_rect);
5755 if (window_rect.bottom > workarea_rect.bottom
5756 && window_rect.top > workarea_rect.top)
5757 f->top_pos = max (window_rect.top
5758 - window_rect.bottom + workarea_rect.bottom,
5759 workarea_rect.top);
5760
5761 x_set_offset (f, f->left_pos, f->top_pos, 0);
5762 }
5763
5764 f->output_data.w32->asked_for_visible = 1;
5765
5766 /* The first of these seems to give more expected behavior, but
5767 was added as a commented out line in Sept 1997, with the
5768 second version remaining uncommented. There may have been
5769 some problem with it that led to it not being enabled,
5770 so the old version remains commented out below in case we
5771 decide we need to go back to it [23.0.60 2008-06-09]. */
5772 my_show_window (f, FRAME_W32_WINDOW (f),
5773 f->async_iconified ? SW_RESTORE : SW_SHOW);
5774 /* my_show_window (f, FRAME_W32_WINDOW (f), SW_SHOWNORMAL); */
5775 }
5776
5777 /* Synchronize to ensure Emacs knows the frame is visible
5778 before we do anything else. We do this loop with input not blocked
5779 so that incoming events are handled. */
5780 {
5781 Lisp_Object frame;
5782 int count;
5783
5784 /* This must come after we set COUNT. */
5785 UNBLOCK_INPUT;
5786
5787 XSETFRAME (frame, f);
5788
5789 /* Wait until the frame is visible. Process X events until a
5790 MapNotify event has been seen, or until we think we won't get a
5791 MapNotify at all.. */
5792 for (count = input_signal_count + 10;
5793 input_signal_count < count && !FRAME_VISIBLE_P (f);)
5794 {
5795 /* Force processing of queued events. */
5796 /* TODO: x_sync equivalent? */
5797
5798 /* Machines that do polling rather than SIGIO have been observed
5799 to go into a busy-wait here. So we'll fake an alarm signal
5800 to let the handler know that there's something to be read.
5801 We used to raise a real alarm, but it seems that the handler
5802 isn't always enabled here. This is probably a bug. */
5803 if (input_polling_used ())
5804 {
5805 /* It could be confusing if a real alarm arrives while processing
5806 the fake one. Turn it off and let the handler reset it. */
5807 int old_poll_suppress_count = poll_suppress_count;
5808 poll_suppress_count = 1;
5809 poll_for_input_1 ();
5810 poll_suppress_count = old_poll_suppress_count;
5811 }
5812 }
5813 FRAME_SAMPLE_VISIBILITY (f);
5814 }
5815 }
5816
5817 /* Change from mapped state to withdrawn state. */
5818
5819 /* Make the frame visible (mapped and not iconified). */
5820
5821 x_make_frame_invisible (f)
5822 struct frame *f;
5823 {
5824 /* Don't keep the highlight on an invisible frame. */
5825 if (FRAME_W32_DISPLAY_INFO (f)->x_highlight_frame == f)
5826 FRAME_W32_DISPLAY_INFO (f)->x_highlight_frame = 0;
5827
5828 BLOCK_INPUT;
5829
5830 my_show_window (f, FRAME_W32_WINDOW (f), SW_HIDE);
5831
5832 /* We can't distinguish this from iconification
5833 just by the event that we get from the server.
5834 So we can't win using the usual strategy of letting
5835 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
5836 and synchronize with the server to make sure we agree. */
5837 f->visible = 0;
5838 FRAME_ICONIFIED_P (f) = 0;
5839 f->async_visible = 0;
5840 f->async_iconified = 0;
5841
5842 UNBLOCK_INPUT;
5843 }
5844
5845 /* Change window state from mapped to iconified. */
5846
5847 void
5848 x_iconify_frame (f)
5849 struct frame *f;
5850 {
5851 Lisp_Object type;
5852
5853 /* Don't keep the highlight on an invisible frame. */
5854 if (FRAME_W32_DISPLAY_INFO (f)->x_highlight_frame == f)
5855 FRAME_W32_DISPLAY_INFO (f)->x_highlight_frame = 0;
5856
5857 if (f->async_iconified)
5858 return;
5859
5860 BLOCK_INPUT;
5861
5862 type = x_icon_type (f);
5863 if (!NILP (type))
5864 x_bitmap_icon (f, type);
5865
5866 /* Simulate the user minimizing the frame. */
5867 SendMessage (FRAME_W32_WINDOW (f), WM_SYSCOMMAND, SC_MINIMIZE, 0);
5868
5869 UNBLOCK_INPUT;
5870 }
5871
5872 \f
5873 /* Free X resources of frame F. */
5874
5875 void
5876 x_free_frame_resources (f)
5877 struct frame *f;
5878 {
5879 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
5880
5881 BLOCK_INPUT;
5882
5883 /* We must free faces before destroying windows because some
5884 font-driver (e.g. xft) access a window while finishing a
5885 face. */
5886 if (FRAME_FACE_CACHE (f))
5887 free_frame_faces (f);
5888
5889 if (FRAME_W32_WINDOW (f))
5890 my_destroy_window (f, FRAME_W32_WINDOW (f));
5891
5892 free_frame_menubar (f);
5893
5894 unload_color (f, FRAME_FOREGROUND_PIXEL (f));
5895 unload_color (f, FRAME_BACKGROUND_PIXEL (f));
5896 unload_color (f, f->output_data.w32->cursor_pixel);
5897 unload_color (f, f->output_data.w32->cursor_foreground_pixel);
5898 unload_color (f, f->output_data.w32->border_pixel);
5899 unload_color (f, f->output_data.w32->mouse_pixel);
5900 if (f->output_data.w32->white_relief.allocated_p)
5901 unload_color (f, f->output_data.w32->white_relief.pixel);
5902 if (f->output_data.w32->black_relief.allocated_p)
5903 unload_color (f, f->output_data.w32->black_relief.pixel);
5904
5905 if (FRAME_FACE_CACHE (f))
5906 free_frame_faces (f);
5907
5908 xfree (f->output_data.w32);
5909 f->output_data.w32 = NULL;
5910
5911 if (f == dpyinfo->w32_focus_frame)
5912 dpyinfo->w32_focus_frame = 0;
5913 if (f == dpyinfo->w32_focus_event_frame)
5914 dpyinfo->w32_focus_event_frame = 0;
5915 if (f == dpyinfo->x_highlight_frame)
5916 dpyinfo->x_highlight_frame = 0;
5917
5918 if (f == dpyinfo->mouse_face_mouse_frame)
5919 {
5920 dpyinfo->mouse_face_beg_row
5921 = dpyinfo->mouse_face_beg_col = -1;
5922 dpyinfo->mouse_face_end_row
5923 = dpyinfo->mouse_face_end_col = -1;
5924 dpyinfo->mouse_face_window = Qnil;
5925 dpyinfo->mouse_face_deferred_gc = 0;
5926 dpyinfo->mouse_face_mouse_frame = 0;
5927 }
5928
5929 UNBLOCK_INPUT;
5930 }
5931
5932
5933 /* Destroy the window of frame F. */
5934 void
5935 x_destroy_window (f)
5936 struct frame *f;
5937 {
5938 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
5939
5940 x_free_frame_resources (f);
5941 dpyinfo->reference_count--;
5942 }
5943
5944 \f
5945 /* Setting window manager hints. */
5946
5947 /* Set the normal size hints for the window manager, for frame F.
5948 FLAGS is the flags word to use--or 0 meaning preserve the flags
5949 that the window now has.
5950 If USER_POSITION is nonzero, we set the USPosition
5951 flag (this is useful when FLAGS is 0). */
5952 void
5953 x_wm_set_size_hint (f, flags, user_position)
5954 struct frame *f;
5955 long flags;
5956 int user_position;
5957 {
5958 Window window = FRAME_W32_WINDOW (f);
5959
5960 enter_crit ();
5961
5962 SetWindowLong (window, WND_FONTWIDTH_INDEX, FRAME_COLUMN_WIDTH (f));
5963 SetWindowLong (window, WND_LINEHEIGHT_INDEX, FRAME_LINE_HEIGHT (f));
5964 SetWindowLong (window, WND_BORDER_INDEX, FRAME_INTERNAL_BORDER_WIDTH (f));
5965 SetWindowLong (window, WND_SCROLLBAR_INDEX, f->scroll_bar_actual_width);
5966
5967 leave_crit ();
5968 }
5969
5970 /* Window manager things */
5971 void
5972 x_wm_set_icon_position (f, icon_x, icon_y)
5973 struct frame *f;
5974 int icon_x, icon_y;
5975 {
5976 #if 0
5977 Window window = FRAME_W32_WINDOW (f);
5978
5979 f->display.x->wm_hints.flags |= IconPositionHint;
5980 f->display.x->wm_hints.icon_x = icon_x;
5981 f->display.x->wm_hints.icon_y = icon_y;
5982
5983 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->display.x->wm_hints);
5984 #endif
5985 }
5986
5987 \f
5988 /***********************************************************************
5989 Initialization
5990 ***********************************************************************/
5991
5992 static int w32_initialized = 0;
5993
5994 void
5995 w32_initialize_display_info (display_name)
5996 Lisp_Object display_name;
5997 {
5998 struct w32_display_info *dpyinfo = &one_w32_display_info;
5999
6000 bzero (dpyinfo, sizeof (*dpyinfo));
6001
6002 /* Put it on w32_display_name_list. */
6003 w32_display_name_list = Fcons (Fcons (display_name, Qnil),
6004 w32_display_name_list);
6005 dpyinfo->name_list_element = XCAR (w32_display_name_list);
6006
6007 dpyinfo->w32_id_name
6008 = (char *) xmalloc (SCHARS (Vinvocation_name)
6009 + SCHARS (Vsystem_name)
6010 + 2);
6011 sprintf (dpyinfo->w32_id_name, "%s@%s",
6012 SDATA (Vinvocation_name), SDATA (Vsystem_name));
6013
6014 /* Default Console mode values - overridden when running in GUI mode
6015 with values obtained from system metrics. */
6016 dpyinfo->resx = 1;
6017 dpyinfo->resy = 1;
6018 dpyinfo->n_planes = 1;
6019 dpyinfo->n_cbits = 4;
6020 dpyinfo->n_fonts = 0;
6021 dpyinfo->smallest_font_height = 1;
6022 dpyinfo->smallest_char_width = 1;
6023
6024 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
6025 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
6026 dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
6027 dpyinfo->mouse_face_window = Qnil;
6028 dpyinfo->mouse_face_overlay = Qnil;
6029 dpyinfo->mouse_face_hidden = 0;
6030
6031 dpyinfo->vertical_scroll_bar_cursor = w32_load_cursor (IDC_ARROW);
6032 /* TODO: dpyinfo->gray */
6033
6034 }
6035
6036 /* Create an xrdb-style database of resources to supercede registry settings.
6037 The database is just a concatenation of C strings, finished by an additional
6038 \0. The strings are submitted to some basic normalization, so
6039
6040 [ *]option[ *]:[ *]value...
6041
6042 becomes
6043
6044 option:value...
6045
6046 but any whitespace following value is not removed. */
6047
6048 static char *
6049 w32_make_rdb (xrm_option)
6050 char *xrm_option;
6051 {
6052 char *buffer = xmalloc (strlen (xrm_option) + 2);
6053 char *current = buffer;
6054 char ch;
6055 int in_option = 1;
6056 int before_value = 0;
6057
6058 do {
6059 ch = *xrm_option++;
6060
6061 if (ch == '\n')
6062 {
6063 *current++ = '\0';
6064 in_option = 1;
6065 before_value = 0;
6066 }
6067 else if (ch != ' ')
6068 {
6069 *current++ = ch;
6070 if (in_option && (ch == ':'))
6071 {
6072 in_option = 0;
6073 before_value = 1;
6074 }
6075 else if (before_value)
6076 {
6077 before_value = 0;
6078 }
6079 }
6080 else if (!(in_option || before_value))
6081 {
6082 *current++ = ch;
6083 }
6084 } while (ch);
6085
6086 *current = '\0';
6087
6088 return buffer;
6089 }
6090
6091 void
6092 x_flush (struct frame * f)
6093 { /* Nothing to do */ }
6094
6095
6096 extern frame_parm_handler w32_frame_parm_handlers[];
6097
6098 static struct redisplay_interface w32_redisplay_interface =
6099 {
6100 w32_frame_parm_handlers,
6101 x_produce_glyphs,
6102 x_write_glyphs,
6103 x_insert_glyphs,
6104 x_clear_end_of_line,
6105 x_scroll_run,
6106 x_after_update_window_line,
6107 x_update_window_begin,
6108 x_update_window_end,
6109 x_cursor_to,
6110 x_flush,
6111 0, /* flush_display_optional */
6112 x_clear_window_mouse_face,
6113 x_get_glyph_overhangs,
6114 x_fix_overlapping_area,
6115 w32_draw_fringe_bitmap,
6116 w32_define_fringe_bitmap,
6117 w32_destroy_fringe_bitmap,
6118 w32_compute_glyph_string_overhangs,
6119 x_draw_glyph_string,
6120 w32_define_frame_cursor,
6121 w32_clear_frame_area,
6122 w32_draw_window_cursor,
6123 w32_draw_vertical_window_border,
6124 w32_shift_glyphs_for_insert
6125 };
6126
6127 static void x_delete_terminal (struct terminal *term);
6128
6129 static struct terminal *
6130 w32_create_terminal (struct w32_display_info *dpyinfo)
6131 {
6132 struct terminal *terminal;
6133
6134 terminal = create_terminal ();
6135
6136 terminal->type = output_w32;
6137 terminal->display_info.w32 = dpyinfo;
6138 dpyinfo->terminal = terminal;
6139
6140 /* MSVC does not type K&R functions with no arguments correctly, and
6141 so we must explicitly cast them. */
6142 terminal->clear_frame_hook = x_clear_frame;
6143 terminal->ins_del_lines_hook = x_ins_del_lines;
6144 terminal->delete_glyphs_hook = x_delete_glyphs;
6145 terminal->ring_bell_hook = w32_ring_bell;
6146 terminal->reset_terminal_modes_hook = w32_reset_terminal_modes;
6147 terminal->set_terminal_modes_hook = w32_set_terminal_modes;
6148 terminal->update_begin_hook = x_update_begin;
6149 terminal->update_end_hook = x_update_end;
6150 terminal->set_terminal_window_hook = w32_set_terminal_window;
6151 terminal->read_socket_hook = w32_read_socket;
6152 terminal->frame_up_to_date_hook = w32_frame_up_to_date;
6153 terminal->mouse_position_hook = w32_mouse_position;
6154 terminal->frame_rehighlight_hook = w32_frame_rehighlight;
6155 terminal->frame_raise_lower_hook = w32_frame_raise_lower;
6156 // terminal->fullscreen_hook = XTfullscreen_hook;
6157 terminal->set_vertical_scroll_bar_hook = w32_set_vertical_scroll_bar;
6158 terminal->condemn_scroll_bars_hook = w32_condemn_scroll_bars;
6159 terminal->redeem_scroll_bar_hook = w32_redeem_scroll_bar;
6160 terminal->judge_scroll_bars_hook = w32_judge_scroll_bars;
6161
6162 terminal->delete_frame_hook = x_destroy_window;
6163 terminal->delete_terminal_hook = x_delete_terminal;
6164
6165 terminal->rif = &w32_redisplay_interface;
6166 terminal->scroll_region_ok = 1; /* We'll scroll partial frames. */
6167 terminal->char_ins_del_ok = 1;
6168 terminal->line_ins_del_ok = 1; /* We'll just blt 'em. */
6169 terminal->fast_clear_end_of_line = 1; /* X does this well. */
6170 terminal->memory_below_frame = 0; /* We don't remember what scrolls
6171 off the bottom. */
6172
6173 /* We don't yet support separate terminals on W32, so don't try to share
6174 keyboards between virtual terminals that are on the same physical
6175 terminal like X does. */
6176 terminal->kboard = (KBOARD *) xmalloc (sizeof (KBOARD));
6177 init_kboard (terminal->kboard);
6178 terminal->kboard->Vwindow_system = intern ("w32");
6179 terminal->kboard->next_kboard = all_kboards;
6180 all_kboards = terminal->kboard;
6181 /* Don't let the initial kboard remain current longer than necessary.
6182 That would cause problems if a file loaded on startup tries to
6183 prompt in the mini-buffer. */
6184 if (current_kboard == initial_kboard)
6185 current_kboard = terminal->kboard;
6186 terminal->kboard->reference_count++;
6187
6188 return terminal;
6189 }
6190
6191 static void
6192 x_delete_terminal (struct terminal *terminal)
6193 {
6194 struct w32_display_info *dpyinfo = terminal->display_info.w32;
6195 int i;
6196
6197 /* Protect against recursive calls. delete_frame in
6198 delete_terminal calls us back when it deletes our last frame. */
6199 if (!terminal->name)
6200 return;
6201
6202 BLOCK_INPUT;
6203
6204 x_delete_display (dpyinfo);
6205 UNBLOCK_INPUT;
6206 }
6207
6208 struct w32_display_info *
6209 w32_term_init (display_name, xrm_option, resource_name)
6210 Lisp_Object display_name;
6211 char *xrm_option;
6212 char *resource_name;
6213 {
6214 struct w32_display_info *dpyinfo;
6215 struct terminal *terminal;
6216 HDC hdc;
6217
6218 BLOCK_INPUT;
6219
6220 if (!w32_initialized)
6221 {
6222 w32_initialize ();
6223 w32_initialized = 1;
6224 }
6225
6226 w32_initialize_display_info (display_name);
6227
6228 dpyinfo = &one_w32_display_info;
6229 terminal = w32_create_terminal (dpyinfo);
6230
6231 /* Set the name of the terminal. */
6232 terminal->name = (char *) xmalloc (SBYTES (display_name) + 1);
6233 strncpy (terminal->name, SDATA (display_name), SBYTES (display_name));
6234 terminal->name[SBYTES (display_name)] = 0;
6235
6236 dpyinfo->xrdb = xrm_option ? w32_make_rdb (xrm_option) : NULL;
6237
6238 /* Put this display on the chain. */
6239 dpyinfo->next = x_display_list;
6240 x_display_list = dpyinfo;
6241
6242 hdc = GetDC (NULL);
6243
6244 dpyinfo->root_window = GetDesktopWindow ();
6245 dpyinfo->n_planes = GetDeviceCaps (hdc, PLANES);
6246 dpyinfo->n_cbits = GetDeviceCaps (hdc, BITSPIXEL);
6247 dpyinfo->resx = GetDeviceCaps (hdc, LOGPIXELSX);
6248 dpyinfo->resy = GetDeviceCaps (hdc, LOGPIXELSY);
6249 dpyinfo->has_palette = GetDeviceCaps (hdc, RASTERCAPS) & RC_PALETTE;
6250 ReleaseDC (NULL, hdc);
6251
6252 /* initialise palette with white and black */
6253 {
6254 XColor color;
6255 w32_defined_color (0, "white", &color, 1);
6256 w32_defined_color (0, "black", &color, 1);
6257 }
6258
6259 /* Add the default keyboard. */
6260 add_keyboard_wait_descriptor (0);
6261
6262 /* Create Fringe Bitmaps and store them for later use.
6263
6264 On W32, bitmaps are all unsigned short, as Windows requires
6265 bitmap data to be Word aligned. For some reason they are
6266 horizontally reflected compared to how they appear on X, so we
6267 need to bitswap and convert to unsigned shorts before creating
6268 the bitmaps. */
6269 w32_init_fringe (terminal->rif);
6270
6271 #ifdef F_SETOWN
6272 fcntl (connection, F_SETOWN, getpid ());
6273 #endif /* ! defined (F_SETOWN) */
6274
6275 #ifdef SIGIO
6276 if (interrupt_input)
6277 init_sigio (connection);
6278 #endif /* ! defined (SIGIO) */
6279
6280 UNBLOCK_INPUT;
6281
6282 return dpyinfo;
6283 }
6284 \f
6285 /* Get rid of display DPYINFO, assuming all frames are already gone. */
6286 void
6287 x_delete_display (dpyinfo)
6288 struct w32_display_info *dpyinfo;
6289 {
6290 /* Discard this display from w32_display_name_list and w32_display_list.
6291 We can't use Fdelq because that can quit. */
6292 if (! NILP (w32_display_name_list)
6293 && EQ (XCAR (w32_display_name_list), dpyinfo->name_list_element))
6294 w32_display_name_list = XCDR (w32_display_name_list);
6295 else
6296 {
6297 Lisp_Object tail;
6298
6299 tail = w32_display_name_list;
6300 while (CONSP (tail) && CONSP (XCDR (tail)))
6301 {
6302 if (EQ (XCAR (XCDR (tail)), dpyinfo->name_list_element))
6303 {
6304 XSETCDR (tail, XCDR (XCDR (tail)));
6305 break;
6306 }
6307 tail = XCDR (tail);
6308 }
6309 }
6310
6311 /* free palette table */
6312 {
6313 struct w32_palette_entry * plist;
6314
6315 plist = dpyinfo->color_list;
6316 while (plist)
6317 {
6318 struct w32_palette_entry * pentry = plist;
6319 plist = plist->next;
6320 xfree (pentry);
6321 }
6322 dpyinfo->color_list = NULL;
6323 if (dpyinfo->palette)
6324 DeleteObject(dpyinfo->palette);
6325 }
6326 xfree (dpyinfo->w32_id_name);
6327
6328 w32_reset_fringes ();
6329 }
6330 \f
6331 /* Set up use of W32. */
6332
6333 DWORD WINAPI w32_msg_worker (void * arg);
6334
6335 static void
6336 w32_initialize ()
6337 {
6338 HANDLE shell;
6339 HRESULT (WINAPI * set_user_model) (wchar_t * id);
6340
6341 baud_rate = 19200;
6342
6343 w32_system_caret_hwnd = NULL;
6344 w32_system_caret_height = 0;
6345 w32_system_caret_x = 0;
6346 w32_system_caret_y = 0;
6347
6348 /* On Windows 7 and later, we need to set the user model ID
6349 to associate emacsclient launched files with Emacs frames
6350 in the UI. */
6351 shell = GetModuleHandle ("shell32.dll");
6352 if (shell)
6353 {
6354 set_user_model
6355 = (void *) GetProcAddress (shell,
6356 "SetCurrentProcessExplicitAppUserModelID");
6357
6358 /* If the function is defined, then we are running on Windows 7
6359 or newer, and the UI uses this to group related windows
6360 together. Since emacs, runemacs, emacsclient are related, we
6361 want them grouped even though the executables are different,
6362 so we need to set a consistent ID between them. */
6363 if (set_user_model)
6364 set_user_model (L"GNU.Emacs");
6365 }
6366
6367 /* Initialize w32_use_visible_system_caret based on whether a screen
6368 reader is in use. */
6369 if (!SystemParametersInfo (SPI_GETSCREENREADER, 0,
6370 &w32_use_visible_system_caret, 0))
6371 w32_use_visible_system_caret = 0;
6372
6373 last_tool_bar_item = -1;
6374 any_help_event_p = 0;
6375
6376 /* Initialize input mode: interrupt_input off, no flow control, allow
6377 8 bit character input, standard quit char. */
6378 Fset_input_mode (Qnil, Qnil, make_number (2), Qnil);
6379
6380 {
6381 DWORD input_locale_id = (DWORD) GetKeyboardLayout (0);
6382 keyboard_codepage = codepage_for_locale ((LCID) (input_locale_id & 0xffff));
6383 }
6384
6385 /* Create the window thread - it will terminate itself when the app
6386 terminates */
6387 init_crit ();
6388
6389 dwMainThreadId = GetCurrentThreadId ();
6390 DuplicateHandle (GetCurrentProcess (), GetCurrentThread (),
6391 GetCurrentProcess (), &hMainThread, 0, TRUE, DUPLICATE_SAME_ACCESS);
6392
6393 /* Wait for thread to start */
6394 {
6395 MSG msg;
6396
6397 PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE);
6398
6399 hWindowsThread = CreateThread (NULL, 0,
6400 w32_msg_worker,
6401 0, 0, &dwWindowsThreadId);
6402
6403 GetMessage (&msg, NULL, WM_EMACS_DONE, WM_EMACS_DONE);
6404 }
6405
6406 /* It is desirable that mainThread should have the same notion of
6407 focus window and active window as windowsThread. Unfortunately, the
6408 following call to AttachThreadInput, which should do precisely what
6409 we need, causes major problems when Emacs is linked as a console
6410 program. Unfortunately, we have good reasons for doing that, so
6411 instead we need to send messages to windowsThread to make some API
6412 calls for us (ones that affect, or depend on, the active/focus
6413 window state.) */
6414 #ifdef ATTACH_THREADS
6415 AttachThreadInput (dwMainThreadId, dwWindowsThreadId, TRUE);
6416 #endif
6417
6418 /* Dynamically link to optional system components. */
6419 {
6420 HMODULE user_lib = GetModuleHandle ("user32.dll");
6421
6422 #define LOAD_PROC(lib, fn) pfn##fn = (void *) GetProcAddress (lib, #fn)
6423
6424 LOAD_PROC (user_lib, SetLayeredWindowAttributes);
6425
6426 #undef LOAD_PROC
6427
6428 /* Ensure scrollbar handle is at least 5 pixels. */
6429 vertical_scroll_bar_min_handle = 5;
6430
6431 /* For either kind of scroll bar, take account of the arrows; these
6432 effectively form the border of the main scroll bar range. */
6433 vertical_scroll_bar_top_border = vertical_scroll_bar_bottom_border
6434 = GetSystemMetrics (SM_CYVSCROLL);
6435 }
6436 }
6437
6438 void
6439 syms_of_w32term ()
6440 {
6441 staticpro (&w32_display_name_list);
6442 w32_display_name_list = Qnil;
6443
6444 staticpro (&last_mouse_scroll_bar);
6445 last_mouse_scroll_bar = Qnil;
6446
6447 DEFSYM (Qvendor_specific_keysyms, "vendor-specific-keysyms");
6448
6449 DEFVAR_INT ("w32-num-mouse-buttons",
6450 &w32_num_mouse_buttons,
6451 doc: /* Number of physical mouse buttons. */);
6452 w32_num_mouse_buttons = 2;
6453
6454 DEFVAR_LISP ("w32-swap-mouse-buttons",
6455 &Vw32_swap_mouse_buttons,
6456 doc: /* Swap the mapping of middle and right mouse buttons.
6457 When nil, middle button is mouse-2 and right button is mouse-3. */);
6458 Vw32_swap_mouse_buttons = Qnil;
6459
6460 DEFVAR_LISP ("w32-grab-focus-on-raise",
6461 &Vw32_grab_focus_on_raise,
6462 doc: /* Raised frame grabs input focus.
6463 When t, `raise-frame' grabs input focus as well. This fits well
6464 with the normal Windows click-to-focus policy, but might not be
6465 desirable when using a point-to-focus policy. */);
6466 Vw32_grab_focus_on_raise = Qt;
6467
6468 DEFVAR_LISP ("w32-capslock-is-shiftlock",
6469 &Vw32_capslock_is_shiftlock,
6470 doc: /* Apply CapsLock state to non character input keys.
6471 When nil, CapsLock only affects normal character input keys. */);
6472 Vw32_capslock_is_shiftlock = Qnil;
6473
6474 DEFVAR_LISP ("w32-recognize-altgr",
6475 &Vw32_recognize_altgr,
6476 doc: /* Recognize right-alt and left-ctrl as AltGr.
6477 When nil, the right-alt and left-ctrl key combination is
6478 interpreted normally. */);
6479 Vw32_recognize_altgr = Qt;
6480
6481 DEFVAR_BOOL ("w32-use-visible-system-caret",
6482 &w32_use_visible_system_caret,
6483 doc: /* Flag to make the system caret visible.
6484 When this is non-nil, Emacs will indicate the position of point by
6485 using the system caret instead of drawing its own cursor. Some screen
6486 reader software does not track the system cursor properly when it is
6487 invisible, and gets confused by Emacs drawing its own cursor, so this
6488 variable is initialized to t when Emacs detects that screen reader
6489 software is running as it starts up.
6490
6491 When this variable is set, other variables affecting the appearance of
6492 the cursor have no effect. */);
6493
6494 w32_use_visible_system_caret = 0;
6495
6496 /* We don't yet support this, but defining this here avoids whining
6497 from cus-start.el and other places, like "M-x set-variable". */
6498 DEFVAR_BOOL ("x-use-underline-position-properties",
6499 &x_use_underline_position_properties,
6500 doc: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
6501 A value of nil means ignore them. If you encounter fonts with bogus
6502 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
6503 to 4.1, set this to nil. */);
6504 x_use_underline_position_properties = 0;
6505
6506 DEFVAR_BOOL ("x-underline-at-descent-line",
6507 &x_underline_at_descent_line,
6508 doc: /* *Non-nil means to draw the underline at the same place as the descent line.
6509 A value of nil means to draw the underline according to the value of the
6510 variable `x-use-underline-position-properties', which is usually at the
6511 baseline level. The default value is nil. */);
6512 x_underline_at_descent_line = 0;
6513
6514 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,
6515 doc: /* If not nil, Emacs uses toolkit scroll bars. */);
6516 Vx_toolkit_scroll_bars = Qt;
6517
6518 staticpro (&last_mouse_motion_frame);
6519 last_mouse_motion_frame = Qnil;
6520 }
6521
6522 /* arch-tag: 5fa70624-ab86-499c-8a85-473958ee4646
6523 (do not change this comment) */