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