(latexenc-find-file-coding-system): Don't inherit the EOL part of the
[emacs.git] / src / w32term.c
blob1223aa310d98e0b099223de902abdb186e05baf8
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.
5 This file is part of GNU Emacs.
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.
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.
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. */
22 #include <config.h>
23 #include <signal.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include "lisp.h"
27 #include "charset.h"
28 #include "blockinput.h"
30 #include "w32heap.h"
31 #include "w32term.h"
32 #include "w32bdf.h"
33 #include <shellapi.h>
35 #include "systty.h"
36 #include "systime.h"
37 #include "atimer.h"
38 #include "keymap.h"
40 #include <ctype.h>
41 #include <errno.h>
42 #include <setjmp.h>
43 #include <sys/stat.h>
45 #include "keyboard.h"
46 #include "frame.h"
47 #include "dispextern.h"
48 #include "fontset.h"
49 #include "termhooks.h"
50 #include "termopts.h"
51 #include "termchar.h"
52 #include "gnu.h"
53 #include "disptab.h"
54 #include "buffer.h"
55 #include "window.h"
56 #include "intervals.h"
57 #include "composite.h"
58 #include "coding.h"
60 #define abs(x) ((x) < 0 ? -(x) : (x))
63 /* Fringe bitmaps. */
65 static int max_fringe_bmp = 0;
66 static HBITMAP *fringe_bmp = 0;
68 /* Non-nil means Emacs uses toolkit scroll bars. */
70 Lisp_Object Vx_toolkit_scroll_bars;
72 /* Temporary variables for w32_read_socket. */
74 static int last_mousemove_x = 0;
75 static int last_mousemove_y = 0;
77 /* Define GET_WHEEL_DELTA_WPARAM macro if system headers don't. */
78 #ifndef GET_WHEEL_DELTA_WPARAM
79 #define GET_WHEEL_DELTA_WPARAM(wparam) ((short)HIWORD (wparam))
80 #endif
82 /* Non-zero means that a HELP_EVENT has been generated since Emacs
83 start. */
85 static int any_help_event_p;
87 /* Last window where we saw the mouse. Used by mouse-autoselect-window. */
88 static Lisp_Object last_window;
90 extern unsigned int msh_mousewheel;
92 extern void free_frame_menubar ();
94 extern int w32_codepage_for_font (char *fontname);
95 extern Cursor w32_load_cursor (LPCTSTR name);
97 extern glyph_metric *w32_BDF_TextMetric(bdffont *fontp,
98 unsigned char *text, int dim);
99 extern Lisp_Object Vwindow_system;
101 #define x_any_window_to_frame x_window_to_frame
102 #define x_top_window_to_frame x_window_to_frame
105 /* This is display since w32 does not support multiple ones. */
106 struct w32_display_info one_w32_display_info;
107 struct w32_display_info *x_display_list;
109 /* This is a list of cons cells, each of the form (NAME . FONT-LIST-CACHE),
110 one for each element of w32_display_list and in the same order.
111 NAME is the name of the frame.
112 FONT-LIST-CACHE records previous values returned by x-list-fonts. */
113 Lisp_Object w32_display_name_list;
115 /* Frame being updated by update_frame. This is declared in term.c.
116 This is set by update_begin and looked at by all the
117 w32 functions. It is zero while not inside an update.
118 In that case, the w32 functions assume that `SELECTED_FRAME ()'
119 is the frame to apply to. */
120 extern struct frame *updating_frame;
122 /* This is a frame waiting to be autoraised, within w32_read_socket. */
123 struct frame *pending_autoraise_frame;
125 /* The handle of the frame that currently owns the system caret. */
126 HWND w32_system_caret_hwnd;
127 int w32_system_caret_height;
128 int w32_system_caret_x;
129 int w32_system_caret_y;
130 int w32_use_visible_system_caret;
132 /* Flag to enable Unicode output in case users wish to use programs
133 like Twinbridge on '95 rather than installed system level support
134 for Far East languages. */
135 int w32_enable_unicode_output;
137 DWORD dwWindowsThreadId = 0;
138 HANDLE hWindowsThread = NULL;
139 DWORD dwMainThreadId = 0;
140 HANDLE hMainThread = NULL;
142 #ifndef SIF_ALL
143 /* These definitions are new with Windows 95. */
144 #define SIF_RANGE 0x0001
145 #define SIF_PAGE 0x0002
146 #define SIF_POS 0x0004
147 #define SIF_DISABLENOSCROLL 0x0008
148 #define SIF_TRACKPOS 0x0010
149 #define SIF_ALL (SIF_RANGE | SIF_PAGE | SIF_POS | SIF_TRACKPOS)
151 typedef struct tagSCROLLINFO
153 UINT cbSize;
154 UINT fMask;
155 int nMin;
156 int nMax;
157 UINT nPage;
158 int nPos;
159 int nTrackPos;
160 } SCROLLINFO, FAR *LPSCROLLINFO;
161 typedef SCROLLINFO CONST FAR *LPCSCROLLINFO;
162 #endif /* SIF_ALL */
164 /* Dynamic linking to new proportional scroll bar functions. */
165 int (PASCAL *pfnSetScrollInfo) (HWND hwnd, int fnBar, LPSCROLLINFO lpsi, BOOL fRedraw);
166 BOOL (PASCAL *pfnGetScrollInfo) (HWND hwnd, int fnBar, LPSCROLLINFO lpsi);
168 int vertical_scroll_bar_min_handle;
169 int vertical_scroll_bar_top_border;
170 int vertical_scroll_bar_bottom_border;
172 int last_scroll_bar_drag_pos;
174 /* Mouse movement. */
176 /* Where the mouse was last time we reported a mouse event. */
178 static RECT last_mouse_glyph;
179 static Lisp_Object last_mouse_press_frame;
181 int w32_num_mouse_buttons;
183 Lisp_Object Vw32_swap_mouse_buttons;
185 /* Control whether x_raise_frame also sets input focus. */
186 Lisp_Object Vw32_grab_focus_on_raise;
188 /* Control whether Caps Lock affects non-ascii characters. */
189 Lisp_Object Vw32_capslock_is_shiftlock;
191 /* Control whether right-alt and left-ctrl should be recognized as AltGr. */
192 Lisp_Object Vw32_recognize_altgr;
194 /* The scroll bar in which the last motion event occurred.
196 If the last motion event occurred in a scroll bar, we set this
197 so w32_mouse_position can know whether to report a scroll bar motion or
198 an ordinary motion.
200 If the last motion event didn't occur in a scroll bar, we set this
201 to Qnil, to tell w32_mouse_position to return an ordinary motion event. */
202 static Lisp_Object last_mouse_scroll_bar;
203 static int last_mouse_scroll_bar_pos;
205 /* This is a hack. We would really prefer that w32_mouse_position would
206 return the time associated with the position it returns, but there
207 doesn't seem to be any way to wrest the time-stamp from the server
208 along with the position query. So, we just keep track of the time
209 of the last movement we received, and return that in hopes that
210 it's somewhat accurate. */
212 static Time last_mouse_movement_time;
214 /* Incremented by w32_read_socket whenever it really tries to read
215 events. */
217 #ifdef __STDC__
218 static int volatile input_signal_count;
219 #else
220 static int input_signal_count;
221 #endif
223 extern Lisp_Object Vcommand_line_args, Vsystem_name;
225 #ifndef USE_CRT_DLL
226 extern int errno;
227 #endif
229 /* A mask of extra modifier bits to put into every keyboard char. */
231 extern EMACS_INT extra_keyboard_modifiers;
233 static void x_update_window_end P_ ((struct window *, int, int));
234 void w32_delete_display P_ ((struct w32_display_info *));
235 static void w32_handle_tool_bar_click P_ ((struct frame *,
236 struct input_event *));
237 void w32_define_cursor P_ ((Window, Cursor));
239 void x_lower_frame P_ ((struct frame *));
240 void x_scroll_bar_clear P_ ((struct frame *));
241 void x_wm_set_size_hint P_ ((struct frame *, long, int));
242 void x_raise_frame P_ ((struct frame *));
243 void x_set_window_size P_ ((struct frame *, int, int, int));
244 void x_wm_set_window_state P_ ((struct frame *, int));
245 void x_wm_set_icon_pixmap P_ ((struct frame *, int));
246 void w32_initialize P_ ((void));
247 static void x_font_min_bounds P_ ((XFontStruct *, int *, int *));
248 int x_compute_min_glyph_bounds P_ ((struct frame *));
249 static void x_update_end P_ ((struct frame *));
250 static void w32_frame_up_to_date P_ ((struct frame *));
251 static void w32_set_terminal_modes P_ ((void));
252 static void w32_reset_terminal_modes P_ ((void));
253 static void x_clear_frame P_ ((void));
254 static void frame_highlight P_ ((struct frame *));
255 static void frame_unhighlight P_ ((struct frame *));
256 static void x_new_focus_frame P_ ((struct w32_display_info *,
257 struct frame *));
258 static void x_focus_changed P_ ((int, int, struct w32_display_info *,
259 struct frame *, struct input_event *));
260 static void w32_detect_focus_change P_ ((struct w32_display_info *,
261 W32Msg *, struct input_event *));
262 static void w32_frame_rehighlight P_ ((struct frame *));
263 static void x_frame_rehighlight P_ ((struct w32_display_info *));
264 static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *));
265 static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int,
266 enum text_cursor_kinds));
267 static void w32_clip_to_row P_ ((struct window *, struct glyph_row *, int, HDC));
269 static Lisp_Object Qvendor_specific_keysyms;
272 /***********************************************************************
273 Debugging
274 ***********************************************************************/
276 #if 0
278 /* This is a function useful for recording debugging information about
279 the sequence of occurrences in this file. */
281 struct record
283 char *locus;
284 int type;
287 struct record event_record[100];
289 int event_record_index;
291 record_event (locus, type)
292 char *locus;
293 int type;
295 if (event_record_index == sizeof (event_record) / sizeof (struct record))
296 event_record_index = 0;
298 event_record[event_record_index].locus = locus;
299 event_record[event_record_index].type = type;
300 event_record_index++;
303 #endif /* 0 */
306 void
307 XChangeGC (void * ignore, XGCValues* gc, unsigned long mask,
308 XGCValues *xgcv)
310 if (mask & GCForeground)
311 gc->foreground = xgcv->foreground;
312 if (mask & GCBackground)
313 gc->background = xgcv->background;
314 if (mask & GCFont)
315 gc->font = xgcv->font;
318 XGCValues *XCreateGC (void * ignore, Window window, unsigned long mask,
319 XGCValues *xgcv)
321 XGCValues *gc = (XGCValues *) xmalloc (sizeof (XGCValues));
322 bzero (gc, sizeof (XGCValues));
324 XChangeGC (ignore, gc, mask, xgcv);
326 return gc;
329 void
330 XGetGCValues (void* ignore, XGCValues *gc,
331 unsigned long mask, XGCValues *xgcv)
333 XChangeGC (ignore, xgcv, mask, gc);
336 static void
337 w32_set_clip_rectangle (HDC hdc, RECT *rect)
339 if (rect)
341 HRGN clip_region = CreateRectRgnIndirect (rect);
342 SelectClipRgn (hdc, clip_region);
343 DeleteObject (clip_region);
345 else
346 SelectClipRgn (hdc, NULL);
350 /* Draw a hollow rectangle at the specified position. */
351 void
352 w32_draw_rectangle (HDC hdc, XGCValues *gc, int x, int y,
353 int width, int height)
355 HBRUSH hb, oldhb;
356 HPEN hp, oldhp;
358 hb = CreateSolidBrush (gc->background);
359 hp = CreatePen (PS_SOLID, 0, gc->foreground);
360 oldhb = SelectObject (hdc, hb);
361 oldhp = SelectObject (hdc, hp);
363 Rectangle (hdc, x, y, x + width, y + height);
365 SelectObject (hdc, oldhb);
366 SelectObject (hdc, oldhp);
367 DeleteObject (hb);
368 DeleteObject (hp);
371 /* Draw a filled rectangle at the specified position. */
372 void
373 w32_fill_rect (f, hdc, pix, lprect)
374 FRAME_PTR f;
375 HDC hdc;
376 COLORREF pix;
377 RECT * lprect;
379 HBRUSH hb;
381 hb = CreateSolidBrush (pix);
382 FillRect (hdc, lprect, hb);
383 DeleteObject (hb);
386 void
387 w32_clear_window (f)
388 FRAME_PTR f;
390 RECT rect;
391 HDC hdc = get_frame_dc (f);
393 /* Under certain conditions, this can be called at startup with
394 a console frame pointer before the GUI frame is created. An HDC
395 of 0 indicates this. */
396 if (hdc)
398 GetClientRect (FRAME_W32_WINDOW (f), &rect);
399 w32_clear_rect (f, hdc, &rect);
402 release_frame_dc (f, hdc);
406 /***********************************************************************
407 Starting and ending an update
408 ***********************************************************************/
410 /* Start an update of frame F. This function is installed as a hook
411 for update_begin, i.e. it is called when update_begin is called.
412 This function is called prior to calls to x_update_window_begin for
413 each window being updated. */
415 static void
416 x_update_begin (f)
417 struct frame *f;
419 struct w32_display_info *display_info = FRAME_W32_DISPLAY_INFO (f);
421 if (! FRAME_W32_P (f))
422 return;
424 /* Regenerate display palette before drawing if list of requested
425 colors has changed. */
426 if (display_info->regen_palette)
428 w32_regenerate_palette (f);
429 display_info->regen_palette = FALSE;
434 /* Start update of window W. Set the global variable updated_window
435 to the window being updated and set output_cursor to the cursor
436 position of W. */
438 static void
439 x_update_window_begin (w)
440 struct window *w;
442 struct frame *f = XFRAME (WINDOW_FRAME (w));
443 struct w32_display_info *display_info = FRAME_W32_DISPLAY_INFO (f);
445 /* Hide the system caret during an update. */
446 if (w32_use_visible_system_caret && w32_system_caret_hwnd)
448 SendMessage (w32_system_caret_hwnd, WM_EMACS_HIDE_CARET, 0, 0);
451 updated_window = w;
452 set_output_cursor (&w->cursor);
454 BLOCK_INPUT;
456 if (f == display_info->mouse_face_mouse_frame)
458 /* Don't do highlighting for mouse motion during the update. */
459 display_info->mouse_face_defer = 1;
461 /* If F needs to be redrawn, simply forget about any prior mouse
462 highlighting. */
463 if (FRAME_GARBAGED_P (f))
464 display_info->mouse_face_window = Qnil;
466 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
467 their mouse_face_p flag set, which means that they are always
468 unequal to rows in a desired matrix which never have that
469 flag set. So, rows containing mouse-face glyphs are never
470 scrolled, and we don't have to switch the mouse highlight off
471 here to prevent it from being scrolled. */
473 /* Can we tell that this update does not affect the window
474 where the mouse highlight is? If so, no need to turn off.
475 Likewise, don't do anything if the frame is garbaged;
476 in that case, the frame's current matrix that we would use
477 is all wrong, and we will redisplay that line anyway. */
478 if (!NILP (display_info->mouse_face_window)
479 && w == XWINDOW (display_info->mouse_face_window))
481 int i;
483 for (i = 0; i < w->desired_matrix->nrows; ++i)
484 if (MATRIX_ROW_ENABLED_P (w->desired_matrix, i))
485 break;
487 if (i < w->desired_matrix->nrows)
488 clear_mouse_face (display_info);
490 #endif /* 0 */
493 UNBLOCK_INPUT;
496 /* Draw a vertical window border from (x,y0) to (x,y1) */
498 static void
499 w32_draw_vertical_window_border (w, x, y0, y1)
500 struct window *w;
501 int x, y0, y1;
503 struct frame *f = XFRAME (WINDOW_FRAME (w));
504 RECT r;
505 HDC hdc;
507 r.left = x;
508 r.right = x + 1;
509 r.top = y0;
510 r.bottom = y1;
512 hdc = get_frame_dc (f);
513 w32_fill_rect (f, hdc, FRAME_FOREGROUND_PIXEL (f), &r);
514 release_frame_dc (f, hdc);
518 /* End update of window W (which is equal to updated_window).
520 Draw vertical borders between horizontally adjacent windows, and
521 display W's cursor if CURSOR_ON_P is non-zero.
523 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
524 glyphs in mouse-face were overwritten. In that case we have to
525 make sure that the mouse-highlight is properly redrawn.
527 W may be a menu bar pseudo-window in case we don't have X toolkit
528 support. Such windows don't have a cursor, so don't display it
529 here. */
531 static void
532 x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p)
533 struct window *w;
534 int cursor_on_p, mouse_face_overwritten_p;
536 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (XFRAME (w->frame));
538 if (!w->pseudo_window_p)
540 BLOCK_INPUT;
542 if (cursor_on_p)
543 display_and_set_cursor (w, 1, output_cursor.hpos,
544 output_cursor.vpos,
545 output_cursor.x, output_cursor.y);
547 if (draw_window_fringes (w, 1))
548 x_draw_vertical_border (w);
550 UNBLOCK_INPUT;
553 /* If a row with mouse-face was overwritten, arrange for
554 XTframe_up_to_date to redisplay the mouse highlight. */
555 if (mouse_face_overwritten_p)
557 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
558 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
559 dpyinfo->mouse_face_window = Qnil;
562 /* Unhide the caret. This won't actually show the cursor, unless it
563 was visible before the corresponding call to HideCaret in
564 x_update_window_begin. */
565 if (w32_use_visible_system_caret && w32_system_caret_hwnd)
567 SendMessage (w32_system_caret_hwnd, WM_EMACS_SHOW_CARET, 0, 0);
570 updated_window = NULL;
574 /* End update of frame F. This function is installed as a hook in
575 update_end. */
577 static void
578 x_update_end (f)
579 struct frame *f;
581 if (! FRAME_W32_P (f))
582 return;
584 /* Mouse highlight may be displayed again. */
585 FRAME_W32_DISPLAY_INFO (f)->mouse_face_defer = 0;
589 /* This function is called from various places in xdisp.c whenever a
590 complete update has been performed. The global variable
591 updated_window is not available here. */
593 static void
594 w32_frame_up_to_date (f)
595 struct frame *f;
597 if (FRAME_W32_P (f))
599 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
601 if (dpyinfo->mouse_face_deferred_gc
602 || f == dpyinfo->mouse_face_mouse_frame)
604 BLOCK_INPUT;
605 if (dpyinfo->mouse_face_mouse_frame)
606 note_mouse_highlight (dpyinfo->mouse_face_mouse_frame,
607 dpyinfo->mouse_face_mouse_x,
608 dpyinfo->mouse_face_mouse_y);
609 dpyinfo->mouse_face_deferred_gc = 0;
610 UNBLOCK_INPUT;
616 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
617 arrow bitmaps, or clear the fringes if no bitmaps are required
618 before DESIRED_ROW is made current. The window being updated is
619 found in updated_window. This function is called from
620 update_window_line only if it is known that there are differences
621 between bitmaps to be drawn between current row and DESIRED_ROW. */
623 static void
624 x_after_update_window_line (desired_row)
625 struct glyph_row *desired_row;
627 struct window *w = updated_window;
628 struct frame *f;
629 int width, height;
631 xassert (w);
633 if (!desired_row->mode_line_p && !w->pseudo_window_p)
634 desired_row->redraw_fringe_bitmaps_p = 1;
636 /* When a window has disappeared, make sure that no rest of
637 full-width rows stays visible in the internal border. Could
638 check here if updated_window is the leftmost/rightmost window,
639 but I guess it's not worth doing since vertically split windows
640 are almost never used, internal border is rarely set, and the
641 overhead is very small. */
642 if (windows_or_buffers_changed
643 && desired_row->full_width_p
644 && (f = XFRAME (w->frame),
645 width = FRAME_INTERNAL_BORDER_WIDTH (f),
646 width != 0)
647 && (height = desired_row->visible_height,
648 height > 0))
650 int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
652 /* Internal border is drawn below the tool bar. */
653 if (WINDOWP (f->tool_bar_window)
654 && w == XWINDOW (f->tool_bar_window))
655 y -= width;
657 BLOCK_INPUT;
659 HDC hdc = get_frame_dc (f);
660 w32_clear_area (f, hdc, 0, y, width, height);
661 w32_clear_area (f, hdc, FRAME_PIXEL_WIDTH (f) - width,
662 y, width, height);
663 release_frame_dc (f, hdc);
665 UNBLOCK_INPUT;
670 /* Draw the bitmap WHICH in one of the left or right fringes of
671 window W. ROW is the glyph row for which to display the bitmap; it
672 determines the vertical position at which the bitmap has to be
673 drawn. */
675 static void
676 w32_draw_fringe_bitmap (w, row, p)
677 struct window *w;
678 struct glyph_row *row;
679 struct draw_fringe_bitmap_params *p;
681 struct frame *f = XFRAME (WINDOW_FRAME (w));
682 HDC hdc;
683 struct face *face = p->face;
684 int rowY;
686 hdc = get_frame_dc (f);
688 /* Must clip because of partially visible lines. */
689 rowY = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
690 if (p->y < rowY)
692 /* Adjust position of "bottom aligned" bitmap on partially
693 visible last row. */
694 int oldY = row->y;
695 int oldVH = row->visible_height;
696 row->visible_height = p->h;
697 row->y -= rowY - p->y;
698 w32_clip_to_row (w, row, -1, hdc);
699 row->y = oldY;
700 row->visible_height = oldVH;
702 else
703 w32_clip_to_row (w, row, -1, hdc);
705 if (p->bx >= 0 && !p->overlay_p)
707 w32_fill_area (f, hdc, face->background,
708 p->bx, p->by, p->nx, p->ny);
711 if (p->which && p->which < max_fringe_bmp)
713 HBITMAP pixmap = fringe_bmp[p->which];
714 HDC compat_hdc;
715 HANDLE horig_obj;
717 compat_hdc = CreateCompatibleDC (hdc);
719 SaveDC (hdc);
721 horig_obj = SelectObject (compat_hdc, pixmap);
723 /* Paint overlays transparently. */
724 if (p->overlay_p)
726 HBRUSH h_brush, h_orig_brush;
728 SetTextColor (hdc, BLACK_PIX_DEFAULT (f));
729 SetBkColor (hdc, WHITE_PIX_DEFAULT (f));
730 h_brush = CreateSolidBrush (face->foreground);
731 h_orig_brush = SelectObject (hdc, h_brush);
733 BitBlt (hdc, p->x, p->y, p->wd, p->h,
734 compat_hdc, 0, p->dh,
735 DSTINVERT);
736 BitBlt (hdc, p->x, p->y, p->wd, p->h,
737 compat_hdc, 0, p->dh,
738 0x2E064A);
739 BitBlt (hdc, p->x, p->y, p->wd, p->h,
740 compat_hdc, 0, p->dh,
741 DSTINVERT);
743 SelectObject (hdc, h_orig_brush);
744 DeleteObject (h_brush);
746 else
748 SetTextColor (hdc, face->background);
749 SetBkColor (hdc, (p->cursor_p
750 ? f->output_data.w32->cursor_pixel
751 : face->foreground));
753 BitBlt (hdc, p->x, p->y, p->wd, p->h,
754 compat_hdc, 0, p->dh,
755 SRCCOPY);
758 SelectObject (compat_hdc, horig_obj);
759 DeleteDC (compat_hdc);
760 RestoreDC (hdc, -1);
763 w32_set_clip_rectangle (hdc, NULL);
765 release_frame_dc (f, hdc);
768 static void
769 w32_define_fringe_bitmap (which, bits, h, wd)
770 int which;
771 unsigned short *bits;
772 int h, wd;
774 if (which >= max_fringe_bmp)
776 int i = max_fringe_bmp;
777 max_fringe_bmp = which + 20;
778 fringe_bmp = (HBITMAP *) xrealloc (fringe_bmp, max_fringe_bmp * sizeof (HBITMAP));
779 while (i < max_fringe_bmp)
780 fringe_bmp[i++] = 0;
783 fringe_bmp[which] = CreateBitmap (wd, h, 1, 1, bits);
786 static void
787 w32_destroy_fringe_bitmap (which)
788 int which;
790 if (which >= max_fringe_bmp)
791 return;
793 if (fringe_bmp[which])
794 DeleteObject (fringe_bmp[which]);
795 fringe_bmp[which] = 0;
800 /* This is called when starting Emacs and when restarting after
801 suspend. When starting Emacs, no window is mapped. And nothing
802 must be done to Emacs's own window if it is suspended (though that
803 rarely happens). */
805 static void
806 w32_set_terminal_modes (void)
810 /* This is called when exiting or suspending Emacs. Exiting will make
811 the W32 windows go away, and suspending requires no action. */
813 static void
814 w32_reset_terminal_modes (void)
820 /***********************************************************************
821 Display Iterator
822 ***********************************************************************/
824 /* Function prototypes of this page. */
826 XCharStruct *w32_per_char_metric P_ ((XFontStruct *, wchar_t *, int));
827 static int w32_encode_char P_ ((int, wchar_t *, struct font_info *, int *));
830 /* Get metrics of character CHAR2B in FONT. Value is always non-null.
831 If CHAR2B is not contained in FONT, the font's default character
832 metric is returned. */
834 static int
835 w32_bdf_per_char_metric (font, char2b, dim, pcm)
836 XFontStruct *font;
837 wchar_t *char2b;
838 int dim;
839 XCharStruct * pcm;
841 glyph_metric * bdf_metric;
842 char buf[2];
844 if (dim == 1)
845 buf[0] = (char)(*char2b);
846 else
848 buf[0] = XCHAR2B_BYTE1 (char2b);
849 buf[1] = XCHAR2B_BYTE2 (char2b);
852 bdf_metric = w32_BDF_TextMetric (font->bdf, buf, dim);
854 if (bdf_metric)
856 pcm->width = bdf_metric->dwidth;
857 pcm->lbearing = bdf_metric->bbox;
858 pcm->rbearing = bdf_metric->dwidth
859 - (bdf_metric->bbox + bdf_metric->bbw);
860 pcm->ascent = bdf_metric->bboy + bdf_metric->bbh;
861 pcm->descent = -bdf_metric->bboy;
863 return 1;
865 return 0;
869 static int
870 w32_native_per_char_metric (font, char2b, font_type, pcm)
871 XFontStruct *font;
872 wchar_t *char2b;
873 enum w32_char_font_type font_type;
874 XCharStruct * pcm;
876 HDC hdc = GetDC (NULL);
877 HFONT old_font;
878 BOOL retval = FALSE;
880 xassert (font && char2b);
881 xassert (font->hfont);
882 xassert (font_type == UNICODE_FONT || font_type == ANSI_FONT);
884 old_font = SelectObject (hdc, font->hfont);
886 if ((font->tm.tmPitchAndFamily & TMPF_TRUETYPE) != 0)
888 ABC char_widths;
890 if (font_type == UNICODE_FONT)
891 retval = GetCharABCWidthsW (hdc, *char2b, *char2b, &char_widths);
892 else
893 retval = GetCharABCWidthsA (hdc, *char2b, *char2b, &char_widths);
895 if (retval)
897 #if 0
898 /* Disabled until we can find a way to get the right results
899 on all versions of Windows. */
901 /* Don't trust the ABC widths. For synthesized fonts they are
902 wrong, and so is the result of GetCharWidth()! */
903 int real_width;
904 GetCharWidth (hdc, *char2b, *char2b, &real_width);
905 #endif
906 pcm->width = char_widths.abcA + char_widths.abcB + char_widths.abcC;
907 #if 0
908 /* As far as I can tell, this is the best way to determine what
909 ExtTextOut will do with the broken font. */
910 if (pcm->width != real_width)
911 pcm->width = (pcm->width + real_width) / 2;
912 #endif
913 pcm->lbearing = char_widths.abcA;
914 pcm->rbearing = char_widths.abcA + char_widths.abcB;
915 pcm->ascent = FONT_BASE (font);
916 pcm->descent = FONT_DESCENT (font);
920 if (!retval)
922 /* Either font is not a True-type font, or GetCharABCWidthsW
923 failed (it is not supported on Windows 9x for instance), so we
924 can't determine the full info we would like. All is not lost
925 though - we can call GetTextExtentPoint32 to get rbearing and
926 deduce width based on the font's per-string overhang. lbearing
927 is assumed to be zero. */
929 /* TODO: Some Thai characters (and other composites if Windows
930 supports them) do have lbearing, and report their total width
931 as zero. Need some way of handling them when
932 GetCharABCWidthsW fails. */
933 SIZE sz;
935 if (font_type == UNICODE_FONT)
936 retval = GetTextExtentPoint32W (hdc, char2b, 1, &sz);
937 else
938 retval = GetTextExtentPoint32A (hdc, (char*)char2b, 1, &sz);
940 if (retval)
942 pcm->width = sz.cx - font->tm.tmOverhang;
943 pcm->rbearing = sz.cx;
944 pcm->lbearing = 0;
945 pcm->ascent = FONT_BASE (font);
946 pcm->descent = FONT_DESCENT (font);
951 if (pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0)
953 retval = FALSE;
956 SelectObject (hdc, old_font);
957 ReleaseDC (NULL, hdc);
959 return retval;
963 XCharStruct *
964 w32_per_char_metric (font, char2b, font_type)
965 XFontStruct *font;
966 wchar_t *char2b;
967 int /* enum w32_char_font_type */ font_type;
969 /* The result metric information. */
970 XCharStruct *pcm;
971 BOOL retval;
973 xassert (font && char2b);
975 /* TODO: This function is currently called through the RIF, and in
976 some cases font_type is UNKNOWN_FONT. We currently allow the
977 cached metrics to be used, which seems to work, but in cases
978 where font_type is UNKNOWN_FONT, we probably haven't encoded
979 char2b appropriately. All callers need checking to see what they
980 are passing. This is most likely to affect variable width fonts
981 outside the Latin-1 range, particularly in languages like Thai
982 that rely on rbearing and lbearing to provide composition. I
983 don't think that is working currently anyway, but we don't seem
984 to have anyone testing such languages on Windows. */
986 /* Handle the common cases quickly. */
987 if (!font->bdf && font->per_char == NULL)
988 /* TODO: determine whether char2b exists in font? */
989 return &font->max_bounds;
990 else if (!font->bdf && *char2b < 128)
991 return &font->per_char[*char2b];
993 xassert (font_type != UNKNOWN_FONT);
995 pcm = &font->scratch;
997 if (font_type == BDF_1D_FONT)
998 retval = w32_bdf_per_char_metric (font, char2b, 1, pcm);
999 else if (font_type == BDF_2D_FONT)
1000 retval = w32_bdf_per_char_metric (font, char2b, 2, pcm);
1001 else
1002 retval = w32_native_per_char_metric (font, char2b, font_type, pcm);
1004 if (retval)
1005 return pcm;
1007 return NULL;
1010 void
1011 w32_cache_char_metrics (font)
1012 XFontStruct *font;
1014 wchar_t char2b = L'x';
1016 /* Cache char metrics for the common cases. */
1017 if (font->bdf)
1019 /* TODO: determine whether font is fixed-pitch. */
1020 if (!w32_bdf_per_char_metric (font, &char2b, 1, &font->max_bounds))
1022 /* Use the font width and height as max bounds, as not all BDF
1023 fonts contain the letter 'x'. */
1024 font->max_bounds.width = FONT_MAX_WIDTH (font);
1025 font->max_bounds.lbearing = -font->bdf->llx;
1026 font->max_bounds.rbearing = FONT_MAX_WIDTH (font) - font->bdf->urx;
1027 font->max_bounds.ascent = FONT_BASE (font);
1028 font->max_bounds.descent = FONT_DESCENT (font);
1031 else
1033 if (((font->tm.tmPitchAndFamily & TMPF_FIXED_PITCH) != 0)
1034 /* Some fonts (eg DBCS fonts) are marked as fixed width even
1035 though they contain characters of different widths. */
1036 || (font->tm.tmMaxCharWidth != font->tm.tmAveCharWidth))
1038 /* Font is not fixed pitch, so cache per_char info for the
1039 ASCII characters. It would be much more work, and probably
1040 not worth it, to cache other chars, since we may change
1041 between using Unicode and ANSI text drawing functions at
1042 run-time. */
1043 int i;
1045 font->per_char = xmalloc (128 * sizeof(XCharStruct));
1046 for (i = 0; i < 128; i++)
1048 char2b = i;
1049 w32_native_per_char_metric (font, &char2b, ANSI_FONT,
1050 &font->per_char[i]);
1053 else
1054 w32_native_per_char_metric (font, &char2b, ANSI_FONT,
1055 &font->max_bounds);
1060 /* Determine if a font is double byte. */
1061 int w32_font_is_double_byte (XFontStruct *font)
1063 return font->double_byte_p;
1067 static BOOL
1068 w32_use_unicode_for_codepage (codepage)
1069 int codepage;
1071 /* If the current codepage is supported, use Unicode for output. */
1072 return (w32_enable_unicode_output
1073 && codepage != CP_8BIT
1074 && (codepage == CP_UNICODE || IsValidCodePage (codepage)));
1077 /* Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
1078 the two-byte form of C. Encoding is returned in *CHAR2B. */
1080 static int /* enum w32_char_font_type */
1081 w32_encode_char (c, char2b, font_info, two_byte_p)
1082 int c;
1083 wchar_t *char2b;
1084 struct font_info *font_info;
1085 int * two_byte_p;
1087 int charset = CHAR_CHARSET (c);
1088 int codepage;
1089 int unicode_p = 0;
1090 int internal_two_byte_p = 0;
1092 XFontStruct *font = font_info->font;
1094 internal_two_byte_p = w32_font_is_double_byte (font);
1096 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
1097 This may be either a program in a special encoder language or a
1098 fixed encoding. */
1099 if (font_info->font_encoder)
1101 /* It's a program. */
1102 struct ccl_program *ccl = font_info->font_encoder;
1104 if (CHARSET_DIMENSION (charset) == 1)
1106 ccl->reg[0] = charset;
1107 ccl->reg[1] = XCHAR2B_BYTE2 (char2b);
1108 ccl->reg[2] = -1;
1110 else
1112 ccl->reg[0] = charset;
1113 ccl->reg[1] = XCHAR2B_BYTE1 (char2b);
1114 ccl->reg[2] = XCHAR2B_BYTE2 (char2b);
1117 ccl_driver (ccl, NULL, NULL, 0, 0, NULL);
1119 /* We assume that MSBs are appropriately set/reset by CCL
1120 program. */
1121 if (!internal_two_byte_p) /* 1-byte font */
1122 STORE_XCHAR2B (char2b, 0, ccl->reg[1]);
1123 else
1124 STORE_XCHAR2B (char2b, ccl->reg[1], ccl->reg[2]);
1126 else if (font_info->encoding[charset])
1128 /* Fixed encoding scheme. See fontset.h for the meaning of the
1129 encoding numbers. */
1130 int enc = font_info->encoding[charset];
1132 if ((enc == 1 || enc == 2)
1133 && CHARSET_DIMENSION (charset) == 2)
1134 STORE_XCHAR2B (char2b, XCHAR2B_BYTE1 (char2b) | 0x80, XCHAR2B_BYTE2 (char2b));
1136 if (enc == 1 || enc == 3
1137 || (enc == 4 && CHARSET_DIMENSION (charset) == 1))
1138 STORE_XCHAR2B (char2b, XCHAR2B_BYTE1 (char2b), XCHAR2B_BYTE2 (char2b) | 0x80);
1139 else if (enc == 4)
1141 int sjis1, sjis2;
1143 ENCODE_SJIS (XCHAR2B_BYTE1 (char2b), XCHAR2B_BYTE2 (char2b),
1144 sjis1, sjis2);
1145 STORE_XCHAR2B (char2b, sjis1, sjis2);
1148 codepage = font_info->codepage;
1150 /* If charset is not ASCII or Latin-1, may need to move it into
1151 Unicode space. */
1152 if ( font && !font->bdf && w32_use_unicode_for_codepage (codepage)
1153 && charset != CHARSET_ASCII && charset != charset_latin_iso8859_1
1154 && charset != CHARSET_8_BIT_CONTROL && charset != CHARSET_8_BIT_GRAPHIC)
1156 char temp[3];
1157 temp[0] = XCHAR2B_BYTE1 (char2b);
1158 temp[1] = XCHAR2B_BYTE2 (char2b);
1159 temp[2] = '\0';
1160 if (codepage != CP_UNICODE)
1162 if (temp[0])
1163 MultiByteToWideChar (codepage, 0, temp, 2, char2b, 1);
1164 else
1165 MultiByteToWideChar (codepage, 0, temp+1, 1, char2b, 1);
1167 unicode_p = 1;
1168 internal_two_byte_p = 1;
1171 if (two_byte_p)
1172 *two_byte_p = internal_two_byte_p;
1174 if (!font)
1175 return UNKNOWN_FONT;
1176 else if (font->bdf && CHARSET_DIMENSION (charset) == 1)
1177 return BDF_1D_FONT;
1178 else if (font->bdf)
1179 return BDF_2D_FONT;
1180 else if (unicode_p)
1181 return UNICODE_FONT;
1182 else
1183 return ANSI_FONT;
1188 /***********************************************************************
1189 Glyph display
1190 ***********************************************************************/
1193 /* Encapsulate the different ways of displaying text under W32. */
1195 static void
1196 w32_text_out (s, x, y,chars,nchars)
1197 struct glyph_string * s;
1198 int x, y;
1199 wchar_t * chars;
1200 int nchars;
1202 int charset_dim = w32_font_is_double_byte (s->font) ? 2 : 1;
1203 if (s->font->bdf)
1204 w32_BDF_TextOut (s->font->bdf, s->hdc,
1205 x, y, (char *) chars, charset_dim,
1206 nchars * charset_dim, 0);
1207 else if (s->first_glyph->font_type == UNICODE_FONT)
1208 ExtTextOutW (s->hdc, x, y, 0, NULL, chars, nchars, NULL);
1209 else
1210 ExtTextOutA (s->hdc, x, y, 0, NULL, (char *) chars,
1211 nchars * charset_dim, NULL);
1215 static void x_set_glyph_string_clipping P_ ((struct glyph_string *));
1216 static void x_set_glyph_string_gc P_ ((struct glyph_string *));
1217 static void x_draw_glyph_string_background P_ ((struct glyph_string *,
1218 int));
1219 static void x_draw_glyph_string_foreground P_ ((struct glyph_string *));
1220 static void x_draw_composite_glyph_string_foreground P_ ((struct glyph_string *));
1221 static void x_draw_glyph_string_box P_ ((struct glyph_string *));
1222 static void x_draw_glyph_string P_ ((struct glyph_string *));
1223 static void x_set_cursor_gc P_ ((struct glyph_string *));
1224 static void x_set_mode_line_face_gc P_ ((struct glyph_string *));
1225 static void x_set_mouse_face_gc P_ ((struct glyph_string *));
1226 static int w32_alloc_lighter_color (struct frame *, COLORREF *, double, int);
1227 static void w32_setup_relief_color P_ ((struct frame *, struct relief *,
1228 double, int, COLORREF));
1229 static void x_setup_relief_colors P_ ((struct glyph_string *));
1230 static void x_draw_image_glyph_string P_ ((struct glyph_string *));
1231 static void x_draw_image_relief P_ ((struct glyph_string *));
1232 static void x_draw_image_foreground P_ ((struct glyph_string *));
1233 static void w32_draw_image_foreground_1 P_ ((struct glyph_string *, HBITMAP));
1234 static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int,
1235 int, int, int));
1236 static void w32_draw_relief_rect P_ ((struct frame *, int, int, int, int,
1237 int, int, int, int, int, int,
1238 RECT *));
1239 static void w32_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,
1240 int, int, int, RECT *));
1242 #if GLYPH_DEBUG
1243 static void x_check_font P_ ((struct frame *, XFontStruct *));
1244 #endif
1247 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
1248 face. */
1250 static void
1251 x_set_cursor_gc (s)
1252 struct glyph_string *s;
1254 if (s->font == FRAME_FONT (s->f)
1255 && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
1256 && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
1257 && !s->cmp)
1258 s->gc = s->f->output_data.w32->cursor_gc;
1259 else
1261 /* Cursor on non-default face: must merge. */
1262 XGCValues xgcv;
1263 unsigned long mask;
1265 xgcv.background = s->f->output_data.w32->cursor_pixel;
1266 xgcv.foreground = s->face->background;
1268 /* If the glyph would be invisible, try a different foreground. */
1269 if (xgcv.foreground == xgcv.background)
1270 xgcv.foreground = s->face->foreground;
1271 if (xgcv.foreground == xgcv.background)
1272 xgcv.foreground = s->f->output_data.w32->cursor_foreground_pixel;
1273 if (xgcv.foreground == xgcv.background)
1274 xgcv.foreground = s->face->foreground;
1276 /* Make sure the cursor is distinct from text in this face. */
1277 if (xgcv.background == s->face->background
1278 && xgcv.foreground == s->face->foreground)
1280 xgcv.background = s->face->foreground;
1281 xgcv.foreground = s->face->background;
1284 IF_DEBUG (x_check_font (s->f, s->font));
1285 xgcv.font = s->font;
1286 mask = GCForeground | GCBackground | GCFont;
1288 if (FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc)
1289 XChangeGC (NULL, FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc,
1290 mask, &xgcv);
1291 else
1292 FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc
1293 = XCreateGC (NULL, s->window, mask, &xgcv);
1295 s->gc = FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc;
1300 /* Set up S->gc of glyph string S for drawing text in mouse face. */
1302 static void
1303 x_set_mouse_face_gc (s)
1304 struct glyph_string *s;
1306 int face_id;
1307 struct face *face;
1309 /* What face has to be used last for the mouse face? */
1310 face_id = FRAME_W32_DISPLAY_INFO (s->f)->mouse_face_face_id;
1311 face = FACE_FROM_ID (s->f, face_id);
1312 if (face == NULL)
1313 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
1315 if (s->first_glyph->type == CHAR_GLYPH)
1316 face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch);
1317 else
1318 face_id = FACE_FOR_CHAR (s->f, face, 0);
1319 s->face = FACE_FROM_ID (s->f, face_id);
1320 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
1322 /* If font in this face is same as S->font, use it. */
1323 if (s->font == s->face->font)
1324 s->gc = s->face->gc;
1325 else
1327 /* Otherwise construct scratch_cursor_gc with values from FACE
1328 but font FONT. */
1329 XGCValues xgcv;
1330 unsigned long mask;
1332 xgcv.background = s->face->background;
1333 xgcv.foreground = s->face->foreground;
1334 IF_DEBUG (x_check_font (s->f, s->font));
1335 xgcv.font = s->font;
1336 mask = GCForeground | GCBackground | GCFont;
1338 if (FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc)
1339 XChangeGC (NULL, FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc,
1340 mask, &xgcv);
1341 else
1342 FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc
1343 = XCreateGC (NULL, s->window, mask, &xgcv);
1345 s->gc = FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc;
1348 xassert (s->gc != 0);
1352 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
1353 Faces to use in the mode line have already been computed when the
1354 matrix was built, so there isn't much to do, here. */
1356 static INLINE void
1357 x_set_mode_line_face_gc (s)
1358 struct glyph_string *s;
1360 s->gc = s->face->gc;
1364 /* Set S->gc of glyph string S for drawing that glyph string. Set
1365 S->stippled_p to a non-zero value if the face of S has a stipple
1366 pattern. */
1368 static INLINE void
1369 x_set_glyph_string_gc (s)
1370 struct glyph_string *s;
1372 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
1374 if (s->hl == DRAW_NORMAL_TEXT)
1376 s->gc = s->face->gc;
1377 s->stippled_p = s->face->stipple != 0;
1379 else if (s->hl == DRAW_INVERSE_VIDEO)
1381 x_set_mode_line_face_gc (s);
1382 s->stippled_p = s->face->stipple != 0;
1384 else if (s->hl == DRAW_CURSOR)
1386 x_set_cursor_gc (s);
1387 s->stippled_p = 0;
1389 else if (s->hl == DRAW_MOUSE_FACE)
1391 x_set_mouse_face_gc (s);
1392 s->stippled_p = s->face->stipple != 0;
1394 else if (s->hl == DRAW_IMAGE_RAISED
1395 || s->hl == DRAW_IMAGE_SUNKEN)
1397 s->gc = s->face->gc;
1398 s->stippled_p = s->face->stipple != 0;
1400 else
1402 s->gc = s->face->gc;
1403 s->stippled_p = s->face->stipple != 0;
1406 /* GC must have been set. */
1407 xassert (s->gc != 0);
1411 /* Set clipping for output of glyph string S. S may be part of a mode
1412 line or menu if we don't have X toolkit support. */
1414 static INLINE void
1415 x_set_glyph_string_clipping (s)
1416 struct glyph_string *s;
1418 RECT r;
1419 get_glyph_string_clip_rect (s, &r);
1420 w32_set_clip_rectangle (s->hdc, &r);
1424 /* RIF:
1425 Compute left and right overhang of glyph string S. If S is a glyph
1426 string for a composition, assume overhangs don't exist. */
1428 static void
1429 w32_compute_glyph_string_overhangs (s)
1430 struct glyph_string *s;
1432 /* TODO: Windows does not appear to have a method for
1433 getting this info without getting the ABC widths for each
1434 individual character and working it out manually. */
1438 static void
1439 w32_get_glyph_overhangs (glyph, f, left, right)
1440 struct glyph *glyph;
1441 struct frame *f;
1442 int *left, *right;
1444 HDC hdc = get_frame_dc (f);
1445 /* Convert to unicode! */
1446 x_get_glyph_overhangs (glyph, f, left, right);
1447 release_frame_dc (f, hdc);
1451 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
1453 static INLINE void
1454 x_clear_glyph_string_rect (s, x, y, w, h)
1455 struct glyph_string *s;
1456 int x, y, w, h;
1458 int real_x = x;
1459 int real_y = y;
1460 int real_w = w;
1461 int real_h = h;
1462 #if 0
1463 /* Take clipping into account. */
1464 if (s->gc->clip_mask == Rect)
1466 real_x = max (real_x, s->gc->clip_rectangle.left);
1467 real_y = max (real_y, s->gc->clip_rectangle.top);
1468 real_w = min (real_w, s->gc->clip_rectangle.right
1469 - s->gc->clip_rectangle.left);
1470 real_h = min (real_h, s->gc->clip_rectangle.bottom
1471 - s->gc->clip_rectangle.top);
1473 #endif
1474 w32_fill_area (s->f, s->hdc, s->gc->background, real_x, real_y,
1475 real_w, real_h);
1479 /* Draw the background of glyph_string S. If S->background_filled_p
1480 is non-zero don't draw it. FORCE_P non-zero means draw the
1481 background even if it wouldn't be drawn normally. This is used
1482 when a string preceding S draws into the background of S, or S
1483 contains the first component of a composition. */
1485 static void
1486 x_draw_glyph_string_background (s, force_p)
1487 struct glyph_string *s;
1488 int force_p;
1490 /* Nothing to do if background has already been drawn or if it
1491 shouldn't be drawn in the first place. */
1492 if (!s->background_filled_p)
1494 int box_line_width = max (s->face->box_line_width, 0);
1496 #if 0 /* TODO: stipple */
1497 if (s->stippled_p)
1499 /* Fill background with a stipple pattern. */
1500 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
1501 XFillRectangle (s->display, s->window, s->gc, s->x,
1502 s->y + box_line_width,
1503 s->background_width,
1504 s->height - 2 * box_line_width);
1505 XSetFillStyle (s->display, s->gc, FillSolid);
1506 s->background_filled_p = 1;
1508 else
1509 #endif
1510 if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
1511 || s->font_not_found_p
1512 || s->extends_to_end_of_line_p
1513 || s->font->bdf
1514 || force_p)
1516 x_clear_glyph_string_rect (s, s->x, s->y + box_line_width,
1517 s->background_width,
1518 s->height - 2 * box_line_width);
1519 s->background_filled_p = 1;
1525 /* Draw the foreground of glyph string S. */
1527 static void
1528 x_draw_glyph_string_foreground (s)
1529 struct glyph_string *s;
1531 int i, x;
1532 HFONT old_font;
1534 /* If first glyph of S has a left box line, start drawing the text
1535 of S to the right of that box line. */
1536 if (s->face->box != FACE_NO_BOX
1537 && s->first_glyph->left_box_line_p)
1538 x = s->x + abs (s->face->box_line_width);
1539 else
1540 x = s->x;
1542 if (s->for_overlaps_p || (s->background_filled_p && s->hl != DRAW_CURSOR))
1543 SetBkMode (s->hdc, TRANSPARENT);
1544 else
1545 SetBkMode (s->hdc, OPAQUE);
1547 SetTextColor (s->hdc, s->gc->foreground);
1548 SetBkColor (s->hdc, s->gc->background);
1549 SetTextAlign (s->hdc, TA_BASELINE | TA_LEFT);
1551 if (s->font && s->font->hfont)
1552 old_font = SelectObject (s->hdc, s->font->hfont);
1554 /* Draw characters of S as rectangles if S's font could not be
1555 loaded. */
1556 if (s->font_not_found_p)
1558 for (i = 0; i < s->nchars; ++i)
1560 struct glyph *g = s->first_glyph + i;
1562 w32_draw_rectangle (s->hdc, s->gc, x, s->y, g->pixel_width - 1,
1563 s->height - 1);
1564 x += g->pixel_width;
1567 else
1569 char *char1b = (char *) s->char2b;
1570 int boff = s->font_info->baseline_offset;
1572 if (s->font_info->vertical_centering)
1573 boff = VCENTER_BASELINE_OFFSET (s->font, s->f) - boff;
1575 /* If we can use 8-bit functions, condense S->char2b. */
1576 if (!s->two_byte_p)
1577 for (i = 0; i < s->nchars; ++i)
1578 char1b[i] = XCHAR2B_BYTE2 (&s->char2b[i]);
1580 /* Draw text with TextOut and friends. */
1581 w32_text_out (s, x, s->ybase - boff, s->char2b, s->nchars);
1583 if (s->face->overstrike)
1585 /* For overstriking (to simulate bold-face), draw the
1586 characters again shifted to the right by one pixel. */
1587 w32_text_out (s, x + 1, s->ybase - boff, s->char2b, s->nchars);
1590 if (s->font && s->font->hfont)
1591 SelectObject (s->hdc, old_font);
1594 /* Draw the foreground of composite glyph string S. */
1596 static void
1597 x_draw_composite_glyph_string_foreground (s)
1598 struct glyph_string *s;
1600 int i, x;
1601 HFONT old_font;
1603 /* If first glyph of S has a left box line, start drawing the text
1604 of S to the right of that box line. */
1605 if (s->face->box != FACE_NO_BOX
1606 && s->first_glyph->left_box_line_p)
1607 x = s->x + abs (s->face->box_line_width);
1608 else
1609 x = s->x;
1611 /* S is a glyph string for a composition. S->gidx is the index of
1612 the first character drawn for glyphs of this composition.
1613 S->gidx == 0 means we are drawing the very first character of
1614 this composition. */
1616 SetTextColor (s->hdc, s->gc->foreground);
1617 SetBkColor (s->hdc, s->gc->background);
1618 SetBkMode (s->hdc, TRANSPARENT);
1619 SetTextAlign (s->hdc, TA_BASELINE | TA_LEFT);
1621 if (s->font && s->font->hfont)
1622 old_font = SelectObject (s->hdc, s->font->hfont);
1624 /* Draw a rectangle for the composition if the font for the very
1625 first character of the composition could not be loaded. */
1626 if (s->font_not_found_p)
1628 if (s->gidx == 0)
1629 w32_draw_rectangle (s->hdc, s->gc, x, s->y, s->width - 1,
1630 s->height - 1);
1632 else
1634 for (i = 0; i < s->nchars; i++, ++s->gidx)
1636 w32_text_out (s, x + s->cmp->offsets[s->gidx * 2],
1637 s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
1638 s->char2b + i, 1);
1639 if (s->face->overstrike)
1640 w32_text_out (s, x + s->cmp->offsets[s->gidx * 2] + 1,
1641 s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
1642 s->char2b + i, 1);
1646 if (s->font && s->font->hfont)
1647 SelectObject (s->hdc, old_font);
1651 /* Brightness beyond which a color won't have its highlight brightness
1652 boosted.
1654 Nominally, highlight colors for `3d' faces are calculated by
1655 brightening an object's color by a constant scale factor, but this
1656 doesn't yield good results for dark colors, so for colors who's
1657 brightness is less than this value (on a scale of 0-255) have to
1658 use an additional additive factor.
1660 The value here is set so that the default menu-bar/mode-line color
1661 (grey75) will not have its highlights changed at all. */
1662 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 187
1665 /* Allocate a color which is lighter or darker than *COLOR by FACTOR
1666 or DELTA. Try a color with RGB values multiplied by FACTOR first.
1667 If this produces the same color as COLOR, try a color where all RGB
1668 values have DELTA added. Return the allocated color in *COLOR.
1669 DISPLAY is the X display, CMAP is the colormap to operate on.
1670 Value is non-zero if successful. */
1672 static int
1673 w32_alloc_lighter_color (f, color, factor, delta)
1674 struct frame *f;
1675 COLORREF *color;
1676 double factor;
1677 int delta;
1679 COLORREF new;
1680 long bright;
1682 /* On Windows, RGB values are 0-255, not 0-65535, so scale delta. */
1683 delta /= 256;
1685 /* Change RGB values by specified FACTOR. Avoid overflow! */
1686 xassert (factor >= 0);
1687 new = PALETTERGB (min (0xff, factor * GetRValue (*color)),
1688 min (0xff, factor * GetGValue (*color)),
1689 min (0xff, factor * GetBValue (*color)));
1691 /* Calculate brightness of COLOR. */
1692 bright = (2 * GetRValue (*color) + 3 * GetGValue (*color)
1693 + GetBValue (*color)) / 6;
1695 /* We only boost colors that are darker than
1696 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
1697 if (bright < HIGHLIGHT_COLOR_DARK_BOOST_LIMIT)
1698 /* Make an additive adjustment to NEW, because it's dark enough so
1699 that scaling by FACTOR alone isn't enough. */
1701 /* How far below the limit this color is (0 - 1, 1 being darker). */
1702 double dimness = 1 - (double)bright / HIGHLIGHT_COLOR_DARK_BOOST_LIMIT;
1703 /* The additive adjustment. */
1704 int min_delta = delta * dimness * factor / 2;
1706 if (factor < 1)
1707 new = PALETTERGB (max (0, min (0xff, min_delta - GetRValue (*color))),
1708 max (0, min (0xff, min_delta - GetGValue (*color))),
1709 max (0, min (0xff, min_delta - GetBValue (*color))));
1710 else
1711 new = PALETTERGB (max (0, min (0xff, min_delta + GetRValue (*color))),
1712 max (0, min (0xff, min_delta + GetGValue (*color))),
1713 max (0, min (0xff, min_delta + GetBValue (*color))));
1716 if (new == *color)
1717 new = PALETTERGB (max (0, min (0xff, delta + GetRValue (*color))),
1718 max (0, min (0xff, delta + GetGValue (*color))),
1719 max (0, min (0xff, delta + GetBValue (*color))));
1721 /* TODO: Map to palette and retry with delta if same? */
1722 /* TODO: Free colors (if using palette)? */
1724 if (new == *color)
1725 return 0;
1727 *color = new;
1729 return 1;
1733 /* Set up the foreground color for drawing relief lines of glyph
1734 string S. RELIEF is a pointer to a struct relief containing the GC
1735 with which lines will be drawn. Use a color that is FACTOR or
1736 DELTA lighter or darker than the relief's background which is found
1737 in S->f->output_data.x->relief_background. If such a color cannot
1738 be allocated, use DEFAULT_PIXEL, instead. */
1740 static void
1741 w32_setup_relief_color (f, relief, factor, delta, default_pixel)
1742 struct frame *f;
1743 struct relief *relief;
1744 double factor;
1745 int delta;
1746 COLORREF default_pixel;
1748 XGCValues xgcv;
1749 struct w32_output *di = f->output_data.w32;
1750 unsigned long mask = GCForeground;
1751 COLORREF pixel;
1752 COLORREF background = di->relief_background;
1753 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
1755 /* TODO: Free colors (if using palette)? */
1757 /* Allocate new color. */
1758 xgcv.foreground = default_pixel;
1759 pixel = background;
1760 if (w32_alloc_lighter_color (f, &pixel, factor, delta))
1762 relief->allocated_p = 1;
1763 xgcv.foreground = relief->pixel = pixel;
1766 if (relief->gc == 0)
1768 #if 0 /* TODO: stipple */
1769 xgcv.stipple = dpyinfo->gray;
1770 mask |= GCStipple;
1771 #endif
1772 relief->gc = XCreateGC (NULL, FRAME_W32_WINDOW (f), mask, &xgcv);
1774 else
1775 XChangeGC (NULL, relief->gc, mask, &xgcv);
1779 /* Set up colors for the relief lines around glyph string S. */
1781 static void
1782 x_setup_relief_colors (s)
1783 struct glyph_string *s;
1785 struct w32_output *di = s->f->output_data.w32;
1786 COLORREF color;
1788 if (s->face->use_box_color_for_shadows_p)
1789 color = s->face->box_color;
1790 else if (s->first_glyph->type == IMAGE_GLYPH
1791 && s->img->pixmap
1792 && !IMAGE_BACKGROUND_TRANSPARENT (s->img, s->f, 0))
1793 color = IMAGE_BACKGROUND (s->img, s->f, 0);
1794 else
1795 color = s->gc->background;
1797 if (di->white_relief.gc == 0
1798 || color != di->relief_background)
1800 di->relief_background = color;
1801 w32_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
1802 WHITE_PIX_DEFAULT (s->f));
1803 w32_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
1804 BLACK_PIX_DEFAULT (s->f));
1809 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
1810 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
1811 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
1812 relief. LEFT_P non-zero means draw a relief on the left side of
1813 the rectangle. RIGHT_P non-zero means draw a relief on the right
1814 side of the rectangle. CLIP_RECT is the clipping rectangle to use
1815 when drawing. */
1817 static void
1818 w32_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
1819 raised_p, top_p, bot_p, left_p, right_p, clip_rect)
1820 struct frame *f;
1821 int left_x, top_y, right_x, bottom_y, width;
1822 int top_p, bot_p, left_p, right_p, raised_p;
1823 RECT *clip_rect;
1825 int i;
1826 XGCValues gc;
1827 HDC hdc = get_frame_dc (f);
1829 if (raised_p)
1830 gc.foreground = f->output_data.w32->white_relief.gc->foreground;
1831 else
1832 gc.foreground = f->output_data.w32->black_relief.gc->foreground;
1834 w32_set_clip_rectangle (hdc, clip_rect);
1836 /* Top. */
1837 if (top_p)
1838 for (i = 0; i < width; ++i)
1839 w32_fill_area (f, hdc, gc.foreground,
1840 left_x + i * left_p, top_y + i,
1841 right_x - left_x - i * (left_p + right_p ) + 1, 1);
1843 /* Left. */
1844 if (left_p)
1845 for (i = 0; i < width; ++i)
1846 w32_fill_area (f, hdc, gc.foreground,
1847 left_x + i, top_y + i, 1,
1848 bottom_y - top_y - 2 * i + 1);
1850 if (raised_p)
1851 gc.foreground = f->output_data.w32->black_relief.gc->foreground;
1852 else
1853 gc.foreground = f->output_data.w32->white_relief.gc->foreground;
1855 /* Bottom. */
1856 if (bot_p)
1857 for (i = 0; i < width; ++i)
1858 w32_fill_area (f, hdc, gc.foreground,
1859 left_x + i * left_p, bottom_y - i,
1860 right_x - left_x - i * (left_p + right_p) + 1, 1);
1862 /* Right. */
1863 if (right_p)
1864 for (i = 0; i < width; ++i)
1865 w32_fill_area (f, hdc, gc.foreground,
1866 right_x - i, top_y + i + 1, 1,
1867 bottom_y - top_y - 2 * i - 1);
1869 w32_set_clip_rectangle (hdc, NULL);
1871 release_frame_dc (f, hdc);
1875 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
1876 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
1877 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
1878 left side of the rectangle. RIGHT_P non-zero means draw a line
1879 on the right side of the rectangle. CLIP_RECT is the clipping
1880 rectangle to use when drawing. */
1882 static void
1883 w32_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
1884 left_p, right_p, clip_rect)
1885 struct glyph_string *s;
1886 int left_x, top_y, right_x, bottom_y, width, left_p, right_p;
1887 RECT *clip_rect;
1889 w32_set_clip_rectangle (s->hdc, clip_rect);
1891 /* Top. */
1892 w32_fill_area (s->f, s->hdc, s->face->box_color,
1893 left_x, top_y, right_x - left_x + 1, width);
1895 /* Left. */
1896 if (left_p)
1898 w32_fill_area (s->f, s->hdc, s->face->box_color,
1899 left_x, top_y, width, bottom_y - top_y + 1);
1902 /* Bottom. */
1903 w32_fill_area (s->f, s->hdc, s->face->box_color,
1904 left_x, bottom_y - width + 1, right_x - left_x + 1, width);
1906 /* Right. */
1907 if (right_p)
1909 w32_fill_area (s->f, s->hdc, s->face->box_color,
1910 right_x - width + 1, top_y, width, bottom_y - top_y + 1);
1913 w32_set_clip_rectangle (s->hdc, NULL);
1917 /* Draw a box around glyph string S. */
1919 static void
1920 x_draw_glyph_string_box (s)
1921 struct glyph_string *s;
1923 int width, left_x, right_x, top_y, bottom_y, last_x, raised_p;
1924 int left_p, right_p;
1925 struct glyph *last_glyph;
1926 RECT clip_rect;
1928 last_x = ((s->row->full_width_p && !s->w->pseudo_window_p)
1929 ? WINDOW_RIGHT_EDGE_X (s->w)
1930 : window_box_right (s->w, s->area));
1932 /* The glyph that may have a right box line. */
1933 last_glyph = (s->cmp || s->img
1934 ? s->first_glyph
1935 : s->first_glyph + s->nchars - 1);
1937 width = abs (s->face->box_line_width);
1938 raised_p = s->face->box == FACE_RAISED_BOX;
1939 left_x = s->x;
1940 right_x = ((s->row->full_width_p && s->extends_to_end_of_line_p
1941 ? last_x - 1
1942 : min (last_x, s->x + s->background_width) - 1));
1943 top_y = s->y;
1944 bottom_y = top_y + s->height - 1;
1946 left_p = (s->first_glyph->left_box_line_p
1947 || (s->hl == DRAW_MOUSE_FACE
1948 && (s->prev == NULL
1949 || s->prev->hl != s->hl)));
1950 right_p = (last_glyph->right_box_line_p
1951 || (s->hl == DRAW_MOUSE_FACE
1952 && (s->next == NULL
1953 || s->next->hl != s->hl)));
1955 get_glyph_string_clip_rect (s, &clip_rect);
1957 if (s->face->box == FACE_SIMPLE_BOX)
1958 w32_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
1959 left_p, right_p, &clip_rect);
1960 else
1962 x_setup_relief_colors (s);
1963 w32_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
1964 width, raised_p, 1, 1, left_p, right_p, &clip_rect);
1969 /* Draw foreground of image glyph string S. */
1971 static void
1972 x_draw_image_foreground (s)
1973 struct glyph_string *s;
1975 int x = s->x;
1976 int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
1978 /* If first glyph of S has a left box line, start drawing it to the
1979 right of that line. */
1980 if (s->face->box != FACE_NO_BOX
1981 && s->first_glyph->left_box_line_p
1982 && s->slice.x == 0)
1983 x += abs (s->face->box_line_width);
1985 /* If there is a margin around the image, adjust x- and y-position
1986 by that margin. */
1987 if (s->slice.x == 0)
1988 x += s->img->hmargin;
1989 if (s->slice.y == 0)
1990 y += s->img->vmargin;
1992 SaveDC (s->hdc);
1994 if (s->img->pixmap)
1996 HDC compat_hdc = CreateCompatibleDC (s->hdc);
1997 HBRUSH fg_brush = CreateSolidBrush (s->gc->foreground);
1998 HBRUSH orig_brush = SelectObject (s->hdc, fg_brush);
1999 HGDIOBJ orig_obj = SelectObject (compat_hdc, s->img->pixmap);
2000 SetBkColor (compat_hdc, RGB (255, 255, 255));
2001 SetTextColor (s->hdc, RGB (0, 0, 0));
2002 x_set_glyph_string_clipping (s);
2004 if (s->img->mask)
2006 HDC mask_dc = CreateCompatibleDC (s->hdc);
2007 HGDIOBJ mask_orig_obj = SelectObject (mask_dc, s->img->mask);
2009 SetTextColor (s->hdc, RGB (255, 255, 255));
2010 SetBkColor (s->hdc, RGB (0, 0, 0));
2012 BitBlt (s->hdc, x, y, s->slice.width, s->slice.height,
2013 compat_hdc, s->slice.x, s->slice.y, SRCINVERT);
2014 BitBlt (s->hdc, x, y, s->slice.width, s->slice.height,
2015 mask_dc, s->slice.x, s->slice.y, SRCAND);
2016 BitBlt (s->hdc, x, y, s->slice.width, s->slice.height,
2017 compat_hdc, s->slice.x, s->slice.y, SRCINVERT);
2019 SelectObject (mask_dc, mask_orig_obj);
2020 DeleteDC (mask_dc);
2022 else
2024 SetTextColor (s->hdc, s->gc->foreground);
2025 SetBkColor (s->hdc, s->gc->background);
2027 BitBlt (s->hdc, x, y, s->slice.width, s->slice.height,
2028 compat_hdc, s->slice.x, s->slice.y, SRCCOPY);
2030 /* When the image has a mask, we can expect that at
2031 least part of a mouse highlight or a block cursor will
2032 be visible. If the image doesn't have a mask, make
2033 a block cursor visible by drawing a rectangle around
2034 the image. I believe it's looking better if we do
2035 nothing here for mouse-face. */
2036 if (s->hl == DRAW_CURSOR)
2038 int r = s->img->relief;
2039 if (r < 0) r = -r;
2040 w32_draw_rectangle (s->hdc, s->gc, x - r, y - r ,
2041 s->slice.width + r*2 - 1,
2042 s->slice.height + r*2 - 1);
2046 w32_set_clip_rectangle (s->hdc, NULL);
2047 SelectObject (s->hdc, orig_brush);
2048 DeleteObject (fg_brush);
2049 SelectObject (compat_hdc, orig_obj);
2050 DeleteDC (compat_hdc);
2052 else
2053 w32_draw_rectangle (s->hdc, s->gc, x, y,
2054 s->slice.width - 1, s->slice.height - 1);
2056 RestoreDC (s->hdc ,-1);
2060 /* Draw a relief around the image glyph string S. */
2062 static void
2063 x_draw_image_relief (s)
2064 struct glyph_string *s;
2066 int x0, y0, x1, y1, thick, raised_p;
2067 RECT r;
2068 int x = s->x;
2069 int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
2071 /* If first glyph of S has a left box line, start drawing it to the
2072 right of that line. */
2073 if (s->face->box != FACE_NO_BOX
2074 && s->first_glyph->left_box_line_p
2075 && s->slice.x == 0)
2076 x += abs (s->face->box_line_width);
2078 /* If there is a margin around the image, adjust x- and y-position
2079 by that margin. */
2080 if (s->slice.x == 0)
2081 x += s->img->hmargin;
2082 if (s->slice.y == 0)
2083 y += s->img->vmargin;
2085 if (s->hl == DRAW_IMAGE_SUNKEN
2086 || s->hl == DRAW_IMAGE_RAISED)
2088 thick = tool_bar_button_relief >= 0 ? tool_bar_button_relief : DEFAULT_TOOL_BAR_BUTTON_RELIEF;
2089 raised_p = s->hl == DRAW_IMAGE_RAISED;
2091 else
2093 thick = abs (s->img->relief);
2094 raised_p = s->img->relief > 0;
2097 x0 = x - thick;
2098 y0 = y - thick;
2099 x1 = x + s->slice.width + thick - 1;
2100 y1 = y + s->slice.height + thick - 1;
2102 x_setup_relief_colors (s);
2103 get_glyph_string_clip_rect (s, &r);
2104 w32_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p,
2105 s->slice.y == 0,
2106 s->slice.y + s->slice.height == s->img->height,
2107 s->slice.x == 0,
2108 s->slice.x + s->slice.width == s->img->width,
2109 &r);
2113 /* Draw the foreground of image glyph string S to PIXMAP. */
2115 static void
2116 w32_draw_image_foreground_1 (s, pixmap)
2117 struct glyph_string *s;
2118 HBITMAP pixmap;
2120 HDC hdc = CreateCompatibleDC (s->hdc);
2121 HGDIOBJ orig_hdc_obj = SelectObject (hdc, pixmap);
2122 int x = 0;
2123 int y = s->ybase - s->y - image_ascent (s->img, s->face, &s->slice);
2125 /* If first glyph of S has a left box line, start drawing it to the
2126 right of that line. */
2127 if (s->face->box != FACE_NO_BOX
2128 && s->first_glyph->left_box_line_p
2129 && s->slice.x == 0)
2130 x += abs (s->face->box_line_width);
2132 /* If there is a margin around the image, adjust x- and y-position
2133 by that margin. */
2134 if (s->slice.x == 0)
2135 x += s->img->hmargin;
2136 if (s->slice.y == 0)
2137 y += s->img->vmargin;
2139 if (s->img->pixmap)
2141 HDC compat_hdc = CreateCompatibleDC (hdc);
2142 HBRUSH fg_brush = CreateSolidBrush (s->gc->foreground);
2143 HBRUSH orig_brush = SelectObject (hdc, fg_brush);
2144 HGDIOBJ orig_obj = SelectObject (compat_hdc, s->img->pixmap);
2146 if (s->img->mask)
2148 HDC mask_dc = CreateCompatibleDC (hdc);
2149 HGDIOBJ mask_orig_obj = SelectObject (mask_dc, s->img->mask);
2151 SetTextColor (hdc, RGB (0, 0, 0));
2152 SetBkColor (hdc, RGB (255, 255, 255));
2153 BitBlt (hdc, x, y, s->slice.width, s->slice.height,
2154 compat_hdc, s->slice.x, s->slice.y, SRCINVERT);
2155 BitBlt (hdc, x, y, s->slice.width, s->slice.height,
2156 mask_dc, s->slice.x, s->slice.y, SRCAND);
2157 BitBlt (hdc, x, y, s->slice.width, s->slice.height,
2158 compat_hdc, s->slice.x, s->slice.y, SRCINVERT);
2160 SelectObject (mask_dc, mask_orig_obj);
2161 DeleteDC (mask_dc);
2163 else
2165 SetTextColor (hdc, s->gc->foreground);
2166 SetBkColor (hdc, s->gc->background);
2168 BitBlt (hdc, x, y, s->slice.width, s->slice.height,
2169 compat_hdc, s->slice.x, s->slice.y, SRCCOPY);
2171 /* When the image has a mask, we can expect that at
2172 least part of a mouse highlight or a block cursor will
2173 be visible. If the image doesn't have a mask, make
2174 a block cursor visible by drawing a rectangle around
2175 the image. I believe it's looking better if we do
2176 nothing here for mouse-face. */
2177 if (s->hl == DRAW_CURSOR)
2179 int r = s->img->relief;
2180 if (r < 0) r = -r;
2181 w32_draw_rectangle (hdc, s->gc, x - r, y - r,
2182 s->slice.width + r*2 - 1,
2183 s->slice.height + r*2 - 1);
2187 SelectObject (hdc, orig_brush);
2188 DeleteObject (fg_brush);
2189 SelectObject (compat_hdc, orig_obj);
2190 DeleteDC (compat_hdc);
2192 else
2193 w32_draw_rectangle (hdc, s->gc, x, y,
2194 s->slice.width - 1, s->slice.height - 1);
2196 SelectObject (hdc, orig_hdc_obj);
2197 DeleteDC (hdc);
2201 /* Draw part of the background of glyph string S. X, Y, W, and H
2202 give the rectangle to draw. */
2204 static void
2205 x_draw_glyph_string_bg_rect (s, x, y, w, h)
2206 struct glyph_string *s;
2207 int x, y, w, h;
2209 #if 0 /* TODO: stipple */
2210 if (s->stippled_p)
2212 /* Fill background with a stipple pattern. */
2213 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
2214 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
2215 XSetFillStyle (s->display, s->gc, FillSolid);
2217 else
2218 #endif
2219 x_clear_glyph_string_rect (s, x, y, w, h);
2223 /* Draw image glyph string S.
2225 s->y
2226 s->x +-------------------------
2227 | s->face->box
2229 | +-------------------------
2230 | | s->img->vmargin
2232 | | +-------------------
2233 | | | the image
2237 static void
2238 x_draw_image_glyph_string (s)
2239 struct glyph_string *s;
2241 int x, y;
2242 int box_line_hwidth = abs (s->face->box_line_width);
2243 int box_line_vwidth = max (s->face->box_line_width, 0);
2244 int height;
2245 HBITMAP pixmap = 0;
2247 height = s->height - 2 * box_line_vwidth;
2249 /* Fill background with face under the image. Do it only if row is
2250 taller than image or if image has a clip mask to reduce
2251 flickering. */
2252 s->stippled_p = s->face->stipple != 0;
2253 if (height > s->slice.height
2254 || s->img->hmargin
2255 || s->img->vmargin
2256 || s->img->mask
2257 || s->img->pixmap == 0
2258 || s->width != s->background_width)
2260 x = s->x;
2261 if (s->first_glyph->left_box_line_p
2262 && s->slice.x == 0)
2263 x += box_line_hwidth;
2265 y = s->y;
2266 if (s->slice.y == 0)
2267 y += box_line_vwidth;
2269 #if 0 /* TODO: figure out if we need to do this on Windows. */
2270 if (s->img->mask)
2272 /* Create a pixmap as large as the glyph string. Fill it
2273 with the background color. Copy the image to it, using
2274 its mask. Copy the temporary pixmap to the display. */
2275 Screen *screen = FRAME_X_SCREEN (s->f);
2276 int depth = DefaultDepthOfScreen (screen);
2278 /* Create a pixmap as large as the glyph string. */
2279 pixmap = XCreatePixmap (s->display, s->window,
2280 s->background_width,
2281 s->height, depth);
2283 /* Don't clip in the following because we're working on the
2284 pixmap. */
2285 XSetClipMask (s->display, s->gc, None);
2287 /* Fill the pixmap with the background color/stipple. */
2288 if (s->stippled_p)
2290 /* Fill background with a stipple pattern. */
2291 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
2292 XFillRectangle (s->display, pixmap, s->gc,
2293 0, 0, s->background_width, s->height);
2294 XSetFillStyle (s->display, s->gc, FillSolid);
2296 else
2298 XGCValues xgcv;
2299 XGetGCValues (s->display, s->gc, GCForeground | GCBackground,
2300 &xgcv);
2301 XSetForeground (s->display, s->gc, xgcv.background);
2302 XFillRectangle (s->display, pixmap, s->gc,
2303 0, 0, s->background_width, s->height);
2304 XSetForeground (s->display, s->gc, xgcv.foreground);
2307 else
2308 #endif
2309 x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
2311 s->background_filled_p = 1;
2314 /* Draw the foreground. */
2315 if (pixmap != 0)
2317 w32_draw_image_foreground_1 (s, pixmap);
2318 x_set_glyph_string_clipping (s);
2320 HDC compat_hdc = CreateCompatibleDC (s->hdc);
2321 HBRUSH fg_brush = CreateSolidBrush (s->gc->foreground);
2322 HBRUSH orig_brush = SelectObject (s->hdc, fg_brush);
2323 HGDIOBJ orig_obj = SelectObject (compat_hdc, pixmap);
2325 SetTextColor (s->hdc, s->gc->foreground);
2326 SetBkColor (s->hdc, s->gc->background);
2327 BitBlt (s->hdc, s->x, s->y, s->background_width, s->height,
2328 compat_hdc, 0, 0, SRCCOPY);
2330 SelectObject (s->hdc, orig_brush);
2331 DeleteObject (fg_brush);
2332 SelectObject (compat_hdc, orig_obj);
2333 DeleteDC (compat_hdc);
2335 DeleteObject (pixmap);
2336 pixmap = 0;
2338 else
2339 x_draw_image_foreground (s);
2341 /* If we must draw a relief around the image, do it. */
2342 if (s->img->relief
2343 || s->hl == DRAW_IMAGE_RAISED
2344 || s->hl == DRAW_IMAGE_SUNKEN)
2345 x_draw_image_relief (s);
2349 /* Draw stretch glyph string S. */
2351 static void
2352 x_draw_stretch_glyph_string (s)
2353 struct glyph_string *s;
2355 xassert (s->first_glyph->type == STRETCH_GLYPH);
2356 s->stippled_p = s->face->stipple != 0;
2358 if (s->hl == DRAW_CURSOR
2359 && !x_stretch_cursor_p)
2361 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
2362 as wide as the stretch glyph. */
2363 int width = min (FRAME_COLUMN_WIDTH (s->f), s->background_width);
2365 /* Draw cursor. */
2366 x_draw_glyph_string_bg_rect (s, s->x, s->y, width, s->height);
2368 /* Clear rest using the GC of the original non-cursor face. */
2369 if (width < s->background_width)
2371 XGCValues *gc = s->face->gc;
2372 int x = s->x + width, y = s->y;
2373 int w = s->background_width - width, h = s->height;
2374 RECT r;
2375 HDC hdc = s->hdc;
2377 if (s->row->mouse_face_p
2378 && cursor_in_mouse_face_p (s->w))
2380 x_set_mouse_face_gc (s);
2381 gc = s->gc;
2383 else
2384 gc = s->face->gc;
2386 get_glyph_string_clip_rect (s, &r);
2387 w32_set_clip_rectangle (hdc, &r);
2389 #if 0 /* TODO: stipple */
2390 if (s->face->stipple)
2392 /* Fill background with a stipple pattern. */
2393 XSetFillStyle (s->display, gc, FillOpaqueStippled);
2394 XFillRectangle (s->display, s->window, gc, x, y, w, h);
2395 XSetFillStyle (s->display, gc, FillSolid);
2397 else
2398 #endif
2400 w32_fill_area (s->f, s->hdc, gc->background, x, y, w, h);
2404 else if (!s->background_filled_p)
2405 x_draw_glyph_string_bg_rect (s, s->x, s->y, s->background_width,
2406 s->height);
2408 s->background_filled_p = 1;
2412 /* Draw glyph string S. */
2414 static void
2415 x_draw_glyph_string (s)
2416 struct glyph_string *s;
2418 int relief_drawn_p = 0;
2420 /* If S draws into the background of its successor, draw the
2421 background of the successor first so that S can draw into it.
2422 This makes S->next use XDrawString instead of XDrawImageString. */
2423 if (s->next && s->right_overhang && !s->for_overlaps_p)
2425 xassert (s->next->img == NULL);
2426 x_set_glyph_string_gc (s->next);
2427 x_set_glyph_string_clipping (s->next);
2428 x_draw_glyph_string_background (s->next, 1);
2431 /* Set up S->gc, set clipping and draw S. */
2432 x_set_glyph_string_gc (s);
2434 /* Draw relief (if any) in advance for char/composition so that the
2435 glyph string can be drawn over it. */
2436 if (!s->for_overlaps_p
2437 && s->face->box != FACE_NO_BOX
2438 && (s->first_glyph->type == CHAR_GLYPH
2439 || s->first_glyph->type == COMPOSITE_GLYPH))
2442 x_set_glyph_string_clipping (s);
2443 x_draw_glyph_string_background (s, 1);
2444 x_draw_glyph_string_box (s);
2445 x_set_glyph_string_clipping (s);
2446 relief_drawn_p = 1;
2448 else
2449 x_set_glyph_string_clipping (s);
2451 switch (s->first_glyph->type)
2453 case IMAGE_GLYPH:
2454 x_draw_image_glyph_string (s);
2455 break;
2457 case STRETCH_GLYPH:
2458 x_draw_stretch_glyph_string (s);
2459 break;
2461 case CHAR_GLYPH:
2462 if (s->for_overlaps_p)
2463 s->background_filled_p = 1;
2464 else
2465 x_draw_glyph_string_background (s, 0);
2466 x_draw_glyph_string_foreground (s);
2467 break;
2469 case COMPOSITE_GLYPH:
2470 if (s->for_overlaps_p || s->gidx > 0)
2471 s->background_filled_p = 1;
2472 else
2473 x_draw_glyph_string_background (s, 1);
2474 x_draw_composite_glyph_string_foreground (s);
2475 break;
2477 default:
2478 abort ();
2481 if (!s->for_overlaps_p)
2483 /* Draw underline. */
2484 if (s->face->underline_p
2485 && (s->font->bdf || !s->font->tm.tmUnderlined))
2487 unsigned long h = 1;
2488 unsigned long dy = s->height - h;
2490 /* TODO: Use font information for positioning and thickness
2491 of underline. See OUTLINETEXTMETRIC, and xterm.c. */
2492 if (s->face->underline_defaulted_p)
2494 w32_fill_area (s->f, s->hdc, s->gc->foreground, s->x,
2495 s->y + dy, s->width, 1);
2497 else
2499 w32_fill_area (s->f, s->hdc, s->face->underline_color, s->x,
2500 s->y + dy, s->width, 1);
2504 /* Draw overline. */
2505 if (s->face->overline_p)
2507 unsigned long dy = 0, h = 1;
2509 if (s->face->overline_color_defaulted_p)
2511 w32_fill_area (s->f, s->hdc, s->gc->foreground, s->x,
2512 s->y + dy, s->width, h);
2514 else
2516 w32_fill_area (s->f, s->hdc, s->face->overline_color, s->x,
2517 s->y + dy, s->width, h);
2521 /* Draw strike-through. */
2522 if (s->face->strike_through_p
2523 && (s->font->bdf || !s->font->tm.tmStruckOut))
2525 unsigned long h = 1;
2526 unsigned long dy = (s->height - h) / 2;
2528 if (s->face->strike_through_color_defaulted_p)
2530 w32_fill_area (s->f, s->hdc, s->gc->foreground, s->x, s->y + dy,
2531 s->width, h);
2533 else
2535 w32_fill_area (s->f, s->hdc, s->face->underline_color, s->x,
2536 s->y + dy, s->width, h);
2540 /* Draw relief. */
2541 if (!relief_drawn_p && s->face->box != FACE_NO_BOX)
2542 x_draw_glyph_string_box (s);
2545 /* Reset clipping. */
2546 w32_set_clip_rectangle (s->hdc, NULL);
2550 /* Shift display to make room for inserted glyphs. */
2552 void
2553 w32_shift_glyphs_for_insert (f, x, y, width, height, shift_by)
2554 struct frame *f;
2555 int x, y, width, height, shift_by;
2557 HDC hdc;
2559 hdc = get_frame_dc (f);
2560 BitBlt (hdc, x + shift_by, y, width, height,
2561 hdc, x, y, SRCCOPY);
2563 release_frame_dc (f, hdc);
2567 /* Delete N glyphs at the nominal cursor position. Not implemented
2568 for X frames. */
2570 static void
2571 x_delete_glyphs (n)
2572 register int n;
2574 struct frame *f;
2576 if (updating_frame)
2577 f = updating_frame;
2578 else
2579 f = SELECTED_FRAME ();
2581 if (! FRAME_W32_P (f))
2582 return;
2584 abort ();
2588 /* Clear entire frame. If updating_frame is non-null, clear that
2589 frame. Otherwise clear the selected frame. */
2591 static void
2592 x_clear_frame ()
2594 struct frame *f;
2596 if (updating_frame)
2597 f = updating_frame;
2598 else
2599 f = SELECTED_FRAME ();
2601 if (! FRAME_W32_P (f))
2602 return;
2604 /* Clearing the frame will erase any cursor, so mark them all as no
2605 longer visible. */
2606 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
2607 output_cursor.hpos = output_cursor.vpos = 0;
2608 output_cursor.x = -1;
2610 /* We don't set the output cursor here because there will always
2611 follow an explicit cursor_to. */
2612 BLOCK_INPUT;
2614 w32_clear_window (f);
2616 /* We have to clear the scroll bars, too. If we have changed
2617 colors or something like that, then they should be notified. */
2618 x_scroll_bar_clear (f);
2620 UNBLOCK_INPUT;
2624 /* Make audible bell. */
2626 static void
2627 w32_ring_bell (void)
2629 struct frame *f;
2631 f = SELECTED_FRAME ();
2633 BLOCK_INPUT;
2635 if (FRAME_W32_P (f) && visible_bell)
2637 int i;
2638 HWND hwnd = FRAME_W32_WINDOW (SELECTED_FRAME ());
2640 for (i = 0; i < 5; i++)
2642 FlashWindow (hwnd, TRUE);
2643 Sleep (10);
2645 FlashWindow (hwnd, FALSE);
2647 else
2648 w32_sys_ring_bell ();
2650 UNBLOCK_INPUT;
2654 /* Specify how many text lines, from the top of the window,
2655 should be affected by insert-lines and delete-lines operations.
2656 This, and those operations, are used only within an update
2657 that is bounded by calls to x_update_begin and x_update_end. */
2659 static void
2660 w32_set_terminal_window (n)
2661 register int n;
2663 /* This function intentionally left blank. */
2667 /***********************************************************************
2668 Line Dance
2669 ***********************************************************************/
2671 /* Perform an insert-lines or delete-lines operation, inserting N
2672 lines or deleting -N lines at vertical position VPOS. */
2674 static void
2675 x_ins_del_lines (vpos, n)
2676 int vpos, n;
2678 struct frame *f;
2680 if (updating_frame)
2681 f = updating_frame;
2682 else
2683 f = SELECTED_FRAME ();
2685 if (! FRAME_W32_P (f))
2686 return;
2688 abort ();
2692 /* Scroll part of the display as described by RUN. */
2694 static void
2695 x_scroll_run (w, run)
2696 struct window *w;
2697 struct run *run;
2699 struct frame *f = XFRAME (w->frame);
2700 int x, y, width, height, from_y, to_y, bottom_y;
2701 HWND hwnd = FRAME_W32_WINDOW (f);
2702 HRGN expect_dirty;
2704 /* Get frame-relative bounding box of the text display area of W,
2705 without mode lines. Include in this box the left and right
2706 fringes of W. */
2707 window_box (w, -1, &x, &y, &width, &height);
2709 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
2710 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
2711 bottom_y = y + height;
2713 if (to_y < from_y)
2715 /* Scrolling up. Make sure we don't copy part of the mode
2716 line at the bottom. */
2717 if (from_y + run->height > bottom_y)
2718 height = bottom_y - from_y;
2719 else
2720 height = run->height;
2721 expect_dirty = CreateRectRgn (x, y + height, x + width, bottom_y);
2723 else
2725 /* Scolling down. Make sure we don't copy over the mode line.
2726 at the bottom. */
2727 if (to_y + run->height > bottom_y)
2728 height = bottom_y - to_y;
2729 else
2730 height = run->height;
2731 expect_dirty = CreateRectRgn (x, y, x + width, to_y);
2734 BLOCK_INPUT;
2736 /* Cursor off. Will be switched on again in x_update_window_end. */
2737 updated_window = w;
2738 x_clear_cursor (w);
2741 RECT from;
2742 RECT to;
2743 HRGN dirty = CreateRectRgn (0, 0, 0, 0);
2744 HRGN combined = CreateRectRgn (0, 0, 0, 0);
2746 from.left = to.left = x;
2747 from.right = to.right = x + width;
2748 from.top = from_y;
2749 from.bottom = from_y + height;
2750 to.top = y;
2751 to.bottom = bottom_y;
2753 ScrollWindowEx (hwnd, 0, to_y - from_y, &from, &to, dirty,
2754 NULL, SW_INVALIDATE);
2756 /* Combine this with what we expect to be dirty. This covers the
2757 case where not all of the region we expect is actually dirty. */
2758 CombineRgn (combined, dirty, expect_dirty, RGN_OR);
2760 /* If the dirty region is not what we expected, redraw the entire frame. */
2761 if (!EqualRgn (combined, expect_dirty))
2762 SET_FRAME_GARBAGED (f);
2764 DeleteObject (dirty);
2765 DeleteObject (combined);
2768 UNBLOCK_INPUT;
2769 DeleteObject (expect_dirty);
2774 /***********************************************************************
2775 Exposure Events
2776 ***********************************************************************/
2778 static void
2779 frame_highlight (f)
2780 struct frame *f;
2782 x_update_cursor (f, 1);
2785 static void
2786 frame_unhighlight (f)
2787 struct frame *f;
2789 x_update_cursor (f, 1);
2792 /* The focus has changed. Update the frames as necessary to reflect
2793 the new situation. Note that we can't change the selected frame
2794 here, because the Lisp code we are interrupting might become confused.
2795 Each event gets marked with the frame in which it occurred, so the
2796 Lisp code can tell when the switch took place by examining the events. */
2798 static void
2799 x_new_focus_frame (dpyinfo, frame)
2800 struct w32_display_info *dpyinfo;
2801 struct frame *frame;
2803 struct frame *old_focus = dpyinfo->w32_focus_frame;
2805 if (frame != dpyinfo->w32_focus_frame)
2807 /* Set this before calling other routines, so that they see
2808 the correct value of w32_focus_frame. */
2809 dpyinfo->w32_focus_frame = frame;
2811 if (old_focus && old_focus->auto_lower)
2812 x_lower_frame (old_focus);
2814 if (dpyinfo->w32_focus_frame && dpyinfo->w32_focus_frame->auto_raise)
2815 pending_autoraise_frame = dpyinfo->w32_focus_frame;
2816 else
2817 pending_autoraise_frame = 0;
2820 x_frame_rehighlight (dpyinfo);
2824 /* Handle FocusIn and FocusOut state changes for FRAME.
2825 If FRAME has focus and there exists more than one frame, puts
2826 a FOCUS_IN_EVENT into *BUFP. */
2828 static void
2829 x_focus_changed (type, state, dpyinfo, frame, bufp)
2830 int type;
2831 int state;
2832 struct w32_display_info *dpyinfo;
2833 struct frame *frame;
2834 struct input_event *bufp;
2836 if (type == WM_SETFOCUS)
2838 if (dpyinfo->w32_focus_event_frame != frame)
2840 x_new_focus_frame (dpyinfo, frame);
2841 dpyinfo->w32_focus_event_frame = frame;
2843 /* Don't stop displaying the initial startup message
2844 for a switch-frame event we don't need. */
2845 if (GC_NILP (Vterminal_frame)
2846 && GC_CONSP (Vframe_list)
2847 && !GC_NILP (XCDR (Vframe_list)))
2849 bufp->kind = FOCUS_IN_EVENT;
2850 XSETFRAME (bufp->frame_or_window, frame);
2854 frame->output_data.x->focus_state |= state;
2856 /* TODO: IME focus? */
2858 else if (type == WM_KILLFOCUS)
2860 frame->output_data.x->focus_state &= ~state;
2862 if (dpyinfo->w32_focus_event_frame == frame)
2864 dpyinfo->w32_focus_event_frame = 0;
2865 x_new_focus_frame (dpyinfo, 0);
2868 /* TODO: IME focus? */
2873 /* The focus may have changed. Figure out if it is a real focus change,
2874 by checking both FocusIn/Out and Enter/LeaveNotify events.
2876 Returns FOCUS_IN_EVENT event in *BUFP. */
2878 static void
2879 w32_detect_focus_change (dpyinfo, event, bufp)
2880 struct w32_display_info *dpyinfo;
2881 W32Msg *event;
2882 struct input_event *bufp;
2884 struct frame *frame;
2886 frame = x_any_window_to_frame (dpyinfo, event->msg.hwnd);
2887 if (! frame)
2888 return;
2890 /* On w32, this is only called from focus events, so no switch needed. */
2891 x_focus_changed (event->msg.message,
2892 (event->msg.message == WM_KILLFOCUS ?
2893 FOCUS_IMPLICIT : FOCUS_EXPLICIT),
2894 dpyinfo, frame, bufp);
2898 /* Handle an event saying the mouse has moved out of an Emacs frame. */
2900 void
2901 x_mouse_leave (dpyinfo)
2902 struct w32_display_info *dpyinfo;
2904 x_new_focus_frame (dpyinfo, dpyinfo->w32_focus_event_frame);
2907 /* The focus has changed, or we have redirected a frame's focus to
2908 another frame (this happens when a frame uses a surrogate
2909 mini-buffer frame). Shift the highlight as appropriate.
2911 The FRAME argument doesn't necessarily have anything to do with which
2912 frame is being highlighted or un-highlighted; we only use it to find
2913 the appropriate X display info. */
2915 static void
2916 w32_frame_rehighlight (frame)
2917 struct frame *frame;
2919 if (! FRAME_W32_P (frame))
2920 return;
2921 x_frame_rehighlight (FRAME_W32_DISPLAY_INFO (frame));
2924 static void
2925 x_frame_rehighlight (dpyinfo)
2926 struct w32_display_info *dpyinfo;
2928 struct frame *old_highlight = dpyinfo->x_highlight_frame;
2930 if (dpyinfo->w32_focus_frame)
2932 dpyinfo->x_highlight_frame
2933 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->w32_focus_frame)))
2934 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->w32_focus_frame))
2935 : dpyinfo->w32_focus_frame);
2936 if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame))
2938 FRAME_FOCUS_FRAME (dpyinfo->w32_focus_frame) = Qnil;
2939 dpyinfo->x_highlight_frame = dpyinfo->w32_focus_frame;
2942 else
2943 dpyinfo->x_highlight_frame = 0;
2945 if (dpyinfo->x_highlight_frame != old_highlight)
2947 if (old_highlight)
2948 frame_unhighlight (old_highlight);
2949 if (dpyinfo->x_highlight_frame)
2950 frame_highlight (dpyinfo->x_highlight_frame);
2954 /* Keyboard processing - modifier keys, etc. */
2956 /* Convert a keysym to its name. */
2958 char *
2959 x_get_keysym_name (keysym)
2960 int keysym;
2962 /* Make static so we can always return it */
2963 static char value[100];
2965 BLOCK_INPUT;
2966 GetKeyNameText (keysym, value, 100);
2967 UNBLOCK_INPUT;
2969 return value;
2974 /* Mouse clicks and mouse movement. Rah. */
2976 /* Parse a button MESSAGE. The button index is returned in PBUTTON, and
2977 the state in PUP. XBUTTON provides extra information for extended mouse
2978 button messages. Returns FALSE if unable to parse the message. */
2979 BOOL
2980 parse_button (message, xbutton, pbutton, pup)
2981 int message;
2982 int xbutton;
2983 int * pbutton;
2984 int * pup;
2986 int button = 0;
2987 int up = 0;
2989 switch (message)
2991 case WM_LBUTTONDOWN:
2992 button = 0;
2993 up = 0;
2994 break;
2995 case WM_LBUTTONUP:
2996 button = 0;
2997 up = 1;
2998 break;
2999 case WM_MBUTTONDOWN:
3000 if (NILP (Vw32_swap_mouse_buttons))
3001 button = 1;
3002 else
3003 button = 2;
3004 up = 0;
3005 break;
3006 case WM_MBUTTONUP:
3007 if (NILP (Vw32_swap_mouse_buttons))
3008 button = 1;
3009 else
3010 button = 2;
3011 up = 1;
3012 break;
3013 case WM_RBUTTONDOWN:
3014 if (NILP (Vw32_swap_mouse_buttons))
3015 button = 2;
3016 else
3017 button = 1;
3018 up = 0;
3019 break;
3020 case WM_RBUTTONUP:
3021 if (NILP (Vw32_swap_mouse_buttons))
3022 button = 2;
3023 else
3024 button = 1;
3025 up = 1;
3026 break;
3027 case WM_XBUTTONDOWN:
3028 button = xbutton + 2;
3029 up = 0;
3030 break;
3031 case WM_XBUTTONUP:
3032 button = xbutton + 2;
3033 up = 1;
3034 break;
3035 default:
3036 return (FALSE);
3039 if (pup) *pup = up;
3040 if (pbutton) *pbutton = button;
3042 return (TRUE);
3046 /* Prepare a mouse-event in *RESULT for placement in the input queue.
3048 If the event is a button press, then note that we have grabbed
3049 the mouse. */
3051 static Lisp_Object
3052 construct_mouse_click (result, msg, f)
3053 struct input_event *result;
3054 W32Msg *msg;
3055 struct frame *f;
3057 int button;
3058 int up;
3060 parse_button (msg->msg.message, HIWORD (msg->msg.wParam),
3061 &button, &up);
3063 /* Make the event type NO_EVENT; we'll change that when we decide
3064 otherwise. */
3065 result->kind = MOUSE_CLICK_EVENT;
3066 result->code = button;
3067 result->timestamp = msg->msg.time;
3068 result->modifiers = (msg->dwModifiers
3069 | (up
3070 ? up_modifier
3071 : down_modifier));
3073 XSETINT (result->x, LOWORD (msg->msg.lParam));
3074 XSETINT (result->y, HIWORD (msg->msg.lParam));
3075 XSETFRAME (result->frame_or_window, f);
3076 result->arg = Qnil;
3077 return Qnil;
3080 static Lisp_Object
3081 construct_mouse_wheel (result, msg, f)
3082 struct input_event *result;
3083 W32Msg *msg;
3084 struct frame *f;
3086 POINT p;
3087 int delta;
3089 result->kind = WHEEL_EVENT;
3090 result->code = 0;
3091 result->timestamp = msg->msg.time;
3093 /* A WHEEL_DELTA positive value indicates that the wheel was rotated
3094 forward, away from the user (up); a negative value indicates that
3095 the wheel was rotated backward, toward the user (down). */
3096 delta = GET_WHEEL_DELTA_WPARAM (msg->msg.wParam);
3098 /* The up and down modifiers indicate if the wheel was rotated up or
3099 down based on WHEEL_DELTA value. */
3100 result->modifiers = (msg->dwModifiers
3101 | ((delta < 0 ) ? down_modifier : up_modifier));
3103 p.x = LOWORD (msg->msg.lParam);
3104 p.y = HIWORD (msg->msg.lParam);
3105 ScreenToClient (msg->msg.hwnd, &p);
3106 XSETINT (result->x, p.x);
3107 XSETINT (result->y, p.y);
3108 XSETFRAME (result->frame_or_window, f);
3109 result->arg = Qnil;
3110 return Qnil;
3113 static Lisp_Object
3114 construct_drag_n_drop (result, msg, f)
3115 struct input_event *result;
3116 W32Msg *msg;
3117 struct frame *f;
3119 Lisp_Object files;
3120 Lisp_Object frame;
3121 HDROP hdrop;
3122 POINT p;
3123 WORD num_files;
3124 char *name;
3125 int i, len;
3127 result->kind = DRAG_N_DROP_EVENT;
3128 result->code = 0;
3129 result->timestamp = msg->msg.time;
3130 result->modifiers = msg->dwModifiers;
3132 hdrop = (HDROP) msg->msg.wParam;
3133 DragQueryPoint (hdrop, &p);
3135 #if 0
3136 p.x = LOWORD (msg->msg.lParam);
3137 p.y = HIWORD (msg->msg.lParam);
3138 ScreenToClient (msg->msg.hwnd, &p);
3139 #endif
3141 XSETINT (result->x, p.x);
3142 XSETINT (result->y, p.y);
3144 num_files = DragQueryFile (hdrop, 0xFFFFFFFF, NULL, 0);
3145 files = Qnil;
3147 for (i = 0; i < num_files; i++)
3149 len = DragQueryFile (hdrop, i, NULL, 0);
3150 if (len <= 0)
3151 continue;
3152 name = alloca (len + 1);
3153 DragQueryFile (hdrop, i, name, len + 1);
3154 files = Fcons (DECODE_FILE (build_string (name)), files);
3157 DragFinish (hdrop);
3159 XSETFRAME (frame, f);
3160 result->frame_or_window = Fcons (frame, files);
3161 result->arg = Qnil;
3162 return Qnil;
3166 /* Function to report a mouse movement to the mainstream Emacs code.
3167 The input handler calls this.
3169 We have received a mouse movement event, which is given in *event.
3170 If the mouse is over a different glyph than it was last time, tell
3171 the mainstream emacs code by setting mouse_moved. If not, ask for
3172 another motion event, so we can check again the next time it moves. */
3174 static MSG last_mouse_motion_event;
3175 static Lisp_Object last_mouse_motion_frame;
3177 static void remember_mouse_glyph P_ ((struct frame *, int, int));
3179 static void
3180 note_mouse_movement (frame, msg)
3181 FRAME_PTR frame;
3182 MSG *msg;
3184 int mouse_x = LOWORD (msg->lParam);
3185 int mouse_y = HIWORD (msg->lParam);
3187 last_mouse_movement_time = msg->time;
3188 memcpy (&last_mouse_motion_event, msg, sizeof (last_mouse_motion_event));
3189 XSETFRAME (last_mouse_motion_frame, frame);
3191 if (msg->hwnd != FRAME_W32_WINDOW (frame))
3193 frame->mouse_moved = 1;
3194 last_mouse_scroll_bar = Qnil;
3195 note_mouse_highlight (frame, -1, -1);
3198 /* Has the mouse moved off the glyph it was on at the last sighting? */
3199 else if (mouse_x < last_mouse_glyph.left
3200 || mouse_x > last_mouse_glyph.right
3201 || mouse_y < last_mouse_glyph.top
3202 || mouse_y > last_mouse_glyph.bottom)
3204 frame->mouse_moved = 1;
3205 last_mouse_scroll_bar = Qnil;
3206 note_mouse_highlight (frame, mouse_x, mouse_y);
3207 /* Remember the mouse position here, as w32_mouse_position only
3208 gets called when mouse tracking is enabled but we also need
3209 to keep track of the mouse for help_echo and highlighting at
3210 other times. */
3211 remember_mouse_glyph (frame, mouse_x, mouse_y);
3216 /************************************************************************
3217 Mouse Face
3218 ************************************************************************/
3220 static struct scroll_bar *x_window_to_scroll_bar ();
3221 static void x_scroll_bar_report_motion ();
3222 static void x_check_fullscreen P_ ((struct frame *));
3223 static int glyph_rect P_ ((struct frame *f, int, int, RECT *));
3226 static void
3227 redo_mouse_highlight ()
3229 if (!NILP (last_mouse_motion_frame)
3230 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame)))
3231 note_mouse_highlight (XFRAME (last_mouse_motion_frame),
3232 LOWORD (last_mouse_motion_event.lParam),
3233 HIWORD (last_mouse_motion_event.lParam));
3236 void
3237 w32_define_cursor (window, cursor)
3238 Window window;
3239 Cursor cursor;
3241 PostMessage (window, WM_EMACS_SETCURSOR, (WPARAM) cursor, 0);
3244 /* Try to determine frame pixel position and size of the glyph under
3245 frame pixel coordinates X/Y on frame F . Return the position and
3246 size in *RECT. Value is non-zero if we could compute these
3247 values. */
3249 static int
3250 glyph_rect (f, x, y, rect)
3251 struct frame *f;
3252 int x, y;
3253 RECT *rect;
3255 Lisp_Object window;
3257 window = window_from_coordinates (f, x, y, 0, &x, &y, 0);
3259 if (!NILP (window))
3261 struct window *w = XWINDOW (window);
3262 struct glyph_row *r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
3263 struct glyph_row *end = r + w->current_matrix->nrows - 1;
3265 for (; r < end && r->enabled_p; ++r)
3266 if (r->y <= y && r->y + r->height > y)
3268 /* Found the row at y. */
3269 struct glyph *g = r->glyphs[TEXT_AREA];
3270 struct glyph *end = g + r->used[TEXT_AREA];
3271 int gx;
3273 rect->top = WINDOW_TO_FRAME_PIXEL_Y (w, r->y);
3274 rect->bottom = rect->top + r->height;
3276 if (x < r->x)
3278 /* x is to the left of the first glyph in the row. */
3279 /* Shouldn't this be a pixel value?
3280 WINDOW_LEFT_EDGE_X (w) seems to be the right value.
3281 ++KFS */
3282 rect->left = WINDOW_LEFT_EDGE_COL (w);
3283 rect->right = WINDOW_TO_FRAME_PIXEL_X (w, r->x);
3284 return 1;
3287 for (gx = r->x; g < end; gx += g->pixel_width, ++g)
3288 if (gx <= x && gx + g->pixel_width > x)
3290 /* x is on a glyph. */
3291 rect->left = WINDOW_TO_FRAME_PIXEL_X (w, gx);
3292 rect->right = rect->left + g->pixel_width;
3293 return 1;
3296 /* x is to the right of the last glyph in the row. */
3297 rect->left = WINDOW_TO_FRAME_PIXEL_X (w, gx);
3298 /* Shouldn't this be a pixel value?
3299 WINDOW_RIGHT_EDGE_X (w) seems to be the right value.
3300 ++KFS */
3301 rect->right = WINDOW_RIGHT_EDGE_COL (w);
3302 return 1;
3306 /* The y is not on any row. */
3307 return 0;
3310 /* Record the position of the mouse in last_mouse_glyph. */
3311 static void
3312 remember_mouse_glyph (f1, gx, gy)
3313 struct frame * f1;
3314 int gx, gy;
3316 if (!glyph_rect (f1, gx, gy, &last_mouse_glyph))
3318 int width = FRAME_SMALLEST_CHAR_WIDTH (f1);
3319 int height = FRAME_SMALLEST_FONT_HEIGHT (f1);
3321 /* Arrange for the division in FRAME_PIXEL_X_TO_COL etc. to
3322 round down even for negative values. */
3323 if (gx < 0)
3324 gx -= width - 1;
3325 if (gy < 0)
3326 gy -= height - 1;
3327 #if 0
3328 /* This was the original code from XTmouse_position, but it seems
3329 to give the position of the glyph diagonally next to the one
3330 the mouse is over. */
3331 gx = (gx + width - 1) / width * width;
3332 gy = (gy + height - 1) / height * height;
3333 #else
3334 gx = gx / width * width;
3335 gy = gy / height * height;
3336 #endif
3338 last_mouse_glyph.left = gx;
3339 last_mouse_glyph.top = gy;
3340 last_mouse_glyph.right = gx + width;
3341 last_mouse_glyph.bottom = gy + height;
3345 /* Return the current position of the mouse.
3346 *fp should be a frame which indicates which display to ask about.
3348 If the mouse movement started in a scroll bar, set *fp, *bar_window,
3349 and *part to the frame, window, and scroll bar part that the mouse
3350 is over. Set *x and *y to the portion and whole of the mouse's
3351 position on the scroll bar.
3353 If the mouse movement started elsewhere, set *fp to the frame the
3354 mouse is on, *bar_window to nil, and *x and *y to the character cell
3355 the mouse is over.
3357 Set *time to the server time-stamp for the time at which the mouse
3358 was at this position.
3360 Don't store anything if we don't have a valid set of values to report.
3362 This clears the mouse_moved flag, so we can wait for the next mouse
3363 movement. */
3365 static void
3366 w32_mouse_position (fp, insist, bar_window, part, x, y, time)
3367 FRAME_PTR *fp;
3368 int insist;
3369 Lisp_Object *bar_window;
3370 enum scroll_bar_part *part;
3371 Lisp_Object *x, *y;
3372 unsigned long *time;
3374 FRAME_PTR f1;
3376 BLOCK_INPUT;
3378 if (! NILP (last_mouse_scroll_bar) && insist == 0)
3379 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
3380 else
3382 POINT pt;
3384 Lisp_Object frame, tail;
3386 /* Clear the mouse-moved flag for every frame on this display. */
3387 FOR_EACH_FRAME (tail, frame)
3388 XFRAME (frame)->mouse_moved = 0;
3390 last_mouse_scroll_bar = Qnil;
3392 GetCursorPos (&pt);
3394 /* Now we have a position on the root; find the innermost window
3395 containing the pointer. */
3397 if (FRAME_W32_DISPLAY_INFO (*fp)->grabbed && last_mouse_frame
3398 && FRAME_LIVE_P (last_mouse_frame))
3400 /* If mouse was grabbed on a frame, give coords for that frame
3401 even if the mouse is now outside it. */
3402 f1 = last_mouse_frame;
3404 else
3406 /* Is window under mouse one of our frames? */
3407 f1 = x_any_window_to_frame (FRAME_W32_DISPLAY_INFO (*fp),
3408 WindowFromPoint (pt));
3411 /* If not, is it one of our scroll bars? */
3412 if (! f1)
3414 struct scroll_bar *bar
3415 = x_window_to_scroll_bar (WindowFromPoint (pt));
3417 if (bar)
3419 f1 = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
3423 if (f1 == 0 && insist > 0)
3424 f1 = SELECTED_FRAME ();
3426 if (f1)
3428 /* Ok, we found a frame. Store all the values.
3429 last_mouse_glyph is a rectangle used to reduce the
3430 generation of mouse events. To not miss any motion
3431 events, we must divide the frame into rectangles of the
3432 size of the smallest character that could be displayed
3433 on it, i.e. into the same rectangles that matrices on
3434 the frame are divided into. */
3436 #if OLD_REDISPLAY_CODE
3437 int ignore1, ignore2;
3439 ScreenToClient (FRAME_W32_WINDOW (f1), &pt);
3441 pixel_to_glyph_coords (f1, pt.x, pt.y, &ignore1, &ignore2,
3442 &last_mouse_glyph,
3443 FRAME_W32_DISPLAY_INFO (f1)->grabbed
3444 || insist);
3445 #else
3446 ScreenToClient (FRAME_W32_WINDOW (f1), &pt);
3447 remember_mouse_glyph (f1, pt.x, pt.y);
3448 #endif
3450 *bar_window = Qnil;
3451 *part = 0;
3452 *fp = f1;
3453 XSETINT (*x, pt.x);
3454 XSETINT (*y, pt.y);
3455 *time = last_mouse_movement_time;
3460 UNBLOCK_INPUT;
3464 /***********************************************************************
3465 Tool-bars
3466 ***********************************************************************/
3468 /* Handle mouse button event on the tool-bar of frame F, at
3469 frame-relative coordinates X/Y. EVENT_TYPE is either ButtionPress
3470 or ButtonRelase. */
3472 static void
3473 w32_handle_tool_bar_click (f, button_event)
3474 struct frame *f;
3475 struct input_event *button_event;
3477 int x = XFASTINT (button_event->x);
3478 int y = XFASTINT (button_event->y);
3480 if (button_event->modifiers & down_modifier)
3481 handle_tool_bar_click (f, x, y, 1, 0);
3482 else
3483 handle_tool_bar_click (f, x, y, 0,
3484 button_event->modifiers & ~up_modifier);
3489 /***********************************************************************
3490 Scroll bars
3491 ***********************************************************************/
3493 /* Scroll bar support. */
3495 /* Given a window ID, find the struct scroll_bar which manages it.
3496 This can be called in GC, so we have to make sure to strip off mark
3497 bits. */
3499 static struct scroll_bar *
3500 x_window_to_scroll_bar (window_id)
3501 Window window_id;
3503 Lisp_Object tail;
3505 for (tail = Vframe_list;
3506 XGCTYPE (tail) == Lisp_Cons;
3507 tail = XCDR (tail))
3509 Lisp_Object frame, bar, condemned;
3511 frame = XCAR (tail);
3512 /* All elements of Vframe_list should be frames. */
3513 if (! GC_FRAMEP (frame))
3514 abort ();
3516 /* Scan this frame's scroll bar list for a scroll bar with the
3517 right window ID. */
3518 condemned = FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame));
3519 for (bar = FRAME_SCROLL_BARS (XFRAME (frame));
3520 /* This trick allows us to search both the ordinary and
3521 condemned scroll bar lists with one loop. */
3522 ! GC_NILP (bar) || (bar = condemned,
3523 condemned = Qnil,
3524 ! GC_NILP (bar));
3525 bar = XSCROLL_BAR (bar)->next)
3526 if (SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar)) == window_id)
3527 return XSCROLL_BAR (bar);
3530 return 0;
3535 /* Set the thumb size and position of scroll bar BAR. We are currently
3536 displaying PORTION out of a whole WHOLE, and our position POSITION. */
3538 static void
3539 w32_set_scroll_bar_thumb (bar, portion, position, whole)
3540 struct scroll_bar *bar;
3541 int portion, position, whole;
3543 Window w = SCROLL_BAR_W32_WINDOW (bar);
3544 double range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
3545 int sb_page, sb_pos;
3546 BOOL draggingp = !NILP (bar->dragging) ? TRUE : FALSE;
3548 if (whole)
3550 /* Position scroll bar at rock bottom if the bottom of the
3551 buffer is visible. This avoids shinking the thumb away
3552 to nothing if it is held at the bottom of the buffer. */
3553 if (position + portion >= whole)
3555 sb_page = range * (whole - position) / whole
3556 + VERTICAL_SCROLL_BAR_MIN_HANDLE;
3557 sb_pos = range;
3560 sb_page = portion * range / whole + VERTICAL_SCROLL_BAR_MIN_HANDLE;
3561 sb_pos = position * range / whole;
3563 else
3565 sb_page = range;
3566 sb_pos = 0;
3569 BLOCK_INPUT;
3571 if (pfnSetScrollInfo)
3573 SCROLLINFO si;
3575 si.cbSize = sizeof (si);
3576 /* Only update page size if currently dragging, to reduce
3577 flicker effects. */
3578 if (draggingp)
3579 si.fMask = SIF_PAGE;
3580 else
3581 si.fMask = SIF_PAGE | SIF_POS;
3582 si.nPage = sb_page;
3583 si.nPos = sb_pos;
3585 pfnSetScrollInfo (w, SB_CTL, &si, !draggingp);
3587 else
3588 SetScrollPos (w, SB_CTL, sb_pos, !draggingp);
3590 UNBLOCK_INPUT;
3594 /************************************************************************
3595 Scroll bars, general
3596 ************************************************************************/
3598 HWND
3599 my_create_scrollbar (f, bar)
3600 struct frame * f;
3601 struct scroll_bar * bar;
3603 return (HWND) SendMessage (FRAME_W32_WINDOW (f),
3604 WM_EMACS_CREATESCROLLBAR, (WPARAM) f,
3605 (LPARAM) bar);
3608 /*#define ATTACH_THREADS*/
3610 BOOL
3611 my_show_window (FRAME_PTR f, HWND hwnd, int how)
3613 #ifndef ATTACH_THREADS
3614 return SendMessage (FRAME_W32_WINDOW (f), WM_EMACS_SHOWWINDOW,
3615 (WPARAM) hwnd, (LPARAM) how);
3616 #else
3617 return ShowWindow (hwnd, how);
3618 #endif
3621 void
3622 my_set_window_pos (HWND hwnd, HWND hwndAfter,
3623 int x, int y, int cx, int cy, UINT flags)
3625 #ifndef ATTACH_THREADS
3626 WINDOWPOS pos;
3627 pos.hwndInsertAfter = hwndAfter;
3628 pos.x = x;
3629 pos.y = y;
3630 pos.cx = cx;
3631 pos.cy = cy;
3632 pos.flags = flags;
3633 SendMessage (hwnd, WM_EMACS_SETWINDOWPOS, (WPARAM) &pos, 0);
3634 #else
3635 SetWindowPos (hwnd, hwndAfter, x, y, cx, cy, flags);
3636 #endif
3639 void
3640 my_set_focus (f, hwnd)
3641 struct frame * f;
3642 HWND hwnd;
3644 SendMessage (FRAME_W32_WINDOW (f), WM_EMACS_SETFOCUS,
3645 (WPARAM) hwnd, 0);
3648 void
3649 my_set_foreground_window (hwnd)
3650 HWND hwnd;
3652 SendMessage (hwnd, WM_EMACS_SETFOREGROUND, (WPARAM) hwnd, 0);
3655 void
3656 my_destroy_window (f, hwnd)
3657 struct frame * f;
3658 HWND hwnd;
3660 SendMessage (FRAME_W32_WINDOW (f), WM_EMACS_DESTROYWINDOW,
3661 (WPARAM) hwnd, 0);
3664 /* Create a scroll bar and return the scroll bar vector for it. W is
3665 the Emacs window on which to create the scroll bar. TOP, LEFT,
3666 WIDTH and HEIGHT are.the pixel coordinates and dimensions of the
3667 scroll bar. */
3669 static struct scroll_bar *
3670 x_scroll_bar_create (w, top, left, width, height)
3671 struct window *w;
3672 int top, left, width, height;
3674 struct frame *f = XFRAME (WINDOW_FRAME (w));
3675 HWND hwnd;
3676 struct scroll_bar *bar
3677 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
3679 BLOCK_INPUT;
3681 XSETWINDOW (bar->window, w);
3682 XSETINT (bar->top, top);
3683 XSETINT (bar->left, left);
3684 XSETINT (bar->width, width);
3685 XSETINT (bar->height, height);
3686 XSETINT (bar->start, 0);
3687 XSETINT (bar->end, 0);
3688 bar->dragging = Qnil;
3690 /* Requires geometry to be set before call to create the real window */
3692 hwnd = my_create_scrollbar (f, bar);
3694 if (pfnSetScrollInfo)
3696 SCROLLINFO si;
3698 si.cbSize = sizeof (si);
3699 si.fMask = SIF_ALL;
3700 si.nMin = 0;
3701 si.nMax = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height)
3702 + VERTICAL_SCROLL_BAR_MIN_HANDLE;
3703 si.nPage = si.nMax;
3704 si.nPos = 0;
3706 pfnSetScrollInfo (hwnd, SB_CTL, &si, FALSE);
3708 else
3710 SetScrollRange (hwnd, SB_CTL, 0,
3711 VERTICAL_SCROLL_BAR_TOP_RANGE (f, height), FALSE);
3712 SetScrollPos (hwnd, SB_CTL, 0, FALSE);
3715 SET_SCROLL_BAR_W32_WINDOW (bar, hwnd);
3717 /* Add bar to its frame's list of scroll bars. */
3718 bar->next = FRAME_SCROLL_BARS (f);
3719 bar->prev = Qnil;
3720 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
3721 if (! NILP (bar->next))
3722 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
3724 UNBLOCK_INPUT;
3726 return bar;
3730 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
3731 nil. */
3733 static void
3734 x_scroll_bar_remove (bar)
3735 struct scroll_bar *bar;
3737 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
3739 BLOCK_INPUT;
3741 /* Destroy the window. */
3742 my_destroy_window (f, SCROLL_BAR_W32_WINDOW (bar));
3744 /* Disassociate this scroll bar from its window. */
3745 XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
3747 UNBLOCK_INPUT;
3750 /* Set the handle of the vertical scroll bar for WINDOW to indicate
3751 that we are displaying PORTION characters out of a total of WHOLE
3752 characters, starting at POSITION. If WINDOW has no scroll bar,
3753 create one. */
3754 static void
3755 w32_set_vertical_scroll_bar (w, portion, whole, position)
3756 struct window *w;
3757 int portion, whole, position;
3759 struct frame *f = XFRAME (w->frame);
3760 struct scroll_bar *bar;
3761 int top, height, left, sb_left, width, sb_width;
3762 int window_y, window_height;
3764 /* Get window dimensions. */
3765 window_box (w, -1, 0, &window_y, 0, &window_height);
3766 top = window_y;
3767 width = WINDOW_CONFIG_SCROLL_BAR_COLS (w) * FRAME_COLUMN_WIDTH (f);
3768 height = window_height;
3770 /* Compute the left edge of the scroll bar area. */
3771 left = WINDOW_SCROLL_BAR_AREA_X (w);
3773 /* Compute the width of the scroll bar which might be less than
3774 the width of the area reserved for the scroll bar. */
3775 if (WINDOW_CONFIG_SCROLL_BAR_WIDTH (w) > 0)
3776 sb_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
3777 else
3778 sb_width = width;
3780 /* Compute the left edge of the scroll bar. */
3781 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w))
3782 sb_left = left + width - sb_width - (width - sb_width) / 2;
3783 else
3784 sb_left = left + (width - sb_width) / 2;
3786 /* Does the scroll bar exist yet? */
3787 if (NILP (w->vertical_scroll_bar))
3789 HDC hdc;
3790 BLOCK_INPUT;
3791 if (width > 0 && height > 0)
3793 hdc = get_frame_dc (f);
3794 w32_clear_area (f, hdc, left, top, width, height);
3795 release_frame_dc (f, hdc);
3797 UNBLOCK_INPUT;
3799 bar = x_scroll_bar_create (w, top, sb_left, sb_width, height);
3801 else
3803 /* It may just need to be moved and resized. */
3804 HWND hwnd;
3806 bar = XSCROLL_BAR (w->vertical_scroll_bar);
3807 hwnd = SCROLL_BAR_W32_WINDOW (bar);
3809 /* If already correctly positioned, do nothing. */
3810 if ( XINT (bar->left) == sb_left
3811 && XINT (bar->top) == top
3812 && XINT (bar->width) == sb_width
3813 && XINT (bar->height) == height )
3815 /* Redraw after clear_frame. */
3816 if (!my_show_window (f, hwnd, SW_NORMAL))
3817 InvalidateRect (hwnd, NULL, FALSE);
3819 else
3821 HDC hdc;
3822 BLOCK_INPUT;
3823 if (width && height)
3825 hdc = get_frame_dc (f);
3826 /* Since Windows scroll bars are smaller than the space reserved
3827 for them on the frame, we have to clear "under" them. */
3828 w32_clear_area (f, hdc,
3829 left,
3830 top,
3831 width,
3832 height);
3833 release_frame_dc (f, hdc);
3835 /* Make sure scroll bar is "visible" before moving, to ensure the
3836 area of the parent window now exposed will be refreshed. */
3837 my_show_window (f, hwnd, SW_HIDE);
3838 MoveWindow (hwnd, sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
3839 top, sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
3840 max (height, 1), TRUE);
3841 if (pfnSetScrollInfo)
3843 SCROLLINFO si;
3845 si.cbSize = sizeof (si);
3846 si.fMask = SIF_RANGE;
3847 si.nMin = 0;
3848 si.nMax = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height)
3849 + VERTICAL_SCROLL_BAR_MIN_HANDLE;
3851 pfnSetScrollInfo (hwnd, SB_CTL, &si, FALSE);
3853 else
3854 SetScrollRange (hwnd, SB_CTL, 0,
3855 VERTICAL_SCROLL_BAR_TOP_RANGE (f, height), FALSE);
3856 my_show_window (f, hwnd, SW_NORMAL);
3857 /* InvalidateRect (w, NULL, FALSE); */
3859 /* Remember new settings. */
3860 XSETINT (bar->left, sb_left);
3861 XSETINT (bar->top, top);
3862 XSETINT (bar->width, sb_width);
3863 XSETINT (bar->height, height);
3865 UNBLOCK_INPUT;
3868 w32_set_scroll_bar_thumb (bar, portion, position, whole);
3870 XSETVECTOR (w->vertical_scroll_bar, bar);
3874 /* The following three hooks are used when we're doing a thorough
3875 redisplay of the frame. We don't explicitly know which scroll bars
3876 are going to be deleted, because keeping track of when windows go
3877 away is a real pain - "Can you say set-window-configuration, boys
3878 and girls?" Instead, we just assert at the beginning of redisplay
3879 that *all* scroll bars are to be removed, and then save a scroll bar
3880 from the fiery pit when we actually redisplay its window. */
3882 /* Arrange for all scroll bars on FRAME to be removed at the next call
3883 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
3884 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
3886 static void
3887 w32_condemn_scroll_bars (frame)
3888 FRAME_PTR frame;
3890 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
3891 while (! NILP (FRAME_SCROLL_BARS (frame)))
3893 Lisp_Object bar;
3894 bar = FRAME_SCROLL_BARS (frame);
3895 FRAME_SCROLL_BARS (frame) = XSCROLL_BAR (bar)->next;
3896 XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
3897 XSCROLL_BAR (bar)->prev = Qnil;
3898 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
3899 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
3900 FRAME_CONDEMNED_SCROLL_BARS (frame) = bar;
3905 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
3906 Note that WINDOW isn't necessarily condemned at all. */
3908 static void
3909 w32_redeem_scroll_bar (window)
3910 struct window *window;
3912 struct scroll_bar *bar;
3913 struct frame *f;
3915 /* We can't redeem this window's scroll bar if it doesn't have one. */
3916 if (NILP (window->vertical_scroll_bar))
3917 abort ();
3919 bar = XSCROLL_BAR (window->vertical_scroll_bar);
3921 /* Unlink it from the condemned list. */
3922 f = XFRAME (WINDOW_FRAME (window));
3923 if (NILP (bar->prev))
3925 /* If the prev pointer is nil, it must be the first in one of
3926 the lists. */
3927 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
3928 /* It's not condemned. Everything's fine. */
3929 return;
3930 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
3931 window->vertical_scroll_bar))
3932 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
3933 else
3934 /* If its prev pointer is nil, it must be at the front of
3935 one or the other! */
3936 abort ();
3938 else
3939 XSCROLL_BAR (bar->prev)->next = bar->next;
3941 if (! NILP (bar->next))
3942 XSCROLL_BAR (bar->next)->prev = bar->prev;
3944 bar->next = FRAME_SCROLL_BARS (f);
3945 bar->prev = Qnil;
3946 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
3947 if (! NILP (bar->next))
3948 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
3951 /* Remove all scroll bars on FRAME that haven't been saved since the
3952 last call to `*condemn_scroll_bars_hook'. */
3954 static void
3955 w32_judge_scroll_bars (f)
3956 FRAME_PTR f;
3958 Lisp_Object bar, next;
3960 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
3962 /* Clear out the condemned list now so we won't try to process any
3963 more events on the hapless scroll bars. */
3964 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
3966 for (; ! NILP (bar); bar = next)
3968 struct scroll_bar *b = XSCROLL_BAR (bar);
3970 x_scroll_bar_remove (b);
3972 next = b->next;
3973 b->next = b->prev = Qnil;
3976 /* Now there should be no references to the condemned scroll bars,
3977 and they should get garbage-collected. */
3980 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
3981 is set to something other than NO_EVENT, it is enqueued.
3983 This may be called from a signal handler, so we have to ignore GC
3984 mark bits. */
3986 static int
3987 w32_scroll_bar_handle_click (bar, msg, emacs_event)
3988 struct scroll_bar *bar;
3989 W32Msg *msg;
3990 struct input_event *emacs_event;
3992 if (! GC_WINDOWP (bar->window))
3993 abort ();
3995 emacs_event->kind = W32_SCROLL_BAR_CLICK_EVENT;
3996 emacs_event->code = 0;
3997 /* not really meaningful to distinguish up/down */
3998 emacs_event->modifiers = msg->dwModifiers;
3999 emacs_event->frame_or_window = bar->window;
4000 emacs_event->arg = Qnil;
4001 emacs_event->timestamp = msg->msg.time;
4004 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
4005 int y;
4006 int dragging = !NILP (bar->dragging);
4008 if (pfnGetScrollInfo)
4010 SCROLLINFO si;
4012 si.cbSize = sizeof (si);
4013 si.fMask = SIF_POS;
4015 pfnGetScrollInfo ((HWND) msg->msg.lParam, SB_CTL, &si);
4016 y = si.nPos;
4018 else
4019 y = GetScrollPos ((HWND) msg->msg.lParam, SB_CTL);
4021 bar->dragging = Qnil;
4024 last_mouse_scroll_bar_pos = msg->msg.wParam;
4026 switch (LOWORD (msg->msg.wParam))
4028 case SB_LINEDOWN:
4029 emacs_event->part = scroll_bar_down_arrow;
4030 break;
4031 case SB_LINEUP:
4032 emacs_event->part = scroll_bar_up_arrow;
4033 break;
4034 case SB_PAGEUP:
4035 emacs_event->part = scroll_bar_above_handle;
4036 break;
4037 case SB_PAGEDOWN:
4038 emacs_event->part = scroll_bar_below_handle;
4039 break;
4040 case SB_TOP:
4041 emacs_event->part = scroll_bar_handle;
4042 y = 0;
4043 break;
4044 case SB_BOTTOM:
4045 emacs_event->part = scroll_bar_handle;
4046 y = top_range;
4047 break;
4048 case SB_THUMBTRACK:
4049 case SB_THUMBPOSITION:
4050 if (VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height)) <= 0xffff)
4051 y = HIWORD (msg->msg.wParam);
4052 bar->dragging = Qt;
4053 emacs_event->part = scroll_bar_handle;
4055 /* "Silently" update current position. */
4056 if (pfnSetScrollInfo)
4058 SCROLLINFO si;
4060 si.cbSize = sizeof (si);
4061 si.fMask = SIF_POS;
4062 si.nPos = y;
4063 /* Remember apparent position (we actually lag behind the real
4064 position, so don't set that directly. */
4065 last_scroll_bar_drag_pos = y;
4067 pfnSetScrollInfo (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, &si, FALSE);
4069 else
4070 SetScrollPos (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, y, FALSE);
4071 break;
4072 case SB_ENDSCROLL:
4073 /* If this is the end of a drag sequence, then reset the scroll
4074 handle size to normal and do a final redraw. Otherwise do
4075 nothing. */
4076 if (dragging)
4078 if (pfnSetScrollInfo)
4080 SCROLLINFO si;
4081 int start = XINT (bar->start);
4082 int end = XINT (bar->end);
4084 si.cbSize = sizeof (si);
4085 si.fMask = SIF_PAGE | SIF_POS;
4086 si.nPage = end - start + VERTICAL_SCROLL_BAR_MIN_HANDLE;
4087 si.nPos = last_scroll_bar_drag_pos;
4088 pfnSetScrollInfo (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, &si, TRUE);
4090 else
4091 SetScrollPos (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, y, TRUE);
4093 /* fall through */
4094 default:
4095 emacs_event->kind = NO_EVENT;
4096 return FALSE;
4099 XSETINT (emacs_event->x, y);
4100 XSETINT (emacs_event->y, top_range);
4102 return TRUE;
4106 /* Return information to the user about the current position of the mouse
4107 on the scroll bar. */
4109 static void
4110 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
4111 FRAME_PTR *fp;
4112 Lisp_Object *bar_window;
4113 enum scroll_bar_part *part;
4114 Lisp_Object *x, *y;
4115 unsigned long *time;
4117 struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
4118 Window w = SCROLL_BAR_W32_WINDOW (bar);
4119 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
4120 int pos;
4121 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
4123 BLOCK_INPUT;
4125 *fp = f;
4126 *bar_window = bar->window;
4128 if (pfnGetScrollInfo)
4130 SCROLLINFO si;
4132 si.cbSize = sizeof (si);
4133 si.fMask = SIF_POS | SIF_PAGE | SIF_RANGE;
4135 pfnGetScrollInfo (w, SB_CTL, &si);
4136 pos = si.nPos;
4137 top_range = si.nMax - si.nPage + 1;
4139 else
4140 pos = GetScrollPos (w, SB_CTL);
4142 switch (LOWORD (last_mouse_scroll_bar_pos))
4144 case SB_THUMBPOSITION:
4145 case SB_THUMBTRACK:
4146 *part = scroll_bar_handle;
4147 if (VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height)) <= 0xffff)
4148 pos = HIWORD (last_mouse_scroll_bar_pos);
4149 break;
4150 case SB_LINEDOWN:
4151 *part = scroll_bar_handle;
4152 pos++;
4153 break;
4154 default:
4155 *part = scroll_bar_handle;
4156 break;
4159 XSETINT (*x, pos);
4160 XSETINT (*y, top_range);
4162 f->mouse_moved = 0;
4163 last_mouse_scroll_bar = Qnil;
4165 *time = last_mouse_movement_time;
4167 UNBLOCK_INPUT;
4171 /* The screen has been cleared so we may have changed foreground or
4172 background colors, and the scroll bars may need to be redrawn.
4173 Clear out the scroll bars, and ask for expose events, so we can
4174 redraw them. */
4176 void
4177 x_scroll_bar_clear (f)
4178 FRAME_PTR f;
4180 Lisp_Object bar;
4182 /* We can have scroll bars even if this is 0,
4183 if we just turned off scroll bar mode.
4184 But in that case we should not clear them. */
4185 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
4186 for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar);
4187 bar = XSCROLL_BAR (bar)->next)
4189 HWND window = SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar));
4190 HDC hdc = GetDC (window);
4191 RECT rect;
4193 /* Hide scroll bar until ready to repaint. x_scroll_bar_move
4194 arranges to refresh the scroll bar if hidden. */
4195 my_show_window (f, window, SW_HIDE);
4197 GetClientRect (window, &rect);
4198 select_palette (f, hdc);
4199 w32_clear_rect (f, hdc, &rect);
4200 deselect_palette (f, hdc);
4202 ReleaseDC (window, hdc);
4207 /* The main W32 event-reading loop - w32_read_socket. */
4209 /* Record the last 100 characters stored
4210 to help debug the loss-of-chars-during-GC problem. */
4212 static int temp_index;
4213 static short temp_buffer[100];
4216 /* Read events coming from the W32 shell.
4217 This routine is called by the SIGIO handler.
4218 We return as soon as there are no more events to be read.
4220 We return the number of characters stored into the buffer,
4221 thus pretending to be `read'.
4223 EXPECTED is nonzero if the caller knows input is available.
4225 Some of these messages are reposted back to the message queue since the
4226 system calls the windows proc directly in a context where we cannot return
4227 the data nor can we guarantee the state we are in. So if we dispatch them
4228 we will get into an infinite loop. To prevent this from ever happening we
4229 will set a variable to indicate we are in the read_socket call and indicate
4230 which message we are processing since the windows proc gets called
4231 recursively with different messages by the system.
4235 w32_read_socket (sd, expected, hold_quit)
4236 register int sd;
4237 int expected;
4238 struct input_event *hold_quit;
4240 int count = 0;
4241 int check_visibility = 0;
4242 W32Msg msg;
4243 struct frame *f;
4244 struct w32_display_info *dpyinfo = &one_w32_display_info;
4246 if (interrupt_input_blocked)
4248 interrupt_input_pending = 1;
4249 return -1;
4252 interrupt_input_pending = 0;
4253 BLOCK_INPUT;
4255 /* So people can tell when we have read the available input. */
4256 input_signal_count++;
4258 /* TODO: ghostscript integration. */
4259 while (get_next_msg (&msg, FALSE))
4261 struct input_event inev;
4262 int do_help = 0;
4264 EVENT_INIT (inev);
4265 inev.kind = NO_EVENT;
4266 inev.arg = Qnil;
4268 switch (msg.msg.message)
4270 case WM_PAINT:
4271 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4273 if (f)
4275 if (msg.rect.right == msg.rect.left ||
4276 msg.rect.bottom == msg.rect.top)
4278 /* We may get paint messages even though the client
4279 area is clipped - these are not expose events. */
4280 DebPrint (("clipped frame %p (%s) got WM_PAINT - ignored\n", f,
4281 SDATA (f->name)));
4283 else if (f->async_visible != 1)
4285 /* Definitely not obscured, so mark as visible. */
4286 f->async_visible = 1;
4287 f->async_iconified = 0;
4288 SET_FRAME_GARBAGED (f);
4289 DebPrint (("frame %p (%s) reexposed by WM_PAINT\n", f,
4290 SDATA (f->name)));
4292 /* WM_PAINT serves as MapNotify as well, so report
4293 visibility changes properly. */
4294 if (f->iconified)
4296 inev.kind = DEICONIFY_EVENT;
4297 XSETFRAME (inev.frame_or_window, f);
4299 else if (! NILP (Vframe_list)
4300 && ! NILP (XCDR (Vframe_list)))
4301 /* Force a redisplay sooner or later to update the
4302 frame titles in case this is the second frame. */
4303 record_asynch_buffer_change ();
4305 else
4307 HDC hdc = get_frame_dc (f);
4309 /* Erase background again for safety. */
4310 w32_clear_rect (f, hdc, &msg.rect);
4311 release_frame_dc (f, hdc);
4312 expose_frame (f,
4313 msg.rect.left,
4314 msg.rect.top,
4315 msg.rect.right - msg.rect.left,
4316 msg.rect.bottom - msg.rect.top);
4319 break;
4321 case WM_INPUTLANGCHANGE:
4322 /* Generate a language change event. */
4323 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4325 if (f)
4327 inev.kind = LANGUAGE_CHANGE_EVENT;
4328 XSETFRAME (inev.frame_or_window, f);
4329 inev.code = msg.msg.wParam;
4330 inev.modifiers = msg.msg.lParam & 0xffff;
4332 break;
4334 case WM_KEYDOWN:
4335 case WM_SYSKEYDOWN:
4336 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4338 if (f && !f->iconified)
4340 if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight))
4342 clear_mouse_face (dpyinfo);
4343 dpyinfo->mouse_face_hidden = 1;
4346 if (temp_index == sizeof temp_buffer / sizeof (short))
4347 temp_index = 0;
4348 temp_buffer[temp_index++] = msg.msg.wParam;
4349 inev.kind = NON_ASCII_KEYSTROKE_EVENT;
4350 inev.code = msg.msg.wParam;
4351 inev.modifiers = msg.dwModifiers;
4352 XSETFRAME (inev.frame_or_window, f);
4353 inev.timestamp = msg.msg.time;
4355 break;
4357 case WM_SYSCHAR:
4358 case WM_CHAR:
4359 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4361 if (f && !f->iconified)
4363 if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight))
4365 clear_mouse_face (dpyinfo);
4366 dpyinfo->mouse_face_hidden = 1;
4369 if (temp_index == sizeof temp_buffer / sizeof (short))
4370 temp_index = 0;
4371 temp_buffer[temp_index++] = msg.msg.wParam;
4372 inev.kind = ASCII_KEYSTROKE_EVENT;
4373 inev.code = msg.msg.wParam;
4374 inev.modifiers = msg.dwModifiers;
4375 XSETFRAME (inev.frame_or_window, f);
4376 inev.timestamp = msg.msg.time;
4378 break;
4380 case WM_MOUSEMOVE:
4381 /* Ignore non-movement. */
4383 int x = LOWORD (msg.msg.lParam);
4384 int y = HIWORD (msg.msg.lParam);
4385 if (x == last_mousemove_x && y == last_mousemove_y)
4386 break;
4387 last_mousemove_x = x;
4388 last_mousemove_y = y;
4391 previous_help_echo_string = help_echo_string;
4393 if (dpyinfo->grabbed && last_mouse_frame
4394 && FRAME_LIVE_P (last_mouse_frame))
4395 f = last_mouse_frame;
4396 else
4397 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4399 if (dpyinfo->mouse_face_hidden)
4401 dpyinfo->mouse_face_hidden = 0;
4402 clear_mouse_face (dpyinfo);
4405 if (f)
4407 /* Generate SELECT_WINDOW_EVENTs when needed. */
4408 if (mouse_autoselect_window)
4410 Lisp_Object window;
4411 int x = LOWORD (msg.msg.lParam);
4412 int y = HIWORD (msg.msg.lParam);
4414 window = window_from_coordinates (f, x, y, 0, 0, 0, 0);
4416 /* Window will be selected only when it is not
4417 selected now and last mouse movement event was
4418 not in it. Minibuffer window will be selected
4419 iff it is active. */
4420 if (WINDOWP(window)
4421 && !EQ (window, last_window)
4422 && !EQ (window, selected_window))
4424 inev.kind = SELECT_WINDOW_EVENT;
4425 inev.frame_or_window = window;
4428 last_window=window;
4430 note_mouse_movement (f, &msg.msg);
4432 else
4434 /* If we move outside the frame, then we're
4435 certainly no longer on any text in the frame. */
4436 clear_mouse_face (dpyinfo);
4439 /* If the contents of the global variable help_echo_string
4440 has changed, generate a HELP_EVENT. */
4441 #if 0 /* The below is an invalid comparison when USE_LISP_UNION_TYPE.
4442 But it was originally changed to this to fix a bug, so I have
4443 not removed it completely in case the bug is still there. */
4444 if (help_echo_string != previous_help_echo_string ||
4445 (!NILP (help_echo_string) && !STRINGP (help_echo_string) && f->mouse_moved))
4446 #else /* This is what xterm.c does. */
4447 if (!NILP (help_echo_string)
4448 || !NILP (previous_help_echo_string))
4449 do_help = 1;
4450 #endif
4451 break;
4453 case WM_LBUTTONDOWN:
4454 case WM_LBUTTONUP:
4455 case WM_MBUTTONDOWN:
4456 case WM_MBUTTONUP:
4457 case WM_RBUTTONDOWN:
4458 case WM_RBUTTONUP:
4459 case WM_XBUTTONDOWN:
4460 case WM_XBUTTONUP:
4462 /* If we decide we want to generate an event to be seen
4463 by the rest of Emacs, we put it here. */
4464 int tool_bar_p = 0;
4465 int button;
4466 int up;
4468 if (dpyinfo->grabbed && last_mouse_frame
4469 && FRAME_LIVE_P (last_mouse_frame))
4470 f = last_mouse_frame;
4471 else
4472 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4474 if (f)
4476 construct_mouse_click (&inev, &msg, f);
4478 /* Is this in the tool-bar? */
4479 if (WINDOWP (f->tool_bar_window)
4480 && WINDOW_TOTAL_LINES (XWINDOW (f->tool_bar_window)))
4482 Lisp_Object window;
4483 int x = XFASTINT (inev.x);
4484 int y = XFASTINT (inev.y);
4486 window = window_from_coordinates (f, x, y, 0, 0, 0, 1);
4488 if (EQ (window, f->tool_bar_window))
4490 w32_handle_tool_bar_click (f, &inev);
4491 tool_bar_p = 1;
4495 if (tool_bar_p
4496 || (dpyinfo->w32_focus_frame
4497 && f != dpyinfo->w32_focus_frame))
4498 inev.kind = NO_EVENT;
4501 parse_button (msg.msg.message, HIWORD (msg.msg.wParam),
4502 &button, &up);
4504 if (up)
4506 dpyinfo->grabbed &= ~ (1 << button);
4508 else
4510 dpyinfo->grabbed |= (1 << button);
4511 last_mouse_frame = f;
4512 /* Ignore any mouse motion that happened
4513 before this event; any subsequent mouse-movement
4514 Emacs events should reflect only motion after
4515 the ButtonPress. */
4516 if (f != 0)
4517 f->mouse_moved = 0;
4519 if (!tool_bar_p)
4520 last_tool_bar_item = -1;
4522 break;
4525 case WM_MOUSEWHEEL:
4527 if (dpyinfo->grabbed && last_mouse_frame
4528 && FRAME_LIVE_P (last_mouse_frame))
4529 f = last_mouse_frame;
4530 else
4531 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4533 if (f)
4536 if (!dpyinfo->w32_focus_frame
4537 || f == dpyinfo->w32_focus_frame)
4539 /* Emit an Emacs wheel-up/down event. */
4540 construct_mouse_wheel (&inev, &msg, f);
4542 /* Ignore any mouse motion that happened before this
4543 event; any subsequent mouse-movement Emacs events
4544 should reflect only motion after the
4545 ButtonPress. */
4546 f->mouse_moved = 0;
4548 last_mouse_frame = f;
4549 last_tool_bar_item = -1;
4551 break;
4553 case WM_DROPFILES:
4554 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4556 if (f)
4557 construct_drag_n_drop (&inev, &msg, f);
4558 break;
4560 case WM_VSCROLL:
4562 struct scroll_bar *bar =
4563 x_window_to_scroll_bar ((HWND)msg.msg.lParam);
4565 if (bar)
4566 w32_scroll_bar_handle_click (bar, &msg, &inev);
4567 break;
4570 case WM_WINDOWPOSCHANGED:
4571 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4572 if (f)
4574 if (f->want_fullscreen & FULLSCREEN_WAIT)
4575 f->want_fullscreen &= ~(FULLSCREEN_WAIT|FULLSCREEN_BOTH);
4577 check_visibility = 1;
4578 break;
4580 case WM_ACTIVATE:
4581 case WM_ACTIVATEAPP:
4582 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4583 if (f)
4584 x_check_fullscreen (f);
4585 check_visibility = 1;
4586 break;
4588 case WM_MOVE:
4589 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4591 if (f && !f->async_iconified)
4593 int x, y;
4595 x_real_positions (f, &x, &y);
4596 f->left_pos = x;
4597 f->top_pos = y;
4600 check_visibility = 1;
4601 break;
4603 case WM_SHOWWINDOW:
4604 /* wParam non-zero means Window is about to be shown, 0 means
4605 about to be hidden. */
4606 /* Redo the mouse-highlight after the tooltip has gone. */
4607 if (!msg.msg.wParam && msg.msg.hwnd == tip_window)
4609 tip_window = NULL;
4610 redo_mouse_highlight ();
4613 /* If window has been obscured or exposed by another window
4614 being maximised or minimised/restored, then recheck
4615 visibility of all frames. Direct changes to our own
4616 windows get handled by WM_SIZE. */
4617 #if 0
4618 if (msg.msg.lParam != 0)
4619 check_visibility = 1;
4620 else
4622 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4623 f->async_visible = msg.msg.wParam;
4625 #endif
4627 check_visibility = 1;
4628 break;
4630 case WM_SIZE:
4631 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4633 /* Inform lisp of whether frame has been iconified etc. */
4634 if (f)
4636 switch (msg.msg.wParam)
4638 case SIZE_MINIMIZED:
4639 f->async_visible = 0;
4640 f->async_iconified = 1;
4642 inev.kind = ICONIFY_EVENT;
4643 XSETFRAME (inev.frame_or_window, f);
4644 break;
4646 case SIZE_MAXIMIZED:
4647 case SIZE_RESTORED:
4648 f->async_visible = 1;
4649 f->async_iconified = 0;
4651 /* wait_reading_process_output will notice this and update
4652 the frame's display structures. */
4653 SET_FRAME_GARBAGED (f);
4655 if (f->iconified)
4657 int x, y;
4659 /* Reset top and left positions of the Window
4660 here since Windows sends a WM_MOVE message
4661 BEFORE telling us the Window is minimized
4662 when the Window is iconified, with 3000,3000
4663 as the co-ords. */
4664 x_real_positions (f, &x, &y);
4665 f->left_pos = x;
4666 f->top_pos = y;
4668 inev.kind = DEICONIFY_EVENT;
4669 XSETFRAME (inev.frame_or_window, f);
4671 else if (! NILP (Vframe_list)
4672 && ! NILP (XCDR (Vframe_list)))
4673 /* Force a redisplay sooner or later
4674 to update the frame titles
4675 in case this is the second frame. */
4676 record_asynch_buffer_change ();
4677 break;
4681 if (f && !f->async_iconified && msg.msg.wParam != SIZE_MINIMIZED)
4683 RECT rect;
4684 int rows;
4685 int columns;
4686 int width;
4687 int height;
4689 GetClientRect (msg.msg.hwnd, &rect);
4691 height = rect.bottom - rect.top;
4692 width = rect.right - rect.left;
4694 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, height);
4695 columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, width);
4697 /* TODO: Clip size to the screen dimensions. */
4699 /* Even if the number of character rows and columns has
4700 not changed, the font size may have changed, so we need
4701 to check the pixel dimensions as well. */
4703 if (columns != FRAME_COLS (f)
4704 || rows != FRAME_LINES (f)
4705 || width != FRAME_PIXEL_WIDTH (f)
4706 || height != FRAME_PIXEL_HEIGHT (f))
4708 change_frame_size (f, rows, columns, 0, 1, 0);
4709 SET_FRAME_GARBAGED (f);
4710 cancel_mouse_face (f);
4711 FRAME_PIXEL_WIDTH (f) = width;
4712 FRAME_PIXEL_HEIGHT (f) = height;
4713 f->win_gravity = NorthWestGravity;
4717 check_visibility = 1;
4718 break;
4720 case WM_MOUSELEAVE:
4721 f = x_any_window_to_frame (dpyinfo, msg.msg.hwnd);
4722 if (f)
4724 if (f == dpyinfo->mouse_face_mouse_frame)
4726 /* If we move outside the frame, then we're
4727 certainly no longer on any text in the frame. */
4728 clear_mouse_face (dpyinfo);
4729 dpyinfo->mouse_face_mouse_frame = 0;
4732 /* Generate a nil HELP_EVENT to cancel a help-echo.
4733 Do it only if there's something to cancel.
4734 Otherwise, the startup message is cleared when
4735 the mouse leaves the frame. */
4736 if (any_help_event_p)
4737 do_help = -1;
4739 break;
4741 case WM_SETFOCUS:
4742 w32_detect_focus_change (dpyinfo, &msg, &inev);
4744 dpyinfo->grabbed = 0;
4745 check_visibility = 1;
4746 break;
4748 case WM_KILLFOCUS:
4749 f = x_top_window_to_frame (dpyinfo, msg.msg.hwnd);
4751 if (f)
4753 if (f == dpyinfo->w32_focus_event_frame)
4754 dpyinfo->w32_focus_event_frame = 0;
4756 if (f == dpyinfo->w32_focus_frame)
4757 x_new_focus_frame (dpyinfo, 0);
4759 if (f == dpyinfo->mouse_face_mouse_frame)
4761 /* If we move outside the frame, then we're
4762 certainly no longer on any text in the frame. */
4763 clear_mouse_face (dpyinfo);
4764 dpyinfo->mouse_face_mouse_frame = 0;
4767 /* Generate a nil HELP_EVENT to cancel a help-echo.
4768 Do it only if there's something to cancel.
4769 Otherwise, the startup message is cleared when
4770 the mouse leaves the frame. */
4771 if (any_help_event_p)
4772 do_help = -1;
4775 dpyinfo->grabbed = 0;
4776 check_visibility = 1;
4777 break;
4779 case WM_CLOSE:
4780 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4782 if (f)
4784 inev.kind = DELETE_WINDOW_EVENT;
4785 XSETFRAME (inev.frame_or_window, f);
4787 break;
4789 case WM_INITMENU:
4790 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4792 if (f)
4794 inev.kind = MENU_BAR_ACTIVATE_EVENT;
4795 XSETFRAME (inev.frame_or_window, f);
4797 break;
4799 case WM_COMMAND:
4800 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4802 if (f)
4804 extern void menubar_selection_callback
4805 (FRAME_PTR f, void * client_data);
4806 menubar_selection_callback (f, (void *)msg.msg.wParam);
4809 check_visibility = 1;
4810 break;
4812 case WM_DISPLAYCHANGE:
4813 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4815 if (f)
4817 dpyinfo->width = (short) LOWORD (msg.msg.lParam);
4818 dpyinfo->height = (short) HIWORD (msg.msg.lParam);
4819 dpyinfo->n_cbits = msg.msg.wParam;
4820 DebPrint (("display change: %d %d\n", dpyinfo->width,
4821 dpyinfo->height));
4824 check_visibility = 1;
4825 break;
4827 default:
4828 /* Check for messages registered at runtime. */
4829 if (msg.msg.message == msh_mousewheel)
4831 /* Forward MSH_MOUSEWHEEL as WM_MOUSEWHEEL. */
4832 msg.msg.message = WM_MOUSEWHEEL;
4833 prepend_msg (&msg);
4835 break;
4838 if (inev.kind != NO_EVENT)
4840 kbd_buffer_store_event_hold (&inev, hold_quit);
4841 count++;
4844 if (do_help
4845 && !(hold_quit && hold_quit->kind != NO_EVENT))
4847 Lisp_Object frame;
4849 if (f)
4850 XSETFRAME (frame, f);
4851 else
4852 frame = Qnil;
4854 if (do_help > 0)
4856 if (NILP (help_echo_string))
4858 help_echo_object = help_echo_window = Qnil;
4859 help_echo_pos = -1;
4862 any_help_event_p = 1;
4863 gen_help_event (help_echo_string, frame, help_echo_window,
4864 help_echo_object, help_echo_pos);
4866 else
4868 help_echo_string = Qnil;
4869 gen_help_event (Qnil, frame, Qnil, Qnil, 0);
4871 count++;
4875 /* If the focus was just given to an autoraising frame,
4876 raise it now. */
4877 /* ??? This ought to be able to handle more than one such frame. */
4878 if (pending_autoraise_frame)
4880 x_raise_frame (pending_autoraise_frame);
4881 pending_autoraise_frame = 0;
4884 /* Check which frames are still visisble, if we have enqueued any user
4885 events or been notified of events that may affect visibility. We
4886 do this here because there doesn't seem to be any direct
4887 notification from Windows that the visibility of a window has
4888 changed (at least, not in all cases). */
4889 if (count > 0 || check_visibility)
4891 Lisp_Object tail, frame;
4893 FOR_EACH_FRAME (tail, frame)
4895 FRAME_PTR f = XFRAME (frame);
4896 /* The tooltip has been drawn already. Avoid the
4897 SET_FRAME_GARBAGED below. */
4898 if (EQ (frame, tip_frame))
4899 continue;
4901 /* Check "visible" frames and mark each as obscured or not.
4902 Note that async_visible is nonzero for unobscured and
4903 obscured frames, but zero for hidden and iconified frames. */
4904 if (FRAME_W32_P (f) && f->async_visible)
4906 RECT clipbox;
4907 HDC hdc;
4909 enter_crit ();
4910 /* Query clipping rectangle for the entire window area
4911 (GetWindowDC), not just the client portion (GetDC).
4912 Otherwise, the scrollbars and menubar aren't counted as
4913 part of the visible area of the frame, and we may think
4914 the frame is obscured when really a scrollbar is still
4915 visible and gets WM_PAINT messages above. */
4916 hdc = GetWindowDC (FRAME_W32_WINDOW (f));
4917 GetClipBox (hdc, &clipbox);
4918 ReleaseDC (FRAME_W32_WINDOW (f), hdc);
4919 leave_crit ();
4921 if (clipbox.right == clipbox.left
4922 || clipbox.bottom == clipbox.top)
4924 /* Frame has become completely obscured so mark as
4925 such (we do this by setting async_visible to 2 so
4926 that FRAME_VISIBLE_P is still true, but redisplay
4927 will skip it). */
4928 f->async_visible = 2;
4930 if (!FRAME_OBSCURED_P (f))
4932 DebPrint (("frame %p (%s) obscured\n", f,
4933 SDATA (f->name)));
4936 else
4938 /* Frame is not obscured, so mark it as such. */
4939 f->async_visible = 1;
4941 if (FRAME_OBSCURED_P (f))
4943 SET_FRAME_GARBAGED (f);
4944 DebPrint (("obscured frame %p (%s) found to be visible\n", f,
4945 SDATA (f->name)));
4947 /* Force a redisplay sooner or later. */
4948 record_asynch_buffer_change ();
4955 UNBLOCK_INPUT;
4956 return count;
4961 /***********************************************************************
4962 Text Cursor
4963 ***********************************************************************/
4965 /* Set clipping for output in glyph row ROW. W is the window in which
4966 we operate. GC is the graphics context to set clipping in.
4968 ROW may be a text row or, e.g., a mode line. Text rows must be
4969 clipped to the interior of the window dedicated to text display,
4970 mode lines must be clipped to the whole window. */
4972 static void
4973 w32_clip_to_row (w, row, area, hdc)
4974 struct window *w;
4975 struct glyph_row *row;
4976 int area;
4977 HDC hdc;
4979 struct frame *f = XFRAME (WINDOW_FRAME (w));
4980 RECT clip_rect;
4981 int window_x, window_y, window_width;
4983 window_box (w, area, &window_x, &window_y, &window_width, 0);
4985 clip_rect.left = window_x;
4986 clip_rect.top = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
4987 clip_rect.top = max (clip_rect.top, window_y);
4988 clip_rect.right = clip_rect.left + window_width;
4989 clip_rect.bottom = clip_rect.top + row->visible_height;
4991 w32_set_clip_rectangle (hdc, &clip_rect);
4995 /* Draw a hollow box cursor on window W in glyph row ROW. */
4997 static void
4998 x_draw_hollow_cursor (w, row)
4999 struct window *w;
5000 struct glyph_row *row;
5002 struct frame *f = XFRAME (WINDOW_FRAME (w));
5003 HDC hdc;
5004 RECT rect;
5005 int h;
5006 struct glyph *cursor_glyph;
5007 HBRUSH hb = CreateSolidBrush (f->output_data.w32->cursor_pixel);
5009 /* Get the glyph the cursor is on. If we can't tell because
5010 the current matrix is invalid or such, give up. */
5011 cursor_glyph = get_phys_cursor_glyph (w);
5012 if (cursor_glyph == NULL)
5013 return;
5015 /* Compute frame-relative coordinates for phys cursor. */
5016 rect.left = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
5017 rect.top = get_phys_cursor_geometry (w, row, cursor_glyph, &h);
5018 rect.bottom = rect.top + h;
5019 rect.right = rect.left + w->phys_cursor_width;
5021 hdc = get_frame_dc (f);
5022 /* Set clipping, draw the rectangle, and reset clipping again. */
5023 w32_clip_to_row (w, row, TEXT_AREA, hdc);
5024 FrameRect (hdc, &rect, hb);
5025 DeleteObject (hb);
5026 w32_set_clip_rectangle (hdc, NULL);
5027 release_frame_dc (f, hdc);
5031 /* Draw a bar cursor on window W in glyph row ROW.
5033 Implementation note: One would like to draw a bar cursor with an
5034 angle equal to the one given by the font property XA_ITALIC_ANGLE.
5035 Unfortunately, I didn't find a font yet that has this property set.
5036 --gerd. */
5038 static void
5039 x_draw_bar_cursor (w, row, width, kind)
5040 struct window *w;
5041 struct glyph_row *row;
5042 int width;
5043 enum text_cursor_kinds kind;
5045 struct frame *f = XFRAME (w->frame);
5046 struct glyph *cursor_glyph;
5047 int x;
5048 HDC hdc;
5050 /* If cursor is out of bounds, don't draw garbage. This can happen
5051 in mini-buffer windows when switching between echo area glyphs
5052 and mini-buffer. */
5053 cursor_glyph = get_phys_cursor_glyph (w);
5054 if (cursor_glyph == NULL)
5055 return;
5057 /* If on an image, draw like a normal cursor. That's usually better
5058 visible than drawing a bar, esp. if the image is large so that
5059 the bar might not be in the window. */
5060 if (cursor_glyph->type == IMAGE_GLYPH)
5062 struct glyph_row *row;
5063 row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
5064 draw_phys_cursor_glyph (w, row, DRAW_CURSOR);
5066 else
5068 COLORREF cursor_color = f->output_data.w32->cursor_pixel;
5069 struct face *face = FACE_FROM_ID (f, cursor_glyph->face_id);
5071 /* If the glyph's background equals the color we normally draw
5072 the bar cursor in, the bar cursor in its normal color is
5073 invisible. Use the glyph's foreground color instead in this
5074 case, on the assumption that the glyph's colors are chosen so
5075 that the glyph is legible. */
5076 if (face->background == cursor_color)
5077 cursor_color = face->foreground;
5079 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
5081 if (width < 0)
5082 width = FRAME_CURSOR_WIDTH (f);
5083 width = min (cursor_glyph->pixel_width, width);
5085 w->phys_cursor_width = width;
5088 hdc = get_frame_dc (f);
5089 w32_clip_to_row (w, row, TEXT_AREA, hdc);
5091 if (kind == BAR_CURSOR)
5093 w32_fill_area (f, hdc, cursor_color, x,
5094 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
5095 width, row->height);
5097 else
5099 w32_fill_area (f, hdc, cursor_color, x,
5100 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y +
5101 row->height - width),
5102 cursor_glyph->pixel_width, width);
5105 w32_set_clip_rectangle (hdc, NULL);
5106 release_frame_dc (f, hdc);
5111 /* RIF: Define cursor CURSOR on frame F. */
5113 static void
5114 w32_define_frame_cursor (f, cursor)
5115 struct frame *f;
5116 Cursor cursor;
5118 w32_define_cursor (FRAME_W32_WINDOW (f), cursor);
5122 /* RIF: Clear area on frame F. */
5124 static void
5125 w32_clear_frame_area (f, x, y, width, height)
5126 struct frame *f;
5127 int x, y, width, height;
5129 HDC hdc;
5131 hdc = get_frame_dc (f);
5132 w32_clear_area (f, hdc, x, y, width, height);
5133 release_frame_dc (f, hdc);
5136 /* RIF: Draw or clear cursor on window W. */
5138 static void
5139 w32_draw_window_cursor (w, glyph_row, x, y, cursor_type, cursor_width, on_p, active_p)
5140 struct window *w;
5141 struct glyph_row *glyph_row;
5142 int x, y;
5143 int cursor_type, cursor_width;
5144 int on_p, active_p;
5146 if (on_p)
5148 /* If the user wants to use the system caret, make sure our own
5149 cursor remains invisible. */
5150 if (w32_use_visible_system_caret)
5152 /* Call to erase_phys_cursor here seems to use the
5153 wrong values of w->phys_cursor, as they have been
5154 overwritten before this function was called. */
5155 if (w->phys_cursor_type != NO_CURSOR)
5156 erase_phys_cursor (w);
5158 cursor_type = w->phys_cursor_type = NO_CURSOR;
5159 w->phys_cursor_width = -1;
5161 else
5163 w->phys_cursor_type = cursor_type;
5166 w->phys_cursor_on_p = 1;
5168 /* If this is the active cursor, we need to track it with the
5169 system caret, so third party software like screen magnifiers
5170 and speech synthesizers can follow the cursor. */
5171 if (active_p)
5173 struct frame *f = XFRAME (WINDOW_FRAME (w));
5174 HWND hwnd = FRAME_W32_WINDOW (f);
5176 w32_system_caret_x
5177 = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
5178 w32_system_caret_y
5179 = (WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y)
5180 + glyph_row->ascent - w->phys_cursor_ascent);
5182 /* If the size of the active cursor changed, destroy the old
5183 system caret. */
5184 if (w32_system_caret_hwnd
5185 && (w32_system_caret_height != w->phys_cursor_height))
5186 PostMessage (hwnd, WM_EMACS_DESTROY_CARET, 0, 0);
5188 w32_system_caret_height = w->phys_cursor_height;
5190 /* Move the system caret. */
5191 PostMessage (hwnd, WM_EMACS_TRACK_CARET, 0, 0);
5194 if (glyph_row->exact_window_width_line_p
5195 && w->phys_cursor.hpos >= glyph_row->used[TEXT_AREA])
5197 glyph_row->cursor_in_fringe_p = 1;
5198 draw_fringe_bitmap (w, glyph_row, 0);
5199 return;
5202 switch (cursor_type)
5204 case HOLLOW_BOX_CURSOR:
5205 x_draw_hollow_cursor (w, glyph_row);
5206 break;
5208 case FILLED_BOX_CURSOR:
5209 draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
5210 break;
5212 case BAR_CURSOR:
5213 x_draw_bar_cursor (w, glyph_row, cursor_width, BAR_CURSOR);
5214 break;
5216 case HBAR_CURSOR:
5217 x_draw_bar_cursor (w, glyph_row, cursor_width, HBAR_CURSOR);
5218 break;
5220 case NO_CURSOR:
5221 w->phys_cursor_width = 0;
5222 break;
5224 default:
5225 abort ();
5232 /* Icons. */
5235 x_bitmap_icon (f, icon)
5236 struct frame *f;
5237 Lisp_Object icon;
5239 HANDLE hicon;
5241 if (FRAME_W32_WINDOW (f) == 0)
5242 return 1;
5244 if (NILP (icon))
5245 hicon = LoadIcon (hinst, EMACS_CLASS);
5246 else if (STRINGP (icon))
5247 hicon = LoadImage (NULL, (LPCTSTR) SDATA (icon), IMAGE_ICON, 0, 0,
5248 LR_DEFAULTSIZE | LR_LOADFROMFILE);
5249 else if (SYMBOLP (icon))
5251 LPCTSTR name;
5253 if (EQ (icon, intern ("application")))
5254 name = (LPCTSTR) IDI_APPLICATION;
5255 else if (EQ (icon, intern ("hand")))
5256 name = (LPCTSTR) IDI_HAND;
5257 else if (EQ (icon, intern ("question")))
5258 name = (LPCTSTR) IDI_QUESTION;
5259 else if (EQ (icon, intern ("exclamation")))
5260 name = (LPCTSTR) IDI_EXCLAMATION;
5261 else if (EQ (icon, intern ("asterisk")))
5262 name = (LPCTSTR) IDI_ASTERISK;
5263 else if (EQ (icon, intern ("winlogo")))
5264 name = (LPCTSTR) IDI_WINLOGO;
5265 else
5266 return 1;
5268 hicon = LoadIcon (NULL, name);
5270 else
5271 return 1;
5273 if (hicon == NULL)
5274 return 1;
5276 PostMessage (FRAME_W32_WINDOW (f), WM_SETICON, (WPARAM) ICON_BIG,
5277 (LPARAM) hicon);
5279 return 0;
5283 /************************************************************************
5284 Handling X errors
5285 ************************************************************************/
5287 /* Display Error Handling functions not used on W32. Listing them here
5288 helps diff stay in step when comparing w32term.c with xterm.c.
5290 x_error_catcher (display, error)
5291 x_catch_errors (dpy)
5292 x_catch_errors_unwind (old_val)
5293 x_check_errors (dpy, format)
5294 x_had_errors_p (dpy)
5295 x_clear_errors (dpy)
5296 x_uncatch_errors (dpy, count)
5297 x_trace_wire ()
5298 x_connection_signal (signalnum)
5299 x_connection_closed (dpy, error_message)
5300 x_error_quitter (display, error)
5301 x_error_handler (display, error)
5302 x_io_error_quitter (display)
5307 /* Changing the font of the frame. */
5309 /* Give frame F the font named FONTNAME as its default font, and
5310 return the full name of that font. FONTNAME may be a wildcard
5311 pattern; in that case, we choose some font that fits the pattern.
5312 The return value shows which font we chose. */
5314 Lisp_Object
5315 x_new_font (f, fontname)
5316 struct frame *f;
5317 register char *fontname;
5319 struct font_info *fontp
5320 = FS_LOAD_FONT (f, 0, fontname, -1);
5322 if (!fontp)
5323 return Qnil;
5325 FRAME_FONT (f) = (XFontStruct *) (fontp->font);
5326 FRAME_BASELINE_OFFSET (f) = fontp->baseline_offset;
5327 FRAME_FONTSET (f) = -1;
5329 FRAME_COLUMN_WIDTH (f) = fontp->average_width;
5330 FRAME_SPACE_WIDTH (f) = fontp->space_width;
5331 FRAME_LINE_HEIGHT (f) = FONT_HEIGHT (FRAME_FONT (f));
5333 compute_fringe_widths (f, 1);
5335 /* Compute the scroll bar width in character columns. */
5336 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0)
5338 int wid = FRAME_COLUMN_WIDTH (f);
5339 FRAME_CONFIG_SCROLL_BAR_COLS (f)
5340 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + wid-1) / wid;
5342 else
5344 int wid = FRAME_COLUMN_WIDTH (f);
5345 FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid;
5348 /* Now make the frame display the given font. */
5349 if (FRAME_W32_WINDOW (f) != 0)
5351 if (NILP (tip_frame) || XFRAME (tip_frame) != f)
5352 x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
5355 return build_string (fontp->full_name);
5358 /* Give frame F the fontset named FONTSETNAME as its default font, and
5359 return the full name of that fontset. FONTSETNAME may be a wildcard
5360 pattern; in that case, we choose some fontset that fits the pattern.
5361 The return value shows which fontset we chose. */
5363 Lisp_Object
5364 x_new_fontset (f, fontsetname)
5365 struct frame *f;
5366 char *fontsetname;
5368 int fontset = fs_query_fontset (build_string (fontsetname), 0);
5369 Lisp_Object result;
5371 if (fontset < 0)
5372 return Qnil;
5374 if (FRAME_FONTSET (f) == fontset)
5375 /* This fontset is already set in frame F. There's nothing more
5376 to do. */
5377 return fontset_name (fontset);
5379 result = x_new_font (f, (SDATA (fontset_ascii (fontset))));
5381 if (!STRINGP (result))
5382 /* Can't load ASCII font. */
5383 return Qnil;
5385 /* Since x_new_font doesn't update any fontset information, do it now. */
5386 FRAME_FONTSET(f) = fontset;
5388 return build_string (fontsetname);
5392 /***********************************************************************
5393 TODO: W32 Input Methods
5394 ***********************************************************************/
5395 /* Listing missing functions from xterm.c helps diff stay in step.
5397 xim_destroy_callback (xim, client_data, call_data)
5398 xim_open_dpy (dpyinfo, resource_name)
5399 struct xim_inst_t
5400 xim_instantiate_callback (display, client_data, call_data)
5401 xim_initialize (dpyinfo, resource_name)
5402 xim_close_dpy (dpyinfo)
5407 /* Calculate the absolute position in frame F
5408 from its current recorded position values and gravity. */
5410 void
5411 x_calc_absolute_position (f)
5412 struct frame *f;
5414 int flags = f->size_hint_flags;
5416 /* Treat negative positions as relative to the leftmost bottommost
5417 position that fits on the screen. */
5418 if (flags & XNegative)
5419 f->left_pos = (FRAME_W32_DISPLAY_INFO (f)->width
5420 - FRAME_PIXEL_WIDTH (f)
5421 + f->left_pos);
5423 if (flags & YNegative)
5424 f->top_pos = (FRAME_W32_DISPLAY_INFO (f)->height
5425 - FRAME_PIXEL_HEIGHT (f)
5426 + f->top_pos);
5427 /* The left_pos and top_pos
5428 are now relative to the top and left screen edges,
5429 so the flags should correspond. */
5430 f->size_hint_flags &= ~ (XNegative | YNegative);
5433 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
5434 to really change the position, and 0 when calling from
5435 x_make_frame_visible (in that case, XOFF and YOFF are the current
5436 position values). It is -1 when calling from x_set_frame_parameters,
5437 which means, do adjust for borders but don't change the gravity. */
5439 void
5440 x_set_offset (f, xoff, yoff, change_gravity)
5441 struct frame *f;
5442 register int xoff, yoff;
5443 int change_gravity;
5445 int modified_top, modified_left;
5447 if (change_gravity > 0)
5449 f->top_pos = yoff;
5450 f->left_pos = xoff;
5451 f->size_hint_flags &= ~ (XNegative | YNegative);
5452 if (xoff < 0)
5453 f->size_hint_flags |= XNegative;
5454 if (yoff < 0)
5455 f->size_hint_flags |= YNegative;
5456 f->win_gravity = NorthWestGravity;
5458 x_calc_absolute_position (f);
5460 BLOCK_INPUT;
5461 x_wm_set_size_hint (f, (long) 0, 0);
5463 modified_left = f->left_pos;
5464 modified_top = f->top_pos;
5466 my_set_window_pos (FRAME_W32_WINDOW (f),
5467 NULL,
5468 modified_left, modified_top,
5469 0, 0,
5470 SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
5471 UNBLOCK_INPUT;
5475 /* Check if we need to resize the frame due to a fullscreen request.
5476 If so needed, resize the frame. */
5477 static void
5478 x_check_fullscreen (f)
5479 struct frame *f;
5481 if (f->want_fullscreen & FULLSCREEN_BOTH)
5483 int width, height, ign;
5485 x_real_positions (f, &f->left_pos, &f->top_pos);
5487 x_fullscreen_adjust (f, &width, &height, &ign, &ign);
5489 /* We do not need to move the window, it shall be taken care of
5490 when setting WM manager hints. */
5491 if (FRAME_COLS (f) != width || FRAME_LINES (f) != height)
5493 change_frame_size (f, height, width, 0, 1, 0);
5494 SET_FRAME_GARBAGED (f);
5495 cancel_mouse_face (f);
5497 /* Wait for the change of frame size to occur */
5498 f->want_fullscreen |= FULLSCREEN_WAIT;
5503 /* Call this to change the size of frame F's x-window.
5504 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
5505 for this size change and subsequent size changes.
5506 Otherwise we leave the window gravity unchanged. */
5508 void
5509 x_set_window_size (f, change_gravity, cols, rows)
5510 struct frame *f;
5511 int change_gravity;
5512 int cols, rows;
5514 int pixelwidth, pixelheight;
5516 BLOCK_INPUT;
5518 check_frame_size (f, &rows, &cols);
5519 f->scroll_bar_actual_width
5520 = FRAME_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f);
5522 compute_fringe_widths (f, 0);
5524 pixelwidth = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, cols);
5525 pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
5527 f->win_gravity = NorthWestGravity;
5528 x_wm_set_size_hint (f, (long) 0, 0);
5531 RECT rect;
5533 rect.left = rect.top = 0;
5534 rect.right = pixelwidth;
5535 rect.bottom = pixelheight;
5537 AdjustWindowRect(&rect, f->output_data.w32->dwStyle,
5538 FRAME_EXTERNAL_MENU_BAR (f));
5540 my_set_window_pos (FRAME_W32_WINDOW (f),
5541 NULL,
5542 0, 0,
5543 rect.right - rect.left,
5544 rect.bottom - rect.top,
5545 SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE);
5548 /* Now, strictly speaking, we can't be sure that this is accurate,
5549 but the window manager will get around to dealing with the size
5550 change request eventually, and we'll hear how it went when the
5551 ConfigureNotify event gets here.
5553 We could just not bother storing any of this information here,
5554 and let the ConfigureNotify event set everything up, but that
5555 might be kind of confusing to the Lisp code, since size changes
5556 wouldn't be reported in the frame parameters until some random
5557 point in the future when the ConfigureNotify event arrives.
5559 We pass 1 for DELAY since we can't run Lisp code inside of
5560 a BLOCK_INPUT. */
5561 change_frame_size (f, rows, cols, 0, 1, 0);
5562 FRAME_PIXEL_WIDTH (f) = pixelwidth;
5563 FRAME_PIXEL_HEIGHT (f) = pixelheight;
5565 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
5566 receive in the ConfigureNotify event; if we get what we asked
5567 for, then the event won't cause the screen to become garbaged, so
5568 we have to make sure to do it here. */
5569 SET_FRAME_GARBAGED (f);
5571 /* If cursor was outside the new size, mark it as off. */
5572 mark_window_cursors_off (XWINDOW (f->root_window));
5574 /* Clear out any recollection of where the mouse highlighting was,
5575 since it might be in a place that's outside the new frame size.
5576 Actually checking whether it is outside is a pain in the neck,
5577 so don't try--just let the highlighting be done afresh with new size. */
5578 cancel_mouse_face (f);
5580 UNBLOCK_INPUT;
5583 /* Mouse warping. */
5585 void x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y);
5587 void
5588 x_set_mouse_position (f, x, y)
5589 struct frame *f;
5590 int x, y;
5592 int pix_x, pix_y;
5594 pix_x = FRAME_COL_TO_PIXEL_X (f, x) + FRAME_COLUMN_WIDTH (f) / 2;
5595 pix_y = FRAME_LINE_TO_PIXEL_Y (f, y) + FRAME_LINE_HEIGHT (f) / 2;
5597 if (pix_x < 0) pix_x = 0;
5598 if (pix_x > FRAME_PIXEL_WIDTH (f)) pix_x = FRAME_PIXEL_WIDTH (f);
5600 if (pix_y < 0) pix_y = 0;
5601 if (pix_y > FRAME_PIXEL_HEIGHT (f)) pix_y = FRAME_PIXEL_HEIGHT (f);
5603 x_set_mouse_pixel_position (f, pix_x, pix_y);
5606 void
5607 x_set_mouse_pixel_position (f, pix_x, pix_y)
5608 struct frame *f;
5609 int pix_x, pix_y;
5611 RECT rect;
5612 POINT pt;
5614 BLOCK_INPUT;
5616 GetClientRect (FRAME_W32_WINDOW (f), &rect);
5617 pt.x = rect.left + pix_x;
5618 pt.y = rect.top + pix_y;
5619 ClientToScreen (FRAME_W32_WINDOW (f), &pt);
5621 SetCursorPos (pt.x, pt.y);
5623 UNBLOCK_INPUT;
5627 /* focus shifting, raising and lowering. */
5629 void
5630 x_focus_on_frame (f)
5631 struct frame *f;
5633 struct w32_display_info *dpyinfo = &one_w32_display_info;
5635 /* Give input focus to frame. */
5636 BLOCK_INPUT;
5637 #if 0
5638 /* Try not to change its Z-order if possible. */
5639 if (x_window_to_frame (dpyinfo, GetForegroundWindow ()))
5640 my_set_focus (f, FRAME_W32_WINDOW (f));
5641 else
5642 #endif
5643 my_set_foreground_window (FRAME_W32_WINDOW (f));
5644 UNBLOCK_INPUT;
5647 void
5648 x_unfocus_frame (f)
5649 struct frame *f;
5653 /* Raise frame F. */
5654 void
5655 x_raise_frame (f)
5656 struct frame *f;
5658 BLOCK_INPUT;
5660 /* Strictly speaking, raise-frame should only change the frame's Z
5661 order, leaving input focus unchanged. This is reasonable behaviour
5662 on X where the usual policy is point-to-focus. However, this
5663 behaviour would be very odd on Windows where the usual policy is
5664 click-to-focus.
5666 On X, if the mouse happens to be over the raised frame, it gets
5667 input focus anyway (so the window with focus will never be
5668 completely obscured) - if not, then just moving the mouse over it
5669 is sufficient to give it focus. On Windows, the user must actually
5670 click on the frame (preferrably the title bar so as not to move
5671 point), which is more awkward. Also, no other Windows program
5672 raises a window to the top but leaves another window (possibly now
5673 completely obscured) with input focus.
5675 Because there is a system setting on Windows that allows the user
5676 to choose the point to focus policy, we make the strict semantics
5677 optional, but by default we grab focus when raising. */
5679 if (NILP (Vw32_grab_focus_on_raise))
5681 /* The obvious call to my_set_window_pos doesn't work if Emacs is
5682 not already the foreground application: the frame is raised
5683 above all other frames belonging to us, but not above the
5684 current top window. To achieve that, we have to resort to this
5685 more cumbersome method. */
5687 HDWP handle = BeginDeferWindowPos (2);
5688 if (handle)
5690 DeferWindowPos (handle,
5691 FRAME_W32_WINDOW (f),
5692 HWND_TOP,
5693 0, 0, 0, 0,
5694 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
5696 DeferWindowPos (handle,
5697 GetForegroundWindow (),
5698 FRAME_W32_WINDOW (f),
5699 0, 0, 0, 0,
5700 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
5702 EndDeferWindowPos (handle);
5705 else
5707 my_set_foreground_window (FRAME_W32_WINDOW (f));
5710 UNBLOCK_INPUT;
5713 /* Lower frame F. */
5714 void
5715 x_lower_frame (f)
5716 struct frame *f;
5718 BLOCK_INPUT;
5719 my_set_window_pos (FRAME_W32_WINDOW (f),
5720 HWND_BOTTOM,
5721 0, 0, 0, 0,
5722 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
5723 UNBLOCK_INPUT;
5726 static void
5727 w32_frame_raise_lower (f, raise_flag)
5728 FRAME_PTR f;
5729 int raise_flag;
5731 if (! FRAME_W32_P (f))
5732 return;
5734 if (raise_flag)
5735 x_raise_frame (f);
5736 else
5737 x_lower_frame (f);
5740 /* Change of visibility. */
5742 /* This tries to wait until the frame is really visible.
5743 However, if the window manager asks the user where to position
5744 the frame, this will return before the user finishes doing that.
5745 The frame will not actually be visible at that time,
5746 but it will become visible later when the window manager
5747 finishes with it. */
5749 void
5750 x_make_frame_visible (f)
5751 struct frame *f;
5753 Lisp_Object type;
5755 BLOCK_INPUT;
5757 type = x_icon_type (f);
5758 if (!NILP (type))
5759 x_bitmap_icon (f, type);
5761 if (! FRAME_VISIBLE_P (f))
5763 /* We test FRAME_GARBAGED_P here to make sure we don't
5764 call x_set_offset a second time
5765 if we get to x_make_frame_visible a second time
5766 before the window gets really visible. */
5767 if (! FRAME_ICONIFIED_P (f)
5768 && ! f->output_data.w32->asked_for_visible)
5769 x_set_offset (f, f->left_pos, f->top_pos, 0);
5771 f->output_data.w32->asked_for_visible = 1;
5773 /* my_show_window (f, FRAME_W32_WINDOW (f), f->async_iconified ? SW_RESTORE : SW_SHOW); */
5774 my_show_window (f, FRAME_W32_WINDOW (f), SW_SHOWNORMAL);
5777 /* Synchronize to ensure Emacs knows the frame is visible
5778 before we do anything else. We do this loop with input not blocked
5779 so that incoming events are handled. */
5781 Lisp_Object frame;
5782 int count;
5784 /* This must come after we set COUNT. */
5785 UNBLOCK_INPUT;
5787 XSETFRAME (frame, f);
5789 /* Wait until the frame is visible. Process X events until a
5790 MapNotify event has been seen, or until we think we won't get a
5791 MapNotify at all.. */
5792 for (count = input_signal_count + 10;
5793 input_signal_count < count && !FRAME_VISIBLE_P (f);)
5795 /* Force processing of queued events. */
5796 /* TODO: x_sync equivalent? */
5798 /* Machines that do polling rather than SIGIO have been observed
5799 to go into a busy-wait here. So we'll fake an alarm signal
5800 to let the handler know that there's something to be read.
5801 We used to raise a real alarm, but it seems that the handler
5802 isn't always enabled here. This is probably a bug. */
5803 if (input_polling_used ())
5805 /* It could be confusing if a real alarm arrives while processing
5806 the fake one. Turn it off and let the handler reset it. */
5807 int old_poll_suppress_count = poll_suppress_count;
5808 poll_suppress_count = 1;
5809 poll_for_input_1 ();
5810 poll_suppress_count = old_poll_suppress_count;
5813 FRAME_SAMPLE_VISIBILITY (f);
5817 /* Change from mapped state to withdrawn state. */
5819 /* Make the frame visible (mapped and not iconified). */
5821 x_make_frame_invisible (f)
5822 struct frame *f;
5824 /* Don't keep the highlight on an invisible frame. */
5825 if (FRAME_W32_DISPLAY_INFO (f)->x_highlight_frame == f)
5826 FRAME_W32_DISPLAY_INFO (f)->x_highlight_frame = 0;
5828 BLOCK_INPUT;
5830 my_show_window (f, FRAME_W32_WINDOW (f), SW_HIDE);
5832 /* We can't distinguish this from iconification
5833 just by the event that we get from the server.
5834 So we can't win using the usual strategy of letting
5835 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
5836 and synchronize with the server to make sure we agree. */
5837 f->visible = 0;
5838 FRAME_ICONIFIED_P (f) = 0;
5839 f->async_visible = 0;
5840 f->async_iconified = 0;
5842 UNBLOCK_INPUT;
5845 /* Change window state from mapped to iconified. */
5847 void
5848 x_iconify_frame (f)
5849 struct frame *f;
5851 Lisp_Object type;
5853 /* Don't keep the highlight on an invisible frame. */
5854 if (FRAME_W32_DISPLAY_INFO (f)->x_highlight_frame == f)
5855 FRAME_W32_DISPLAY_INFO (f)->x_highlight_frame = 0;
5857 if (f->async_iconified)
5858 return;
5860 BLOCK_INPUT;
5862 type = x_icon_type (f);
5863 if (!NILP (type))
5864 x_bitmap_icon (f, type);
5866 /* Simulate the user minimizing the frame. */
5867 SendMessage (FRAME_W32_WINDOW (f), WM_SYSCOMMAND, SC_MINIMIZE, 0);
5869 UNBLOCK_INPUT;
5873 /* Free X resources of frame F. */
5875 void
5876 x_free_frame_resources (f)
5877 struct frame *f;
5879 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
5881 BLOCK_INPUT;
5883 if (FRAME_W32_WINDOW (f))
5884 my_destroy_window (f, FRAME_W32_WINDOW (f));
5886 free_frame_menubar (f);
5888 unload_color (f, f->output_data.x->foreground_pixel);
5889 unload_color (f, f->output_data.x->background_pixel);
5890 unload_color (f, f->output_data.w32->cursor_pixel);
5891 unload_color (f, f->output_data.w32->cursor_foreground_pixel);
5892 unload_color (f, f->output_data.w32->border_pixel);
5893 unload_color (f, f->output_data.w32->mouse_pixel);
5894 if (f->output_data.w32->white_relief.allocated_p)
5895 unload_color (f, f->output_data.w32->white_relief.pixel);
5896 if (f->output_data.w32->black_relief.allocated_p)
5897 unload_color (f, f->output_data.w32->black_relief.pixel);
5899 if (FRAME_FACE_CACHE (f))
5900 free_frame_faces (f);
5902 xfree (f->output_data.w32);
5903 f->output_data.w32 = NULL;
5905 if (f == dpyinfo->w32_focus_frame)
5906 dpyinfo->w32_focus_frame = 0;
5907 if (f == dpyinfo->w32_focus_event_frame)
5908 dpyinfo->w32_focus_event_frame = 0;
5909 if (f == dpyinfo->x_highlight_frame)
5910 dpyinfo->x_highlight_frame = 0;
5912 if (f == dpyinfo->mouse_face_mouse_frame)
5914 dpyinfo->mouse_face_beg_row
5915 = dpyinfo->mouse_face_beg_col = -1;
5916 dpyinfo->mouse_face_end_row
5917 = dpyinfo->mouse_face_end_col = -1;
5918 dpyinfo->mouse_face_window = Qnil;
5919 dpyinfo->mouse_face_deferred_gc = 0;
5920 dpyinfo->mouse_face_mouse_frame = 0;
5923 UNBLOCK_INPUT;
5927 /* Destroy the window of frame F. */
5929 x_destroy_window (f)
5930 struct frame *f;
5932 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
5934 x_free_frame_resources (f);
5936 dpyinfo->reference_count--;
5940 /* Setting window manager hints. */
5942 /* Set the normal size hints for the window manager, for frame F.
5943 FLAGS is the flags word to use--or 0 meaning preserve the flags
5944 that the window now has.
5945 If USER_POSITION is nonzero, we set the USPosition
5946 flag (this is useful when FLAGS is 0). */
5947 void
5948 x_wm_set_size_hint (f, flags, user_position)
5949 struct frame *f;
5950 long flags;
5951 int user_position;
5953 Window window = FRAME_W32_WINDOW (f);
5955 enter_crit ();
5957 SetWindowLong (window, WND_FONTWIDTH_INDEX, FRAME_COLUMN_WIDTH (f));
5958 SetWindowLong (window, WND_LINEHEIGHT_INDEX, FRAME_LINE_HEIGHT (f));
5959 SetWindowLong (window, WND_BORDER_INDEX, FRAME_INTERNAL_BORDER_WIDTH (f));
5960 SetWindowLong (window, WND_SCROLLBAR_INDEX, f->scroll_bar_actual_width);
5962 leave_crit ();
5965 /* Window manager things */
5966 void
5967 x_wm_set_icon_position (f, icon_x, icon_y)
5968 struct frame *f;
5969 int icon_x, icon_y;
5971 #if 0
5972 Window window = FRAME_W32_WINDOW (f);
5974 f->display.x->wm_hints.flags |= IconPositionHint;
5975 f->display.x->wm_hints.icon_x = icon_x;
5976 f->display.x->wm_hints.icon_y = icon_y;
5978 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->display.x->wm_hints);
5979 #endif
5983 /***********************************************************************
5984 Fonts
5985 ***********************************************************************/
5987 /* The following functions are listed here to help diff stay in step
5988 with xterm.c. See w32fns.c for definitions.
5990 x_get_font_info (f, font_idx)
5991 x_list_fonts (f, pattern, size, maxnames)
5995 #if GLYPH_DEBUG
5997 /* Check that FONT is valid on frame F. It is if it can be found in F's
5998 font table. */
6000 static void
6001 x_check_font (f, font)
6002 struct frame *f;
6003 XFontStruct *font;
6005 int i;
6006 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
6008 xassert (font != NULL);
6010 for (i = 0; i < dpyinfo->n_fonts; i++)
6011 if (dpyinfo->font_table[i].name
6012 && font == dpyinfo->font_table[i].font)
6013 break;
6015 xassert (i < dpyinfo->n_fonts);
6018 #endif /* GLYPH_DEBUG != 0 */
6020 /* Set *W to the minimum width, *H to the minimum font height of FONT.
6021 Note: There are (broken) X fonts out there with invalid XFontStruct
6022 min_bounds contents. For example, handa@etl.go.jp reports that
6023 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
6024 have font->min_bounds.width == 0. */
6026 static INLINE void
6027 x_font_min_bounds (font, w, h)
6028 XFontStruct *font;
6029 int *w, *h;
6032 * TODO: Windows does not appear to offer min bound, only
6033 * average and maximum width, and maximum height.
6035 *h = FONT_HEIGHT (font);
6036 *w = FONT_WIDTH (font);
6040 /* Compute the smallest character width and smallest font height over
6041 all fonts available on frame F. Set the members smallest_char_width
6042 and smallest_font_height in F's x_display_info structure to
6043 the values computed. Value is non-zero if smallest_font_height or
6044 smallest_char_width become smaller than they were before. */
6047 x_compute_min_glyph_bounds (f)
6048 struct frame *f;
6050 int i;
6051 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
6052 XFontStruct *font;
6053 int old_width = dpyinfo->smallest_char_width;
6054 int old_height = dpyinfo->smallest_font_height;
6056 dpyinfo->smallest_font_height = 100000;
6057 dpyinfo->smallest_char_width = 100000;
6059 for (i = 0; i < dpyinfo->n_fonts; ++i)
6060 if (dpyinfo->font_table[i].name)
6062 struct font_info *fontp = dpyinfo->font_table + i;
6063 int w, h;
6065 font = (XFontStruct *) fontp->font;
6066 xassert (font != (XFontStruct *) ~0);
6067 x_font_min_bounds (font, &w, &h);
6069 dpyinfo->smallest_font_height = min (dpyinfo->smallest_font_height, h);
6070 dpyinfo->smallest_char_width = min (dpyinfo->smallest_char_width, w);
6073 xassert (dpyinfo->smallest_char_width > 0
6074 && dpyinfo->smallest_font_height > 0);
6076 return (dpyinfo->n_fonts == 1
6077 || dpyinfo->smallest_char_width < old_width
6078 || dpyinfo->smallest_font_height < old_height);
6081 /* The following functions are listed here to help diff stay in step
6082 with xterm.c. See w32fns.c for definitions.
6084 x_load_font (f, fontname, size)
6085 x_query_font (f, fontname)
6086 x_find_ccl_program (fontp)
6090 /***********************************************************************
6091 Initialization
6092 ***********************************************************************/
6094 static int w32_initialized = 0;
6096 void
6097 w32_initialize_display_info (display_name)
6098 Lisp_Object display_name;
6100 struct w32_display_info *dpyinfo = &one_w32_display_info;
6102 bzero (dpyinfo, sizeof (*dpyinfo));
6104 /* Put it on w32_display_name_list. */
6105 w32_display_name_list = Fcons (Fcons (display_name, Qnil),
6106 w32_display_name_list);
6107 dpyinfo->name_list_element = XCAR (w32_display_name_list);
6109 dpyinfo->w32_id_name
6110 = (char *) xmalloc (SCHARS (Vinvocation_name)
6111 + SCHARS (Vsystem_name)
6112 + 2);
6113 sprintf (dpyinfo->w32_id_name, "%s@%s",
6114 SDATA (Vinvocation_name), SDATA (Vsystem_name));
6116 /* Default Console mode values - overridden when running in GUI mode
6117 with values obtained from system metrics. */
6118 dpyinfo->resx = 1;
6119 dpyinfo->resy = 1;
6120 dpyinfo->height_in = 1;
6121 dpyinfo->width_in = 1;
6122 dpyinfo->n_planes = 1;
6123 dpyinfo->n_cbits = 4;
6124 dpyinfo->n_fonts = 0;
6125 dpyinfo->smallest_font_height = 1;
6126 dpyinfo->smallest_char_width = 1;
6128 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
6129 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
6130 dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
6131 dpyinfo->mouse_face_window = Qnil;
6132 dpyinfo->mouse_face_overlay = Qnil;
6133 dpyinfo->mouse_face_hidden = 0;
6135 dpyinfo->vertical_scroll_bar_cursor = w32_load_cursor (IDC_ARROW);
6136 /* TODO: dpyinfo->gray */
6140 /* Create an xrdb-style database of resources to supercede registry settings.
6141 The database is just a concatenation of C strings, finished by an additional
6142 \0. The string are submitted to some basic normalization, so
6144 [ *]option[ *]:[ *]value...
6146 becomes
6148 option:value...
6150 but any whitespace following value is not removed. */
6152 static char *
6153 w32_make_rdb (xrm_option)
6154 char *xrm_option;
6156 char *buffer = xmalloc (strlen (xrm_option) + 2);
6157 char *current = buffer;
6158 char ch;
6159 int in_option = 1;
6160 int before_value = 0;
6162 do {
6163 ch = *xrm_option++;
6165 if (ch == '\n')
6167 *current++ = '\0';
6168 in_option = 1;
6169 before_value = 0;
6171 else if (ch != ' ')
6173 *current++ = ch;
6174 if (in_option && (ch == ':'))
6176 in_option = 0;
6177 before_value = 1;
6179 else if (before_value)
6181 before_value = 0;
6184 else if (!(in_option || before_value))
6186 *current++ = ch;
6188 } while (ch);
6190 *current = '\0';
6192 return buffer;
6195 struct w32_display_info *
6196 w32_term_init (display_name, xrm_option, resource_name)
6197 Lisp_Object display_name;
6198 char *xrm_option;
6199 char *resource_name;
6201 struct w32_display_info *dpyinfo;
6202 HDC hdc;
6204 BLOCK_INPUT;
6206 if (!w32_initialized)
6208 w32_initialize ();
6209 w32_initialized = 1;
6212 w32_initialize_display_info (display_name);
6214 dpyinfo = &one_w32_display_info;
6216 dpyinfo->xrdb = xrm_option ? w32_make_rdb (xrm_option) : NULL;
6218 /* Put this display on the chain. */
6219 dpyinfo->next = x_display_list;
6220 x_display_list = dpyinfo;
6222 hdc = GetDC (GetDesktopWindow ());
6224 dpyinfo->height = GetDeviceCaps (hdc, VERTRES);
6225 dpyinfo->width = GetDeviceCaps (hdc, HORZRES);
6226 dpyinfo->root_window = GetDesktopWindow ();
6227 dpyinfo->n_planes = GetDeviceCaps (hdc, PLANES);
6228 dpyinfo->n_cbits = GetDeviceCaps (hdc, BITSPIXEL);
6229 dpyinfo->resx = GetDeviceCaps (hdc, LOGPIXELSX);
6230 dpyinfo->resy = GetDeviceCaps (hdc, LOGPIXELSY);
6231 dpyinfo->has_palette = GetDeviceCaps (hdc, RASTERCAPS) & RC_PALETTE;
6232 dpyinfo->image_cache = make_image_cache ();
6233 dpyinfo->height_in = dpyinfo->height / dpyinfo->resx;
6234 dpyinfo->width_in = dpyinfo->width / dpyinfo->resy;
6235 ReleaseDC (GetDesktopWindow (), hdc);
6237 /* initialise palette with white and black */
6239 XColor color;
6240 w32_defined_color (0, "white", &color, 1);
6241 w32_defined_color (0, "black", &color, 1);
6244 /* Create Fringe Bitmaps and store them for later use.
6246 On W32, bitmaps are all unsigned short, as Windows requires
6247 bitmap data to be Word aligned. For some reason they are
6248 horizontally reflected compared to how they appear on X, so we
6249 need to bitswap and convert to unsigned shorts before creating
6250 the bitmaps. */
6251 w32_init_fringe ();
6253 #ifndef F_SETOWN_BUG
6254 #ifdef F_SETOWN
6255 #ifdef F_SETOWN_SOCK_NEG
6256 /* stdin is a socket here */
6257 fcntl (connection, F_SETOWN, -getpid ());
6258 #else /* ! defined (F_SETOWN_SOCK_NEG) */
6259 fcntl (connection, F_SETOWN, getpid ());
6260 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
6261 #endif /* ! defined (F_SETOWN) */
6262 #endif /* F_SETOWN_BUG */
6264 #ifdef SIGIO
6265 if (interrupt_input)
6266 init_sigio (connection);
6267 #endif /* ! defined (SIGIO) */
6269 UNBLOCK_INPUT;
6271 return dpyinfo;
6274 /* Get rid of display DPYINFO, assuming all frames are already gone. */
6276 void
6277 x_delete_display (dpyinfo)
6278 struct w32_display_info *dpyinfo;
6280 /* Discard this display from w32_display_name_list and w32_display_list.
6281 We can't use Fdelq because that can quit. */
6282 if (! NILP (w32_display_name_list)
6283 && EQ (XCAR (w32_display_name_list), dpyinfo->name_list_element))
6284 w32_display_name_list = XCDR (w32_display_name_list);
6285 else
6287 Lisp_Object tail;
6289 tail = w32_display_name_list;
6290 while (CONSP (tail) && CONSP (XCDR (tail)))
6292 if (EQ (XCAR (XCDR (tail)), dpyinfo->name_list_element))
6294 XSETCDR (tail, XCDR (XCDR (tail)));
6295 break;
6297 tail = XCDR (tail);
6301 /* free palette table */
6303 struct w32_palette_entry * plist;
6305 plist = dpyinfo->color_list;
6306 while (plist)
6308 struct w32_palette_entry * pentry = plist;
6309 plist = plist->next;
6310 xfree (pentry);
6312 dpyinfo->color_list = NULL;
6313 if (dpyinfo->palette)
6314 DeleteObject(dpyinfo->palette);
6316 xfree (dpyinfo->font_table);
6317 xfree (dpyinfo->w32_id_name);
6319 w32_reset_fringes ();
6322 /* Set up use of W32. */
6324 DWORD w32_msg_worker ();
6326 void
6327 x_flush (struct frame * f)
6328 { /* Nothing to do */ }
6330 extern frame_parm_handler w32_frame_parm_handlers[];
6332 static struct redisplay_interface w32_redisplay_interface =
6334 w32_frame_parm_handlers,
6335 x_produce_glyphs,
6336 x_write_glyphs,
6337 x_insert_glyphs,
6338 x_clear_end_of_line,
6339 x_scroll_run,
6340 x_after_update_window_line,
6341 x_update_window_begin,
6342 x_update_window_end,
6343 x_cursor_to,
6344 x_flush,
6345 0, /* flush_display_optional */
6346 x_clear_window_mouse_face,
6347 w32_get_glyph_overhangs,
6348 x_fix_overlapping_area,
6349 w32_draw_fringe_bitmap,
6350 w32_define_fringe_bitmap,
6351 w32_destroy_fringe_bitmap,
6352 w32_per_char_metric,
6353 w32_encode_char,
6354 NULL, /* w32_compute_glyph_string_overhangs */
6355 x_draw_glyph_string,
6356 w32_define_frame_cursor,
6357 w32_clear_frame_area,
6358 w32_draw_window_cursor,
6359 w32_draw_vertical_window_border,
6360 w32_shift_glyphs_for_insert
6363 void
6364 w32_initialize ()
6366 rif = &w32_redisplay_interface;
6368 /* MSVC does not type K&R functions with no arguments correctly, and
6369 so we must explicitly cast them. */
6370 clear_frame_hook = (void (*)(void)) x_clear_frame;
6371 ring_bell_hook = (void (*)(void)) w32_ring_bell;
6372 update_begin_hook = x_update_begin;
6373 update_end_hook = x_update_end;
6375 read_socket_hook = w32_read_socket;
6377 frame_up_to_date_hook = w32_frame_up_to_date;
6379 mouse_position_hook = w32_mouse_position;
6380 frame_rehighlight_hook = w32_frame_rehighlight;
6381 frame_raise_lower_hook = w32_frame_raise_lower;
6382 set_vertical_scroll_bar_hook = w32_set_vertical_scroll_bar;
6383 condemn_scroll_bars_hook = w32_condemn_scroll_bars;
6384 redeem_scroll_bar_hook = w32_redeem_scroll_bar;
6385 judge_scroll_bars_hook = w32_judge_scroll_bars;
6387 scroll_region_ok = 1; /* we'll scroll partial frames */
6388 char_ins_del_ok = 1;
6389 line_ins_del_ok = 1; /* we'll just blt 'em */
6390 fast_clear_end_of_line = 1; /* X does this well */
6391 memory_below_frame = 0; /* we don't remember what scrolls
6392 off the bottom */
6393 baud_rate = 19200;
6395 w32_system_caret_hwnd = NULL;
6396 w32_system_caret_height = 0;
6397 w32_system_caret_x = 0;
6398 w32_system_caret_y = 0;
6400 last_tool_bar_item = -1;
6401 any_help_event_p = 0;
6403 /* Initialize input mode: interrupt_input off, no flow control, allow
6404 8 bit character input, standard quit char. */
6405 Fset_input_mode (Qnil, Qnil, make_number (2), Qnil);
6407 /* Create the window thread - it will terminate itself or when the app terminates */
6409 init_crit ();
6411 dwMainThreadId = GetCurrentThreadId ();
6412 DuplicateHandle (GetCurrentProcess (), GetCurrentThread (),
6413 GetCurrentProcess (), &hMainThread, 0, TRUE, DUPLICATE_SAME_ACCESS);
6415 /* Wait for thread to start */
6418 MSG msg;
6420 PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE);
6422 hWindowsThread = CreateThread (NULL, 0,
6423 (LPTHREAD_START_ROUTINE) w32_msg_worker,
6424 0, 0, &dwWindowsThreadId);
6426 GetMessage (&msg, NULL, WM_EMACS_DONE, WM_EMACS_DONE);
6429 /* It is desirable that mainThread should have the same notion of
6430 focus window and active window as windowsThread. Unfortunately, the
6431 following call to AttachThreadInput, which should do precisely what
6432 we need, causes major problems when Emacs is linked as a console
6433 program. Unfortunately, we have good reasons for doing that, so
6434 instead we need to send messages to windowsThread to make some API
6435 calls for us (ones that affect, or depend on, the active/focus
6436 window state. */
6437 #ifdef ATTACH_THREADS
6438 AttachThreadInput (dwMainThreadId, dwWindowsThreadId, TRUE);
6439 #endif
6441 /* Dynamically link to optional system components. */
6443 HANDLE user_lib = LoadLibrary ("user32.dll");
6445 #define LOAD_PROC(fn) pfn##fn = (void *) GetProcAddress (user_lib, #fn)
6447 /* New proportional scroll bar functions. */
6448 LOAD_PROC (SetScrollInfo);
6449 LOAD_PROC (GetScrollInfo);
6451 #undef LOAD_PROC
6453 FreeLibrary (user_lib);
6455 /* If using proportional scroll bars, ensure handle is at least 5 pixels;
6456 otherwise use the fixed height. */
6457 vertical_scroll_bar_min_handle = (pfnSetScrollInfo != NULL) ? 5 :
6458 GetSystemMetrics (SM_CYVTHUMB);
6460 /* For either kind of scroll bar, take account of the arrows; these
6461 effectively form the border of the main scroll bar range. */
6462 vertical_scroll_bar_top_border = vertical_scroll_bar_bottom_border
6463 = GetSystemMetrics (SM_CYVSCROLL);
6467 void
6468 syms_of_w32term ()
6470 staticpro (&w32_display_name_list);
6471 w32_display_name_list = Qnil;
6473 staticpro (&last_mouse_scroll_bar);
6474 last_mouse_scroll_bar = Qnil;
6476 staticpro (&Qvendor_specific_keysyms);
6477 Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
6479 DEFVAR_INT ("w32-num-mouse-buttons",
6480 &w32_num_mouse_buttons,
6481 doc: /* Number of physical mouse buttons. */);
6482 w32_num_mouse_buttons = 2;
6484 DEFVAR_LISP ("w32-swap-mouse-buttons",
6485 &Vw32_swap_mouse_buttons,
6486 doc: /* Swap the mapping of middle and right mouse buttons.
6487 When nil, middle button is mouse-2 and right button is mouse-3. */);
6488 Vw32_swap_mouse_buttons = Qnil;
6490 DEFVAR_LISP ("w32-grab-focus-on-raise",
6491 &Vw32_grab_focus_on_raise,
6492 doc: /* Raised frame grabs input focus.
6493 When t, `raise-frame' grabs input focus as well. This fits well
6494 with the normal Windows click-to-focus policy, but might not be
6495 desirable when using a point-to-focus policy. */);
6496 Vw32_grab_focus_on_raise = Qt;
6498 DEFVAR_LISP ("w32-capslock-is-shiftlock",
6499 &Vw32_capslock_is_shiftlock,
6500 doc: /* Apply CapsLock state to non character input keys.
6501 When nil, CapsLock only affects normal character input keys. */);
6502 Vw32_capslock_is_shiftlock = Qnil;
6504 DEFVAR_LISP ("w32-recognize-altgr",
6505 &Vw32_recognize_altgr,
6506 doc: /* Recognize right-alt and left-ctrl as AltGr.
6507 When nil, the right-alt and left-ctrl key combination is
6508 interpreted normally. */);
6509 Vw32_recognize_altgr = Qt;
6511 DEFVAR_BOOL ("w32-enable-unicode-output",
6512 &w32_enable_unicode_output,
6513 doc: /* Enable the use of Unicode for text output if non-nil.
6514 Unicode output may prevent some third party applications for displaying
6515 Far-East Languages on Windows 95/98 from working properly.
6516 NT uses Unicode internally anyway, so this flag will probably have no
6517 affect on NT machines. */);
6518 w32_enable_unicode_output = 1;
6520 DEFVAR_BOOL ("w32-use-visible-system-caret",
6521 &w32_use_visible_system_caret,
6522 doc: /* Flag to make the system caret visible.
6523 When this is non-nil, Emacs will indicate the position of point by
6524 using the system caret instead of drawing its own cursor. Some screen
6525 reader software does not track the system cursor properly when it is
6526 invisible, and gets confused by Emacs drawing its own cursor, so this
6527 variable is initialized to t when Emacs detects that screen reader
6528 software is running as it starts up.
6530 When this variable is set, other variables affecting the appearance of
6531 the cursor have no effect. */);
6533 /* Initialize w32_use_visible_system_caret based on whether a screen
6534 reader is in use. */
6535 if (!SystemParametersInfo (SPI_GETSCREENREADER, 0,
6536 &w32_use_visible_system_caret, 0))
6537 w32_use_visible_system_caret = 0;
6539 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,
6540 doc: /* If not nil, Emacs uses toolkit scroll bars. */);
6541 Vx_toolkit_scroll_bars = Qt;
6543 staticpro (&last_mouse_motion_frame);
6544 last_mouse_motion_frame = Qnil;
6547 /* arch-tag: 5fa70624-ab86-499c-8a85-473958ee4646
6548 (do not change this comment) */