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