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