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