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