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