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