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