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