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