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