(w32_executable_type): Properly cast dos_header when
[bpt/emacs.git] / src / w32term.c
CommitLineData
e9e23e23 1/* Implementation of GUI terminal on the Microsoft W32 API.
ee78dc32
GV
2 Copyright (C) 1989, 1993, 1994, 1995 Free Software Foundation, Inc.
3
4This file is part of GNU Emacs.
5
6GNU Emacs is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2, or (at your option)
9any later version.
10
11GNU Emacs is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
1fb87c77
KH
17along with GNU Emacs; see the file COPYING. If not, write to the
18Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19Boston, MA 02111-1307, USA. */
ee78dc32
GV
20
21/* Added by Kevin Gallo */
22
23#include <signal.h>
24#include <config.h>
25#include <stdio.h>
26#include "lisp.h"
2091aeb2 27#include "charset.h"
ee78dc32
GV
28#include "blockinput.h"
29
689004fa 30#include "w32term.h"
ee78dc32
GV
31
32#include "systty.h"
33#include "systime.h"
34
35#include <ctype.h>
36#include <errno.h>
37#include <setjmp.h>
38#include <sys/stat.h>
39
40#include "frame.h"
41#include "dispextern.h"
42#include "termhooks.h"
43#include "termopts.h"
44#include "termchar.h"
45#include "gnu.h"
46#include "disptab.h"
47#include "buffer.h"
48#include "window.h"
49#include "keyboard.h"
50#include "intervals.h"
51
03887dd3
KH
52#undef min
53#undef max
54#define min(x, y) (((x) < (y)) ? (x) : (y))
55#define max(x, y) (((x) > (y)) ? (x) : (y))
56
ee78dc32
GV
57extern void free_frame_menubar ();
58
52cf03a1
GV
59extern Lisp_Object Vwindow_system;
60
ee78dc32
GV
61#define x_any_window_to_frame x_window_to_frame
62#define x_top_window_to_frame x_window_to_frame
63
64\f
fbd6baed
GV
65/* This is display since w32 does not support multiple ones. */
66struct w32_display_info one_w32_display_info;
ee78dc32
GV
67
68/* This is a list of cons cells, each of the form (NAME . FONT-LIST-CACHE),
fbd6baed 69 one for each element of w32_display_list and in the same order.
ee78dc32
GV
70 NAME is the name of the frame.
71 FONT-LIST-CACHE records previous values returned by x-list-fonts. */
fbd6baed 72Lisp_Object w32_display_name_list;
ee78dc32
GV
73
74/* Frame being updated by update_frame. This is declared in term.c.
75 This is set by update_begin and looked at by all the
fbd6baed
GV
76 w32 functions. It is zero while not inside an update.
77 In that case, the w32 functions assume that `selected_frame'
ee78dc32
GV
78 is the frame to apply to. */
79extern struct frame *updating_frame;
80
81/* This is a frame waiting to be autoraised, within w32_read_socket. */
82struct frame *pending_autoraise_frame;
83
84/* During an update, maximum vpos for ins/del line operations to affect. */
85
86static int flexlines;
87
88/* During an update, nonzero if chars output now should be highlighted. */
89
90static int highlight;
91
92/* Nominal cursor position -- where to draw output.
93 During an update, these are different from the cursor-box position. */
94
95static int curs_x;
96static int curs_y;
97
e9e23e23
GV
98DWORD dwWindowsThreadId = 0;
99HANDLE hWindowsThread = NULL;
ee78dc32
GV
100DWORD dwMainThreadId = 0;
101HANDLE hMainThread = NULL;
102
689004fa
GV
103#ifndef SIF_ALL
104/* These definitions are new with Windows 95. */
105#define SIF_RANGE 0x0001
106#define SIF_PAGE 0x0002
107#define SIF_POS 0x0004
108#define SIF_DISABLENOSCROLL 0x0008
109#define SIF_TRACKPOS 0x0010
110#define SIF_ALL (SIF_RANGE | SIF_PAGE | SIF_POS | SIF_TRACKPOS)
111
112typedef struct tagSCROLLINFO
113{
114 UINT cbSize;
115 UINT fMask;
116 int nMin;
117 int nMax;
118 UINT nPage;
119 int nPos;
120 int nTrackPos;
121} SCROLLINFO, FAR *LPSCROLLINFO;
122typedef SCROLLINFO CONST FAR *LPCSCROLLINFO;
123#endif /* SIF_ALL */
124
125/* Dynamic linking to new proportional scroll bar functions. */
126int (PASCAL *pfnSetScrollInfo) (HWND hwnd, int fnBar, LPSCROLLINFO lpsi, BOOL fRedraw);
127BOOL (PASCAL *pfnGetScrollInfo) (HWND hwnd, int fnBar, LPSCROLLINFO lpsi);
128
129int vertical_scroll_bar_min_handle;
130int vertical_scroll_bar_top_border;
131int vertical_scroll_bar_bottom_border;
132
133int last_scroll_bar_drag_pos;
134
ee78dc32
GV
135/* Mouse movement. */
136
137/* Where the mouse was last time we reported a mouse event. */
138static FRAME_PTR last_mouse_frame;
139static RECT last_mouse_glyph;
140
fbd6baed 141Lisp_Object Vw32_num_mouse_buttons;
52cf03a1 142
fbd6baed 143Lisp_Object Vw32_swap_mouse_buttons;
52cf03a1 144
689004fa
GV
145/* Control whether x_raise_frame also sets input focus. */
146Lisp_Object Vw32_grab_focus_on_raise;
147
148/* Control whether Caps Lock affects non-ascii characters. */
149Lisp_Object Vw32_capslock_is_shiftlock;
150
ee78dc32
GV
151/* The scroll bar in which the last motion event occurred.
152
153 If the last motion event occurred in a scroll bar, we set this
fbd6baed 154 so w32_mouse_position can know whether to report a scroll bar motion or
ee78dc32
GV
155 an ordinary motion.
156
157 If the last motion event didn't occur in a scroll bar, we set this
fbd6baed 158 to Qnil, to tell w32_mouse_position to return an ordinary motion event. */
ee78dc32
GV
159Lisp_Object last_mouse_scroll_bar;
160int last_mouse_scroll_bar_pos;
161
fbd6baed 162/* This is a hack. We would really prefer that w32_mouse_position would
ee78dc32
GV
163 return the time associated with the position it returns, but there
164 doesn't seem to be any way to wrest the timestamp from the server
165 along with the position query. So, we just keep track of the time
166 of the last movement we received, and return that in hopes that
167 it's somewhat accurate. */
168Time last_mouse_movement_time;
169
170/* Incremented by w32_read_socket whenever it really tries to read events. */
171#ifdef __STDC__
172static int volatile input_signal_count;
173#else
174static int input_signal_count;
175#endif
176
177extern Lisp_Object Vcommand_line_args, Vsystem_name;
178
179extern Lisp_Object Qface, Qmouse_face;
180
181extern int errno;
182
183/* A mask of extra modifier bits to put into every keyboard char. */
184extern int extra_keyboard_modifiers;
185
186static Lisp_Object Qvendor_specific_keysyms;
187
fbd6baed 188void w32_delete_display ();
ee78dc32
GV
189
190static void redraw_previous_char ();
191static void redraw_following_char ();
fbd6baed 192static unsigned int w32_get_modifiers ();
ee78dc32
GV
193
194static int fast_find_position ();
195static void note_mouse_highlight ();
196static void clear_mouse_face ();
197static void show_mouse_face ();
198static void do_line_dance ();
199
fbd6baed
GV
200static int w32_cursor_to ();
201static int w32_clear_end_of_line ();
ee78dc32
GV
202\f
203#if 0
204/* This is a function useful for recording debugging information
205 about the sequence of occurrences in this file. */
206
207struct record
208{
209 char *locus;
210 int type;
211};
212
213struct record event_record[100];
214
215int event_record_index;
216
217record_event (locus, type)
218 char *locus;
219 int type;
220{
221 if (event_record_index == sizeof (event_record) / sizeof (struct record))
222 event_record_index = 0;
223
224 event_record[event_record_index].locus = locus;
225 event_record[event_record_index].type = type;
226 event_record_index++;
227}
228
229#endif /* 0 */
230\f
fbd6baed 231/* Return the struct w32_display_info. */
ee78dc32 232
fbd6baed
GV
233struct w32_display_info *
234w32_display_info_for_display ()
ee78dc32 235{
fbd6baed 236 return (&one_w32_display_info);
ee78dc32
GV
237}
238
239void
fbd6baed 240w32_fill_rect (f, _hdc, pix, lprect)
ee78dc32
GV
241 FRAME_PTR f;
242 HDC _hdc;
243 COLORREF pix;
244 RECT * lprect;
245{
246 HDC hdc;
247 HBRUSH hb;
ee78dc32
GV
248 RECT rect;
249
250 if (_hdc)
251 hdc = _hdc;
252 else
253 {
254 if (!f) return;
52cf03a1 255 hdc = get_frame_dc (f);
ee78dc32
GV
256 }
257
258 hb = CreateSolidBrush (pix);
ee78dc32 259 FillRect (hdc, lprect, hb);
ee78dc32
GV
260 DeleteObject (hb);
261
262 if (!_hdc)
52cf03a1 263 release_frame_dc (f, hdc);
ee78dc32
GV
264}
265
266void
fbd6baed 267w32_clear_window (f)
ee78dc32
GV
268 FRAME_PTR f;
269{
270 RECT rect;
52cf03a1 271
fbd6baed
GV
272 GetClientRect (FRAME_W32_WINDOW (f), &rect);
273 w32_clear_rect (f, NULL, &rect);
ee78dc32
GV
274}
275
276\f
277/* Starting and ending updates.
278
279 These hooks are called by update_frame at the beginning and end
280 of a frame update. We record in `updating_frame' the identity
fbd6baed
GV
281 of the frame being updated, so that the w32_... functions do not
282 need to take a frame as argument. Most of the w32_... functions
ee78dc32 283 should never be called except during an update, the only exceptions
fbd6baed 284 being w32_cursor_to, w32_write_glyphs and w32_reassert_line_highlight. */
ee78dc32
GV
285
286static
fbd6baed 287w32_update_begin (f)
ee78dc32
GV
288 struct frame *f;
289{
290 if (f == 0)
291 abort ();
292
293 flexlines = f->height;
294 highlight = 0;
295
296 BLOCK_INPUT;
297
52cf03a1
GV
298 /* Regenerate display palette before drawing if list of requested
299 colors has changed. */
fbd6baed 300 if (FRAME_W32_DISPLAY_INFO (f)->regen_palette)
52cf03a1 301 {
fbd6baed
GV
302 w32_regenerate_palette (f);
303 FRAME_W32_DISPLAY_INFO (f)->regen_palette = FALSE;
52cf03a1
GV
304 }
305
fbd6baed 306 if (f == FRAME_W32_DISPLAY_INFO (f)->mouse_face_mouse_frame)
ee78dc32
GV
307 {
308 /* Don't do highlighting for mouse motion during the update. */
fbd6baed 309 FRAME_W32_DISPLAY_INFO (f)->mouse_face_defer = 1;
ee78dc32
GV
310
311 /* If the frame needs to be redrawn,
312 simply forget about any prior mouse highlighting. */
313 if (FRAME_GARBAGED_P (f))
fbd6baed 314 FRAME_W32_DISPLAY_INFO (f)->mouse_face_window = Qnil;
ee78dc32 315
fbd6baed 316 if (!NILP (FRAME_W32_DISPLAY_INFO (f)->mouse_face_window))
ee78dc32
GV
317 {
318 int firstline, lastline, i;
fbd6baed 319 struct window *w = XWINDOW (FRAME_W32_DISPLAY_INFO (f)->mouse_face_window);
ee78dc32
GV
320
321 /* Find the first, and the last+1, lines affected by redisplay. */
322 for (firstline = 0; firstline < f->height; firstline++)
323 if (FRAME_DESIRED_GLYPHS (f)->enable[firstline])
324 break;
325
326 lastline = f->height;
327 for (i = f->height - 1; i >= 0; i--)
328 {
329 if (FRAME_DESIRED_GLYPHS (f)->enable[i])
330 break;
331 else
332 lastline = i;
333 }
334
335 /* Can we tell that this update does not affect the window
336 where the mouse highlight is? If so, no need to turn off.
337 Likewise, don't do anything if the frame is garbaged;
338 in that case, the FRAME_CURRENT_GLYPHS that we would use
339 are all wrong, and we will redisplay that line anyway. */
340 if (! (firstline > (XFASTINT (w->top) + window_internal_height (w))
341 || lastline < XFASTINT (w->top)))
fbd6baed 342 clear_mouse_face (FRAME_W32_DISPLAY_INFO (f));
ee78dc32
GV
343 }
344 }
345
346 UNBLOCK_INPUT;
347}
348
349static
fbd6baed 350w32_update_end (f)
ee78dc32
GV
351 struct frame *f;
352{
353 BLOCK_INPUT;
354
355 do_line_dance ();
356 x_display_cursor (f, 1);
357
fbd6baed
GV
358 if (f == FRAME_W32_DISPLAY_INFO (f)->mouse_face_mouse_frame)
359 FRAME_W32_DISPLAY_INFO (f)->mouse_face_defer = 0;
ee78dc32
GV
360
361 UNBLOCK_INPUT;
362}
363
364/* This is called after a redisplay on frame F. */
365
366static
fbd6baed 367w32_frame_up_to_date (f)
ee78dc32
GV
368 FRAME_PTR f;
369{
689004fa 370 BLOCK_INPUT;
fbd6baed
GV
371 if (FRAME_W32_DISPLAY_INFO (f)->mouse_face_deferred_gc
372 || f == FRAME_W32_DISPLAY_INFO (f)->mouse_face_mouse_frame)
ee78dc32 373 {
fbd6baed
GV
374 note_mouse_highlight (FRAME_W32_DISPLAY_INFO (f)->mouse_face_mouse_frame,
375 FRAME_W32_DISPLAY_INFO (f)->mouse_face_mouse_x,
376 FRAME_W32_DISPLAY_INFO (f)->mouse_face_mouse_y);
377 FRAME_W32_DISPLAY_INFO (f)->mouse_face_deferred_gc = 0;
ee78dc32 378 }
689004fa 379 UNBLOCK_INPUT;
ee78dc32
GV
380}
381\f
382/* External interface to control of standout mode.
383 Call this when about to modify line at position VPOS
384 and not change whether it is highlighted. */
385
fbd6baed 386w32_reassert_line_highlight (new, vpos)
ee78dc32
GV
387 int new, vpos;
388{
389 highlight = new;
390}
391
392/* Call this when about to modify line at position VPOS
393 and change whether it is highlighted. */
394
395static
fbd6baed 396w32_change_line_highlight (new_highlight, vpos, first_unused_hpos)
ee78dc32
GV
397 int new_highlight, vpos, first_unused_hpos;
398{
399 highlight = new_highlight;
fbd6baed
GV
400 w32_cursor_to (vpos, 0);
401 w32_clear_end_of_line (updating_frame->width);
ee78dc32
GV
402}
403
404/* This is used when starting Emacs and when restarting after suspend.
405 When starting Emacs, no window is mapped. And nothing must be done
406 to Emacs's own window if it is suspended (though that rarely happens). */
407
408static
fbd6baed 409w32_set_terminal_modes ()
ee78dc32
GV
410{
411}
412
413/* This is called when exiting or suspending Emacs.
fbd6baed 414 Exiting will make the W32 windows go away, and suspending
ee78dc32
GV
415 requires no action. */
416
417static
fbd6baed 418w32_reset_terminal_modes ()
ee78dc32
GV
419{
420}
421\f
422/* Set the nominal cursor position of the frame.
423 This is where display update commands will take effect.
424 This does not affect the place where the cursor-box is displayed. */
425
426static int
fbd6baed 427w32_cursor_to (row, col)
ee78dc32
GV
428 register int row, col;
429{
430 int orow = row;
431
432 curs_x = col;
433 curs_y = row;
434
435 if (updating_frame == 0)
436 {
437 BLOCK_INPUT;
438 x_display_cursor (selected_frame, 1);
439 UNBLOCK_INPUT;
440 }
441}
442\f
443/* Display a sequence of N glyphs found at GP.
444 WINDOW is the window to output to. LEFT and TOP are starting coords.
445 HL is 1 if this text is highlighted, 2 if the cursor is on it,
446 3 if should appear in its mouse-face.
447 JUST_FOREGROUND if 1 means draw only the foreground;
448 don't alter the background.
449
450 FONT is the default font to use (for glyphs whose font-code is 0).
451
452 Since the display generation code is responsible for calling
453 compute_char_face and compute_glyph_face on everything it puts in
454 the display structure, we can assume that the face code on each
455 glyph is a valid index into FRAME_COMPUTED_FACES (f), and the one
456 to which we can actually apply intern_face.
457 Call this function with input blocked. */
458
459static void
460dumpglyphs (f, left, top, gp, n, hl, just_foreground)
461 struct frame *f;
462 int left, top;
463 register GLYPH *gp; /* Points to first GLYPH. */
464 register int n; /* Number of glyphs to display. */
465 int hl;
466 int just_foreground;
467{
468 /* Holds characters to be displayed. */
469 char *buf = (char *) alloca (f->width * sizeof (*buf));
470 register char *cp; /* Steps through buf[]. */
471 register int tlen = GLYPH_TABLE_LENGTH;
472 register Lisp_Object *tbase = GLYPH_TABLE_BASE;
fbd6baed 473 Window window = FRAME_W32_WINDOW (f);
ee78dc32
GV
474 int orig_left = left;
475 HDC hdc;
476
52cf03a1 477 hdc = get_frame_dc (f);
ee78dc32
GV
478
479 while (n > 0)
480 {
481 /* Get the face-code of the next GLYPH. */
482 int cf, len;
483 int g = *gp;
484
485 GLYPH_FOLLOW_ALIASES (tbase, tlen, g);
486 cf = FAST_GLYPH_FACE (g);
487
488 /* Find the run of consecutive glyphs with the same face-code.
489 Extract their character codes into BUF. */
490 cp = buf;
491 while (n > 0)
492 {
493 g = *gp;
494 GLYPH_FOLLOW_ALIASES (tbase, tlen, g);
495 if (FAST_GLYPH_FACE (g) != cf)
496 break;
497
498 *cp++ = FAST_GLYPH_CHAR (g);
499 --n;
500 ++gp;
501 }
502
503 /* LEN gets the length of the run. */
504 len = cp - buf;
505
506 /* Now output this run of chars, with the font and pixel values
507 determined by the face code CF. */
508 {
509 struct face *face = FRAME_DEFAULT_FACE (f);
510 XFontStruct *font = FACE_FONT (face);
511 int stippled = 0;
512 COLORREF fg;
513 COLORREF bg;
514
515 /* HL = 3 means use a mouse face previously chosen. */
516 if (hl == 3)
fbd6baed 517 cf = FRAME_W32_DISPLAY_INFO (f)->mouse_face_face_id;
ee78dc32
GV
518
519 /* First look at the face of the text itself. */
520 if (cf != 0)
521 {
522 /* It's possible for the display table to specify
523 a face code that is out of range. Use 0 in that case. */
524 if (cf < 0 || cf >= FRAME_N_COMPUTED_FACES (f)
525 || FRAME_COMPUTED_FACES (f) [cf] == 0)
526 cf = 0;
527
528 if (cf == 1)
529 face = FRAME_MODE_LINE_FACE (f);
530 else
531 face = intern_face (f, FRAME_COMPUTED_FACES (f) [cf]);
532 font = FACE_FONT (face);
533 if (FACE_STIPPLE (face))
534 stippled = 1;
535 }
536
537 /* Then comes the distinction between modeline and normal text. */
538 else if (hl == 0)
539 ;
540 else if (hl == 1)
541 {
542 face = FRAME_MODE_LINE_FACE (f);
543 font = FACE_FONT (face);
544 if (FACE_STIPPLE (face))
545 stippled = 1;
546 }
547
548 fg = face->foreground;
549 bg = face->background;
550
551 /* Now override that if the cursor's on this character. */
552 if (hl == 2)
553 {
554 /* The cursor overrides stippling. */
555 stippled = 0;
556
557 if ((!face->font
558 || face->font == (XFontStruct *) FACE_DEFAULT
fbd6baed
GV
559 || face->font == f->output_data.w32->font)
560 && face->background == f->output_data.w32->background_pixel
561 && face->foreground == f->output_data.w32->foreground_pixel)
ee78dc32 562 {
fbd6baed 563 bg = f->output_data.w32->cursor_pixel;
ee78dc32
GV
564 fg = face->background;
565 }
566 /* Cursor on non-default face: must merge. */
567 else
568 {
fbd6baed 569 bg = f->output_data.w32->cursor_pixel;
ee78dc32
GV
570 fg = face->background;
571 /* If the glyph would be invisible,
572 try a different foreground. */
573 if (fg == bg)
574 fg = face->foreground;
575 if (fg == bg)
fbd6baed 576 fg = f->output_data.w32->cursor_foreground_pixel;
ee78dc32
GV
577 if (fg == bg)
578 fg = face->foreground;
579 /* Make sure the cursor is distinct from text in this face. */
580 if (bg == face->background
581 && fg == face->foreground)
582 {
583 bg = face->foreground;
584 fg = face->background;
585 }
586 }
587 }
588
589 if (font == (XFontStruct *) FACE_DEFAULT)
fbd6baed 590 font = f->output_data.w32->font;
ee78dc32
GV
591
592 SetBkMode (hdc, just_foreground ? TRANSPARENT : OPAQUE);
593
594 SetTextColor (hdc, fg);
595 SetBkColor (hdc, bg);
596
597 SelectObject (hdc, font->hfont);
598
599 TextOut (hdc, left, top, buf, len);
600
601 if (!just_foreground)
602 {
603 /* Clear the rest of the line's height. */
fbd6baed
GV
604 if (f->output_data.w32->line_height != FONT_HEIGHT (font))
605 w32_fill_area (f, hdc, bg,
ee78dc32
GV
606 left,
607 top + FONT_HEIGHT (font),
608 FONT_WIDTH (font) * len,
fbd6baed 609 f->output_data.w32->line_height - FONT_HEIGHT (font));
ee78dc32
GV
610 }
611
612 {
613 int underline_position = 1;
614
615 if (font->tm.tmDescent <= underline_position)
616 underline_position = font->tm.tmDescent - 1;
617
618 if (face->underline)
fbd6baed 619 w32_fill_area (f, hdc, fg,
ee78dc32
GV
620 left, (top
621 + FONT_BASE (font)
622 + underline_position),
623 len * FONT_WIDTH (font), 1);
624 }
625
626 left += len * FONT_WIDTH (font);
627 }
628 }
629
52cf03a1 630 release_frame_dc (f, hdc);
ee78dc32
GV
631}
632
633\f
634/* Output some text at the nominal frame cursor position.
635 Advance the cursor over the text.
636 Output LEN glyphs at START.
637
fbd6baed 638 `highlight', set up by w32_reassert_line_highlight or w32_change_line_highlight,
ee78dc32
GV
639 controls the pixel values used for foreground and background. */
640
641static
fbd6baed 642w32_write_glyphs (start, len)
ee78dc32
GV
643 register GLYPH *start;
644 int len;
645{
646 register int temp_length;
647 struct frame *f;
648
649 BLOCK_INPUT;
650
651 do_line_dance ();
652 f = updating_frame;
653 if (f == 0)
654 {
655 f = selected_frame;
656 /* If not within an update,
657 output at the frame's visible cursor. */
658 curs_x = f->cursor_x;
659 curs_y = f->cursor_y;
660 }
661
662 dumpglyphs (f,
663 CHAR_TO_PIXEL_COL (f, curs_x),
664 CHAR_TO_PIXEL_ROW (f, curs_y),
665 start, len, highlight, 0);
666
667 /* If we drew on top of the cursor, note that it is turned off. */
668 if (curs_y == f->phys_cursor_y
669 && curs_x <= f->phys_cursor_x
670 && curs_x + len > f->phys_cursor_x)
671 f->phys_cursor_x = -1;
672
673 if (updating_frame == 0)
674 {
675 f->cursor_x += len;
676 x_display_cursor (f, 1);
677 f->cursor_x -= len;
678 }
679 else
680 curs_x += len;
681
682 UNBLOCK_INPUT;
683}
684\f
685/* Clear to the end of the line.
686 Erase the current text line from the nominal cursor position (inclusive)
687 to column FIRST_UNUSED (exclusive). The idea is that everything
688 from FIRST_UNUSED onward is already erased. */
689
690static
fbd6baed 691w32_clear_end_of_line (first_unused)
ee78dc32
GV
692 register int first_unused;
693{
694 struct frame *f = updating_frame;
695
696 if (f == 0)
697 abort ();
698
699 if (curs_y < 0 || curs_y >= f->height)
700 return 1;
701 if (first_unused <= 0)
702 return 1;
703
704 if (first_unused >= f->width)
705 first_unused = f->width;
706
11606873
GV
707 first_unused += FRAME_LEFT_SCROLL_BAR_WIDTH (f);
708
ee78dc32
GV
709 BLOCK_INPUT;
710
711 do_line_dance ();
712
713 /* Notice if the cursor will be cleared by this operation. */
714 if (curs_y == f->phys_cursor_y
715 && curs_x <= f->phys_cursor_x
716 && f->phys_cursor_x < first_unused)
717 f->phys_cursor_x = -1;
718
fbd6baed 719 w32_clear_area (f, NULL,
ee78dc32
GV
720 CHAR_TO_PIXEL_COL (f, curs_x),
721 CHAR_TO_PIXEL_ROW (f, curs_y),
fbd6baed
GV
722 FONT_WIDTH (f->output_data.w32->font) * (first_unused - curs_x),
723 f->output_data.w32->line_height);
ee78dc32
GV
724
725 UNBLOCK_INPUT;
726}
727
728static
fbd6baed 729w32_clear_frame ()
ee78dc32
GV
730{
731 struct frame *f = updating_frame;
732
733 if (f == 0)
734 f = selected_frame;
735
736 f->phys_cursor_x = -1; /* Cursor not visible. */
737 curs_x = 0; /* Nominal cursor position is top left. */
738 curs_y = 0;
739
740 BLOCK_INPUT;
741
fbd6baed 742 w32_clear_window (f);
ee78dc32
GV
743
744 /* We have to clear the scroll bars, too. If we have changed
745 colors or something like that, then they should be notified. */
746 x_scroll_bar_clear (f);
747
748 UNBLOCK_INPUT;
749}
750\f
751/* Make audible bell. */
752
fbd6baed 753w32_ring_bell ()
ee78dc32
GV
754{
755 BLOCK_INPUT;
756
757 if (visible_bell)
fbd6baed 758 FlashWindow (FRAME_W32_WINDOW (selected_frame), FALSE);
ee78dc32 759 else
fbd6baed 760 w32_sys_ring_bell ();
ee78dc32
GV
761
762 UNBLOCK_INPUT;
763
764 return 1;
765}
766\f
767/* Insert and delete character.
768 These are not supposed to be used because we are supposed to turn
769 off the feature of using them. */
770
771static
fbd6baed 772w32_insert_glyphs (start, len)
ee78dc32
GV
773 register char *start;
774 register int len;
775{
776 abort ();
777}
778
779static
fbd6baed 780w32_delete_glyphs (n)
ee78dc32
GV
781 register int n;
782{
783 abort ();
784}
785\f
786/* Specify how many text lines, from the top of the window,
787 should be affected by insert-lines and delete-lines operations.
788 This, and those operations, are used only within an update
fbd6baed 789 that is bounded by calls to w32_update_begin and w32_update_end. */
ee78dc32
GV
790
791static
fbd6baed 792w32_set_terminal_window (n)
ee78dc32
GV
793 register int n;
794{
795 if (updating_frame == 0)
796 abort ();
797
798 if ((n <= 0) || (n > updating_frame->height))
799 flexlines = updating_frame->height;
800 else
801 flexlines = n;
802}
803\f
804/* These variables need not be per frame
805 because redisplay is done on a frame-by-frame basis
806 and the line dance for one frame is finished before
807 anything is done for another frame. */
808
809/* Array of line numbers from cached insert/delete operations.
810 line_dance[i] is the old position of the line that we want
811 to move to line i, or -1 if we want a blank line there. */
812static int *line_dance;
813
814/* Allocated length of that array. */
815static int line_dance_len;
816
817/* Flag indicating whether we've done any work. */
818static int line_dance_in_progress;
819
820/* Perform an insert-lines or delete-lines operation,
821 inserting N lines or deleting -N lines at vertical position VPOS. */
fbd6baed 822w32_ins_del_lines (vpos, n)
ee78dc32
GV
823 int vpos, n;
824{
825 register int fence, i;
826
827 if (vpos >= flexlines)
828 return 1;
829
830 if (!line_dance_in_progress)
831 {
832 int ht = updating_frame->height;
833 if (ht > line_dance_len)
834 {
835 line_dance = (int *)xrealloc (line_dance, ht * sizeof (int));
836 line_dance_len = ht;
837 }
838 for (i = 0; i < ht; ++i) line_dance[i] = i;
839 line_dance_in_progress = 1;
840 }
841 if (n >= 0)
842 {
843 if (n > flexlines - vpos)
844 n = flexlines - vpos;
845 fence = vpos + n;
846 for (i = flexlines; --i >= fence;)
847 line_dance[i] = line_dance[i-n];
848 for (i = fence; --i >= vpos;)
849 line_dance[i] = -1;
850 }
851 else
852 {
853 n = -n;
854 if (n > flexlines - vpos)
855 n = flexlines - vpos;
856 fence = flexlines - n;
857 for (i = vpos; i < fence; ++i)
858 line_dance[i] = line_dance[i + n];
859 for (i = fence; i < flexlines; ++i)
860 line_dance[i] = -1;
861 }
862}
863
864/* Here's where we actually move the pixels around.
865 Must be called with input blocked. */
866static void
867do_line_dance ()
868{
869 register int i, j, distance;
870 register struct frame *f;
871 int ht;
872 int intborder;
873 HDC hdc;
874
875 /* Must check this flag first. If it's not set, then not only is the
876 array uninitialized, but we might not even have a frame. */
877 if (!line_dance_in_progress)
878 return;
879
880 f = updating_frame;
881 if (f == 0)
882 abort ();
883
884 ht = f->height;
fbd6baed 885 intborder = f->output_data.w32->internal_border_width;
ee78dc32
GV
886
887 x_display_cursor (updating_frame, 0);
888
52cf03a1 889 hdc = get_frame_dc (f);
ee78dc32
GV
890
891 for (i = 0; i < ht; ++i)
892 if (line_dance[i] != -1 && (distance = line_dance[i]-i) > 0)
893 {
894 for (j = i; (j < ht && line_dance[j] != -1
895 && line_dance[j]-j == distance); ++j);
896 /* Copy [i,j) upward from [i+distance, j+distance) */
897 BitBlt (hdc,
898 intborder, CHAR_TO_PIXEL_ROW (f, i+distance),
fbd6baed
GV
899 f->width * FONT_WIDTH (f->output_data.w32->font),
900 (j-i) * f->output_data.w32->line_height,
ee78dc32
GV
901 hdc,
902 intborder, CHAR_TO_PIXEL_ROW (f, i),
903 SRCCOPY);
904 i = j-1;
905 }
906
907 for (i = ht; --i >=0; )
908 if (line_dance[i] != -1 && (distance = line_dance[i]-i) < 0)
909 {
910 for (j = i; (--j >= 0 && line_dance[j] != -1
911 && line_dance[j]-j == distance););
912 /* Copy (j, i] downward from (j+distance, i+distance] */
913 BitBlt (hdc,
914 intborder, CHAR_TO_PIXEL_ROW (f, j+1+distance),
fbd6baed
GV
915 f->width * FONT_WIDTH (f->output_data.w32->font),
916 (i-j) * f->output_data.w32->line_height,
ee78dc32
GV
917 hdc,
918 intborder, CHAR_TO_PIXEL_ROW (f, j+1),
919 SRCCOPY);
920 i = j+1;
921 }
922
ee78dc32
GV
923 for (i = 0; i < ht; ++i)
924 if (line_dance[i] == -1)
925 {
926 for (j = i; j < ht && line_dance[j] == -1; ++j);
927 /* Clear [i,j) */
689004fa 928 w32_clear_area (f, hdc,
ee78dc32
GV
929 intborder,
930 CHAR_TO_PIXEL_ROW (f, i),
fbd6baed
GV
931 f->width * FONT_WIDTH (f->output_data.w32->font),
932 (j-i) * f->output_data.w32->line_height);
ee78dc32
GV
933 i = j-1;
934 }
935 line_dance_in_progress = 0;
689004fa
GV
936
937 release_frame_dc (f, hdc);
ee78dc32
GV
938}
939\f
940/* Support routines for exposure events. */
941static void clear_cursor ();
942
943/* Output into a rectangle of a window (for frame F)
944 the characters in f->phys_lines that overlap that rectangle.
945 TOP and LEFT are the position of the upper left corner of the rectangle.
946 ROWS and COLS are the size of the rectangle.
947 Call this function with input blocked. */
948
949void
950dumprectangle (f, left, top, cols, rows)
951 struct frame *f;
952 register int left, top, cols, rows;
953{
954 register struct frame_glyphs *active_frame = FRAME_CURRENT_GLYPHS (f);
955 int cursor_cleared = 0;
956 int bottom, right;
957 register int y;
958
959 if (FRAME_GARBAGED_P (f))
960 return;
961
962 /* Express rectangle as four edges, instead of position-and-size. */
963 bottom = top + rows;
964 right = left + cols;
965
966 /* Convert rectangle edges in pixels to edges in chars.
967 Round down for left and top, up for right and bottom. */
968 top = PIXEL_TO_CHAR_ROW (f, top);
969 left = PIXEL_TO_CHAR_COL (f, left);
fbd6baed
GV
970 bottom += (f->output_data.w32->line_height - 1);
971 right += (FONT_WIDTH (f->output_data.w32->font) - 1);
ee78dc32
GV
972 bottom = PIXEL_TO_CHAR_ROW (f, bottom);
973 right = PIXEL_TO_CHAR_COL (f, right);
974
975 /* Clip the rectangle to what can be visible. */
976 if (left < 0)
977 left = 0;
978 if (top < 0)
979 top = 0;
980 if (right > f->width)
981 right = f->width;
982 if (bottom > f->height)
983 bottom = f->height;
984
985 /* Get size in chars of the rectangle. */
986 cols = right - left;
987 rows = bottom - top;
988
989 /* If rectangle has zero area, return. */
990 if (rows <= 0) return;
991 if (cols <= 0) return;
992
993 /* Turn off the cursor if it is in the rectangle.
994 We will turn it back on afterward. */
995 if ((f->phys_cursor_x >= left) && (f->phys_cursor_x < right)
996 && (f->phys_cursor_y >= top) && (f->phys_cursor_y < bottom))
997 {
998 clear_cursor (f);
999 cursor_cleared = 1;
1000 }
1001
1002 /* Display the text in the rectangle, one text line at a time. */
1003
1004 for (y = top; y < bottom; y++)
1005 {
1006 GLYPH *line = &active_frame->glyphs[y][left];
1007
1008 if (! active_frame->enable[y] || left > active_frame->used[y])
1009 continue;
1010
1011 dumpglyphs (f,
1012 CHAR_TO_PIXEL_COL (f, left),
1013 CHAR_TO_PIXEL_ROW (f, y),
1014 line, min (cols, active_frame->used[y] - left),
1015 active_frame->highlight[y], 0);
1016 }
1017
1018 /* Turn the cursor on if we turned it off. */
1019
1020 if (cursor_cleared)
1021 x_display_cursor (f, 1);
1022}
1023\f
1024static void
1025frame_highlight (f)
1026 struct frame *f;
1027{
1028 x_display_cursor (f, 1);
1029}
1030
1031static void
1032frame_unhighlight (f)
1033 struct frame *f;
1034{
1035 x_display_cursor (f, 1);
1036}
1037
fbd6baed 1038static void w32_frame_rehighlight ();
ee78dc32
GV
1039static void x_frame_rehighlight ();
1040
1041/* The focus has changed. Update the frames as necessary to reflect
1042 the new situation. Note that we can't change the selected frame
1043 here, because the Lisp code we are interrupting might become confused.
1044 Each event gets marked with the frame in which it occurred, so the
1045 Lisp code can tell when the switch took place by examining the events. */
1046
1047void
1048x_new_focus_frame (dpyinfo, frame)
fbd6baed 1049 struct w32_display_info *dpyinfo;
ee78dc32
GV
1050 struct frame *frame;
1051{
fbd6baed 1052 struct frame *old_focus = dpyinfo->w32_focus_frame;
ee78dc32
GV
1053 int events_enqueued = 0;
1054
fbd6baed 1055 if (frame != dpyinfo->w32_focus_frame)
ee78dc32
GV
1056 {
1057 /* Set this before calling other routines, so that they see
fbd6baed
GV
1058 the correct value of w32_focus_frame. */
1059 dpyinfo->w32_focus_frame = frame;
ee78dc32
GV
1060
1061 if (old_focus && old_focus->auto_lower)
1062 x_lower_frame (old_focus);
1063
fbd6baed
GV
1064 if (dpyinfo->w32_focus_frame && dpyinfo->w32_focus_frame->auto_raise)
1065 pending_autoraise_frame = dpyinfo->w32_focus_frame;
ee78dc32
GV
1066 else
1067 pending_autoraise_frame = 0;
1068 }
1069
1070 x_frame_rehighlight (dpyinfo);
1071}
1072
1073/* Handle an event saying the mouse has moved out of an Emacs frame. */
1074
1075void
1076x_mouse_leave (dpyinfo)
fbd6baed 1077 struct w32_display_info *dpyinfo;
ee78dc32 1078{
fbd6baed 1079 x_new_focus_frame (dpyinfo, dpyinfo->w32_focus_event_frame);
ee78dc32
GV
1080}
1081
1082/* The focus has changed, or we have redirected a frame's focus to
1083 another frame (this happens when a frame uses a surrogate
1084 minibuffer frame). Shift the highlight as appropriate.
1085
1086 The FRAME argument doesn't necessarily have anything to do with which
1087 frame is being highlighted or unhighlighted; we only use it to find
1088 the appropriate display info. */
1089static void
fbd6baed 1090w32_frame_rehighlight (frame)
ee78dc32
GV
1091 struct frame *frame;
1092{
fbd6baed 1093 x_frame_rehighlight (FRAME_W32_DISPLAY_INFO (frame));
ee78dc32
GV
1094}
1095
1096static void
1097x_frame_rehighlight (dpyinfo)
fbd6baed 1098 struct w32_display_info *dpyinfo;
ee78dc32 1099{
fbd6baed 1100 struct frame *old_highlight = dpyinfo->w32_highlight_frame;
ee78dc32 1101
fbd6baed 1102 if (dpyinfo->w32_focus_frame)
ee78dc32 1103 {
fbd6baed
GV
1104 dpyinfo->w32_highlight_frame
1105 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->w32_focus_frame)))
1106 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->w32_focus_frame))
1107 : dpyinfo->w32_focus_frame);
1108 if (! FRAME_LIVE_P (dpyinfo->w32_highlight_frame))
ee78dc32 1109 {
fbd6baed
GV
1110 FRAME_FOCUS_FRAME (dpyinfo->w32_focus_frame) = Qnil;
1111 dpyinfo->w32_highlight_frame = dpyinfo->w32_focus_frame;
ee78dc32
GV
1112 }
1113 }
1114 else
fbd6baed 1115 dpyinfo->w32_highlight_frame = 0;
ee78dc32 1116
fbd6baed 1117 if (dpyinfo->w32_highlight_frame != old_highlight)
ee78dc32
GV
1118 {
1119 if (old_highlight)
1120 frame_unhighlight (old_highlight);
fbd6baed
GV
1121 if (dpyinfo->w32_highlight_frame)
1122 frame_highlight (dpyinfo->w32_highlight_frame);
ee78dc32
GV
1123 }
1124}
1125\f
1126/* Keyboard processing - modifier keys, etc. */
1127
1128/* Convert a keysym to its name. */
1129
1130char *
1131x_get_keysym_name (keysym)
1132 int keysym;
1133{
1134 /* Make static so we can always return it */
1135 static char value[100];
1136
1137 BLOCK_INPUT;
1138 GetKeyNameText(keysym, value, 100);
1139 UNBLOCK_INPUT;
1140
1141 return value;
1142}
1143\f
1144/* Mouse clicks and mouse movement. Rah. */
1145
1146/* Given a pixel position (PIX_X, PIX_Y) on the frame F, return
1147 glyph co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle
1148 that the glyph at X, Y occupies, if BOUNDS != 0.
1149 If NOCLIP is nonzero, do not force the value into range. */
1150
1151void
1152pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds, noclip)
1153 FRAME_PTR f;
1154 register int pix_x, pix_y;
1155 register int *x, *y;
1156 RECT *bounds;
1157 int noclip;
1158{
52cf03a1
GV
1159 /* Support tty mode: if Vwindow_system is nil, behave correctly. */
1160 if (NILP (Vwindow_system))
1161 {
1162 *x = pix_x;
1163 *y = pix_y;
1164 return;
1165 }
1166
ee78dc32
GV
1167 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
1168 even for negative values. */
1169 if (pix_x < 0)
fbd6baed 1170 pix_x -= FONT_WIDTH ((f)->output_data.w32->font) - 1;
ee78dc32 1171 if (pix_y < 0)
fbd6baed 1172 pix_y -= (f)->output_data.w32->line_height - 1;
ee78dc32
GV
1173
1174 pix_x = PIXEL_TO_CHAR_COL (f, pix_x);
1175 pix_y = PIXEL_TO_CHAR_ROW (f, pix_y);
1176
1177 if (bounds)
1178 {
1179 bounds->left = CHAR_TO_PIXEL_COL (f, pix_x);
1180 bounds->top = CHAR_TO_PIXEL_ROW (f, pix_y);
fbd6baed
GV
1181 bounds->right = bounds->left + FONT_WIDTH (f->output_data.w32->font) - 1;
1182 bounds->bottom = bounds->top + f->output_data.w32->line_height - 1;
ee78dc32
GV
1183 }
1184
1185 if (!noclip)
1186 {
1187 if (pix_x < 0)
1188 pix_x = 0;
1189 else if (pix_x > f->width)
1190 pix_x = f->width;
1191
1192 if (pix_y < 0)
1193 pix_y = 0;
1194 else if (pix_y > f->height)
1195 pix_y = f->height;
1196 }
1197
1198 *x = pix_x;
1199 *y = pix_y;
1200}
1201
1202void
1203glyph_to_pixel_coords (f, x, y, pix_x, pix_y)
1204 FRAME_PTR f;
1205 register int x, y;
1206 register int *pix_x, *pix_y;
1207{
52cf03a1
GV
1208 /* Support tty mode: if Vwindow_system is nil, behave correctly. */
1209 if (NILP (Vwindow_system))
1210 {
1211 *pix_x = x;
1212 *pix_y = y;
1213 return;
1214 }
1215
ee78dc32
GV
1216 *pix_x = CHAR_TO_PIXEL_COL (f, x);
1217 *pix_y = CHAR_TO_PIXEL_ROW (f, y);
1218}
1219
1220BOOL
1221parse_button (message, pbutton, pup)
1222 int message;
1223 int * pbutton;
1224 int * pup;
1225{
1226 int button = 0;
1227 int up = 0;
1228
1229 switch (message)
1230 {
1231 case WM_LBUTTONDOWN:
1232 button = 0;
1233 up = 0;
1234 break;
1235 case WM_LBUTTONUP:
1236 button = 0;
1237 up = 1;
1238 break;
1239 case WM_MBUTTONDOWN:
fbd6baed 1240 if (NILP (Vw32_swap_mouse_buttons))
52cf03a1
GV
1241 button = 1;
1242 else
1243 button = 2;
ee78dc32
GV
1244 up = 0;
1245 break;
1246 case WM_MBUTTONUP:
fbd6baed 1247 if (NILP (Vw32_swap_mouse_buttons))
52cf03a1
GV
1248 button = 1;
1249 else
1250 button = 2;
ee78dc32
GV
1251 up = 1;
1252 break;
1253 case WM_RBUTTONDOWN:
fbd6baed 1254 if (NILP (Vw32_swap_mouse_buttons))
52cf03a1
GV
1255 button = 2;
1256 else
1257 button = 1;
ee78dc32
GV
1258 up = 0;
1259 break;
1260 case WM_RBUTTONUP:
fbd6baed 1261 if (NILP (Vw32_swap_mouse_buttons))
52cf03a1
GV
1262 button = 2;
1263 else
1264 button = 1;
ee78dc32
GV
1265 up = 1;
1266 break;
1267 default:
1268 return (FALSE);
1269 }
1270
1271 if (pup) *pup = up;
1272 if (pbutton) *pbutton = button;
1273
1274 return (TRUE);
1275}
1276
1277
1278/* Prepare a mouse-event in *RESULT for placement in the input queue.
1279
1280 If the event is a button press, then note that we have grabbed
1281 the mouse. */
1282
1283static void
1284construct_mouse_click (result, msg, f)
1285 struct input_event *result;
fbd6baed 1286 W32Msg *msg;
ee78dc32
GV
1287 struct frame *f;
1288{
1289 int button;
1290 int up;
1291
1292 parse_button (msg->msg.message, &button, &up);
1293
1294 /* Make the event type no_event; we'll change that when we decide
1295 otherwise. */
1296 result->kind = mouse_click;
1297 result->code = button;
1298 result->timestamp = msg->msg.time;
1299 result->modifiers = (msg->dwModifiers
1300 | (up
1301 ? up_modifier
1302 : down_modifier));
1303
1304 {
1305 int row, column;
1306
1307 XSETINT (result->x, LOWORD (msg->msg.lParam));
1308 XSETINT (result->y, HIWORD (msg->msg.lParam));
1309 XSETFRAME (result->frame_or_window, f);
1310 }
1311}
1312
689004fa
GV
1313static void
1314construct_mouse_wheel (result, msg, f)
1315 struct input_event *result;
1316 W32Msg *msg;
1317 struct frame *f;
1318{
1319 POINT p;
1320 result->kind = mouse_wheel;
1321 result->code = (short) HIWORD (msg->msg.wParam);
1322 result->timestamp = msg->msg.time;
1323 result->modifiers = msg->dwModifiers;
1324 p.x = LOWORD (msg->msg.lParam);
1325 p.y = HIWORD (msg->msg.lParam);
1326 ScreenToClient(msg->msg.hwnd, &p);
1327 XSETINT (result->x, p.x);
1328 XSETINT (result->y, p.y);
1329 XSETFRAME (result->frame_or_window, f);
1330}
1331
ee78dc32
GV
1332\f
1333/* Function to report a mouse movement to the mainstream Emacs code.
1334 The input handler calls this.
1335
1336 We have received a mouse movement event, which is given in *event.
1337 If the mouse is over a different glyph than it was last time, tell
1338 the mainstream emacs code by setting mouse_moved. If not, ask for
1339 another motion event, so we can check again the next time it moves. */
1340
1341static void
1342note_mouse_movement (frame, msg)
1343 FRAME_PTR frame;
1344 MSG *msg;
1345{
1346 last_mouse_movement_time = msg->time;
1347
fbd6baed 1348 if (msg->hwnd != FRAME_W32_WINDOW (frame))
ee78dc32
GV
1349 {
1350 frame->mouse_moved = 1;
1351 last_mouse_scroll_bar = Qnil;
1352
1353 note_mouse_highlight (frame, -1, -1);
1354 }
1355
1356 /* Has the mouse moved off the glyph it was on at the last sighting? */
1357 else if (LOWORD (msg->lParam) < last_mouse_glyph.left
1358 || LOWORD (msg->lParam) > last_mouse_glyph.right
9bf7b6aa 1359 || HIWORD (msg->lParam) < last_mouse_glyph.top
ee78dc32
GV
1360 || HIWORD (msg->lParam) > last_mouse_glyph.bottom)
1361 {
1362 frame->mouse_moved = 1;
1363 last_mouse_scroll_bar = Qnil;
1364
1365 note_mouse_highlight (frame, LOWORD (msg->lParam), HIWORD (msg->lParam));
1366 }
1367}
1368
1369/* This is used for debugging, to turn off note_mouse_highlight. */
1370static int disable_mouse_highlight;
1371
1372/* Take proper action when the mouse has moved to position X, Y on frame F
1373 as regards highlighting characters that have mouse-face properties.
1374 Also dehighlighting chars where the mouse was before.
1375 X and Y can be negative or out of range. */
1376
1377static void
1378note_mouse_highlight (f, x, y)
1379 FRAME_PTR f;
1380 int x, y;
1381{
1382 int row, column, portion;
1383 RECT new_glyph;
1384 Lisp_Object window;
1385 struct window *w;
1386
1387 if (disable_mouse_highlight)
1388 return;
1389
fbd6baed
GV
1390 FRAME_W32_DISPLAY_INFO (f)->mouse_face_mouse_x = x;
1391 FRAME_W32_DISPLAY_INFO (f)->mouse_face_mouse_y = y;
1392 FRAME_W32_DISPLAY_INFO (f)->mouse_face_mouse_frame = f;
ee78dc32 1393
fbd6baed 1394 if (FRAME_W32_DISPLAY_INFO (f)->mouse_face_defer)
ee78dc32
GV
1395 return;
1396
1397 if (gc_in_progress)
1398 {
fbd6baed 1399 FRAME_W32_DISPLAY_INFO (f)->mouse_face_deferred_gc = 1;
ee78dc32
GV
1400 return;
1401 }
1402
1403 /* Find out which glyph the mouse is on. */
1404 pixel_to_glyph_coords (f, x, y, &column, &row,
fbd6baed 1405 &new_glyph, FRAME_W32_DISPLAY_INFO (f)->grabbed);
ee78dc32
GV
1406
1407 /* Which window is that in? */
1408 window = window_from_coordinates (f, column, row, &portion);
1409 w = XWINDOW (window);
1410
1411 /* If we were displaying active text in another window, clear that. */
fbd6baed
GV
1412 if (! EQ (window, FRAME_W32_DISPLAY_INFO (f)->mouse_face_window))
1413 clear_mouse_face (FRAME_W32_DISPLAY_INFO (f));
ee78dc32
GV
1414
1415 /* Are we in a window whose display is up to date?
1416 And verify the buffer's text has not changed. */
1417 if (WINDOWP (window) && portion == 0 && row >= 0 && column >= 0
1418 && row < FRAME_HEIGHT (f) && column < FRAME_WIDTH (f)
1419 && EQ (w->window_end_valid, w->buffer)
bade65fd
RS
1420 && w->last_modified == BUF_MODIFF (XBUFFER (w->buffer))
1421 && w->last_overlay_modified == BUF_OVERLAY_MODIFF (XBUFFER (w->buffer)))
ee78dc32
GV
1422 {
1423 int *ptr = FRAME_CURRENT_GLYPHS (f)->charstarts[row];
1424 int i, pos;
1425
1426 /* Find which buffer position the mouse corresponds to. */
1427 for (i = column; i >= 0; i--)
1428 if (ptr[i] > 0)
1429 break;
1430 pos = ptr[i];
1431 /* Is it outside the displayed active region (if any)? */
1432 if (pos <= 0)
fbd6baed
GV
1433 clear_mouse_face (FRAME_W32_DISPLAY_INFO (f));
1434 else if (! (EQ (window, FRAME_W32_DISPLAY_INFO (f)->mouse_face_window)
1435 && row >= FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_row
1436 && row <= FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_row
1437 && (row > FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_row
1438 || column >= FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_col)
1439 && (row < FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_row
1440 || column < FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_col
1441 || FRAME_W32_DISPLAY_INFO (f)->mouse_face_past_end)))
ee78dc32
GV
1442 {
1443 Lisp_Object mouse_face, overlay, position;
1444 Lisp_Object *overlay_vec;
1445 int len, noverlays, ignor1;
1446 struct buffer *obuf;
1447 int obegv, ozv;
1448
1449 /* If we get an out-of-range value, return now; avoid an error. */
1450 if (pos > BUF_Z (XBUFFER (w->buffer)))
1451 return;
1452
1453 /* Make the window's buffer temporarily current for
1454 overlays_at and compute_char_face. */
1455 obuf = current_buffer;
1456 current_buffer = XBUFFER (w->buffer);
1457 obegv = BEGV;
1458 ozv = ZV;
1459 BEGV = BEG;
1460 ZV = Z;
1461
1462 /* Yes. Clear the display of the old active region, if any. */
fbd6baed 1463 clear_mouse_face (FRAME_W32_DISPLAY_INFO (f));
ee78dc32
GV
1464
1465 /* Is this char mouse-active? */
1466 XSETINT (position, pos);
1467
1468 len = 10;
1469 overlay_vec = (Lisp_Object *) xmalloc (len * sizeof (Lisp_Object));
1470
1471 /* Put all the overlays we want in a vector in overlay_vec.
1472 Store the length in len. */
1473 noverlays = overlays_at (XINT (pos), 1, &overlay_vec, &len,
1474 NULL, NULL);
1475 noverlays = sort_overlays (overlay_vec, noverlays, w);
1476
1477 /* Find the highest priority overlay that has a mouse-face prop. */
1478 overlay = Qnil;
1479 for (i = 0; i < noverlays; i++)
1480 {
1481 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
1482 if (!NILP (mouse_face))
1483 {
1484 overlay = overlay_vec[i];
1485 break;
1486 }
1487 }
1488 free (overlay_vec);
1489 /* If no overlay applies, get a text property. */
1490 if (NILP (overlay))
1491 mouse_face = Fget_text_property (position, Qmouse_face, w->buffer);
1492
1493 /* Handle the overlay case. */
1494 if (! NILP (overlay))
1495 {
1496 /* Find the range of text around this char that
1497 should be active. */
1498 Lisp_Object before, after;
1499 int ignore;
1500
1501 before = Foverlay_start (overlay);
1502 after = Foverlay_end (overlay);
1503 /* Record this as the current active region. */
1504 fast_find_position (window, before,
fbd6baed
GV
1505 &FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_col,
1506 &FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_row);
1507 FRAME_W32_DISPLAY_INFO (f)->mouse_face_past_end
ee78dc32 1508 = !fast_find_position (window, after,
fbd6baed
GV
1509 &FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_col,
1510 &FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_row);
1511 FRAME_W32_DISPLAY_INFO (f)->mouse_face_window = window;
1512 FRAME_W32_DISPLAY_INFO (f)->mouse_face_face_id
ee78dc32
GV
1513 = compute_char_face (f, w, pos, 0, 0,
1514 &ignore, pos + 1, 1);
1515
1516 /* Display it as active. */
fbd6baed 1517 show_mouse_face (FRAME_W32_DISPLAY_INFO (f), 1);
ee78dc32
GV
1518 }
1519 /* Handle the text property case. */
1520 else if (! NILP (mouse_face))
1521 {
1522 /* Find the range of text around this char that
1523 should be active. */
1524 Lisp_Object before, after, beginning, end;
1525 int ignore;
1526
1527 beginning = Fmarker_position (w->start);
1528 XSETINT (end, (BUF_Z (XBUFFER (w->buffer))
1529 - XFASTINT (w->window_end_pos)));
1530 before
1531 = Fprevious_single_property_change (make_number (pos + 1),
1532 Qmouse_face,
1533 w->buffer, beginning);
1534 after
1535 = Fnext_single_property_change (position, Qmouse_face,
1536 w->buffer, end);
1537 /* Record this as the current active region. */
1538 fast_find_position (window, before,
fbd6baed
GV
1539 &FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_col,
1540 &FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_row);
1541 FRAME_W32_DISPLAY_INFO (f)->mouse_face_past_end
ee78dc32 1542 = !fast_find_position (window, after,
fbd6baed
GV
1543 &FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_col,
1544 &FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_row);
1545 FRAME_W32_DISPLAY_INFO (f)->mouse_face_window = window;
1546 FRAME_W32_DISPLAY_INFO (f)->mouse_face_face_id
ee78dc32
GV
1547 = compute_char_face (f, w, pos, 0, 0,
1548 &ignore, pos + 1, 1);
1549
1550 /* Display it as active. */
fbd6baed 1551 show_mouse_face (FRAME_W32_DISPLAY_INFO (f), 1);
ee78dc32
GV
1552 }
1553 BEGV = obegv;
1554 ZV = ozv;
1555 current_buffer = obuf;
1556 }
1557 }
1558}
1559\f
1560/* Find the row and column of position POS in window WINDOW.
1561 Store them in *COLUMNP and *ROWP.
1562 This assumes display in WINDOW is up to date.
1563 If POS is above start of WINDOW, return coords
1564 of start of first screen line.
1565 If POS is after end of WINDOW, return coords of end of last screen line.
1566
1567 Value is 1 if POS is in range, 0 if it was off screen. */
1568
1569static int
1570fast_find_position (window, pos, columnp, rowp)
1571 Lisp_Object window;
1572 int pos;
1573 int *columnp, *rowp;
1574{
1575 struct window *w = XWINDOW (window);
1576 FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
1577 int i;
1578 int row = 0;
03218728 1579 int left = WINDOW_LEFT_MARGIN (w);
ee78dc32
GV
1580 int top = w->top;
1581 int height = XFASTINT (w->height) - ! MINI_WINDOW_P (w);
1582 int width = window_internal_width (w);
1583 int *charstarts;
1584 int lastcol;
1585 int maybe_next_line = 0;
1586
1587 /* Find the right row. */
1588 for (i = 0;
1589 i < height;
1590 i++)
1591 {
1592 int linestart = FRAME_CURRENT_GLYPHS (f)->charstarts[top + i][left];
1593 if (linestart > pos)
1594 break;
1595 /* If the position sought is the end of the buffer,
1596 don't include the blank lines at the bottom of the window. */
1597 if (linestart == pos && pos == BUF_ZV (XBUFFER (w->buffer)))
1598 {
1599 maybe_next_line = 1;
1600 break;
1601 }
1602 if (linestart > 0)
1603 row = i;
1604 }
1605
1606 /* Find the right column with in it. */
1607 charstarts = FRAME_CURRENT_GLYPHS (f)->charstarts[top + row];
1608 lastcol = left;
1609 for (i = 0; i < width; i++)
1610 {
1611 if (charstarts[left + i] == pos)
1612 {
1613 *rowp = row + top;
1614 *columnp = i + left;
1615 return 1;
1616 }
1617 else if (charstarts[left + i] > pos)
1618 break;
1619 else if (charstarts[left + i] > 0)
1620 lastcol = left + i;
1621 }
1622
1623 /* If we're looking for the end of the buffer,
1624 and we didn't find it in the line we scanned,
1625 use the start of the following line. */
1626 if (maybe_next_line)
1627 {
1628 row++;
1629 i = 0;
1630 }
1631
1632 *rowp = row + top;
1633 *columnp = lastcol;
1634 return 0;
1635}
1636
1637/* Display the active region described by mouse_face_*
1638 in its mouse-face if HL > 0, in its normal face if HL = 0. */
1639
1640static void
1641show_mouse_face (dpyinfo, hl)
fbd6baed 1642 struct w32_display_info *dpyinfo;
ee78dc32
GV
1643 int hl;
1644{
1645 struct window *w = XWINDOW (dpyinfo->mouse_face_window);
1646 int width = window_internal_width (w);
1647 FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
1648 int i;
1649 int cursor_off = 0;
1650 int old_curs_x = curs_x;
1651 int old_curs_y = curs_y;
1652
1653 /* Set these variables temporarily
1654 so that if we have to turn the cursor off and on again
1655 we will put it back at the same place. */
1656 curs_x = f->phys_cursor_x;
1657 curs_y = f->phys_cursor_y;
1658
fbd6baed
GV
1659 for (i = FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_row;
1660 i <= FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_row; i++)
ee78dc32 1661 {
fbd6baed
GV
1662 int column = (i == FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_row
1663 ? FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_col
03218728 1664 : WINDOW_LEFT_MARGIN (w));
fbd6baed
GV
1665 int endcolumn = (i == FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_row
1666 ? FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_col
03218728 1667 : WINDOW_LEFT_MARGIN (w) + width);
ee78dc32
GV
1668 endcolumn = min (endcolumn, FRAME_CURRENT_GLYPHS (f)->used[i]);
1669
1670 /* If the cursor's in the text we are about to rewrite,
1671 turn the cursor off. */
1672 if (i == curs_y
689004fa
GV
1673 && curs_x >= column - 1
1674 && curs_x <= endcolumn)
ee78dc32
GV
1675 {
1676 x_display_cursor (f, 0);
1677 cursor_off = 1;
1678 }
1679
1680 dumpglyphs (f,
1681 CHAR_TO_PIXEL_COL (f, column),
1682 CHAR_TO_PIXEL_ROW (f, i),
1683 FRAME_CURRENT_GLYPHS (f)->glyphs[i] + column,
1684 endcolumn - column,
1685 /* Highlight with mouse face if hl > 0. */
1686 hl > 0 ? 3 : 0, 0);
1687 }
1688
1689 /* If we turned the cursor off, turn it back on. */
1690 if (cursor_off)
1691 x_display_cursor (f, 1);
1692
1693 curs_x = old_curs_x;
1694 curs_y = old_curs_y;
1695
1696 /* Change the mouse cursor according to the value of HL. */
1697 if (hl > 0)
fbd6baed 1698 SetCursor (f->output_data.w32->cross_cursor);
ee78dc32 1699 else
fbd6baed 1700 SetCursor (f->output_data.w32->text_cursor);
ee78dc32
GV
1701}
1702
1703/* Clear out the mouse-highlighted active region.
1704 Redraw it unhighlighted first. */
1705
1706static void
1707clear_mouse_face (dpyinfo)
fbd6baed 1708 struct w32_display_info *dpyinfo;
ee78dc32
GV
1709{
1710 if (! NILP (dpyinfo->mouse_face_window))
1711 show_mouse_face (dpyinfo, 0);
1712
1713 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
1714 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
1715 dpyinfo->mouse_face_window = Qnil;
1716}
1717\f
1718struct scroll_bar *x_window_to_scroll_bar ();
1719static void x_scroll_bar_report_motion ();
1720
1721/* Return the current position of the mouse.
1722 *fp should be a frame which indicates which display to ask about.
1723
1724 If the mouse movement started in a scroll bar, set *fp, *bar_window,
1725 and *part to the frame, window, and scroll bar part that the mouse
1726 is over. Set *x and *y to the portion and whole of the mouse's
1727 position on the scroll bar.
1728
1729 If the mouse movement started elsewhere, set *fp to the frame the
1730 mouse is on, *bar_window to nil, and *x and *y to the character cell
1731 the mouse is over.
1732
1733 Set *time to the server timestamp for the time at which the mouse
1734 was at this position.
1735
1736 Don't store anything if we don't have a valid set of values to report.
1737
1738 This clears the mouse_moved flag, so we can wait for the next mouse
1739 movement. This also calls XQueryPointer, which will cause the
1740 server to give us another MotionNotify when the mouse moves
1741 again. */
1742
1743static void
fbd6baed 1744w32_mouse_position (fp, insist, bar_window, part, x, y, time)
ee78dc32
GV
1745 FRAME_PTR *fp;
1746 int insist;
1747 Lisp_Object *bar_window;
1748 enum scroll_bar_part *part;
1749 Lisp_Object *x, *y;
1750 unsigned long *time;
1751{
1752 FRAME_PTR f1;
1753
1754 BLOCK_INPUT;
1755
95fa970d 1756 if (! NILP (last_mouse_scroll_bar) && insist == 0)
689004fa 1757 /* This is never called at the moment. */
ee78dc32
GV
1758 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
1759 else
1760 {
1761 POINT pt;
1762
1763 Lisp_Object frame, tail;
1764
1765 /* Clear the mouse-moved flag for every frame on this display. */
1766 FOR_EACH_FRAME (tail, frame)
1767 XFRAME (frame)->mouse_moved = 0;
1768
1769 last_mouse_scroll_bar = Qnil;
1770
1771 GetCursorPos (&pt);
1772
1773 /* Now we have a position on the root; find the innermost window
1774 containing the pointer. */
1775 {
fbd6baed 1776 if (FRAME_W32_DISPLAY_INFO (*fp)->grabbed && last_mouse_frame
ee78dc32
GV
1777 && FRAME_LIVE_P (last_mouse_frame))
1778 {
1779 f1 = last_mouse_frame;
1780 }
1781 else
1782 {
1783 /* Is win one of our frames? */
fbd6baed 1784 f1 = x_window_to_frame (FRAME_W32_DISPLAY_INFO (*fp), WindowFromPoint(pt));
ee78dc32
GV
1785 }
1786
1787 /* If not, is it one of our scroll bars? */
1788 if (! f1)
1789 {
1790 struct scroll_bar *bar = x_window_to_scroll_bar (WindowFromPoint(pt));
1791
1792 if (bar)
1793 {
1794 f1 = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
1795 }
1796 }
1797
95fa970d 1798 if (f1 == 0 && insist > 0)
ee78dc32
GV
1799 f1 = selected_frame;
1800
1801 if (f1)
1802 {
1803 int ignore1, ignore2;
1804
fbd6baed 1805 ScreenToClient (FRAME_W32_WINDOW (f1), &pt);
ee78dc32
GV
1806
1807 /* Ok, we found a frame. Store all the values. */
1808
1809 pixel_to_glyph_coords (f1, pt.x, pt.y, &ignore1, &ignore2,
1810 &last_mouse_glyph,
fbd6baed 1811 FRAME_W32_DISPLAY_INFO (f1)->grabbed
ee78dc32
GV
1812 || insist);
1813
1814 *bar_window = Qnil;
1815 *part = 0;
1816 *fp = f1;
1817 XSETINT (*x, pt.x);
1818 XSETINT (*y, pt.y);
1819 *time = last_mouse_movement_time;
1820 }
1821 }
1822 }
1823
1824 UNBLOCK_INPUT;
1825}
1826\f
1827/* Scroll bar support. */
1828
1829/* Given an window ID, find the struct scroll_bar which manages it.
1830 This can be called in GC, so we have to make sure to strip off mark
1831 bits. */
1832struct scroll_bar *
1833x_window_to_scroll_bar (window_id)
1834 Window window_id;
1835{
1836 Lisp_Object tail, frame;
1837
1838 for (tail = Vframe_list;
1839 XGCTYPE (tail) == Lisp_Cons;
1840 tail = XCONS (tail)->cdr)
1841 {
1842 Lisp_Object frame, bar, condemned;
1843
1844 frame = XCONS (tail)->car;
1845 /* All elements of Vframe_list should be frames. */
1846 if (! GC_FRAMEP (frame))
1847 abort ();
1848
1849 /* Scan this frame's scroll bar list for a scroll bar with the
1850 right window ID. */
1851 condemned = FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame));
1852 for (bar = FRAME_SCROLL_BARS (XFRAME (frame));
1853 /* This trick allows us to search both the ordinary and
1854 condemned scroll bar lists with one loop. */
1855 ! GC_NILP (bar) || (bar = condemned,
1856 condemned = Qnil,
1857 ! GC_NILP (bar));
1858 bar = XSCROLL_BAR (bar)->next)
fbd6baed 1859 if (SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar)) == window_id)
ee78dc32
GV
1860 return XSCROLL_BAR (bar);
1861 }
1862
1863 return 0;
1864}
1865
1866HWND
1867my_create_scrollbar (f, bar)
1868 struct frame * f;
1869 struct scroll_bar * bar;
1870{
689004fa
GV
1871 return (HWND) SendMessage (FRAME_W32_WINDOW (f),
1872 WM_EMACS_CREATESCROLLBAR, (WPARAM) f,
1873 (LPARAM) bar);
ee78dc32
GV
1874}
1875
52cf03a1
GV
1876//#define ATTACH_THREADS
1877
689004fa
GV
1878BOOL
1879my_show_window (FRAME_PTR f, HWND hwnd, int how)
52cf03a1
GV
1880{
1881#ifndef ATTACH_THREADS
689004fa
GV
1882 return SendMessage (FRAME_W32_WINDOW (f), WM_EMACS_SHOWWINDOW,
1883 (WPARAM) hwnd, (LPARAM) how);
52cf03a1 1884#else
689004fa 1885 return ShowWindow (hwnd, how);
52cf03a1
GV
1886#endif
1887}
1888
1889void
1890my_set_window_pos (HWND hwnd, HWND hwndAfter,
689004fa 1891 int x, int y, int cx, int cy, UINT flags)
52cf03a1
GV
1892{
1893#ifndef ATTACH_THREADS
689004fa
GV
1894 WINDOWPOS pos;
1895 pos.hwndInsertAfter = hwndAfter;
52cf03a1
GV
1896 pos.x = x;
1897 pos.y = y;
1898 pos.cx = cx;
1899 pos.cy = cy;
1900 pos.flags = flags;
1901 SendMessage (hwnd, WM_EMACS_SETWINDOWPOS, (WPARAM) &pos, 0);
1902#else
1903 SetWindowPos (hwnd, hwndAfter, x, y, cx, cy, flags);
1904#endif
1905}
1906
689004fa
GV
1907BOOL
1908my_set_focus (f, hwnd)
1909 struct frame * f;
1910 HWND hwnd;
1911{
1912 SendMessage (FRAME_W32_WINDOW (f), WM_EMACS_SETFOCUS,
1913 (WPARAM) hwnd, 0);
1914}
1915
ee78dc32
GV
1916void
1917my_destroy_window (f, hwnd)
1918 struct frame * f;
1919 HWND hwnd;
1920{
fbd6baed 1921 SendMessage (FRAME_W32_WINDOW (f), WM_EMACS_DESTROYWINDOW,
ee78dc32
GV
1922 (WPARAM) hwnd, 0);
1923}
1924
1925/* Open a new window to serve as a scroll bar, and return the
1926 scroll bar vector for it. */
1927static struct scroll_bar *
1928x_scroll_bar_create (window, top, left, width, height)
1929 struct window *window;
1930 int top, left, width, height;
1931{
1932 FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
1933 struct scroll_bar *bar
1934 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
1935 HWND hwnd;
1936
1937 BLOCK_INPUT;
1938
1939 XSETWINDOW (bar->window, window);
1940 XSETINT (bar->top, top);
1941 XSETINT (bar->left, left);
1942 XSETINT (bar->width, width);
1943 XSETINT (bar->height, height);
1944 XSETINT (bar->start, 0);
1945 XSETINT (bar->end, 0);
1946 bar->dragging = Qnil;
1947
1948 /* Requires geometry to be set before call to create the real window */
1949
1950 hwnd = my_create_scrollbar (f, bar);
1951
689004fa
GV
1952 if (pfnSetScrollInfo)
1953 {
1954 SCROLLINFO si;
1955
1956 si.cbSize = sizeof (si);
1957 si.fMask = SIF_ALL;
1958 si.nMin = 0;
1959 si.nMax = VERTICAL_SCROLL_BAR_TOP_RANGE (height)
1960 + VERTICAL_SCROLL_BAR_MIN_HANDLE;
1961 si.nPage = si.nMax;
1962 si.nPos = 0;
1963
1964 pfnSetScrollInfo (hwnd, SB_CTL, &si, FALSE);
1965 }
1966 else
1967 {
1968 SetScrollRange (hwnd, SB_CTL, 0, VERTICAL_SCROLL_BAR_TOP_RANGE (height), FALSE);
1969 SetScrollPos (hwnd, SB_CTL, 0, FALSE);
1970 }
ee78dc32 1971
fbd6baed 1972 SET_SCROLL_BAR_W32_WINDOW (bar, hwnd);
ee78dc32
GV
1973
1974 /* Add bar to its frame's list of scroll bars. */
1975 bar->next = FRAME_SCROLL_BARS (f);
1976 bar->prev = Qnil;
1977 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
1978 if (! NILP (bar->next))
1979 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
1980
1981 UNBLOCK_INPUT;
1982
1983 return bar;
1984}
1985
1986/* Draw BAR's handle in the proper position.
1987 If the handle is already drawn from START to END, don't bother
1988 redrawing it, unless REBUILD is non-zero; in that case, always
1989 redraw it. (REBUILD is handy for drawing the handle after expose
1990 events.)
1991
1992 Normally, we want to constrain the start and end of the handle to
1993 fit inside its rectangle, but if the user is dragging the scroll bar
1994 handle, we want to let them drag it down all the way, so that the
1995 bar's top is as far down as it goes; otherwise, there's no way to
1996 move to the very end of the buffer. */
1997static void
1998x_scroll_bar_set_handle (bar, start, end, rebuild)
1999 struct scroll_bar *bar;
2000 int start, end;
2001 int rebuild;
2002{
2003 int dragging = ! NILP (bar->dragging);
fbd6baed 2004 Window w = SCROLL_BAR_W32_WINDOW (bar);
ee78dc32
GV
2005 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
2006
2007 /* If the display is already accurate, do nothing. */
2008 if (! rebuild
2009 && start == XINT (bar->start)
2010 && end == XINT (bar->end))
2011 return;
2012
2013 BLOCK_INPUT;
2014
689004fa
GV
2015 {
2016 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar->height));
2017
2018 /* Make sure the values are reasonable, and try to preserve
2019 the distance between start and end. */
2020 {
2021 int length = end - start;
2022
2023 if (start < 0)
2024 start = 0;
2025 else if (start > top_range)
2026 start = top_range;
2027 end = start + length;
2028
2029 if (end < start)
2030 end = start;
2031 else if (end > top_range && ! dragging)
2032 end = top_range;
2033 }
2034 }
2035
ee78dc32
GV
2036 /* Store the adjusted setting in the scroll bar. */
2037 XSETINT (bar->start, start);
2038 XSETINT (bar->end, end);
2039
689004fa
GV
2040 /* If being dragged, let scroll bar update itself. */
2041 if (!dragging)
2042 {
2043 if (pfnSetScrollInfo)
2044 {
2045 SCROLLINFO si;
2046
2047 si.cbSize = sizeof (si);
2048 si.fMask = SIF_PAGE | SIF_POS;
2049 si.nPage = end - start + VERTICAL_SCROLL_BAR_MIN_HANDLE;
2050 si.nPos = start;
2051
2052 pfnSetScrollInfo (w, SB_CTL, &si, TRUE);
2053 }
2054 else
2055 SetScrollPos (w, SB_CTL, start, TRUE);
2056 }
ee78dc32
GV
2057
2058 UNBLOCK_INPUT;
2059}
2060
2061/* Move a scroll bar around on the screen, to accommodate changing
2062 window configurations. */
2063static void
2064x_scroll_bar_move (bar, top, left, width, height)
2065 struct scroll_bar *bar;
2066 int top, left, width, height;
2067{
fbd6baed 2068 Window w = SCROLL_BAR_W32_WINDOW (bar);
ee78dc32
GV
2069 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
2070
689004fa
GV
2071 /* If already correctly positioned, do nothing. */
2072 if ( XINT (bar->left) == left
2073 && XINT (bar->top) == top
2074 && XINT (bar->width) == width
2075 && XINT (bar->height) == height )
2076 {
2077 /* Redraw after clear_frame. */
2078 if (!my_show_window (f, w, SW_NORMAL))
2079 InvalidateRect (w, NULL, FALSE);
2080 return;
2081 }
2082
ee78dc32
GV
2083 BLOCK_INPUT;
2084
689004fa
GV
2085 /* Make sure scroll bar is "visible" before moving, to ensure the
2086 area of the parent window now exposed will be refreshed. */
2087 my_show_window (f, w, SW_HIDE);
ee78dc32 2088 MoveWindow (w, left, top, width, height, TRUE);
689004fa
GV
2089 if (pfnSetScrollInfo)
2090 {
2091 SCROLLINFO si;
2092
2093 si.cbSize = sizeof (si);
2094 si.fMask = SIF_RANGE;
2095 si.nMin = 0;
2096 si.nMax = VERTICAL_SCROLL_BAR_TOP_RANGE (height)
2097 + VERTICAL_SCROLL_BAR_MIN_HANDLE;
2098
2099 pfnSetScrollInfo (w, SB_CTL, &si, FALSE);
2100 }
2101 else
2102 SetScrollRange (w, SB_CTL, 0, VERTICAL_SCROLL_BAR_TOP_RANGE (height), FALSE);
2103 my_show_window (f, w, SW_NORMAL);
2104// InvalidateRect (w, NULL, FALSE);
ee78dc32
GV
2105
2106 XSETINT (bar->left, left);
2107 XSETINT (bar->top, top);
2108 XSETINT (bar->width, width);
2109 XSETINT (bar->height, height);
2110
2111 UNBLOCK_INPUT;
2112}
2113
2114/* Destroy the window for BAR, and set its Emacs window's scroll bar
2115 to nil. */
2116static void
2117x_scroll_bar_remove (bar)
2118 struct scroll_bar *bar;
2119{
2120 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
2121
2122 BLOCK_INPUT;
2123
2124 /* Destroy the window. */
fbd6baed 2125 my_destroy_window (f, SCROLL_BAR_W32_WINDOW (bar));
ee78dc32
GV
2126
2127 /* Disassociate this scroll bar from its window. */
2128 XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
2129
2130 UNBLOCK_INPUT;
2131}
2132
2133/* Set the handle of the vertical scroll bar for WINDOW to indicate
2134 that we are displaying PORTION characters out of a total of WHOLE
2135 characters, starting at POSITION. If WINDOW has no scroll bar,
2136 create one. */
2137static void
fbd6baed 2138w32_set_vertical_scroll_bar (window, portion, whole, position)
ee78dc32
GV
2139 struct window *window;
2140 int portion, whole, position;
2141{
2142 FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
2143 int top = XINT (window->top);
2144 int left = WINDOW_VERTICAL_SCROLL_BAR_COLUMN (window);
2145 int height = WINDOW_VERTICAL_SCROLL_BAR_HEIGHT (window);
2146
2147 /* Where should this scroll bar be, pixelwise? */
2148 int pixel_top = CHAR_TO_PIXEL_ROW (f, top);
2149 int pixel_left = CHAR_TO_PIXEL_COL (f, left);
2150 int pixel_width
2151 = (FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0
2152 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f)
fbd6baed 2153 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.w32->font)));
ee78dc32
GV
2154 int pixel_height = VERTICAL_SCROLL_BAR_PIXEL_HEIGHT (f, height);
2155
2156 struct scroll_bar *bar;
2157
2158 /* Does the scroll bar exist yet? */
2159 if (NILP (window->vertical_scroll_bar))
2160 bar = x_scroll_bar_create (window,
2161 pixel_top, pixel_left,
2162 pixel_width, pixel_height);
2163 else
2164 {
2165 /* It may just need to be moved and resized. */
2166 bar = XSCROLL_BAR (window->vertical_scroll_bar);
2167 x_scroll_bar_move (bar, pixel_top, pixel_left, pixel_width, pixel_height);
2168 }
2169
689004fa
GV
2170 /* Set the scroll bar's current state. */
2171 {
2172 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (pixel_height);
ee78dc32 2173
689004fa
GV
2174 if (whole == 0)
2175 x_scroll_bar_set_handle (bar, 0, top_range, 0);
2176 else
2177 {
2178 int start = (int) (((double) position * top_range) / whole);
2179 int end = (int) (((double) (position + portion) * top_range) / whole);
ee78dc32 2180
689004fa
GV
2181 x_scroll_bar_set_handle (bar, start, end, 0);
2182 }
2183 }
ee78dc32
GV
2184
2185 XSETVECTOR (window->vertical_scroll_bar, bar);
2186}
2187
2188
2189/* The following three hooks are used when we're doing a thorough
2190 redisplay of the frame. We don't explicitly know which scroll bars
2191 are going to be deleted, because keeping track of when windows go
2192 away is a real pain - "Can you say set-window-configuration, boys
2193 and girls?" Instead, we just assert at the beginning of redisplay
2194 that *all* scroll bars are to be removed, and then save a scroll bar
2195 from the fiery pit when we actually redisplay its window. */
2196
2197/* Arrange for all scroll bars on FRAME to be removed at the next call
2198 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
2199 `*redeem_scroll_bar_hook' is applied to its window before the judgement. */
2200static void
fbd6baed 2201w32_condemn_scroll_bars (frame)
ee78dc32
GV
2202 FRAME_PTR frame;
2203{
2204 /* The condemned list should be empty at this point; if it's not,
2205 then the rest of Emacs isn't using the condemn/redeem/judge
2206 protocol correctly. */
2207 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
2208 abort ();
2209
2210 /* Move them all to the "condemned" list. */
2211 FRAME_CONDEMNED_SCROLL_BARS (frame) = FRAME_SCROLL_BARS (frame);
2212 FRAME_SCROLL_BARS (frame) = Qnil;
2213}
2214
2215/* Unmark WINDOW's scroll bar for deletion in this judgement cycle.
2216 Note that WINDOW isn't necessarily condemned at all. */
2217static void
fbd6baed 2218w32_redeem_scroll_bar (window)
ee78dc32
GV
2219 struct window *window;
2220{
2221 struct scroll_bar *bar;
2222
2223 /* We can't redeem this window's scroll bar if it doesn't have one. */
2224 if (NILP (window->vertical_scroll_bar))
2225 abort ();
2226
2227 bar = XSCROLL_BAR (window->vertical_scroll_bar);
2228
2229 /* Unlink it from the condemned list. */
2230 {
2231 FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
2232
2233 if (NILP (bar->prev))
2234 {
2235 /* If the prev pointer is nil, it must be the first in one of
2236 the lists. */
2237 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
2238 /* It's not condemned. Everything's fine. */
2239 return;
2240 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
2241 window->vertical_scroll_bar))
2242 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
2243 else
2244 /* If its prev pointer is nil, it must be at the front of
2245 one or the other! */
2246 abort ();
2247 }
2248 else
2249 XSCROLL_BAR (bar->prev)->next = bar->next;
2250
2251 if (! NILP (bar->next))
2252 XSCROLL_BAR (bar->next)->prev = bar->prev;
2253
2254 bar->next = FRAME_SCROLL_BARS (f);
2255 bar->prev = Qnil;
2256 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
2257 if (! NILP (bar->next))
2258 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
2259 }
2260}
2261
2262/* Remove all scroll bars on FRAME that haven't been saved since the
2263 last call to `*condemn_scroll_bars_hook'. */
2264static void
fbd6baed 2265w32_judge_scroll_bars (f)
ee78dc32
GV
2266 FRAME_PTR f;
2267{
2268 Lisp_Object bar, next;
2269
2270 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
2271
2272 /* Clear out the condemned list now so we won't try to process any
2273 more events on the hapless scroll bars. */
2274 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
2275
2276 for (; ! NILP (bar); bar = next)
2277 {
2278 struct scroll_bar *b = XSCROLL_BAR (bar);
2279
2280 x_scroll_bar_remove (b);
2281
2282 next = b->next;
2283 b->next = b->prev = Qnil;
2284 }
2285
2286 /* Now there should be no references to the condemned scroll bars,
2287 and they should get garbage-collected. */
2288}
2289
2290/* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
2291 is set to something other than no_event, it is enqueued.
2292
2293 This may be called from a signal handler, so we have to ignore GC
2294 mark bits. */
2c28562d 2295
52cf03a1 2296static int
ee78dc32
GV
2297x_scroll_bar_handle_click (bar, msg, emacs_event)
2298 struct scroll_bar *bar;
fbd6baed 2299 W32Msg *msg;
ee78dc32
GV
2300 struct input_event *emacs_event;
2301{
2302 if (! GC_WINDOWP (bar->window))
2303 abort ();
2304
fbd6baed 2305 emacs_event->kind = w32_scroll_bar_click;
ee78dc32 2306 emacs_event->code = 0;
52cf03a1
GV
2307 /* not really meaningful to distinguish up/down */
2308 emacs_event->modifiers = msg->dwModifiers;
ee78dc32
GV
2309 emacs_event->frame_or_window = bar->window;
2310 emacs_event->timestamp = msg->msg.time;
2311
2312 {
689004fa
GV
2313 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar->height));
2314 int y;
2315 int dragging = !NILP (bar->dragging);
2316
2317 if (pfnGetScrollInfo)
2318 {
2319 SCROLLINFO si;
2320
2321 si.cbSize = sizeof (si);
2322 si.fMask = SIF_POS;
2323
2324 pfnGetScrollInfo ((HWND) msg->msg.lParam, SB_CTL, &si);
2325 y = si.nPos;
2326 }
2327 else
2328 y = GetScrollPos ((HWND) msg->msg.lParam, SB_CTL);
2329
2330 bar->dragging = Qnil;
ee78dc32
GV
2331
2332 switch (LOWORD (msg->msg.wParam))
2c28562d 2333 {
2c28562d 2334 case SB_LINEDOWN:
52cf03a1 2335 emacs_event->part = scroll_bar_down_arrow;
ee78dc32 2336 break;
2c28562d 2337 case SB_LINEUP:
52cf03a1 2338 emacs_event->part = scroll_bar_up_arrow;
ee78dc32 2339 break;
2c28562d 2340 case SB_PAGEUP:
ee78dc32
GV
2341 emacs_event->part = scroll_bar_above_handle;
2342 break;
2c28562d 2343 case SB_PAGEDOWN:
ee78dc32
GV
2344 emacs_event->part = scroll_bar_below_handle;
2345 break;
2c28562d 2346 case SB_TOP:
ee78dc32
GV
2347 emacs_event->part = scroll_bar_handle;
2348 y = 0;
2349 break;
2c28562d 2350 case SB_BOTTOM:
ee78dc32
GV
2351 emacs_event->part = scroll_bar_handle;
2352 y = top_range;
2353 break;
689004fa 2354 case SB_THUMBTRACK:
2c28562d 2355 case SB_THUMBPOSITION:
689004fa
GV
2356 if (VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar->height)) <= 0xffff)
2357 y = HIWORD (msg->msg.wParam);
2358 bar->dragging = Qt;
ee78dc32 2359 emacs_event->part = scroll_bar_handle;
689004fa
GV
2360
2361 /* "Silently" update current position. */
2362 if (pfnSetScrollInfo)
2363 {
2364 SCROLLINFO si;
2365
2366 si.cbSize = sizeof (si);
2367 si.fMask = SIF_POS;
2368
2369#if 0
2370 /* Shrink handle if necessary to allow full range for position. */
2371 {
2372 int start = XINT (bar->start);
2373 int end = XINT (bar->end);
2374 int len = end - start;
2375
2376 /* If new end is nearly hitting bottom, we must shrink
2377 handle. How much we shrink it depends on the relative
2378 sizes of len and top_range. */
2379 if (y + len > top_range - 2)
2380 {
2381 len -= min (top_range / 10, (len / 3) + 2);
2382 if (len < 0)
2383 len = 0;
2384 }
2385 si.nPage = len + VERTICAL_SCROLL_BAR_MIN_HANDLE;
2386 si.fMask |= SIF_PAGE;
2387 }
2388#endif
2389 si.nPos = y;
2390 /* Remember apparent position (we actually lag behind the real
2391 position, so don't set that directly. */
2392 last_scroll_bar_drag_pos = y;
2393
2394 pfnSetScrollInfo (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, &si, FALSE);
2395 }
2396 else
2397 SetScrollPos (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, y, FALSE);
ee78dc32 2398 break;
2c28562d 2399 case SB_ENDSCROLL:
689004fa
GV
2400 /* If this is the end of a drag sequence, then reset the scroll
2401 handle size to normal and do a final redraw. Otherwise do
2402 nothing. */
2403 if (dragging)
2404 {
2405 if (pfnSetScrollInfo)
2406 {
2407 SCROLLINFO si;
2408 int start = XINT (bar->start);
2409 int end = XINT (bar->end);
2410
2411 si.cbSize = sizeof (si);
2412 si.fMask = SIF_PAGE | SIF_POS;
2413 si.nPage = end - start + VERTICAL_SCROLL_BAR_MIN_HANDLE;
2414 si.nPos = last_scroll_bar_drag_pos;
2415
2416 pfnSetScrollInfo (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, &si, TRUE);
2417 }
2418 else
2419 SetScrollPos (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, y, TRUE);
2420 }
2421 /* fall through */
2c28562d 2422 default:
689004fa 2423 emacs_event->kind = no_event;
52cf03a1 2424 return FALSE;
2c28562d 2425 }
52cf03a1 2426
ee78dc32
GV
2427 XSETINT (emacs_event->x, y);
2428 XSETINT (emacs_event->y, top_range);
52cf03a1
GV
2429
2430 return TRUE;
ee78dc32
GV
2431 }
2432}
2433
2434/* Return information to the user about the current position of the mouse
2435 on the scroll bar. */
2436static void
2437x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
2438 FRAME_PTR *fp;
2439 Lisp_Object *bar_window;
2440 enum scroll_bar_part *part;
2441 Lisp_Object *x, *y;
2442 unsigned long *time;
2443{
2444 struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
fbd6baed 2445 Window w = SCROLL_BAR_W32_WINDOW (bar);
ee78dc32
GV
2446 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
2447 int pos;
689004fa 2448 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar->height));
ee78dc32
GV
2449
2450 BLOCK_INPUT;
2451
2452 *fp = f;
2453 *bar_window = bar->window;
2454
689004fa
GV
2455 if (pfnGetScrollInfo)
2456 {
2457 SCROLLINFO si;
2458
2459 si.cbSize = sizeof (si);
2460 si.fMask = SIF_POS | SIF_PAGE | SIF_RANGE;
2461
2462 pfnGetScrollInfo (w, SB_CTL, &si);
2463 pos = si.nPos;
2464 top_range = si.nMax - si.nPage + 1;
2465 }
2466 else
2467 pos = GetScrollPos (w, SB_CTL);
ee78dc32
GV
2468
2469 switch (LOWORD (last_mouse_scroll_bar_pos))
2470 {
2471 case SB_THUMBPOSITION:
2472 case SB_THUMBTRACK:
2473 *part = scroll_bar_handle;
2474 if (VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar->height)) <= 0xffff)
2475 pos = HIWORD (last_mouse_scroll_bar_pos);
2476 break;
2477 case SB_LINEDOWN:
2478 *part = scroll_bar_handle;
2479 pos++;
2480 break;
2481 default:
2482 *part = scroll_bar_handle;
2483 break;
2484 }
2485
2486 XSETINT(*x, pos);
689004fa 2487 XSETINT(*y, top_range);
ee78dc32
GV
2488
2489 f->mouse_moved = 0;
2490 last_mouse_scroll_bar = Qnil;
2491
2492 *time = last_mouse_movement_time;
2493
2494 UNBLOCK_INPUT;
2495}
2496
2497/* The screen has been cleared so we may have changed foreground or
2498 background colors, and the scroll bars may need to be redrawn.
2499 Clear out the scroll bars, and ask for expose events, so we can
2500 redraw them. */
2501
2502x_scroll_bar_clear (f)
2503 FRAME_PTR f;
2504{
ee78dc32
GV
2505 Lisp_Object bar;
2506
2507 for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar);
2508 bar = XSCROLL_BAR (bar)->next)
52cf03a1 2509 {
fbd6baed 2510 HWND window = SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar));
52cf03a1
GV
2511 HDC hdc = GetDC (window);
2512 RECT rect;
2513
689004fa
GV
2514 /* Hide scroll bar until ready to repaint. x_scroll_bar_move
2515 arranges to refresh the scroll bar if hidden. */
2516 my_show_window (f, window, SW_HIDE);
2517
52cf03a1
GV
2518 GetClientRect (window, &rect);
2519 select_palette (f, hdc);
fbd6baed 2520 w32_clear_rect (f, hdc, &rect);
52cf03a1 2521 deselect_palette (f, hdc);
689004fa
GV
2522
2523 ReleaseDC (window, hdc);
52cf03a1
GV
2524 }
2525}
2526
2527show_scroll_bars (f, how)
2528 FRAME_PTR f;
2529 int how;
2530{
2531 Lisp_Object bar;
2532
2533 for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar);
2534 bar = XSCROLL_BAR (bar)->next)
2535 {
fbd6baed 2536 HWND window = SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar));
689004fa 2537 my_show_window (f, window, how);
52cf03a1 2538 }
ee78dc32
GV
2539}
2540
2541\f
fbd6baed 2542/* The main W32 event-reading loop - w32_read_socket. */
ee78dc32
GV
2543
2544/* Timestamp of enter window event. This is only used by w32_read_socket,
2545 but we have to put it out here, since static variables within functions
2546 sometimes don't work. */
2547static Time enter_timestamp;
2548
2549/* Record the last 100 characters stored
2550 to help debug the loss-of-chars-during-GC problem. */
2551int temp_index;
2552short temp_buffer[100];
2553
689004fa 2554extern int key_event (KEY_EVENT_RECORD *, struct input_event *, int *isdead);
afd153f0 2555
fbd6baed 2556/* Map a W32 WM_CHAR message into a KEY_EVENT_RECORD so that
afd153f0
GV
2557 we can use the same routines to handle input in both console
2558 and window modes. */
2559
2560static void
fbd6baed 2561convert_to_key_event (W32Msg *msgp, KEY_EVENT_RECORD *eventp)
afd153f0
GV
2562{
2563 eventp->bKeyDown = TRUE;
2564 eventp->wRepeatCount = 1;
2565 eventp->wVirtualKeyCode = msgp->msg.wParam;
2566 eventp->wVirtualScanCode = (msgp->msg.lParam & 0xFF0000) >> 16;
2567 eventp->uChar.AsciiChar = 0;
2568 eventp->dwControlKeyState = msgp->dwModifiers;
2569}
2570
2571/* Return nonzero if the virtual key is a dead key. */
2572
2573static int
2574is_dead_key (int wparam)
2575{
2576 unsigned int code = MapVirtualKey (wparam, 2);
2577
e9e23e23 2578 /* Windows 95 returns 0x8000, NT returns 0x80000000. */
afd153f0
GV
2579 if ((code & 0x8000) || (code & 0x80000000))
2580 return 1;
2581 else
2582 return 0;
2583}
2584
fbd6baed 2585/* Read events coming from the W32 shell.
ee78dc32
GV
2586 This routine is called by the SIGIO handler.
2587 We return as soon as there are no more events to be read.
2588
2589 Events representing keys are stored in buffer BUFP,
2590 which can hold up to NUMCHARS characters.
2591 We return the number of characters stored into the buffer,
2592 thus pretending to be `read'.
2593
ee78dc32
GV
2594 EXPECTED is nonzero if the caller knows input is available.
2595
2596 Some of these messages are reposted back to the message queue since the
e9e23e23
GV
2597 system calls the windows proc directly in a context where we cannot return
2598 the data nor can we guarantee the state we are in. So if we dispatch them
ee78dc32
GV
2599 we will get into an infinite loop. To prevent this from ever happening we
2600 will set a variable to indicate we are in the read_socket call and indicate
e9e23e23
GV
2601 which message we are processing since the windows proc gets called
2602 recursively with different messages by the system.
ee78dc32
GV
2603*/
2604
2605int
3aad7613 2606w32_read_socket (sd, bufp, numchars, expected)
ee78dc32
GV
2607 register int sd;
2608 register struct input_event *bufp;
2609 register int numchars;
ee78dc32
GV
2610 int expected;
2611{
2612 int count = 0;
689004fa 2613 int check_visibility = 0;
fbd6baed 2614 W32Msg msg;
ee78dc32 2615 struct frame *f;
ee78dc32 2616 Lisp_Object part;
fbd6baed 2617 struct w32_display_info *dpyinfo = &one_w32_display_info;
ee78dc32
GV
2618
2619 if (interrupt_input_blocked)
2620 {
2621 interrupt_input_pending = 1;
2622 return -1;
2623 }
2624
2625 interrupt_input_pending = 0;
2626 BLOCK_INPUT;
2627
2628 /* So people can tell when we have read the available input. */
2629 input_signal_count++;
2630
2631 if (numchars <= 0)
2632 abort (); /* Don't think this happens. */
2633
52cf03a1 2634 while (get_next_msg (&msg, FALSE))
ee78dc32
GV
2635 {
2636 switch (msg.msg.message)
2637 {
ee78dc32 2638 case WM_PAINT:
ee78dc32
GV
2639 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
2640
2641 if (f)
2642 {
689004fa 2643 if (f->async_visible != 1)
ee78dc32 2644 {
689004fa 2645 /* Definitely not obscured, so mark as visible. */
ee78dc32
GV
2646 f->async_visible = 1;
2647 f->async_iconified = 0;
2648 SET_FRAME_GARBAGED (f);
689004fa
GV
2649 DebPrint (("frame %04x (%s) reexposed\n", f,
2650 XSTRING (f->name)->data));
2651
2652 /* WM_PAINT serves as MapNotify as well, so report
2653 visibility changes properly. */
2654 if (f->iconified)
2655 {
2656 bufp->kind = deiconify_event;
2657 XSETFRAME (bufp->frame_or_window, f);
2658 bufp++;
2659 count++;
2660 numchars--;
2661 }
2662 else if (! NILP(Vframe_list)
2663 && ! NILP (XCONS (Vframe_list)->cdr))
2664 /* Force a redisplay sooner or later to update the
2665 frame titles in case this is the second frame. */
2666 record_asynch_buffer_change ();
ee78dc32
GV
2667 }
2668 else
2669 {
97e6de38 2670 /* Erase background again for safety. */
fbd6baed 2671 w32_clear_rect (f, NULL, &msg.rect);
ee78dc32
GV
2672 dumprectangle (f,
2673 msg.rect.left,
2674 msg.rect.top,
689004fa
GV
2675 msg.rect.right - msg.rect.left,
2676 msg.rect.bottom - msg.rect.top);
ee78dc32
GV
2677 }
2678 }
52cf03a1 2679 break;
689004fa 2680
ee78dc32
GV
2681 case WM_KEYDOWN:
2682 case WM_SYSKEYDOWN:
2683 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
2684
2685 if (f && !f->iconified)
2686 {
2687 if (temp_index == sizeof temp_buffer / sizeof (short))
2688 temp_index = 0;
2689 temp_buffer[temp_index++] = msg.msg.wParam;
2690 bufp->kind = non_ascii_keystroke;
2691 bufp->code = msg.msg.wParam;
689004fa
GV
2692 bufp->modifiers = w32_kbd_mods_to_emacs (msg.dwModifiers,
2693 msg.msg.wParam);
ee78dc32
GV
2694 XSETFRAME (bufp->frame_or_window, f);
2695 bufp->timestamp = msg.msg.time;
2696 bufp++;
2697 numchars--;
2698 count++;
2699 }
2700 break;
689004fa 2701
ee78dc32
GV
2702 case WM_SYSCHAR:
2703 case WM_CHAR:
2704 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
2705
2706 if (f && !f->iconified)
2707 {
2708 if (numchars > 1)
2709 {
afd153f0 2710 int add;
689004fa 2711 int isdead = 0;
afd153f0
GV
2712 KEY_EVENT_RECORD key, *keyp = &key;
2713
ee78dc32
GV
2714 if (temp_index == sizeof temp_buffer / sizeof (short))
2715 temp_index = 0;
afd153f0
GV
2716
2717 convert_to_key_event (&msg, keyp);
689004fa 2718 add = key_event (keyp, bufp, &isdead);
a92989c3 2719 XSETFRAME (bufp->frame_or_window, f);
afd153f0
GV
2720 if (add == -1)
2721 {
2722 /* The key pressed generated two characters, most likely
2723 an accent character and a key that could not be
2724 combined with it. Prepend the message on the queue
2725 again to process the second character (which is
2726 being held internally in key_event), and process
2727 the first character now. */
2728 prepend_msg (&msg);
2729 add = 1;
2730 }
2731
689004fa 2732 if (isdead)
afd153f0
GV
2733 break;
2734
2735 bufp += add;
2736 numchars -= add;
2737 count += add;
ee78dc32
GV
2738 }
2739 else
2740 {
2741 abort ();
2742 }
2743 }
2744 break;
689004fa 2745
ee78dc32
GV
2746 case WM_MOUSEMOVE:
2747 if (dpyinfo->grabbed && last_mouse_frame
2748 && FRAME_LIVE_P (last_mouse_frame))
2749 f = last_mouse_frame;
2750 else
2751 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
2752
2753 if (f)
2754 note_mouse_movement (f, &msg.msg);
2755 else
fbd6baed 2756 clear_mouse_face (FRAME_W32_DISPLAY_INFO (f));
ee78dc32
GV
2757
2758 break;
689004fa 2759
ee78dc32
GV
2760 case WM_LBUTTONDOWN:
2761 case WM_LBUTTONUP:
2762 case WM_MBUTTONDOWN:
2763 case WM_MBUTTONUP:
2764 case WM_RBUTTONDOWN:
2765 case WM_RBUTTONUP:
2766 {
2767 int button;
2768 int up;
2769
2770 if (dpyinfo->grabbed && last_mouse_frame
2771 && FRAME_LIVE_P (last_mouse_frame))
2772 f = last_mouse_frame;
2773 else
2774 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
2775
2776 if (f)
2777 {
fbd6baed 2778 if ((!dpyinfo->w32_focus_frame || f == dpyinfo->w32_focus_frame)
ee78dc32
GV
2779 && (numchars >= 1))
2780 {
2781 construct_mouse_click (bufp, &msg, f);
2782 bufp++;
2783 count++;
2784 numchars--;
2785 }
2786 }
2787
2788 parse_button (msg.msg.message, &button, &up);
2789
2790 if (up)
2791 {
2792 dpyinfo->grabbed &= ~ (1 << button);
2793 }
2794 else
2795 {
2796 dpyinfo->grabbed |= (1 << button);
2797 last_mouse_frame = f;
2798 }
689004fa 2799 break;
ee78dc32
GV
2800 }
2801
689004fa
GV
2802 case WM_MOUSEWHEEL:
2803 if (dpyinfo->grabbed && last_mouse_frame
2804 && FRAME_LIVE_P (last_mouse_frame))
2805 f = last_mouse_frame;
2806 else
2807 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
2808
2809 if (f)
2810 {
2811 if ((!dpyinfo->w32_focus_frame
2812 || f == dpyinfo->w32_focus_frame)
2813 && (numchars >= 1))
2814 {
2815 construct_mouse_wheel (bufp, &msg, f);
2816 bufp++;
2817 count++;
2818 numchars--;
2819 }
2820 }
ee78dc32 2821 break;
689004fa 2822
ee78dc32
GV
2823 case WM_VSCROLL:
2824 {
689004fa
GV
2825 struct scroll_bar *bar =
2826 x_window_to_scroll_bar ((HWND)msg.msg.lParam);
ee78dc32
GV
2827
2828 if (bar && numchars >= 1)
2829 {
52cf03a1
GV
2830 if (x_scroll_bar_handle_click (bar, &msg, bufp))
2831 {
2832 bufp++;
2833 count++;
2834 numchars--;
2835 }
ee78dc32 2836 }
689004fa 2837 break;
ee78dc32
GV
2838 }
2839
689004fa
GV
2840 case WM_WINDOWPOSCHANGED:
2841 case WM_ACTIVATE:
2842 case WM_ACTIVATEAPP:
2843 check_visibility = 1;
ee78dc32 2844 break;
689004fa 2845
ee78dc32
GV
2846 case WM_MOVE:
2847 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
2848
2849 if (f && !f->async_iconified)
2850 {
689004fa
GV
2851 int x, y;
2852
2853 x_real_positions (f, &x, &y);
2854 f->output_data.w32->left_pos = x;
2855 f->output_data.w32->top_pos = y;
ee78dc32 2856 }
689004fa
GV
2857
2858 check_visibility = 1;
2859 break;
2860
2861 case WM_SHOWWINDOW:
2862 /* If window has been obscured or exposed by another window
2863 being maximised or minimised/restored, then recheck
2864 visibility of all frames. Direct changes to our own
2865 windows get handled by WM_SIZE. */
2866#if 0
2867 if (msg.msg.lParam != 0)
2868 check_visibility = 1;
2869 else
2870 {
2871 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
2872 f->async_visible = msg.msg.wParam;
2873 }
2874#endif
2875
2876 check_visibility = 1;
ee78dc32 2877 break;
689004fa 2878
ee78dc32
GV
2879 case WM_SIZE:
2880 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
2881
2882 if (f && !f->async_iconified && msg.msg.wParam != SIZE_MINIMIZED)
2883 {
2884 RECT rect;
2885 int rows;
2886 int columns;
2887 int width;
2888 int height;
2889
97c23857 2890 GetClientRect(msg.msg.hwnd, &rect);
ee78dc32 2891
689004fa
GV
2892 height = rect.bottom - rect.top;
2893 width = rect.right - rect.left;
ee78dc32
GV
2894
2895 rows = PIXEL_TO_CHAR_HEIGHT (f, height);
2896 columns = PIXEL_TO_CHAR_WIDTH (f, width);
2897
689004fa
GV
2898 /* TODO: Clip size to the screen dimensions. */
2899
ee78dc32
GV
2900 /* Even if the number of character rows and columns has
2901 not changed, the font size may have changed, so we need
2902 to check the pixel dimensions as well. */
2903
2904 if (columns != f->width
2905 || rows != f->height
fbd6baed
GV
2906 || width != f->output_data.w32->pixel_width
2907 || height != f->output_data.w32->pixel_height)
ee78dc32
GV
2908 {
2909 /* I had set this to 0, 0 - I am not sure why?? */
2910
2911 change_frame_size (f, rows, columns, 0, 1);
2912 SET_FRAME_GARBAGED (f);
2913
fbd6baed
GV
2914 f->output_data.w32->pixel_width = width;
2915 f->output_data.w32->pixel_height = height;
2916 f->output_data.w32->win_gravity = NorthWestGravity;
ee78dc32
GV
2917 }
2918 }
689004fa
GV
2919
2920 /* Inform lisp of whether frame has been iconified etc. */
2921 if (f)
ee78dc32 2922 {
689004fa 2923 switch (msg.msg.wParam)
ee78dc32 2924 {
689004fa
GV
2925 case SIZE_MINIMIZED:
2926 f->async_visible = 0;
ee78dc32
GV
2927 f->async_iconified = 1;
2928
2929 bufp->kind = iconify_event;
2930 XSETFRAME (bufp->frame_or_window, f);
2931 bufp++;
2932 count++;
2933 numchars--;
689004fa
GV
2934 break;
2935
2936 case SIZE_MAXIMIZED:
2937 case SIZE_RESTORED:
ee78dc32
GV
2938 f->async_visible = 1;
2939 f->async_iconified = 0;
2940
2941 /* wait_reading_process_input will notice this and update
2942 the frame's display structures. */
2943 SET_FRAME_GARBAGED (f);
2944
2945 if (f->iconified)
2946 {
2947 bufp->kind = deiconify_event;
2948 XSETFRAME (bufp->frame_or_window, f);
2949 bufp++;
2950 count++;
2951 numchars--;
2952 }
2953 else
2954 /* Force a redisplay sooner or later
2955 to update the frame titles
2956 in case this is the second frame. */
2957 record_asynch_buffer_change ();
689004fa 2958 break;
ee78dc32 2959 }
ee78dc32 2960 }
689004fa
GV
2961
2962 check_visibility = 1;
2963 break;
2964
2965 case WM_SETFOCUS:
2966 case WM_KILLFOCUS:
2967 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
ee78dc32 2968
689004fa
GV
2969 if (msg.msg.message == WM_SETFOCUS)
2970 {
2971 x_new_focus_frame (dpyinfo, f);
2972 }
2973 else if (f == dpyinfo->w32_focus_frame)
2974 {
2975 x_new_focus_frame (dpyinfo, 0);
2976 }
2977
2978 check_visibility = 1;
ee78dc32 2979 break;
689004fa 2980
ee78dc32
GV
2981 case WM_CLOSE:
2982 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
2983
2984 if (f)
2985 {
2986 if (numchars == 0)
2987 abort ();
2988
2989 bufp->kind = delete_window_event;
2990 XSETFRAME (bufp->frame_or_window, f);
2991 bufp++;
2992 count++;
2993 numchars--;
2994 }
689004fa
GV
2995 break;
2996
2997 case WM_INITMENU:
2998 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
2999
3000 if (f)
3001 {
3002 if (numchars == 0)
3003 abort ();
ee78dc32 3004
689004fa
GV
3005 bufp->kind = menu_bar_activate_event;
3006 XSETFRAME (bufp->frame_or_window, f);
3007 bufp++;
3008 count++;
3009 numchars--;
3010 }
ee78dc32 3011 break;
689004fa 3012
ee78dc32
GV
3013 case WM_COMMAND:
3014 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
3015
689004fa 3016#if 1
ee78dc32
GV
3017 if (f)
3018 {
3019 if (msg.msg.lParam == 0)
3020 {
3021 /* Came from window menu */
3022
3023 extern Lisp_Object get_frame_menubar_event ();
3024 Lisp_Object event = get_frame_menubar_event (f, msg.msg.wParam);
3025 struct input_event buf;
3026 Lisp_Object frame;
3027
3028 XSETFRAME (frame, f);
3029 buf.kind = menu_bar_event;
3030
3031 /* Store initial menu bar event */
3032
3033 if (!NILP (event))
3034 {
3035 buf.frame_or_window = Fcons (frame, Fcons (Qmenu_bar, Qnil));
3036 kbd_buffer_store_event (&buf);
3037 }
3038
3039 /* Enqueue the events */
3040
3041 while (!NILP (event))
3042 {
3043 buf.frame_or_window = Fcons (frame, XCONS (event)->car);
3044 kbd_buffer_store_event (&buf);
3045 event = XCONS (event)->cdr;
3046 }
3047 }
3048 else
3049 {
3050 /* Came from popup menu */
3051 }
3052 }
689004fa
GV
3053#endif
3054
3055 check_visibility = 1;
3056 break;
3057
3058 case WM_DISPLAYCHANGE:
3059 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
3060
3061 if (f)
3062 {
3063 dpyinfo->width = (short) LOWORD (msg.msg.lParam);
3064 dpyinfo->height = (short) HIWORD (msg.msg.lParam);
3065 dpyinfo->n_cbits = msg.msg.wParam;
3066 DebPrint (("display change: %d %d\n", dpyinfo->width,
3067 dpyinfo->height));
3068 }
3069
3070 check_visibility = 1;
ee78dc32
GV
3071 break;
3072 }
3073 }
3074
3075 /* If the focus was just given to an autoraising frame,
3076 raise it now. */
3077 /* ??? This ought to be able to handle more than one such frame. */
3078 if (pending_autoraise_frame)
3079 {
3080 x_raise_frame (pending_autoraise_frame);
3081 pending_autoraise_frame = 0;
3082 }
3083
689004fa
GV
3084 /* Check which frames are still visisble, if we have enqueued any user
3085 events or been notified of events that may affect visibility. We
3086 do this here because there doesn't seem to be any direct
3087 notification from Windows that the visibility of a window has
3088 changed (at least, not in all cases). */
3089 if (count > 0 || check_visibility)
3090 {
3091 Lisp_Object tail, frame;
3092
3093 FOR_EACH_FRAME (tail, frame)
3094 {
3095 FRAME_PTR f = XFRAME (frame);
3096 /* Check "visible" frames and mark each as obscured or not.
3097 Note that async_visible is nonzero for unobscured and
3098 obscured frames, but zero for hidden and iconified frames. */
3099 if (FRAME_W32_P (f) && f->async_visible)
3100 {
3101 RECT clipbox;
3102 HDC hdc = get_frame_dc (f);
3103 GetClipBox (hdc, &clipbox);
3104 release_frame_dc (f, hdc);
3105
3106 if (clipbox.right == clipbox.left
3107 || clipbox.bottom == clipbox.top)
3108 {
3109 /* Frame has become completely obscured so mark as
3110 such (we do this by setting async_visible to 2 so
3111 that FRAME_VISIBLE_P is still true, but redisplay
3112 will skip it). */
3113 f->async_visible = 2;
3114
3115 if (!FRAME_OBSCURED_P (f))
3116 {
3117 DebPrint (("frame %04x (%s) obscured\n", f,
3118 XSTRING (f->name)->data));
3119 }
3120 }
3121 else
3122 {
3123 /* Frame is not obscured, so mark it as such. */
3124 f->async_visible = 1;
3125
3126 if (FRAME_OBSCURED_P (f))
3127 {
3128 SET_FRAME_GARBAGED (f);
3129 DebPrint (("frame %04x (%s) reexposed\n", f,
3130 XSTRING (f->name)->data));
3131
3132 /* Force a redisplay sooner or later. */
3133 record_asynch_buffer_change ();
3134 }
3135 }
3136 }
3137 }
3138 }
3139
ee78dc32
GV
3140 UNBLOCK_INPUT;
3141 return count;
3142}
3143\f
3144/* Drawing the cursor. */
3145
3146
3147/* Draw a hollow box cursor. Don't change the inside of the box. */
3148
3149static void
3150x_draw_box (f)
3151 struct frame *f;
3152{
3153 RECT rect;
3154 HBRUSH hb;
3155 HDC hdc;
3156
52cf03a1 3157 hdc = get_frame_dc (f);
ee78dc32 3158
fbd6baed 3159 hb = CreateSolidBrush (f->output_data.w32->cursor_pixel);
ee78dc32
GV
3160
3161 rect.left = CHAR_TO_PIXEL_COL (f, curs_x);
3162 rect.top = CHAR_TO_PIXEL_ROW (f, curs_y);
fbd6baed
GV
3163 rect.right = rect.left + FONT_WIDTH (f->output_data.w32->font);
3164 rect.bottom = rect.top + f->output_data.w32->line_height;
52cf03a1 3165
ee78dc32 3166 FrameRect (hdc, &rect, hb);
ee78dc32 3167 DeleteObject (hb);
52cf03a1
GV
3168
3169 release_frame_dc (f, hdc);
ee78dc32
GV
3170}
3171
3172/* Clear the cursor of frame F to background color,
3173 and mark the cursor as not shown.
3174 This is used when the text where the cursor is
3175 is about to be rewritten. */
3176
3177static void
3178clear_cursor (f)
3179 struct frame *f;
3180{
3181 if (! FRAME_VISIBLE_P (f)
3182 || f->phys_cursor_x < 0)
3183 return;
3184
3185 x_display_cursor (f, 0);
3186 f->phys_cursor_x = -1;
3187}
3188
3189/* Redraw the glyph at ROW, COLUMN on frame F, in the style
3190 HIGHLIGHT. HIGHLIGHT is as defined for dumpglyphs. Return the
3191 glyph drawn. */
3192
3193static void
3194x_draw_single_glyph (f, row, column, glyph, highlight)
3195 struct frame *f;
3196 int row, column;
3197 GLYPH glyph;
3198 int highlight;
3199{
3200 dumpglyphs (f,
3201 CHAR_TO_PIXEL_COL (f, column),
3202 CHAR_TO_PIXEL_ROW (f, row),
3203 &glyph, 1, highlight, 0);
3204}
3205
3206static void
3207x_display_bar_cursor (f, on)
3208 struct frame *f;
3209 int on;
3210{
3211 struct frame_glyphs *current_glyphs = FRAME_CURRENT_GLYPHS (f);
3212
3213 /* This is pointless on invisible frames, and dangerous on garbaged
3214 frames; in the latter case, the frame may be in the midst of
3215 changing its size, and curs_x and curs_y may be off the frame. */
3216 if (! FRAME_VISIBLE_P (f) || FRAME_GARBAGED_P (f))
3217 return;
3218
3219 if (! on && f->phys_cursor_x < 0)
3220 return;
3221
ee78dc32
GV
3222 /* If there is anything wrong with the current cursor state, remove it. */
3223 if (f->phys_cursor_x >= 0
3224 && (!on
3225 || f->phys_cursor_x != curs_x
3226 || f->phys_cursor_y != curs_y
fbd6baed 3227 || f->output_data.w32->current_cursor != bar_cursor))
ee78dc32
GV
3228 {
3229 /* Erase the cursor by redrawing the character underneath it. */
3230 x_draw_single_glyph (f, f->phys_cursor_y, f->phys_cursor_x,
3231 f->phys_cursor_glyph,
3232 current_glyphs->highlight[f->phys_cursor_y]);
3233 f->phys_cursor_x = -1;
3234 }
3235
3236 /* If we now need a cursor in the new place or in the new form, do it so. */
3237 if (on
3238 && (f->phys_cursor_x < 0
fbd6baed 3239 || (f->output_data.w32->current_cursor != bar_cursor)))
ee78dc32
GV
3240 {
3241 f->phys_cursor_glyph
3242 = ((current_glyphs->enable[curs_y]
3243 && curs_x < current_glyphs->used[curs_y])
3244 ? current_glyphs->glyphs[curs_y][curs_x]
3245 : SPACEGLYPH);
fbd6baed 3246 w32_fill_area (f, NULL, f->output_data.w32->cursor_pixel,
ee78dc32
GV
3247 CHAR_TO_PIXEL_COL (f, curs_x),
3248 CHAR_TO_PIXEL_ROW (f, curs_y),
fbd6baed
GV
3249 max (f->output_data.w32->cursor_width, 1),
3250 f->output_data.w32->line_height);
ee78dc32
GV
3251
3252 f->phys_cursor_x = curs_x;
3253 f->phys_cursor_y = curs_y;
3254
fbd6baed 3255 f->output_data.w32->current_cursor = bar_cursor;
ee78dc32
GV
3256 }
3257}
3258
3259
3260/* Turn the displayed cursor of frame F on or off according to ON.
3261 If ON is nonzero, where to put the cursor is specified
3262 by F->cursor_x and F->cursor_y. */
3263
3264static void
3265x_display_box_cursor (f, on)
3266 struct frame *f;
3267 int on;
3268{
3269 struct frame_glyphs *current_glyphs = FRAME_CURRENT_GLYPHS (f);
3270
3271 /* This is pointless on invisible frames, and dangerous on garbaged
3272 frames; in the latter case, the frame may be in the midst of
3273 changing its size, and curs_x and curs_y may be off the frame. */
3274 if (! FRAME_VISIBLE_P (f) || FRAME_GARBAGED_P (f))
3275 return;
3276
3277 /* If cursor is off and we want it off, return quickly. */
3278 if (!on && f->phys_cursor_x < 0)
3279 return;
3280
ee78dc32
GV
3281 /* If cursor is currently being shown and we don't want it to be
3282 or it is in the wrong place,
3283 or we want a hollow box and it's not so, (pout!)
3284 erase it. */
3285 if (f->phys_cursor_x >= 0
3286 && (!on
3287 || f->phys_cursor_x != curs_x
3288 || f->phys_cursor_y != curs_y
fbd6baed
GV
3289 || (f->output_data.w32->current_cursor != hollow_box_cursor
3290 && (f != FRAME_W32_DISPLAY_INFO (f)->w32_highlight_frame))))
ee78dc32
GV
3291 {
3292 int mouse_face_here = 0;
3293 struct frame_glyphs *active_glyphs = FRAME_CURRENT_GLYPHS (f);
3294
3295 /* If the cursor is in the mouse face area, redisplay that when
3296 we clear the cursor. */
fbd6baed 3297 if (f == FRAME_W32_DISPLAY_INFO (f)->mouse_face_mouse_frame
689004fa
GV
3298 && (f->phys_cursor_y > FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_row
3299 || (f->phys_cursor_y == FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_row
3300 && f->phys_cursor_x >= FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_col))
3301 && (f->phys_cursor_y < FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_row
3302 || (f->phys_cursor_y == FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_row
3303 && f->phys_cursor_x < FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_col))
ee78dc32
GV
3304 /* Don't redraw the cursor's spot in mouse face
3305 if it is at the end of a line (on a newline).
3306 The cursor appears there, but mouse highlighting does not. */
3307 && active_glyphs->used[f->phys_cursor_y] > f->phys_cursor_x)
3308 mouse_face_here = 1;
3309
3310 /* If the font is not as tall as a whole line,
3311 we must explicitly clear the line's whole height. */
fbd6baed
GV
3312 if (FONT_HEIGHT (f->output_data.w32->font) != f->output_data.w32->line_height)
3313 w32_clear_area (f, NULL,
ee78dc32
GV
3314 CHAR_TO_PIXEL_COL (f, f->phys_cursor_x),
3315 CHAR_TO_PIXEL_ROW (f, f->phys_cursor_y),
fbd6baed
GV
3316 FONT_WIDTH (f->output_data.w32->font),
3317 f->output_data.w32->line_height);
ee78dc32
GV
3318 /* Erase the cursor by redrawing the character underneath it. */
3319 x_draw_single_glyph (f, f->phys_cursor_y, f->phys_cursor_x,
3320 f->phys_cursor_glyph,
3321 (mouse_face_here
3322 ? 3
3323 : current_glyphs->highlight[f->phys_cursor_y]));
3324 f->phys_cursor_x = -1;
3325 }
3326
3327 /* If we want to show a cursor,
3328 or we want a box cursor and it's not so,
3329 write it in the right place. */
3330 if (on
3331 && (f->phys_cursor_x < 0
fbd6baed
GV
3332 || (f->output_data.w32->current_cursor != filled_box_cursor
3333 && f == FRAME_W32_DISPLAY_INFO (f)->w32_highlight_frame)))
ee78dc32
GV
3334 {
3335 f->phys_cursor_glyph
3336 = ((current_glyphs->enable[curs_y]
3337 && curs_x < current_glyphs->used[curs_y])
3338 ? current_glyphs->glyphs[curs_y][curs_x]
3339 : SPACEGLYPH);
fbd6baed 3340 if (f != FRAME_W32_DISPLAY_INFO (f)->w32_highlight_frame)
ee78dc32
GV
3341 {
3342 x_draw_box (f);
fbd6baed 3343 f->output_data.w32->current_cursor = hollow_box_cursor;
ee78dc32
GV
3344 }
3345 else
3346 {
3347 x_draw_single_glyph (f, curs_y, curs_x,
3348 f->phys_cursor_glyph, 2);
fbd6baed 3349 f->output_data.w32->current_cursor = filled_box_cursor;
ee78dc32
GV
3350 }
3351
3352 f->phys_cursor_x = curs_x;
3353 f->phys_cursor_y = curs_y;
3354 }
3355}
3356
689004fa
GV
3357/* Display the cursor on frame F, or clear it, according to ON.
3358 Use the position specified by curs_x and curs_y
3359 if we are doing an update of frame F now.
3360 Otherwise use the position in the FRAME_CURSOR_X and FRAME_CURSOR_Y fields
3361 of F. */
3362
ee78dc32
GV
3363x_display_cursor (f, on)
3364 struct frame *f;
3365 int on;
3366{
3367 BLOCK_INPUT;
3368
689004fa
GV
3369 /* If we're not updating, then we want to use the current frame's
3370 cursor position, not our local idea of where the cursor ought to be. */
3371 if (f != updating_frame)
3372 {
3373 curs_x = FRAME_CURSOR_X (f);
3374 curs_y = FRAME_CURSOR_Y (f);
3375 }
3376
ee78dc32
GV
3377 if (FRAME_DESIRED_CURSOR (f) == filled_box_cursor)
3378 x_display_box_cursor (f, on);
3379 else if (FRAME_DESIRED_CURSOR (f) == bar_cursor)
3380 x_display_bar_cursor (f, on);
3381 else
3382 /* Those are the only two we have implemented! */
3383 abort ();
3384
3385 UNBLOCK_INPUT;
3386}
3387\f
3388/* Changing the font of the frame. */
3389
3390/* Give frame F the font named FONTNAME as its default font, and
3391 return the full name of that font. FONTNAME may be a wildcard
3392 pattern; in that case, we choose some font that fits the pattern.
3393 The return value shows which font we chose. */
3394
3395Lisp_Object
3396x_new_font (f, fontname)
3397 struct frame *f;
3398 register char *fontname;
3399{
3400 int already_loaded;
3401 int n_matching_fonts;
3402 XFontStruct *font_info;
3403 char new_font_name[101];
3404
3405 /* Get a font which matches this name */
3406 {
3407 LOGFONT lf;
3408
fbd6baed
GV
3409 if (!x_to_w32_font(fontname, &lf)
3410 || !w32_to_x_font(&lf, new_font_name, 100))
ee78dc32
GV
3411 {
3412 return Qnil;
3413 }
3414 }
3415
3416 /* See if we've already loaded a matching font. */
3417 already_loaded = -1;
3418
3419 {
3420 int i;
3421
fbd6baed
GV
3422 for (i = 0; i < FRAME_W32_DISPLAY_INFO (f)->n_fonts; i++)
3423 if (!strcmp (FRAME_W32_DISPLAY_INFO (f)->font_table[i].name, new_font_name))
ee78dc32
GV
3424 {
3425 already_loaded = i;
fbd6baed 3426 fontname = FRAME_W32_DISPLAY_INFO (f)->font_table[i].name;
ee78dc32
GV
3427 break;
3428 }
3429 }
3430
3431 /* If we have, just return it from the table. */
3432 if (already_loaded >= 0)
fbd6baed 3433 f->output_data.w32->font = FRAME_W32_DISPLAY_INFO (f)->font_table[already_loaded].font;
ee78dc32
GV
3434 /* Otherwise, load the font and add it to the table. */
3435 else
3436 {
3437 XFontStruct *font;
3438 int n_fonts;
3439
fbd6baed 3440 font = w32_load_font(FRAME_W32_DISPLAY_INFO (f), fontname);
ee78dc32
GV
3441
3442 if (! font)
3443 {
3444 return Qnil;
3445 }
3446
3447 /* Do we need to create the table? */
fbd6baed 3448 if (FRAME_W32_DISPLAY_INFO (f)->font_table_size == 0)
ee78dc32 3449 {
fbd6baed
GV
3450 FRAME_W32_DISPLAY_INFO (f)->font_table_size = 16;
3451 FRAME_W32_DISPLAY_INFO (f)->font_table
3452 = (struct font_info *) xmalloc (FRAME_W32_DISPLAY_INFO (f)->font_table_size
ee78dc32
GV
3453 * sizeof (struct font_info));
3454 }
3455 /* Do we need to grow the table? */
fbd6baed
GV
3456 else if (FRAME_W32_DISPLAY_INFO (f)->n_fonts
3457 >= FRAME_W32_DISPLAY_INFO (f)->font_table_size)
ee78dc32 3458 {
fbd6baed
GV
3459 FRAME_W32_DISPLAY_INFO (f)->font_table_size *= 2;
3460 FRAME_W32_DISPLAY_INFO (f)->font_table
3461 = (struct font_info *) xrealloc (FRAME_W32_DISPLAY_INFO (f)->font_table,
3462 (FRAME_W32_DISPLAY_INFO (f)->font_table_size
ee78dc32
GV
3463 * sizeof (struct font_info)));
3464 }
3465
fbd6baed
GV
3466 n_fonts = FRAME_W32_DISPLAY_INFO (f)->n_fonts;
3467 FRAME_W32_DISPLAY_INFO (f)->font_table[n_fonts].name = (char *) xmalloc (strlen (fontname) + 1);
3468 bcopy (fontname, FRAME_W32_DISPLAY_INFO (f)->font_table[n_fonts].name, strlen (fontname) + 1);
3469 f->output_data.w32->font = FRAME_W32_DISPLAY_INFO (f)->font_table[n_fonts].font = font;
3470 FRAME_W32_DISPLAY_INFO (f)->n_fonts++;
ee78dc32
GV
3471 }
3472
3473 /* Compute the scroll bar width in character columns. */
3474 if (f->scroll_bar_pixel_width > 0)
3475 {
fbd6baed 3476 int wid = FONT_WIDTH (f->output_data.w32->font);
ee78dc32
GV
3477 f->scroll_bar_cols = (f->scroll_bar_pixel_width + wid-1) / wid;
3478 }
3479 else
3480 f->scroll_bar_cols = 2;
3481
3482 /* Now make the frame display the given font. */
fbd6baed 3483 if (FRAME_W32_WINDOW (f) != 0)
ee78dc32
GV
3484 {
3485 frame_update_line_height (f);
3486 x_set_window_size (f, 0, f->width, f->height);
3487 }
3488 else
3489 /* If we are setting a new frame's font for the first time,
3490 there are no faces yet, so this font's height is the line height. */
fbd6baed 3491 f->output_data.w32->line_height = FONT_HEIGHT (f->output_data.w32->font);
ee78dc32
GV
3492
3493 {
3494 Lisp_Object lispy_name;
3495
3496 lispy_name = build_string (fontname);
3497
3498 return lispy_name;
3499 }
3500}
3501\f
689004fa
GV
3502/* Calculate the absolute position in frame F
3503 from its current recorded position values and gravity. */
3504
ee78dc32
GV
3505x_calc_absolute_position (f)
3506 struct frame *f;
3507{
3508 Window win, child;
3509 POINT pt;
fbd6baed 3510 int flags = f->output_data.w32->size_hint_flags;
ee78dc32
GV
3511
3512 pt.x = pt.y = 0;
3513
3514 /* Find the position of the outside upper-left corner of
3515 the inner window, with respect to the outer window. */
fbd6baed 3516 if (f->output_data.w32->parent_desc != FRAME_W32_DISPLAY_INFO (f)->root_window)
ee78dc32
GV
3517 {
3518 BLOCK_INPUT;
fbd6baed
GV
3519 MapWindowPoints (FRAME_W32_WINDOW (f),
3520 f->output_data.w32->parent_desc,
ee78dc32
GV
3521 &pt, 1);
3522 UNBLOCK_INPUT;
3523 }
3524
3525 {
3526 RECT rt;
3527 rt.left = rt.right = rt.top = rt.bottom = 0;
3528
3529 BLOCK_INPUT;
fbd6baed 3530 AdjustWindowRect(&rt, f->output_data.w32->dwStyle,
97c23857 3531 FRAME_EXTERNAL_MENU_BAR (f));
ee78dc32
GV
3532 UNBLOCK_INPUT;
3533
3534 pt.x += (rt.right - rt.left);
3535 pt.y += (rt.bottom - rt.top);
3536 }
3537
3538 /* Treat negative positions as relative to the leftmost bottommost
3539 position that fits on the screen. */
3540 if (flags & XNegative)
fbd6baed
GV
3541 f->output_data.w32->left_pos = (FRAME_W32_DISPLAY_INFO (f)->width
3542 - 2 * f->output_data.w32->border_width - pt.x
ee78dc32 3543 - PIXEL_WIDTH (f)
fbd6baed 3544 + f->output_data.w32->left_pos);
ee78dc32
GV
3545
3546 if (flags & YNegative)
fbd6baed
GV
3547 f->output_data.w32->top_pos = (FRAME_W32_DISPLAY_INFO (f)->height
3548 - 2 * f->output_data.w32->border_width - pt.y
ee78dc32 3549 - PIXEL_HEIGHT (f)
fbd6baed 3550 + f->output_data.w32->top_pos);
ee78dc32
GV
3551 /* The left_pos and top_pos
3552 are now relative to the top and left screen edges,
3553 so the flags should correspond. */
fbd6baed 3554 f->output_data.w32->size_hint_flags &= ~ (XNegative | YNegative);
ee78dc32
GV
3555}
3556
3557/* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
3558 to really change the position, and 0 when calling from
3559 x_make_frame_visible (in that case, XOFF and YOFF are the current
3560 position values). It is -1 when calling from x_set_frame_parameters,
3561 which means, do adjust for borders but don't change the gravity. */
3562
3563x_set_offset (f, xoff, yoff, change_gravity)
3564 struct frame *f;
3565 register int xoff, yoff;
3566 int change_gravity;
3567{
3568 int modified_top, modified_left;
3569
3570 if (change_gravity > 0)
3571 {
fbd6baed
GV
3572 f->output_data.w32->top_pos = yoff;
3573 f->output_data.w32->left_pos = xoff;
3574 f->output_data.w32->size_hint_flags &= ~ (XNegative | YNegative);
ee78dc32 3575 if (xoff < 0)
fbd6baed 3576 f->output_data.w32->size_hint_flags |= XNegative;
ee78dc32 3577 if (yoff < 0)
fbd6baed
GV
3578 f->output_data.w32->size_hint_flags |= YNegative;
3579 f->output_data.w32->win_gravity = NorthWestGravity;
ee78dc32
GV
3580 }
3581 x_calc_absolute_position (f);
3582
3583 BLOCK_INPUT;
3584 x_wm_set_size_hint (f, (long) 0, 0);
3585
3586 /* It is a mystery why we need to add the border_width here
3587 when the frame is already visible, but experiment says we do. */
fbd6baed
GV
3588 modified_left = f->output_data.w32->left_pos;
3589 modified_top = f->output_data.w32->top_pos;
689004fa
GV
3590#ifndef HAVE_NTGUI
3591 /* Do not add in border widths under W32. */
ee78dc32
GV
3592 if (change_gravity != 0)
3593 {
fbd6baed
GV
3594 modified_left += f->output_data.w32->border_width;
3595 modified_top += f->output_data.w32->border_width;
ee78dc32 3596 }
689004fa 3597#endif
ee78dc32 3598
fbd6baed 3599 my_set_window_pos (FRAME_W32_WINDOW (f),
52cf03a1
GV
3600 NULL,
3601 modified_left, modified_top,
3602 0,0,
689004fa 3603 SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
ee78dc32
GV
3604 UNBLOCK_INPUT;
3605}
3606
3607/* Call this to change the size of frame F's x-window.
3608 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
3609 for this size change and subsequent size changes.
3610 Otherwise we leave the window gravity unchanged. */
3611
3612x_set_window_size (f, change_gravity, cols, rows)
3613 struct frame *f;
3614 int change_gravity;
3615 int cols, rows;
3616{
3617 int pixelwidth, pixelheight;
689004fa
GV
3618 Lisp_Object window;
3619 struct w32_display_info *dpyinfo = &one_w32_display_info;
ee78dc32
GV
3620
3621 BLOCK_INPUT;
3622
3623 check_frame_size (f, &rows, &cols);
fbd6baed 3624 f->output_data.w32->vertical_scroll_bar_extra
ee78dc32
GV
3625 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
3626 ? 0
3627 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0
3628 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f)
fbd6baed 3629 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.w32->font)));
ee78dc32
GV
3630 pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols);
3631 pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows);
3632
fbd6baed 3633 f->output_data.w32->win_gravity = NorthWestGravity;
ee78dc32
GV
3634 x_wm_set_size_hint (f, (long) 0, 0);
3635
3636 {
3637 RECT rect;
3638
3639 rect.left = rect.top = 0;
3640 rect.right = pixelwidth;
3641 rect.bottom = pixelheight;
3642
fbd6baed 3643 AdjustWindowRect(&rect, f->output_data.w32->dwStyle,
97c23857 3644 FRAME_EXTERNAL_MENU_BAR (f));
ee78dc32 3645
fbd6baed 3646 my_set_window_pos (FRAME_W32_WINDOW (f),
52cf03a1
GV
3647 NULL,
3648 0, 0,
689004fa
GV
3649 rect.right - rect.left,
3650 rect.bottom - rect.top,
3651 SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE);
ee78dc32
GV
3652 }
3653
3654 /* Now, strictly speaking, we can't be sure that this is accurate,
3655 but the window manager will get around to dealing with the size
3656 change request eventually, and we'll hear how it went when the
3657 ConfigureNotify event gets here.
3658
3659 We could just not bother storing any of this information here,
3660 and let the ConfigureNotify event set everything up, but that
3661 might be kind of confusing to the lisp code, since size changes
3662 wouldn't be reported in the frame parameters until some random
3663 point in the future when the ConfigureNotify event arrives. */
3664 change_frame_size (f, rows, cols, 0, 0);
3665 PIXEL_WIDTH (f) = pixelwidth;
3666 PIXEL_HEIGHT (f) = pixelheight;
3667
689004fa
GV
3668 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
3669 receive in the ConfigureNotify event; if we get what we asked
3670 for, then the event won't cause the screen to become garbaged, so
3671 we have to make sure to do it here. */
3672 SET_FRAME_GARBAGED (f);
3673
ee78dc32
GV
3674 /* If cursor was outside the new size, mark it as off. */
3675 if (f->phys_cursor_y >= rows
3676 || f->phys_cursor_x >= cols)
3677 {
3678 f->phys_cursor_x = -1;
3679 f->phys_cursor_y = -1;
3680 }
3681
689004fa
GV
3682 /* Clear out any recollection of where the mouse highlighting was,
3683 since it might be in a place that's outside the new frame size.
3684 Actually checking whether it is outside is a pain in the neck,
3685 so don't try--just let the highlighting be done afresh with new size. */
3686 window = dpyinfo->mouse_face_window;
3687 if (! NILP (window) && XFRAME (window) == f)
3688 {
3689 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
3690 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
3691 dpyinfo->mouse_face_window = Qnil;
3692 }
ee78dc32
GV
3693
3694 UNBLOCK_INPUT;
3695}
3696\f
3697/* Mouse warping. */
3698
1bcd16f2
MB
3699void
3700x_set_mouse_pixel_position (f, pix_x, pix_y)
3701 struct frame *f;
3702 int pix_x, pix_y;
3703{
689004fa
GV
3704 RECT rect;
3705 POINT pt;
3706
1bcd16f2
MB
3707 BLOCK_INPUT;
3708
689004fa
GV
3709 GetClientRect (FRAME_W32_WINDOW (f), &rect);
3710 pt.x = rect.left + pix_x;
3711 pt.y = rect.top + pix_y;
3712 ClientToScreen (FRAME_W32_WINDOW (f), &pt);
1bcd16f2 3713
689004fa 3714 SetCursorPos (pt.x, pt.y);
1bcd16f2
MB
3715
3716 UNBLOCK_INPUT;
3717}
3718
ee78dc32
GV
3719void
3720x_set_mouse_position (f, x, y)
3721 struct frame *f;
3722 int x, y;
3723{
3724 int pix_x, pix_y;
3725
fbd6baed
GV
3726 pix_x = CHAR_TO_PIXEL_COL (f, x) + FONT_WIDTH (f->output_data.w32->font) / 2;
3727 pix_y = CHAR_TO_PIXEL_ROW (f, y) + f->output_data.w32->line_height / 2;
ee78dc32
GV
3728
3729 if (pix_x < 0) pix_x = 0;
3730 if (pix_x > PIXEL_WIDTH (f)) pix_x = PIXEL_WIDTH (f);
3731
3732 if (pix_y < 0) pix_y = 0;
3733 if (pix_y > PIXEL_HEIGHT (f)) pix_y = PIXEL_HEIGHT (f);
3734
1bcd16f2 3735 x_set_mouse_pixel_position (f, pix_x, pix_y);
ee78dc32
GV
3736}
3737\f
3738/* focus shifting, raising and lowering. */
3739
3740x_focus_on_frame (f)
3741 struct frame *f;
3742{
689004fa
GV
3743 struct w32_display_info *dpyinfo = &one_w32_display_info;
3744
3745 /* Give input focus to frame. */
3746 BLOCK_INPUT;
3747#if 0
3748 /* Try not to change its Z-order if possible. */
3749 if (x_window_to_frame (dpyinfo, GetForegroundWindow ()))
3750 my_set_focus (f, FRAME_W32_WINDOW (f));
3751 else
3752#endif
3753 SetForegroundWindow (FRAME_W32_WINDOW (f));
3754 UNBLOCK_INPUT;
ee78dc32
GV
3755}
3756
3757x_unfocus_frame (f)
3758 struct frame *f;
3759{
3760}
3761
3762/* Raise frame F. */
3763
3764x_raise_frame (f)
3765 struct frame *f;
3766{
689004fa
GV
3767 BLOCK_INPUT;
3768
3769 /* Strictly speaking, raise-frame should only change the frame's Z
3770 order, leaving input focus unchanged. This is reasonable behaviour
3771 on X where the usual policy is point-to-focus. However, this
3772 behaviour would be very odd on Windows where the usual policy is
3773 click-to-focus.
3774
3775 On X, if the mouse happens to be over the raised frame, it gets
3776 input focus anyway (so the window with focus will never be
3777 completely obscured) - if not, then just moving the mouse over it
3778 is sufficient to give it focus. On Windows, the user must actually
3779 click on the frame (preferrably the title bar so as not to move
3780 point), which is more awkward. Also, no other Windows program
3781 raises a window to the top but leaves another window (possibly now
3782 completely obscured) with input focus.
3783
3784 Because there is a system setting on Windows that allows the user
3785 to choose the point to focus policy, we make the strict semantics
3786 optional, but by default we grab focus when raising. */
3787
3788 if (NILP (Vw32_grab_focus_on_raise))
ee78dc32 3789 {
689004fa
GV
3790 /* The obvious call to my_set_window_pos doesn't work if Emacs is
3791 not already the foreground application: the frame is raised
3792 above all other frames belonging to us, but not above the
3793 current top window. To achieve that, we have to resort to this
3794 more cumbersome method. */
3795
3796 HDWP handle = BeginDeferWindowPos (2);
3797 if (handle)
3798 {
3799 DeferWindowPos (handle,
3800 FRAME_W32_WINDOW (f),
3801 HWND_TOP,
3802 0, 0, 0, 0,
3803 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
3804
3805 DeferWindowPos (handle,
3806 GetForegroundWindow (),
3807 FRAME_W32_WINDOW (f),
3808 0, 0, 0, 0,
3809 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
3810
3811 EndDeferWindowPos (handle);
3812 }
ee78dc32 3813 }
689004fa
GV
3814 else
3815 {
3816 SetForegroundWindow (FRAME_W32_WINDOW (f));
3817 }
3818
3819 UNBLOCK_INPUT;
ee78dc32
GV
3820}
3821
3822/* Lower frame F. */
3823
3824x_lower_frame (f)
3825 struct frame *f;
3826{
689004fa
GV
3827 BLOCK_INPUT;
3828 my_set_window_pos (FRAME_W32_WINDOW (f),
3829 HWND_BOTTOM,
3830 0, 0, 0, 0,
3831 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
3832 UNBLOCK_INPUT;
ee78dc32
GV
3833}
3834
3835static void
fbd6baed 3836w32_frame_raise_lower (f, raise)
ee78dc32
GV
3837 FRAME_PTR f;
3838 int raise;
3839{
3840 if (raise)
3841 x_raise_frame (f);
3842 else
3843 x_lower_frame (f);
3844}
3845\f
3846/* Change of visibility. */
3847
3848/* This tries to wait until the frame is really visible.
3849 However, if the window manager asks the user where to position
3850 the frame, this will return before the user finishes doing that.
3851 The frame will not actually be visible at that time,
3852 but it will become visible later when the window manager
3853 finishes with it. */
3854
3855x_make_frame_visible (f)
3856 struct frame *f;
3857{
3858 BLOCK_INPUT;
3859
3860 if (! FRAME_VISIBLE_P (f))
3861 {
3862 /* We test FRAME_GARBAGED_P here to make sure we don't
3863 call x_set_offset a second time
3864 if we get to x_make_frame_visible a second time
3865 before the window gets really visible. */
3866 if (! FRAME_ICONIFIED_P (f)
fbd6baed 3867 && ! f->output_data.w32->asked_for_visible)
fbd6baed 3868 x_set_offset (f, f->output_data.w32->left_pos, f->output_data.w32->top_pos, 0);
ee78dc32 3869
fbd6baed 3870 f->output_data.w32->asked_for_visible = 1;
52cf03a1 3871
689004fa
GV
3872// my_show_window (f, FRAME_W32_WINDOW (f), f->async_iconified ? SW_RESTORE : SW_SHOW);
3873 my_show_window (f, FRAME_W32_WINDOW (f), SW_SHOWNORMAL);
ee78dc32
GV
3874 }
3875
3876 /* Synchronize to ensure Emacs knows the frame is visible
3877 before we do anything else. We do this loop with input not blocked
3878 so that incoming events are handled. */
3879 {
3880 Lisp_Object frame;
3881 int count = input_signal_count;
3882
3883 /* This must come after we set COUNT. */
3884 UNBLOCK_INPUT;
3885
3886 XSETFRAME (frame, f);
3887
3888 while (1)
3889 {
3890 /* Once we have handled input events,
3891 we should have received the MapNotify if one is coming.
3892 So if we have not got it yet, stop looping.
3893 Some window managers make their own decisions
3894 about visibility. */
3895 if (input_signal_count != count)
3896 break;
3897 /* Machines that do polling rather than SIGIO have been observed
3898 to go into a busy-wait here. So we'll fake an alarm signal
3899 to let the handler know that there's something to be read.
3900 We used to raise a real alarm, but it seems that the handler
3901 isn't always enabled here. This is probably a bug. */
3902 if (input_polling_used ())
3903 {
3904 /* It could be confusing if a real alarm arrives while processing
3905 the fake one. Turn it off and let the handler reset it. */
3906 alarm (0);
3907 input_poll_signal ();
3908 }
3909 /* Once we have handled input events,
3910 we should have received the MapNotify if one is coming.
3911 So if we have not got it yet, stop looping.
3912 Some window managers make their own decisions
3913 about visibility. */
3914 if (input_signal_count != count)
3915 break;
3916 }
3917 FRAME_SAMPLE_VISIBILITY (f);
3918 }
3919}
3920
3921/* Change from mapped state to withdrawn state. */
3922
3923/* Make the frame visible (mapped and not iconified). */
3924
3925x_make_frame_invisible (f)
3926 struct frame *f;
3927{
3928 Window window;
3929
3930 /* Don't keep the highlight on an invisible frame. */
fbd6baed
GV
3931 if (FRAME_W32_DISPLAY_INFO (f)->w32_highlight_frame == f)
3932 FRAME_W32_DISPLAY_INFO (f)->w32_highlight_frame = 0;
ee78dc32
GV
3933
3934 BLOCK_INPUT;
3935
689004fa 3936 my_show_window (f, FRAME_W32_WINDOW (f), SW_HIDE);
ee78dc32
GV
3937
3938 /* We can't distinguish this from iconification
3939 just by the event that we get from the server.
3940 So we can't win using the usual strategy of letting
3941 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
3942 and synchronize with the server to make sure we agree. */
3943 f->visible = 0;
3944 FRAME_ICONIFIED_P (f) = 0;
3945 f->async_visible = 0;
3946 f->async_iconified = 0;
3947
3948 UNBLOCK_INPUT;
3949}
3950
3951/* Change window state from mapped to iconified. */
3952
52cf03a1
GV
3953void
3954x_iconify_frame (f)
ee78dc32
GV
3955 struct frame *f;
3956{
3957 int result;
3958
3959 /* Don't keep the highlight on an invisible frame. */
fbd6baed
GV
3960 if (FRAME_W32_DISPLAY_INFO (f)->w32_highlight_frame == f)
3961 FRAME_W32_DISPLAY_INFO (f)->w32_highlight_frame = 0;
ee78dc32
GV
3962
3963 if (f->async_iconified)
3964 return;
3965
3966 BLOCK_INPUT;
3967
689004fa
GV
3968 /* Simulate the user minimizing the frame. */
3969 PostMessage (FRAME_W32_WINDOW (f), WM_SYSCOMMAND, SC_MINIMIZE, 0);
ee78dc32
GV
3970
3971 f->async_iconified = 1;
3972
3973 UNBLOCK_INPUT;
3974}
3975\f
3976/* Destroy the window of frame F. */
3977
3978x_destroy_window (f)
3979 struct frame *f;
3980{
fbd6baed 3981 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
ee78dc32
GV
3982
3983 BLOCK_INPUT;
3984
fbd6baed 3985 my_destroy_window (f, FRAME_W32_WINDOW (f));
ee78dc32
GV
3986 free_frame_menubar (f);
3987 free_frame_faces (f);
3988
fbd6baed
GV
3989 xfree (f->output_data.w32);
3990 f->output_data.w32 = 0;
3991 if (f == dpyinfo->w32_focus_frame)
3992 dpyinfo->w32_focus_frame = 0;
3993 if (f == dpyinfo->w32_focus_event_frame)
3994 dpyinfo->w32_focus_event_frame = 0;
3995 if (f == dpyinfo->w32_highlight_frame)
3996 dpyinfo->w32_highlight_frame = 0;
ee78dc32
GV
3997
3998 dpyinfo->reference_count--;
3999
4000 if (f == dpyinfo->mouse_face_mouse_frame)
4001 {
4002 dpyinfo->mouse_face_beg_row
4003 = dpyinfo->mouse_face_beg_col = -1;
4004 dpyinfo->mouse_face_end_row
4005 = dpyinfo->mouse_face_end_col = -1;
4006 dpyinfo->mouse_face_window = Qnil;
4007 }
4008
4009 UNBLOCK_INPUT;
4010}
4011\f
4012/* Setting window manager hints. */
4013
4014/* Set the normal size hints for the window manager, for frame F.
4015 FLAGS is the flags word to use--or 0 meaning preserve the flags
4016 that the window now has.
4017 If USER_POSITION is nonzero, we set the USPosition
4018 flag (this is useful when FLAGS is 0). */
4019
4020x_wm_set_size_hint (f, flags, user_position)
4021 struct frame *f;
4022 long flags;
4023 int user_position;
4024{
fbd6baed 4025 Window window = FRAME_W32_WINDOW (f);
ee78dc32
GV
4026
4027 flexlines = f->height;
4028
97c23857 4029 enter_crit ();
ee78dc32 4030
689004fa
GV
4031 SetWindowLong (window, WND_FONTWIDTH_INDEX, FONT_WIDTH (f->output_data.w32->font));
4032 SetWindowLong (window, WND_LINEHEIGHT_INDEX, f->output_data.w32->line_height);
4033 SetWindowLong (window, WND_BORDER_INDEX, f->output_data.w32->internal_border_width);
4034 SetWindowLong (window, WND_SCROLLBAR_INDEX, f->output_data.w32->vertical_scroll_bar_extra);
ee78dc32 4035
97c23857 4036 leave_crit ();
ee78dc32
GV
4037}
4038
4039/* Window manager things */
4040x_wm_set_icon_position (f, icon_x, icon_y)
4041 struct frame *f;
4042 int icon_x, icon_y;
4043{
4044#if 0
fbd6baed 4045 Window window = FRAME_W32_WINDOW (f);
ee78dc32
GV
4046
4047 f->display.x->wm_hints.flags |= IconPositionHint;
4048 f->display.x->wm_hints.icon_x = icon_x;
4049 f->display.x->wm_hints.icon_y = icon_y;
4050
4051 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->display.x->wm_hints);
4052#endif
4053}
4054
4055\f
4056/* Initialization. */
4057
4058#ifdef USE_X_TOOLKIT
4059static XrmOptionDescRec emacs_options[] = {
4060 {"-geometry", ".geometry", XrmoptionSepArg, NULL},
4061 {"-iconic", ".iconic", XrmoptionNoArg, (XtPointer) "yes"},
4062
4063 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
4064 XrmoptionSepArg, NULL},
4065 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg, NULL},
4066
4067 {"-T", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
4068 {"-wn", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
4069 {"-title", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
4070 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
4071 {"-in", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
4072 {"-mc", "*pointerColor", XrmoptionSepArg, (XtPointer) NULL},
4073 {"-cr", "*cursorColor", XrmoptionSepArg, (XtPointer) NULL}
4074};
4075#endif /* USE_X_TOOLKIT */
4076
fbd6baed 4077static int w32_initialized = 0;
ee78dc32 4078
fbd6baed
GV
4079struct w32_display_info *
4080w32_term_init (display_name, xrm_option, resource_name)
ee78dc32
GV
4081 Lisp_Object display_name;
4082 char *xrm_option;
4083 char *resource_name;
4084{
4085 Lisp_Object frame;
4086 char *defaultvalue;
fbd6baed 4087 struct w32_display_info *dpyinfo;
ee78dc32 4088 HDC hdc;
97c23857 4089
ee78dc32
GV
4090 BLOCK_INPUT;
4091
fbd6baed 4092 if (!w32_initialized)
ee78dc32 4093 {
fbd6baed
GV
4094 w32_initialize ();
4095 w32_initialized = 1;
ee78dc32
GV
4096 }
4097
4098 {
4099 int argc = 0;
4100 char *argv[3];
4101
4102 argv[0] = "";
4103 argc = 1;
4104 if (xrm_option)
4105 {
4106 argv[argc++] = "-xrm";
4107 argv[argc++] = xrm_option;
4108 }
4109 }
4110
fbd6baed 4111 dpyinfo = &one_w32_display_info;
ee78dc32
GV
4112
4113 /* Put this display on the chain. */
4114 dpyinfo->next = NULL;
4115
fbd6baed
GV
4116 /* Put it on w32_display_name_list as well, to keep them parallel. */
4117 w32_display_name_list = Fcons (Fcons (display_name, Qnil),
4118 w32_display_name_list);
4119 dpyinfo->name_list_element = XCONS (w32_display_name_list)->car;
97c23857 4120
fbd6baed 4121 dpyinfo->w32_id_name
ee78dc32
GV
4122 = (char *) xmalloc (XSTRING (Vinvocation_name)->size
4123 + XSTRING (Vsystem_name)->size
4124 + 2);
fbd6baed 4125 sprintf (dpyinfo->w32_id_name, "%s@%s",
ee78dc32
GV
4126 XSTRING (Vinvocation_name)->data, XSTRING (Vsystem_name)->data);
4127
4128#if 0
4129 xrdb = x_load_resources (dpyinfo->display, xrm_option,
4130 resource_name, EMACS_CLASS);
4131
4132 /* Put the rdb where we can find it in a way that works on
4133 all versions. */
4134 dpyinfo->xrdb = xrdb;
4135#endif
52cf03a1 4136 hdc = GetDC (GetDesktopWindow ());
ee78dc32
GV
4137
4138 dpyinfo->height = GetDeviceCaps (hdc, VERTRES);
4139 dpyinfo->width = GetDeviceCaps (hdc, HORZRES);
4140 dpyinfo->root_window = GetDesktopWindow ();
4141 dpyinfo->n_planes = GetDeviceCaps (hdc, PLANES);
4142 dpyinfo->n_cbits = GetDeviceCaps (hdc, BITSPIXEL);
4143 dpyinfo->height_in = GetDeviceCaps (hdc, LOGPIXELSX);
4144 dpyinfo->width_in = GetDeviceCaps (hdc, LOGPIXELSY);
52cf03a1 4145 dpyinfo->has_palette = GetDeviceCaps (hdc, RASTERCAPS) & RC_PALETTE;
ee78dc32
GV
4146 dpyinfo->grabbed = 0;
4147 dpyinfo->reference_count = 0;
4148 dpyinfo->n_fonts = 0;
4149 dpyinfo->font_table_size = 0;
4150 dpyinfo->bitmaps = 0;
4151 dpyinfo->bitmaps_size = 0;
4152 dpyinfo->bitmaps_last = 0;
4153 dpyinfo->mouse_face_mouse_frame = 0;
4154 dpyinfo->mouse_face_deferred_gc = 0;
4155 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
4156 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
4157 dpyinfo->mouse_face_face_id = 0;
4158 dpyinfo->mouse_face_window = Qnil;
4159 dpyinfo->mouse_face_mouse_x = dpyinfo->mouse_face_mouse_y = 0;
4160 dpyinfo->mouse_face_defer = 0;
fbd6baed
GV
4161 dpyinfo->w32_focus_frame = 0;
4162 dpyinfo->w32_focus_event_frame = 0;
4163 dpyinfo->w32_highlight_frame = 0;
ee78dc32
GV
4164
4165 ReleaseDC (GetDesktopWindow (), hdc);
4166
52cf03a1
GV
4167 /* Determine if there is a middle mouse button, to allow parse_button
4168 to decide whether right mouse events should be mouse-2 or
4169 mouse-3. */
fbd6baed 4170 XSETINT (Vw32_num_mouse_buttons, GetSystemMetrics (SM_CMOUSEBUTTONS));
52cf03a1
GV
4171
4172 /* initialise palette with white and black */
4173 {
4174 COLORREF color;
4175 defined_color (0, "white", &color, 1);
4176 defined_color (0, "black", &color, 1);
4177 }
4178
ee78dc32
GV
4179#ifndef F_SETOWN_BUG
4180#ifdef F_SETOWN
4181#ifdef F_SETOWN_SOCK_NEG
4182 /* stdin is a socket here */
4183 fcntl (connection, F_SETOWN, -getpid ());
4184#else /* ! defined (F_SETOWN_SOCK_NEG) */
4185 fcntl (connection, F_SETOWN, getpid ());
4186#endif /* ! defined (F_SETOWN_SOCK_NEG) */
4187#endif /* ! defined (F_SETOWN) */
4188#endif /* F_SETOWN_BUG */
4189
4190#ifdef SIGIO
4191 if (interrupt_input)
4192 init_sigio (connection);
4193#endif /* ! defined (SIGIO) */
4194
4195 UNBLOCK_INPUT;
4196
4197 return dpyinfo;
4198}
4199\f
4200/* Get rid of display DPYINFO, assuming all frames are already gone. */
4201
4202void
4203x_delete_display (dpyinfo)
fbd6baed 4204 struct w32_display_info *dpyinfo;
ee78dc32 4205{
fbd6baed 4206 /* Discard this display from w32_display_name_list and w32_display_list.
ee78dc32 4207 We can't use Fdelq because that can quit. */
fbd6baed
GV
4208 if (! NILP (w32_display_name_list)
4209 && EQ (XCONS (w32_display_name_list)->car, dpyinfo->name_list_element))
4210 w32_display_name_list = XCONS (w32_display_name_list)->cdr;
ee78dc32
GV
4211 else
4212 {
4213 Lisp_Object tail;
4214
fbd6baed 4215 tail = w32_display_name_list;
ee78dc32
GV
4216 while (CONSP (tail) && CONSP (XCONS (tail)->cdr))
4217 {
4218 if (EQ (XCONS (XCONS (tail)->cdr)->car,
4219 dpyinfo->name_list_element))
4220 {
4221 XCONS (tail)->cdr = XCONS (XCONS (tail)->cdr)->cdr;
4222 break;
4223 }
4224 tail = XCONS (tail)->cdr;
4225 }
4226 }
4227
52cf03a1
GV
4228 /* free palette table */
4229 {
fbd6baed 4230 struct w32_palette_entry * plist;
52cf03a1
GV
4231
4232 plist = dpyinfo->color_list;
4233 while (plist)
4234 {
fbd6baed 4235 struct w32_palette_entry * pentry = plist;
52cf03a1
GV
4236 plist = plist->next;
4237 xfree(pentry);
4238 }
4239 dpyinfo->color_list = NULL;
4240 if (dpyinfo->palette)
4241 DeleteObject(dpyinfo->palette);
4242 }
ee78dc32 4243 xfree (dpyinfo->font_table);
fbd6baed 4244 xfree (dpyinfo->w32_id_name);
ee78dc32
GV
4245}
4246\f
fbd6baed 4247/* Set up use of W32. */
ee78dc32 4248
689004fa 4249DWORD w32_msg_worker ();
ee78dc32 4250
fbd6baed
GV
4251w32_initialize ()
4252{
4253 clear_frame_hook = w32_clear_frame;
4254 clear_end_of_line_hook = w32_clear_end_of_line;
4255 ins_del_lines_hook = w32_ins_del_lines;
4256 change_line_highlight_hook = w32_change_line_highlight;
4257 insert_glyphs_hook = w32_insert_glyphs;
4258 write_glyphs_hook = w32_write_glyphs;
4259 delete_glyphs_hook = w32_delete_glyphs;
4260 ring_bell_hook = w32_ring_bell;
4261 reset_terminal_modes_hook = w32_reset_terminal_modes;
4262 set_terminal_modes_hook = w32_set_terminal_modes;
4263 update_begin_hook = w32_update_begin;
4264 update_end_hook = w32_update_end;
4265 set_terminal_window_hook = w32_set_terminal_window;
ee78dc32 4266 read_socket_hook = w32_read_socket;
fbd6baed
GV
4267 frame_up_to_date_hook = w32_frame_up_to_date;
4268 cursor_to_hook = w32_cursor_to;
4269 reassert_line_highlight_hook = w32_reassert_line_highlight;
4270 mouse_position_hook = w32_mouse_position;
4271 frame_rehighlight_hook = w32_frame_rehighlight;
4272 frame_raise_lower_hook = w32_frame_raise_lower;
4273 set_vertical_scroll_bar_hook = w32_set_vertical_scroll_bar;
4274 condemn_scroll_bars_hook = w32_condemn_scroll_bars;
4275 redeem_scroll_bar_hook = w32_redeem_scroll_bar;
4276 judge_scroll_bars_hook = w32_judge_scroll_bars;
ee78dc32
GV
4277
4278 scroll_region_ok = 1; /* we'll scroll partial frames */
4279 char_ins_del_ok = 0; /* just as fast to write the line */
4280 line_ins_del_ok = 1; /* we'll just blt 'em */
4281 fast_clear_end_of_line = 1; /* X does this well */
4282 memory_below_frame = 0; /* we don't remember what scrolls
4283 off the bottom */
4284 baud_rate = 19200;
4285
689004fa
GV
4286 /* Initialize input mode: interrupt_input off, no flow control, allow
4287 8 bit character input, standard quit char. */
4288 Fset_input_mode (Qnil, Qnil, make_number (2), Qnil);
ee78dc32
GV
4289
4290 /* Create the window thread - it will terminate itself or when the app terminates */
4291
4292 init_crit ();
4293
4294 dwMainThreadId = GetCurrentThreadId ();
4295 DuplicateHandle (GetCurrentProcess (), GetCurrentThread (),
4296 GetCurrentProcess (), &hMainThread, 0, TRUE, DUPLICATE_SAME_ACCESS);
4297
4298 /* Wait for thread to start */
4299
4300 {
4301 MSG msg;
4302
4303 PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE);
4304
e9e23e23 4305 hWindowsThread = CreateThread (NULL, 0,
689004fa 4306 (LPTHREAD_START_ROUTINE) w32_msg_worker,
e9e23e23 4307 0, 0, &dwWindowsThreadId);
ee78dc32
GV
4308
4309 GetMessage (&msg, NULL, WM_EMACS_DONE, WM_EMACS_DONE);
4310 }
4311
52cf03a1 4312 /* It is desirable that mainThread should have the same notion of
e9e23e23 4313 focus window and active window as windowsThread. Unfortunately, the
52cf03a1
GV
4314 following call to AttachThreadInput, which should do precisely what
4315 we need, causes major problems when Emacs is linked as a console
4316 program. Unfortunately, we have good reasons for doing that, so
e9e23e23 4317 instead we need to send messages to windowsThread to make some API
52cf03a1
GV
4318 calls for us (ones that affect, or depend on, the active/focus
4319 window state. */
4320#ifdef ATTACH_THREADS
e9e23e23 4321 AttachThreadInput (dwMainThreadId, dwWindowsThreadId, TRUE);
52cf03a1 4322#endif
689004fa
GV
4323
4324 /* Dynamically link to optional system components. */
4325 {
4326 HANDLE user_lib = LoadLibrary ("user32.dll");
4327
4328#define LOAD_PROC(fn) pfn##fn = (void *) GetProcAddress (user_lib, #fn)
4329
4330 /* New proportional scroll bar functions. */
4331 LOAD_PROC( SetScrollInfo );
4332 LOAD_PROC( GetScrollInfo );
4333
4334#undef LOAD_PROC
4335
4336 FreeLibrary (user_lib);
4337
4338 /* If using proportional scroll bars, ensure handle is at least 5 pixels;
4339 otherwise use the fixed height. */
4340 vertical_scroll_bar_min_handle = (pfnSetScrollInfo != NULL) ? 5 :
4341 GetSystemMetrics (SM_CYVTHUMB);
4342
4343 /* For either kind of scroll bar, take account of the arrows; these
4344 effectively form the border of the main scroll bar range. */
4345 vertical_scroll_bar_top_border = vertical_scroll_bar_bottom_border
4346 = GetSystemMetrics (SM_CYVSCROLL);
4347 }
ee78dc32
GV
4348}
4349
4350void
fbd6baed 4351syms_of_w32term ()
ee78dc32 4352{
fbd6baed
GV
4353 staticpro (&w32_display_name_list);
4354 w32_display_name_list = Qnil;
ee78dc32
GV
4355
4356 staticpro (&last_mouse_scroll_bar);
4357 last_mouse_scroll_bar = Qnil;
4358
4359 staticpro (&Qvendor_specific_keysyms);
4360 Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
52cf03a1 4361
fbd6baed
GV
4362 DEFVAR_INT ("w32-num-mouse-buttons",
4363 &Vw32_num_mouse_buttons,
52cf03a1 4364 "Number of physical mouse buttons.");
fbd6baed 4365 Vw32_num_mouse_buttons = Qnil;
52cf03a1 4366
fbd6baed
GV
4367 DEFVAR_LISP ("w32-swap-mouse-buttons",
4368 &Vw32_swap_mouse_buttons,
52cf03a1
GV
4369 "Swap the mapping of middle and right mouse buttons.\n\
4370When nil, middle button is mouse-2 and right button is mouse-3.");
fbd6baed 4371 Vw32_swap_mouse_buttons = Qnil;
689004fa
GV
4372
4373 DEFVAR_LISP ("w32-grab-focus-on-raise",
4374 &Vw32_grab_focus_on_raise,
4375 "Raised frame grabs input focus.\n\
4376When t, `raise-frame' grabs input focus as well. This fits well\n\
4377with the normal Windows click-to-focus policy, but might not be\n\
4378desirable when using a point-to-focus policy.");
4379 Vw32_grab_focus_on_raise = Qt;
4380
4381 DEFVAR_LISP ("w32-capslock-is-shiftlock",
4382 &Vw32_capslock_is_shiftlock,
4383 "Apply CapsLock state to non character input keys.\n\
4384When nil, CapsLock only affects normal character input keys.");
4385 Vw32_capslock_is_shiftlock = Qnil;
ee78dc32 4386}