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