[HAVE_TERMCAP_H]: Include <termcap.h>.
[emacs.git] / src / w32term.c
blobba2b14d19ff5c9bb71772c791960ec1799883bc8
1 /* Implementation of GUI terminal on the Microsoft W32 API.
2 Copyright (C) 1989, 93, 94, 95, 96, 1997, 1998, 1999, 2000
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"
39 #include <ctype.h>
40 #include <errno.h>
41 #include <setjmp.h>
42 #include <sys/stat.h>
44 #include "frame.h"
45 #include "dispextern.h"
46 #include "fontset.h"
47 #include "termhooks.h"
48 #include "termopts.h"
49 #include "termchar.h"
50 #include "gnu.h"
51 #include "disptab.h"
52 #include "buffer.h"
53 #include "window.h"
54 #include "keyboard.h"
55 #include "intervals.h"
56 #include "composite.h"
57 #include "coding.h"
59 #undef min
60 #undef max
61 #define min(x, y) (((x) < (y)) ? (x) : (y))
62 #define max(x, y) (((x) > (y)) ? (x) : (y))
64 #define abs(x) ((x) < 0 ? -(x) : (x))
66 #define BETWEEN(X, LOWER, UPPER) ((X) >= (LOWER) && (X) < (UPPER))
69 /* Bitmaps for truncated lines. */
71 enum bitmap_type
73 NO_BITMAP,
74 LEFT_TRUNCATION_BITMAP,
75 RIGHT_TRUNCATION_BITMAP,
76 OVERLAY_ARROW_BITMAP,
77 CONTINUED_LINE_BITMAP,
78 CONTINUATION_LINE_BITMAP,
79 ZV_LINE_BITMAP
82 enum w32_char_font_type
84 UNKNOWN_FONT,
85 ANSI_FONT,
86 UNICODE_FONT,
87 BDF_FONT
90 /* Bitmaps are all unsigned short, as Windows requires bitmap data to
91 be Word aligned. For some reason they are horizontally reflected
92 compared to how they appear on X, so changes in xterm.c should be
93 reflected here. */
95 /* Bitmap drawn to indicate lines not displaying text if
96 `indicate-empty-lines' is non-nil. */
98 #define zv_width 8
99 #define zv_height 8
100 static unsigned short zv_bits[] = {
101 0x00, 0x00, 0x78, 0x78, 0x78, 0x78, 0x00, 0x00};
102 static HBITMAP zv_bmp;
104 /* An arrow like this: `<-'. */
106 #define left_width 8
107 #define left_height 8
108 static unsigned short left_bits[] = {
109 0x18, 0x30, 0x60, 0xfc, 0xfc, 0x60, 0x30, 0x18};
110 static HBITMAP left_bmp;
112 /* Right truncation arrow bitmap `->'. */
114 #define right_width 8
115 #define right_height 8
116 static unsigned short right_bits[] = {
117 0x18, 0x0c, 0x06, 0x3f, 0x3f, 0x06, 0x0c, 0x18};
118 static HBITMAP right_bmp;
120 /* Marker for continued lines. */
122 #define continued_width 8
123 #define continued_height 8
124 static unsigned short continued_bits[] = {
125 0x3c, 0x3e, 0x03, 0x27, 0x3f, 0x3e, 0x3c, 0x3e};
126 static HBITMAP continued_bmp;
128 /* Marker for continuation lines. */
130 #define continuation_width 8
131 #define continuation_height 8
132 static unsigned short continuation_bits[] = {
133 0x3c, 0x7c, 0xc0, 0xe4, 0xfc, 0x7c, 0x3c, 0x7c};
134 static HBITMAP continuation_bmp;
136 /* Overlay arrow bitmap. */
138 #if 0
139 /* A bomb. */
140 #define ov_width 8
141 #define ov_height 8
142 static unsigned short ov_bits[] = {
143 0x0c, 0x10, 0x3c, 0x7e, 0x5e, 0x5e, 0x46, 0x3c};
144 #else
145 /* A triangular arrow. */
146 #define ov_width 8
147 #define ov_height 8
148 static unsigned short ov_bits[] = {
149 0xc0, 0xf0, 0xf8, 0xfc, 0xfc, 0xf8, 0xf0, 0xc0};
150 #endif
151 static HBITMAP ov_bmp;
153 extern Lisp_Object Qhelp_echo;
156 /* Non-zero means Emacs uses toolkit scroll bars. */
158 int x_toolkit_scroll_bars_p;
160 /* If a string, w32_read_socket generates an event to display that string.
161 (The display is done in read_char.) */
163 static Lisp_Object help_echo;
164 static Lisp_Object help_echo_object;
165 static int help_echo_pos;
167 /* Temporary variable for w32_read_socket. */
169 static Lisp_Object previous_help_echo;
171 /* Non-zero means that a HELP_EVENT has been generated since Emacs
172 start. */
174 static int any_help_event_p;
176 /* Non-zero means draw block and hollow cursor as wide as the glyph
177 under it. For example, if a block cursor is over a tab, it will be
178 drawn as wide as that tab on the display. */
180 int x_stretch_cursor_p;
182 extern unsigned int msh_mousewheel;
184 extern void free_frame_menubar ();
186 extern void w32_menu_display_help (HMENU menu, UINT menu_item, UINT flags);
188 extern int w32_codepage_for_font (char *fontname);
190 extern Lisp_Object Vwindow_system;
192 #define x_any_window_to_frame x_window_to_frame
193 #define x_top_window_to_frame x_window_to_frame
196 /* This is display since w32 does not support multiple ones. */
197 struct w32_display_info one_w32_display_info;
199 /* This is a list of cons cells, each of the form (NAME . FONT-LIST-CACHE),
200 one for each element of w32_display_list and in the same order.
201 NAME is the name of the frame.
202 FONT-LIST-CACHE records previous values returned by x-list-fonts. */
203 Lisp_Object w32_display_name_list;
205 /* Frame being updated by update_frame. This is declared in term.c.
206 This is set by update_begin and looked at by all the
207 w32 functions. It is zero while not inside an update.
208 In that case, the w32 functions assume that `SELECTED_FRAME ()'
209 is the frame to apply to. */
210 extern struct frame *updating_frame;
212 /* This is a frame waiting to be autoraised, within w32_read_socket. */
213 struct frame *pending_autoraise_frame;
215 /* Nominal cursor position -- where to draw output.
216 HPOS and VPOS are window relative glyph matrix coordinates.
217 X and Y are window relative pixel coordinates. */
219 struct cursor_pos output_cursor;
221 /* Flag to enable Unicode output in case users wish to use programs
222 like Twinbridge on '95 rather than installed system level support
223 for Far East languages. */
224 int w32_enable_unicode_output;
226 DWORD dwWindowsThreadId = 0;
227 HANDLE hWindowsThread = NULL;
228 DWORD dwMainThreadId = 0;
229 HANDLE hMainThread = NULL;
231 #ifndef SIF_ALL
232 /* These definitions are new with Windows 95. */
233 #define SIF_RANGE 0x0001
234 #define SIF_PAGE 0x0002
235 #define SIF_POS 0x0004
236 #define SIF_DISABLENOSCROLL 0x0008
237 #define SIF_TRACKPOS 0x0010
238 #define SIF_ALL (SIF_RANGE | SIF_PAGE | SIF_POS | SIF_TRACKPOS)
240 typedef struct tagSCROLLINFO
242 UINT cbSize;
243 UINT fMask;
244 int nMin;
245 int nMax;
246 UINT nPage;
247 int nPos;
248 int nTrackPos;
249 } SCROLLINFO, FAR *LPSCROLLINFO;
250 typedef SCROLLINFO CONST FAR *LPCSCROLLINFO;
251 #endif /* SIF_ALL */
253 /* Dynamic linking to new proportional scroll bar functions. */
254 int (PASCAL *pfnSetScrollInfo) (HWND hwnd, int fnBar, LPSCROLLINFO lpsi, BOOL fRedraw);
255 BOOL (PASCAL *pfnGetScrollInfo) (HWND hwnd, int fnBar, LPSCROLLINFO lpsi);
257 int vertical_scroll_bar_min_handle;
258 int vertical_scroll_bar_top_border;
259 int vertical_scroll_bar_bottom_border;
261 int last_scroll_bar_drag_pos;
263 /* Mouse movement. */
265 /* Where the mouse was last time we reported a mouse event. */
267 FRAME_PTR last_mouse_frame;
268 static RECT last_mouse_glyph;
269 static Lisp_Object last_mouse_press_frame;
271 Lisp_Object Vw32_num_mouse_buttons;
273 Lisp_Object Vw32_swap_mouse_buttons;
275 /* Control whether x_raise_frame also sets input focus. */
276 Lisp_Object Vw32_grab_focus_on_raise;
278 /* Control whether Caps Lock affects non-ascii characters. */
279 Lisp_Object Vw32_capslock_is_shiftlock;
281 /* Control whether right-alt and left-ctrl should be recognized as AltGr. */
282 Lisp_Object Vw32_recognize_altgr;
284 /* The scroll bar in which the last motion event occurred.
286 If the last motion event occurred in a scroll bar, we set this
287 so w32_mouse_position can know whether to report a scroll bar motion or
288 an ordinary motion.
290 If the last motion event didn't occur in a scroll bar, we set this
291 to Qnil, to tell w32_mouse_position to return an ordinary motion event. */
292 static Lisp_Object last_mouse_scroll_bar;
293 static int last_mouse_scroll_bar_pos;
295 /* This is a hack. We would really prefer that w32_mouse_position would
296 return the time associated with the position it returns, but there
297 doesn't seem to be any way to wrest the time-stamp from the server
298 along with the position query. So, we just keep track of the time
299 of the last movement we received, and return that in hopes that
300 it's somewhat accurate. */
302 static Time last_mouse_movement_time;
304 /* Incremented by w32_read_socket whenever it really tries to read
305 events. */
307 #ifdef __STDC__
308 static int volatile input_signal_count;
309 #else
310 static int input_signal_count;
311 #endif
313 extern Lisp_Object Vcommand_line_args, Vsystem_name;
315 extern Lisp_Object Qface, Qmouse_face;
317 extern int errno;
319 /* A mask of extra modifier bits to put into every keyboard char. */
321 extern int extra_keyboard_modifiers;
323 /* Enumeration for overriding/changing the face to use for drawing
324 glyphs in x_draw_glyphs. */
326 enum draw_glyphs_face
328 DRAW_NORMAL_TEXT,
329 DRAW_INVERSE_VIDEO,
330 DRAW_CURSOR,
331 DRAW_MOUSE_FACE,
332 DRAW_IMAGE_RAISED,
333 DRAW_IMAGE_SUNKEN
336 static void x_update_window_end P_ ((struct window *, int));
337 static void frame_to_window_pixel_xy P_ ((struct window *, int *, int *));
338 void w32_delete_display P_ ((struct w32_display_info *));
339 static int fast_find_position P_ ((struct window *, int, int *, int *,
340 int *, int *));
341 static void set_output_cursor P_ ((struct cursor_pos *));
342 static struct glyph *x_y_to_hpos_vpos P_ ((struct window *, int, int,
343 int *, int *, int *));
344 static void note_mode_line_highlight P_ ((struct window *, int, int));
345 static void x_check_font P_ ((struct frame *, XFontStruct *));
346 static void note_mouse_highlight P_ ((struct frame *, int, int));
347 static void note_tool_bar_highlight P_ ((struct frame *f, int, int));
348 static void w32_handle_tool_bar_click P_ ((struct frame *,
349 struct input_event *));
350 static void show_mouse_face P_ ((struct w32_display_info *,
351 enum draw_glyphs_face));
352 void clear_mouse_face P_ ((struct w32_display_info *));
354 void x_lower_frame P_ ((struct frame *));
355 void x_scroll_bar_clear P_ ((struct frame *));
356 void x_wm_set_size_hint P_ ((struct frame *, long, int));
357 void x_raise_frame P_ ((struct frame *));
358 void x_set_window_size P_ ((struct frame *, int, int, int));
359 void x_wm_set_window_state P_ ((struct frame *, int));
360 void x_wm_set_icon_pixmap P_ ((struct frame *, int));
361 void w32_initialize P_ ((void));
362 static void x_font_min_bounds P_ ((XFontStruct *, int *, int *));
363 int x_compute_min_glyph_bounds P_ ((struct frame *));
364 static void x_draw_phys_cursor_glyph P_ ((struct window *,
365 struct glyph_row *,
366 enum draw_glyphs_face));
367 static void x_update_end P_ ((struct frame *));
368 static void w32_frame_up_to_date P_ ((struct frame *));
369 static void w32_reassert_line_highlight P_ ((int, int));
370 static void x_change_line_highlight P_ ((int, int, int, int));
371 static void w32_set_terminal_modes P_ ((void));
372 static void w32_reset_terminal_modes P_ ((void));
373 static void w32_cursor_to P_ ((int, int, int, int));
374 static void x_write_glyphs P_ ((struct glyph *, int));
375 static void x_clear_end_of_line P_ ((int));
376 static void x_clear_frame P_ ((void));
377 static void x_clear_cursor P_ ((struct window *));
378 static void frame_highlight P_ ((struct frame *));
379 static void frame_unhighlight P_ ((struct frame *));
380 static void w32_new_focus_frame P_ ((struct w32_display_info *,
381 struct frame *));
382 static void w32_frame_rehighlight P_ ((struct frame *));
383 static void x_frame_rehighlight P_ ((struct w32_display_info *));
384 static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *));
385 static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int));
386 static int w32_intersect_rectangles P_ ((RECT *, RECT *, RECT *));
387 static void expose_frame P_ ((struct frame *, int, int, int, int));
388 static void expose_window_tree P_ ((struct window *, RECT *));
389 static void expose_window P_ ((struct window *, RECT *));
390 static void expose_area P_ ((struct window *, struct glyph_row *,
391 RECT *, enum glyph_row_area));
392 static void expose_line P_ ((struct window *, struct glyph_row *,
393 RECT *));
394 void x_update_cursor P_ ((struct frame *, int));
395 static void x_update_cursor_in_window_tree P_ ((struct window *, int));
396 static void x_update_window_cursor P_ ((struct window *, int));
397 static void x_erase_phys_cursor P_ ((struct window *));
398 void x_display_cursor P_ ((struct window *w, int, int, int, int, int));
399 void x_display_and_set_cursor P_ ((struct window *, int, int, int, int, int));
400 static void w32_draw_bitmap P_ ((struct window *, HDC hdc, struct glyph_row *,
401 enum bitmap_type));
402 static int x_phys_cursor_in_rect_p P_ ((struct window *, RECT *));
403 static void x_draw_row_bitmaps P_ ((struct window *, struct glyph_row *));
404 static void note_overwritten_text_cursor P_ ((struct window *, int, int));
405 static void w32_clip_to_row P_ ((struct window *, struct glyph_row *,
406 HDC, int));
408 static Lisp_Object Qvendor_specific_keysyms;
411 /***********************************************************************
412 Debugging
413 ***********************************************************************/
415 #if 0
417 /* This is a function useful for recording debugging information about
418 the sequence of occurrences in this file. */
420 struct record
422 char *locus;
423 int type;
426 struct record event_record[100];
428 int event_record_index;
430 record_event (locus, type)
431 char *locus;
432 int type;
434 if (event_record_index == sizeof (event_record) / sizeof (struct record))
435 event_record_index = 0;
437 event_record[event_record_index].locus = locus;
438 event_record[event_record_index].type = type;
439 event_record_index++;
442 #endif /* 0 */
445 void XChangeGC (void * ignore, XGCValues* gc, unsigned long mask,
446 XGCValues *xgcv)
448 if (mask & GCForeground)
449 gc->foreground = xgcv->foreground;
450 if (mask & GCBackground)
451 gc->background = xgcv->background;
452 if (mask & GCFont)
453 gc->font = xgcv->font;
456 XGCValues *XCreateGC (void * ignore, Window window, unsigned long mask,
457 XGCValues *xgcv)
459 XGCValues *gc = (XGCValues *) xmalloc (sizeof (XGCValues));
460 bzero (gc, sizeof (XGCValues));
462 XChangeGC (ignore, gc, mask, xgcv);
464 return gc;
467 void XGetGCValues (void* ignore, XGCValues *gc,
468 unsigned long mask, XGCValues *xgcv)
470 XChangeGC (ignore, xgcv, mask, gc);
473 void XTextExtents16 (XFontStruct *font, wchar_t *text, int nchars,
474 int *direction,int *font_ascent,
475 int *font_descent, XCharStruct *cs)
477 /* NTEMACS_TODO: Use GetTextMetrics to do this and inline it below. */
480 static void
481 w32_set_clip_rectangle (HDC hdc, RECT *rect)
483 if (rect)
485 HRGN clip_region = CreateRectRgnIndirect (rect);
486 SelectClipRgn (hdc, clip_region);
487 DeleteObject (clip_region);
489 else
490 SelectClipRgn (hdc, NULL);
494 /* Draw a hollow rectangle at the specified position. */
495 void
496 w32_draw_rectangle (HDC hdc, XGCValues *gc, int x, int y,
497 int width, int height)
499 HBRUSH hb, oldhb;
500 HPEN hp, oldhp;
502 hb = CreateSolidBrush (gc->background);
503 hp = CreatePen (PS_SOLID, 0, gc->foreground);
504 oldhb = SelectObject (hdc, hb);
505 oldhp = SelectObject (hdc, hp);
507 Rectangle (hdc, x, y, x + width, y + height);
509 SelectObject (hdc, oldhb);
510 SelectObject (hdc, oldhp);
511 DeleteObject (hb);
512 DeleteObject (hp);
515 /* Draw a filled rectangle at the specified position. */
516 void
517 w32_fill_rect (f, hdc, pix, lprect)
518 FRAME_PTR f;
519 HDC hdc;
520 COLORREF pix;
521 RECT * lprect;
523 HBRUSH hb;
524 RECT rect;
526 hb = CreateSolidBrush (pix);
527 FillRect (hdc, lprect, hb);
528 DeleteObject (hb);
531 void
532 w32_clear_window (f)
533 FRAME_PTR f;
535 RECT rect;
536 HDC hdc = get_frame_dc (f);
538 GetClientRect (FRAME_W32_WINDOW (f), &rect);
539 w32_clear_rect (f, hdc, &rect);
540 release_frame_dc (f, hdc);
544 /***********************************************************************
545 Starting and ending an update
546 ***********************************************************************/
548 /* Start an update of frame F. This function is installed as a hook
549 for update_begin, i.e. it is called when update_begin is called.
550 This function is called prior to calls to x_update_window_begin for
551 each window being updated. Currently, there is nothing to do here
552 because all interesting stuff is done on a window basis. */
554 static void
555 x_update_begin (f)
556 struct frame *f;
558 /* Nothing to do. We have to do something though, otherwise the
559 function gets optimized away and the hook is no longer valid. */
560 struct frame *cf = f;
564 /* Start update of window W. Set the global variable updated_window
565 to the window being updated and set output_cursor to the cursor
566 position of W. */
568 static void
569 x_update_window_begin (w)
570 struct window *w;
572 struct frame *f = XFRAME (WINDOW_FRAME (w));
573 struct w32_display_info *display_info = FRAME_W32_DISPLAY_INFO (f);
575 updated_window = w;
576 set_output_cursor (&w->cursor);
578 BLOCK_INPUT;
580 /* Regenerate display palette before drawing if list of requested
581 colors has changed. */
582 if (display_info->regen_palette)
584 w32_regenerate_palette (f);
585 display_info->regen_palette = FALSE;
588 if (f == display_info->mouse_face_mouse_frame)
590 /* Don't do highlighting for mouse motion during the update. */
591 display_info->mouse_face_defer = 1;
593 /* If F needs to be redrawn, simply forget about any prior mouse
594 highlighting. */
595 if (FRAME_GARBAGED_P (f))
596 display_info->mouse_face_window = Qnil;
598 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
599 their mouse_face_p flag set, which means that they are always
600 unequal to rows in a desired matrix which never have that
601 flag set. So, rows containing mouse-face glyphs are never
602 scrolled, and we don't have to switch the mouse highlight off
603 here to prevent it from being scrolled. */
605 /* Can we tell that this update does not affect the window
606 where the mouse highlight is? If so, no need to turn off.
607 Likewise, don't do anything if the frame is garbaged;
608 in that case, the frame's current matrix that we would use
609 is all wrong, and we will redisplay that line anyway. */
610 if (!NILP (display_info->mouse_face_window)
611 && w == XWINDOW (display_info->mouse_face_window))
613 int i;
615 for (i = 0; i < w->desired_matrix->nrows; ++i)
616 if (MATRIX_ROW_ENABLED_P (w->desired_matrix, i))
617 break;
619 if (i < w->desired_matrix->nrows)
620 clear_mouse_face (display_info);
622 #endif /* 0 */
625 UNBLOCK_INPUT;
629 /* Draw a vertical window border to the right of window W if W doesn't
630 have vertical scroll bars. */
632 static void
633 x_draw_vertical_border (w)
634 struct window *w;
636 struct frame *f = XFRAME (WINDOW_FRAME (w));
638 /* Redraw borders between horizontally adjacent windows. Don't
639 do it for frames with vertical scroll bars because either the
640 right scroll bar of a window, or the left scroll bar of its
641 neighbor will suffice as a border. */
642 if (!WINDOW_RIGHTMOST_P (w)
643 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
645 RECT r;
646 HDC hdc;
648 window_box_edges (w, -1, &r.left, &r.top, &r.right, &r.bottom);
649 r.left = r.right + FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f);
650 r.right = r.left + 1;
651 r.bottom -= 1;
653 hdc = get_frame_dc (f);
654 w32_fill_rect (f, hdc, FRAME_FOREGROUND_PIXEL (f), r);
655 release_frame_dc (f, hdc);
660 /* End update of window W (which is equal to updated_window).
662 Draw vertical borders between horizontally adjacent windows, and
663 display W's cursor if CURSOR_ON_P is non-zero.
665 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
666 glyphs in mouse-face were overwritten. In that case we have to
667 make sure that the mouse-highlight is properly redrawn.
669 W may be a menu bar pseudo-window in case we don't have X toolkit
670 support. Such windows don't have a cursor, so don't display it
671 here. */
673 static void
674 x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p)
675 struct window *w;
676 int cursor_on_p, mouse_face_overwritten_p;
678 if (!w->pseudo_window_p)
680 struct w32_display_info *dpyinfo
681 = FRAME_W32_DISPLAY_INFO (XFRAME (w->frame));
683 BLOCK_INPUT;
685 /* If a row with mouse-face was overwritten, arrange for
686 XTframe_up_to_date to redisplay the mouse highlight. */
687 if (mouse_face_overwritten_p)
689 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
690 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
691 dpyinfo->mouse_face_window = Qnil;
694 if (cursor_on_p)
695 x_display_and_set_cursor (w, 1, output_cursor.hpos,
696 output_cursor.vpos,
697 output_cursor.x, output_cursor.y);
698 x_draw_vertical_border (w);
699 UNBLOCK_INPUT;
702 updated_window = NULL;
706 /* End update of frame F. This function is installed as a hook in
707 update_end. */
709 static void
710 x_update_end (f)
711 struct frame *f;
713 /* Mouse highlight may be displayed again. */
714 FRAME_W32_DISPLAY_INFO (f)->mouse_face_defer = 0;
718 /* This function is called from various places in xdisp.c whenever a
719 complete update has been performed. The global variable
720 updated_window is not available here. */
722 static void
723 w32_frame_up_to_date (f)
724 struct frame *f;
726 if (FRAME_W32_P (f))
728 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
729 if (dpyinfo->mouse_face_deferred_gc
730 || f == dpyinfo->mouse_face_mouse_frame)
732 BLOCK_INPUT;
733 if (dpyinfo->mouse_face_mouse_frame)
734 note_mouse_highlight (dpyinfo->mouse_face_mouse_frame,
735 dpyinfo->mouse_face_mouse_x,
736 dpyinfo->mouse_face_mouse_y);
737 dpyinfo->mouse_face_deferred_gc = 0;
738 UNBLOCK_INPUT;
744 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
745 arrow bitmaps, or clear the areas where they would be displayed
746 before DESIRED_ROW is made current. The window being updated is
747 found in updated_window. This function It is called from
748 update_window_line only if it is known that there are differences
749 between bitmaps to be drawn between current row and DESIRED_ROW. */
751 static void
752 x_after_update_window_line (desired_row)
753 struct glyph_row *desired_row;
755 struct window *w = updated_window;
757 xassert (w);
759 if (!desired_row->mode_line_p && !w->pseudo_window_p)
761 BLOCK_INPUT;
762 x_draw_row_bitmaps (w, desired_row);
764 /* When a window has disappeared, make sure that no rest of
765 full-width rows stays visible in the internal border. */
766 if (windows_or_buffers_changed)
768 struct frame *f = XFRAME (w->frame);
769 int width = FRAME_INTERNAL_BORDER_WIDTH (f);
770 int height = desired_row->visible_height;
771 int x = (window_box_right (w, -1)
772 + FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f));
773 int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
774 HDC hdc = get_frame_dc (f);
776 w32_clear_area (f, hdc, x, y, width, height);
777 release_frame_dc (f, hdc);
780 UNBLOCK_INPUT;
785 /* Draw the bitmap WHICH in one of the areas to the left or right of
786 window W. ROW is the glyph row for which to display the bitmap; it
787 determines the vertical position at which the bitmap has to be
788 drawn. */
790 static void
791 w32_draw_bitmap (w, hdc, row, which)
792 struct window *w;
793 HDC hdc;
794 struct glyph_row *row;
795 enum bitmap_type which;
797 struct frame *f = XFRAME (WINDOW_FRAME (w));
798 Window window = FRAME_W32_WINDOW (f);
799 HDC compat_hdc;
800 int x, y, wd, h, dy;
801 HBITMAP pixmap;
802 HBRUSH fg_brush, orig_brush;
803 HANDLE horig_obj;
804 struct face *face;
806 /* Must clip because of partially visible lines. */
807 w32_clip_to_row (w, row, hdc, 1);
809 switch (which)
811 case LEFT_TRUNCATION_BITMAP:
812 wd = left_width;
813 h = left_height;
814 pixmap = left_bmp;
815 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
816 - wd
817 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
818 break;
820 case OVERLAY_ARROW_BITMAP:
821 wd = ov_width;
822 h = ov_height;
823 pixmap = ov_bmp;
824 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
825 - wd
826 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
827 break;
829 case RIGHT_TRUNCATION_BITMAP:
830 wd = right_width;
831 h = right_height;
832 pixmap = right_bmp;
833 x = window_box_right (w, -1);
834 x += (FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f) - wd) / 2;
835 break;
837 case CONTINUED_LINE_BITMAP:
838 wd = continued_width;
839 h = continued_height;
840 pixmap = continued_bmp;
841 x = window_box_right (w, -1);
842 x += (FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f) - wd) / 2;
843 break;
845 case CONTINUATION_LINE_BITMAP:
846 wd = continuation_width;
847 h = continuation_height;
848 pixmap = continuation_bmp;
849 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
850 - wd
851 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
852 break;
854 case ZV_LINE_BITMAP:
855 wd = zv_width;
856 h = zv_height;
857 pixmap = zv_bmp;
858 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
859 - wd
860 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
861 break;
863 default:
864 abort ();
867 /* Convert to frame coordinates. Set dy to the offset in the row to
868 start drawing the bitmap. */
869 y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
870 dy = (row->height - h) / 2;
872 /* Draw the bitmap. */
873 face = FACE_FROM_ID (f, BITMAP_AREA_FACE_ID);
875 compat_hdc = CreateCompatibleDC (hdc);
876 SaveDC (hdc);
877 fg_brush = CreateSolidBrush (FRAME_FOREGROUND_PIXEL (f));
878 orig_brush = SelectObject (hdc, fg_brush);
879 horig_obj = SelectObject (compat_hdc, pixmap);
880 SetTextColor (hdc, FRAME_BACKGROUND_PIXEL (f));
881 SetBkColor (hdc, FRAME_FOREGROUND_PIXEL (f));
882 #if 0 /* From w32bdf.c (which is from Meadow). */
883 BitBlt (hdc, x, y + dy, wd, h, compat_hdc, 0, 0, SRCCOPY);
884 #else
885 BitBlt (hdc, x, y + dy, wd, h, compat_hdc, 0, 0, 0xB8074A);
886 #endif
887 SelectObject (compat_hdc, horig_obj);
888 SelectObject (hdc, orig_brush);
889 DeleteObject (fg_brush);
890 DeleteDC (compat_hdc);
891 RestoreDC (hdc, -1);
895 /* Draw flags bitmaps for glyph row ROW on window W. Call this
896 function with input blocked. */
898 static void
899 x_draw_row_bitmaps (w, row)
900 struct window *w;
901 struct glyph_row *row;
903 struct frame *f = XFRAME (w->frame);
904 enum bitmap_type bitmap;
905 struct face *face;
906 int header_line_height = -1;
907 HDC hdc = get_frame_dc (f);
909 xassert (interrupt_input_blocked);
911 /* If row is completely invisible, because of vscrolling, we
912 don't have to draw anything. */
913 if (row->visible_height <= 0)
914 return;
916 face = FACE_FROM_ID (f, BITMAP_AREA_FACE_ID);
917 PREPARE_FACE_FOR_DISPLAY (f, face);
919 /* Decide which bitmap to draw at the left side. */
920 if (row->overlay_arrow_p)
921 bitmap = OVERLAY_ARROW_BITMAP;
922 else if (row->truncated_on_left_p)
923 bitmap = LEFT_TRUNCATION_BITMAP;
924 else if (MATRIX_ROW_CONTINUATION_LINE_P (row))
925 bitmap = CONTINUATION_LINE_BITMAP;
926 else if (row->indicate_empty_line_p)
927 bitmap = ZV_LINE_BITMAP;
928 else
929 bitmap = NO_BITMAP;
931 /* Clear flags area if no bitmap to draw or if bitmap doesn't fill
932 the flags area. */
933 if (bitmap == NO_BITMAP
934 || FRAME_FLAGS_BITMAP_WIDTH (f) < FRAME_X_LEFT_FLAGS_AREA_WIDTH (f)
935 || row->height > FRAME_FLAGS_BITMAP_HEIGHT (f))
937 /* If W has a vertical border to its left, don't draw over it. */
938 int border = ((XFASTINT (w->left) > 0
939 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
940 ? 1 : 0);
941 int left = window_box_left (w, -1);
943 if (header_line_height < 0)
944 header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
946 w32_fill_area (f, hdc, face->background,
947 left - FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) + border,
948 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
949 row->y)),
950 FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - border,
951 row->visible_height);
954 /* Draw the left bitmap. */
955 if (bitmap != NO_BITMAP)
956 w32_draw_bitmap (w, hdc, row, bitmap);
958 /* Decide which bitmap to draw at the right side. */
959 if (row->truncated_on_right_p)
960 bitmap = RIGHT_TRUNCATION_BITMAP;
961 else if (row->continued_p)
962 bitmap = CONTINUED_LINE_BITMAP;
963 else
964 bitmap = NO_BITMAP;
966 /* Clear flags area if no bitmap to draw of if bitmap doesn't fill
967 the flags area. */
968 if (bitmap == NO_BITMAP
969 || FRAME_FLAGS_BITMAP_WIDTH (f) < FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f)
970 || row->height > FRAME_FLAGS_BITMAP_HEIGHT (f))
972 int right = window_box_right (w, -1);
974 if (header_line_height < 0)
975 header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
977 w32_fill_area (f, hdc, face->background,
978 right,
979 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
980 row->y)),
981 FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f),
982 row->visible_height);
985 /* Draw the right bitmap. */
986 if (bitmap != NO_BITMAP)
987 w32_draw_bitmap (w, hdc, row, bitmap);
989 release_frame_dc (f, hdc);
993 /***********************************************************************
994 Line Highlighting
995 ***********************************************************************/
997 /* External interface to control of standout mode. Not used for W32
998 frames. Aborts when called. */
1000 static void
1001 w32_reassert_line_highlight (new, vpos)
1002 int new, vpos;
1004 abort ();
1007 /* Call this when about to modify line at position VPOS and change
1008 whether it is highlighted. Not used for W32 frames. Aborts when
1009 called. */
1011 static void
1012 x_change_line_highlight (new_highlight, vpos, y, first_unused_hpos)
1013 int new_highlight, vpos, y, first_unused_hpos;
1015 abort ();
1018 /* This is called when starting Emacs and when restarting after
1019 suspend. When starting Emacs, no window is mapped. And nothing
1020 must be done to Emacs's own window if it is suspended (though that
1021 rarely happens). */
1023 static void
1024 w32_set_terminal_modes (void)
1028 /* This is called when exiting or suspending Emacs. Exiting will make
1029 the W32 windows go away, and suspending requires no action. */
1031 static void
1032 w32_reset_terminal_modes (void)
1038 /***********************************************************************
1039 Output Cursor
1040 ***********************************************************************/
1042 /* Set the global variable output_cursor to CURSOR. All cursor
1043 positions are relative to updated_window. */
1045 static void
1046 set_output_cursor (cursor)
1047 struct cursor_pos *cursor;
1049 output_cursor.hpos = cursor->hpos;
1050 output_cursor.vpos = cursor->vpos;
1051 output_cursor.x = cursor->x;
1052 output_cursor.y = cursor->y;
1056 /* Set a nominal cursor position.
1058 HPOS and VPOS are column/row positions in a window glyph matrix. X
1059 and Y are window text area relative pixel positions.
1061 If this is done during an update, updated_window will contain the
1062 window that is being updated and the position is the future output
1063 cursor position for that window. If updated_window is null, use
1064 selected_window and display the cursor at the given position. */
1066 static void
1067 w32_cursor_to (vpos, hpos, y, x)
1068 int vpos, hpos, y, x;
1070 struct window *w;
1072 /* If updated_window is not set, work on selected_window. */
1073 if (updated_window)
1074 w = updated_window;
1075 else
1076 w = XWINDOW (selected_window);
1078 /* Set the output cursor. */
1079 output_cursor.hpos = hpos;
1080 output_cursor.vpos = vpos;
1081 output_cursor.x = x;
1082 output_cursor.y = y;
1084 /* If not called as part of an update, really display the cursor.
1085 This will also set the cursor position of W. */
1086 if (updated_window == NULL)
1088 BLOCK_INPUT;
1089 x_display_cursor (w, 1, hpos, vpos, x, y);
1090 UNBLOCK_INPUT;
1096 /***********************************************************************
1097 Display Iterator
1098 ***********************************************************************/
1100 /* Function prototypes of this page. */
1102 static struct face *x_get_glyph_face_and_encoding P_ ((struct frame *,
1103 struct glyph *,
1104 wchar_t *,
1105 int *));
1106 static struct face *x_get_char_face_and_encoding P_ ((struct frame *, int,
1107 int, wchar_t *, int));
1108 static XCharStruct *w32_per_char_metric P_ ((HDC hdc, XFontStruct *,
1109 wchar_t *,
1110 enum w32_char_font_type));
1111 static enum w32_char_font_type
1112 w32_encode_char P_ ((int, wchar_t *, struct font_info *, int *));
1113 static void x_append_glyph P_ ((struct it *));
1114 static void x_append_composite_glyph P_ ((struct it *));
1115 static void x_append_stretch_glyph P_ ((struct it *it, Lisp_Object,
1116 int, int, double));
1117 static void x_produce_glyphs P_ ((struct it *));
1118 static void x_produce_image_glyph P_ ((struct it *it));
1121 /* Dealing with bits of wchar_t as if they were an XChar2B. */
1122 #define BUILD_WCHAR_T(byte1, byte2) \
1123 ((wchar_t)((((byte1) & 0x00ff) << 8) | ((byte2) & 0x00ff)))
1126 #define BYTE1(ch) \
1127 (((ch) & 0xff00) >> 8)
1129 #define BYTE2(ch) \
1130 ((ch) & 0x00ff)
1133 /* NTEMACS_TODO: Add support for bdf fonts back in. */
1135 /* Get metrics of character CHAR2B in FONT. Value is always non-null.
1136 If CHAR2B is not contained in FONT, the font's default character
1137 metric is returned. */
1139 static XCharStruct *
1140 w32_per_char_metric (hdc, font, char2b, font_type)
1141 HDC hdc;
1142 XFontStruct *font;
1143 wchar_t *char2b;
1144 enum w32_char_font_type font_type;
1146 /* The result metric information. */
1147 XCharStruct *pcm;
1148 ABC char_widths;
1149 SIZE sz;
1150 BOOL retval;
1152 xassert (font && char2b);
1154 if (font_type == UNKNOWN_FONT)
1156 if (font->bdf)
1157 font_type = BDF_FONT;
1158 else if (!w32_enable_unicode_output)
1159 font_type = ANSI_FONT;
1160 else
1161 font_type = UNICODE_FONT; /* NTEMACS_TODO: Need encoding? */
1164 pcm = (XCharStruct *) xmalloc (sizeof (XCharStruct));
1166 if (font->hfont)
1167 SelectObject (hdc, font->hfont);
1169 if (font_type == UNICODE_FONT)
1170 retval = GetCharABCWidthsW (hdc, *char2b, *char2b, &char_widths);
1171 else if (font_type == ANSI_FONT)
1172 retval = GetCharABCWidthsA (hdc, *char2b, *char2b, &char_widths);
1174 if (retval)
1176 pcm->width = char_widths.abcA + char_widths.abcB + char_widths.abcC;
1177 pcm->lbearing = char_widths.abcA;
1178 pcm->rbearing = pcm->width - char_widths.abcC;
1180 else
1182 /* Windows 9x does not implement GetCharABCWidthsW, so if that
1183 failed, try GetTextExtentPoint32W, which is implemented and
1184 at least gives us some of the info we are after (total
1185 character width). */
1186 if (font_type == UNICODE_FONT)
1187 retval = GetTextExtentPoint32W (hdc, char2b, 1, &sz);
1189 if (retval)
1191 pcm->width = sz.cx;
1192 pcm->rbearing = sz.cx;
1193 pcm->lbearing = 0;
1195 else
1197 xfree (pcm);
1198 return NULL;
1202 pcm->ascent = FONT_BASE (font);
1203 pcm->descent = FONT_DESCENT (font);
1205 if (pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0)
1207 xfree (pcm);
1208 pcm = NULL;
1211 return pcm;
1215 /* Determine if a font is double byte. */
1216 int w32_font_is_double_byte (XFontStruct *font)
1218 return font->double_byte_p;
1222 /* Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
1223 the two-byte form of C. Encoding is returned in *CHAR2B. */
1225 static INLINE enum w32_char_font_type
1226 w32_encode_char (c, char2b, font_info, two_byte_p)
1227 int c;
1228 wchar_t *char2b;
1229 struct font_info *font_info;
1230 int * two_byte_p;
1232 int charset = CHAR_CHARSET (c);
1233 int codepage;
1234 int unicode_p = 0;
1236 XFontStruct *font = font_info->font;
1238 xassert(two_byte_p);
1240 *two_byte_p = w32_font_is_double_byte (font);
1242 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
1243 This may be either a program in a special encoder language or a
1244 fixed encoding. */
1245 if (font_info->font_encoder)
1247 /* It's a program. */
1248 struct ccl_program *ccl = font_info->font_encoder;
1250 if (CHARSET_DIMENSION (charset) == 1)
1252 ccl->reg[0] = charset;
1253 ccl->reg[1] = BYTE2 (*char2b);
1255 else
1257 ccl->reg[0] = charset;
1258 ccl->reg[1] = BYTE1 (*char2b);
1259 ccl->reg[2] = BYTE2 (*char2b);
1262 ccl_driver (ccl, NULL, NULL, 0, 0, NULL);
1264 /* We assume that MSBs are appropriately set/reset by CCL
1265 program. */
1266 if (!*two_byte_p) /* 1-byte font */
1267 *char2b = BUILD_WCHAR_T (0, ccl->reg[1]);
1268 else
1269 *char2b = BUILD_WCHAR_T (ccl->reg[1], ccl->reg[2]);
1271 else if (font_info->encoding[charset])
1273 /* Fixed encoding scheme. See fontset.h for the meaning of the
1274 encoding numbers. */
1275 int enc = font_info->encoding[charset];
1277 if ((enc == 1 || enc == 2)
1278 && CHARSET_DIMENSION (charset) == 2)
1279 *char2b = BUILD_WCHAR_T (BYTE1 (*char2b) | 0x80, BYTE2 (*char2b));
1281 if (enc == 1 || enc == 3
1282 || (enc == 4 && CHARSET_DIMENSION (charset) == 1))
1283 *char2b = BUILD_WCHAR_T (BYTE1 (*char2b), BYTE2 (*char2b) | 0x80);
1284 else if (enc == 4)
1286 int sjis1, sjis2;
1288 ENCODE_SJIS (BYTE1 (*char2b), BYTE2 (*char2b),
1289 sjis1, sjis2);
1290 *char2b = BUILD_WCHAR_T (sjis1, sjis2);
1293 codepage = w32_codepage_for_font (font_info->name);
1295 /* If charset is not ASCII or Latin-1, may need to move it into
1296 Unicode space. */
1297 if ( font && !font->bdf && w32_use_unicode_for_codepage (codepage)
1298 && charset != CHARSET_ASCII && charset != charset_latin_iso8859_1)
1300 char temp[3];
1301 temp[0] = BYTE1 (*char2b);
1302 temp[1] = BYTE2 (*char2b);
1303 temp[2] = '\0';
1304 if (temp[0])
1305 MultiByteToWideChar (codepage, 0, temp, 2, char2b, 1);
1306 else
1307 MultiByteToWideChar (codepage, 0, temp+1, 1, char2b, 1);
1308 unicode_p = 1;
1309 *two_byte_p = 1;
1311 if (!font)
1312 return UNKNOWN_FONT;
1313 else if (font->bdf)
1314 return BDF_FONT;
1315 else if (unicode_p)
1316 return UNICODE_FONT;
1317 else
1318 return ANSI_FONT;
1322 /* Get face and two-byte form of character C in face FACE_ID on frame
1323 F. The encoding of C is returned in *CHAR2B. MULTIBYTE_P non-zero
1324 means we want to display multibyte text. Value is a pointer to a
1325 realized face that is ready for display. */
1327 static INLINE struct face *
1328 x_get_char_face_and_encoding (f, c, face_id, char2b, multibyte_p)
1329 struct frame *f;
1330 int c, face_id;
1331 wchar_t *char2b;
1332 int multibyte_p;
1334 struct face *face = FACE_FROM_ID (f, face_id);
1336 if (!multibyte_p)
1338 /* Unibyte case. We don't have to encode, but we have to make
1339 sure to use a face suitable for unibyte. */
1340 *char2b = BUILD_WCHAR_T (0, c);
1341 face_id = FACE_FOR_CHAR (f, face, c);
1342 face = FACE_FROM_ID (f, face_id);
1344 else if (c < 128 && face_id < BASIC_FACE_ID_SENTINEL)
1346 /* Case of ASCII in a face known to fit ASCII. */
1347 *char2b = BUILD_WCHAR_T (0, c);
1349 else
1351 int c1, c2, charset;
1353 /* Split characters into bytes. If c2 is -1 afterwards, C is
1354 really a one-byte character so that byte1 is zero. */
1355 SPLIT_CHAR (c, charset, c1, c2);
1356 if (c2 > 0)
1357 *char2b = BUILD_WCHAR_T (c1, c2);
1358 else
1359 *char2b = BUILD_WCHAR_T (0, c1);
1361 /* Maybe encode the character in *CHAR2B. */
1362 if (face->font != NULL)
1364 struct font_info *font_info
1365 = FONT_INFO_FROM_ID (f, face->font_info_id);
1366 if (font_info)
1367 w32_encode_char (c, char2b, font_info, &multibyte_p);
1371 /* Make sure X resources of the face are allocated. */
1372 xassert (face != NULL);
1373 PREPARE_FACE_FOR_DISPLAY (f, face);
1375 return face;
1379 /* Get face and two-byte form of character glyph GLYPH on frame F.
1380 The encoding of GLYPH->u.ch is returned in *CHAR2B. Value is
1381 a pointer to a realized face that is ready for display. */
1383 static INLINE struct face *
1384 x_get_glyph_face_and_encoding (f, glyph, char2b, two_byte_p)
1385 struct frame *f;
1386 struct glyph *glyph;
1387 wchar_t *char2b;
1388 int *two_byte_p;
1390 struct face *face;
1391 int dummy = 0;
1393 xassert (glyph->type == CHAR_GLYPH);
1394 face = FACE_FROM_ID (f, glyph->face_id);
1396 if (two_byte_p)
1397 *two_byte_p = 0;
1398 else
1399 two_byte_p = &dummy;
1401 if (!glyph->multibyte_p)
1403 /* Unibyte case. We don't have to encode, but we have to make
1404 sure to use a face suitable for unibyte. */
1405 *char2b = BUILD_WCHAR_T (0, glyph->u.ch);
1407 else if (glyph->u.ch < 128
1408 && glyph->face_id < BASIC_FACE_ID_SENTINEL)
1410 /* Case of ASCII in a face known to fit ASCII. */
1411 *char2b = BUILD_WCHAR_T (0, glyph->u.ch);
1413 else
1415 int c1, c2, charset;
1417 /* Split characters into bytes. If c2 is -1 afterwards, C is
1418 really a one-byte character so that byte1 is zero. */
1419 SPLIT_CHAR (glyph->u.ch, charset, c1, c2);
1420 if (c2 > 0)
1421 *char2b = BUILD_WCHAR_T (c1, c2);
1422 else
1423 *char2b = BUILD_WCHAR_T (0, c1);
1425 /* Maybe encode the character in *CHAR2B. */
1426 if (charset != CHARSET_ASCII)
1428 struct font_info *font_info
1429 = FONT_INFO_FROM_ID (f, face->font_info_id);
1430 if (font_info)
1432 glyph->w32_font_type
1433 = w32_encode_char (glyph->u.ch, char2b, font_info, two_byte_p);
1438 /* Make sure X resources of the face are allocated. */
1439 xassert (face != NULL);
1440 PREPARE_FACE_FOR_DISPLAY (f, face);
1441 return face;
1445 /* Store one glyph for IT->char_to_display in IT->glyph_row.
1446 Called from x_produce_glyphs when IT->glyph_row is non-null. */
1448 static INLINE void
1449 x_append_glyph (it)
1450 struct it *it;
1452 struct glyph *glyph;
1453 enum glyph_row_area area = it->area;
1455 xassert (it->glyph_row);
1456 xassert (it->char_to_display != '\n' && it->char_to_display != '\t');
1458 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1459 if (glyph < it->glyph_row->glyphs[area + 1])
1461 glyph->charpos = CHARPOS (it->position);
1462 glyph->object = it->object;
1463 glyph->pixel_width = it->pixel_width;
1464 glyph->voffset = it->voffset;
1465 glyph->type = CHAR_GLYPH;
1466 glyph->multibyte_p = it->multibyte_p;
1467 glyph->left_box_line_p = it->start_of_box_run_p;
1468 glyph->right_box_line_p = it->end_of_box_run_p;
1469 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
1470 || it->phys_descent > it->descent);
1471 glyph->padding_p = 0;
1472 glyph->glyph_not_available_p = it->glyph_not_available_p;
1473 glyph->face_id = it->face_id;
1474 glyph->u.ch = it->char_to_display;
1475 glyph->w32_font_type = UNKNOWN_FONT;
1476 ++it->glyph_row->used[area];
1480 /* Store one glyph for the composition IT->cmp_id in IT->glyph_row.
1481 Called from x_produce_glyphs when IT->glyph_row is non-null. */
1483 static INLINE void
1484 x_append_composite_glyph (it)
1485 struct it *it;
1487 struct glyph *glyph;
1488 enum glyph_row_area area = it->area;
1490 xassert (it->glyph_row);
1492 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1493 if (glyph < it->glyph_row->glyphs[area + 1])
1495 glyph->charpos = CHARPOS (it->position);
1496 glyph->object = it->object;
1497 glyph->pixel_width = it->pixel_width;
1498 glyph->voffset = it->voffset;
1499 glyph->type = COMPOSITE_GLYPH;
1500 glyph->multibyte_p = it->multibyte_p;
1501 glyph->left_box_line_p = it->start_of_box_run_p;
1502 glyph->right_box_line_p = it->end_of_box_run_p;
1503 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
1504 || it->phys_descent > it->descent);
1505 glyph->padding_p = 0;
1506 glyph->glyph_not_available_p = 0;
1507 glyph->face_id = it->face_id;
1508 glyph->u.cmp_id = it->cmp_id;
1509 glyph->w32_font_type = UNKNOWN_FONT;
1510 ++it->glyph_row->used[area];
1515 /* Change IT->ascent and IT->height according to the setting of
1516 IT->voffset. */
1518 static INLINE void
1519 take_vertical_position_into_account (it)
1520 struct it *it;
1522 if (it->voffset)
1524 if (it->voffset < 0)
1525 /* Increase the ascent so that we can display the text higher
1526 in the line. */
1527 it->ascent += abs (it->voffset);
1528 else
1529 /* Increase the descent so that we can display the text lower
1530 in the line. */
1531 it->descent += it->voffset;
1536 /* Produce glyphs/get display metrics for the image IT is loaded with.
1537 See the description of struct display_iterator in dispextern.h for
1538 an overview of struct display_iterator. */
1540 static void
1541 x_produce_image_glyph (it)
1542 struct it *it;
1544 struct image *img;
1545 struct face *face;
1547 xassert (it->what == IT_IMAGE);
1549 face = FACE_FROM_ID (it->f, it->face_id);
1550 img = IMAGE_FROM_ID (it->f, it->image_id);
1551 xassert (img);
1553 /* Make sure X resources of the face and image are loaded. */
1554 PREPARE_FACE_FOR_DISPLAY (it->f, face);
1555 prepare_image_for_display (it->f, img);
1557 it->ascent = it->phys_ascent = image_ascent (img, face);
1558 it->descent = it->phys_descent = img->height + 2 * img->margin - it->ascent;
1559 it->pixel_width = img->width + 2 * img->margin;
1561 it->nglyphs = 1;
1563 if (face->box != FACE_NO_BOX)
1565 it->ascent += face->box_line_width;
1566 it->descent += face->box_line_width;
1568 if (it->start_of_box_run_p)
1569 it->pixel_width += face->box_line_width;
1570 if (it->end_of_box_run_p)
1571 it->pixel_width += face->box_line_width;
1574 take_vertical_position_into_account (it);
1576 if (it->glyph_row)
1578 struct glyph *glyph;
1579 enum glyph_row_area area = it->area;
1581 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1582 if (glyph < it->glyph_row->glyphs[area + 1])
1584 glyph->charpos = CHARPOS (it->position);
1585 glyph->object = it->object;
1586 glyph->pixel_width = it->pixel_width;
1587 glyph->voffset = it->voffset;
1588 glyph->type = IMAGE_GLYPH;
1589 glyph->multibyte_p = it->multibyte_p;
1590 glyph->left_box_line_p = it->start_of_box_run_p;
1591 glyph->right_box_line_p = it->end_of_box_run_p;
1592 glyph->overlaps_vertically_p = 0;
1593 glyph->padding_p = 0;
1594 glyph->glyph_not_available_p = 0;
1595 glyph->face_id = it->face_id;
1596 glyph->u.img_id = img->id;
1597 glyph->w32_font_type = UNKNOWN_FONT;
1598 ++it->glyph_row->used[area];
1604 /* Append a stretch glyph to IT->glyph_row. OBJECT is the source
1605 of the glyph, WIDTH and HEIGHT are the width and height of the
1606 stretch. ASCENT is the percentage/100 of HEIGHT to use for the
1607 ascent of the glyph (0 <= ASCENT <= 1). */
1609 static void
1610 x_append_stretch_glyph (it, object, width, height, ascent)
1611 struct it *it;
1612 Lisp_Object object;
1613 int width, height;
1614 double ascent;
1616 struct glyph *glyph;
1617 enum glyph_row_area area = it->area;
1619 xassert (ascent >= 0 && ascent <= 1);
1621 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1622 if (glyph < it->glyph_row->glyphs[area + 1])
1624 glyph->charpos = CHARPOS (it->position);
1625 glyph->object = object;
1626 glyph->pixel_width = width;
1627 glyph->voffset = it->voffset;
1628 glyph->type = STRETCH_GLYPH;
1629 glyph->multibyte_p = it->multibyte_p;
1630 glyph->left_box_line_p = it->start_of_box_run_p;
1631 glyph->right_box_line_p = it->end_of_box_run_p;
1632 glyph->overlaps_vertically_p = 0;
1633 glyph->padding_p = 0;
1634 glyph->glyph_not_available_p = 0;
1635 glyph->face_id = it->face_id;
1636 glyph->u.stretch.ascent = height * ascent;
1637 glyph->u.stretch.height = height;
1638 glyph->w32_font_type = UNKNOWN_FONT;
1639 ++it->glyph_row->used[area];
1644 /* Produce a stretch glyph for iterator IT. IT->object is the value
1645 of the glyph property displayed. The value must be a list
1646 `(space KEYWORD VALUE ...)' with the following KEYWORD/VALUE pairs
1647 being recognized:
1649 1. `:width WIDTH' specifies that the space should be WIDTH *
1650 canonical char width wide. WIDTH may be an integer or floating
1651 point number.
1653 2. `:relative-width FACTOR' specifies that the width of the stretch
1654 should be computed from the width of the first character having the
1655 `glyph' property, and should be FACTOR times that width.
1657 3. `:align-to HPOS' specifies that the space should be wide enough
1658 to reach HPOS, a value in canonical character units.
1660 Exactly one of the above pairs must be present.
1662 4. `:height HEIGHT' specifies that the height of the stretch produced
1663 should be HEIGHT, measured in canonical character units.
1665 5. `:relative-height FACTOR' specifies that the height of the the
1666 stretch should be FACTOR times the height of the characters having
1667 the glyph property.
1669 Either none or exactly one of 4 or 5 must be present.
1671 6. `:ascent ASCENT' specifies that ASCENT percent of the height
1672 of the stretch should be used for the ascent of the stretch.
1673 ASCENT must be in the range 0 <= ASCENT <= 100. */
1675 #define NUMVAL(X) \
1676 ((INTEGERP (X) || FLOATP (X)) \
1677 ? XFLOATINT (X) \
1678 : - 1)
1681 static void
1682 x_produce_stretch_glyph (it)
1683 struct it *it;
1685 /* (space :width WIDTH :height HEIGHT. */
1686 extern Lisp_Object QCwidth, QCheight, QCascent, Qspace;
1687 extern Lisp_Object QCrelative_width, QCrelative_height;
1688 extern Lisp_Object QCalign_to;
1689 Lisp_Object prop, plist;
1690 double width = 0, height = 0, ascent = 0;
1691 struct face *face = FACE_FROM_ID (it->f, it->face_id);
1692 XFontStruct *font = face->font ? face->font : FRAME_FONT (it->f);
1694 PREPARE_FACE_FOR_DISPLAY (it->f, face);
1696 /* List should start with `space'. */
1697 xassert (CONSP (it->object) && EQ (XCAR (it->object), Qspace));
1698 plist = XCDR (it->object);
1700 /* Compute the width of the stretch. */
1701 if (prop = Fplist_get (plist, QCwidth),
1702 NUMVAL (prop) > 0)
1703 /* Absolute width `:width WIDTH' specified and valid. */
1704 width = NUMVAL (prop) * CANON_X_UNIT (it->f);
1705 else if (prop = Fplist_get (plist, QCrelative_width),
1706 NUMVAL (prop) > 0)
1708 /* Relative width `:relative-width FACTOR' specified and valid.
1709 Compute the width of the characters having the `glyph'
1710 property. */
1711 struct it it2;
1712 unsigned char *p = BYTE_POS_ADDR (IT_BYTEPOS (*it));
1714 it2 = *it;
1715 if (it->multibyte_p)
1717 int maxlen = ((IT_BYTEPOS (*it) >= GPT ? ZV : GPT)
1718 - IT_BYTEPOS (*it));
1719 it2.c = STRING_CHAR_AND_LENGTH (p, maxlen, it2.len);
1721 else
1722 it2.c = *p, it2.len = 1;
1724 it2.glyph_row = NULL;
1725 it2.what = IT_CHARACTER;
1726 x_produce_glyphs (&it2);
1727 width = NUMVAL (prop) * it2.pixel_width;
1729 else if (prop = Fplist_get (plist, QCalign_to),
1730 NUMVAL (prop) > 0)
1731 width = NUMVAL (prop) * CANON_X_UNIT (it->f) - it->current_x;
1732 else
1733 /* Nothing specified -> width defaults to canonical char width. */
1734 width = CANON_X_UNIT (it->f);
1736 /* Compute height. */
1737 if (prop = Fplist_get (plist, QCheight),
1738 NUMVAL (prop) > 0)
1739 height = NUMVAL (prop) * CANON_Y_UNIT (it->f);
1740 else if (prop = Fplist_get (plist, QCrelative_height),
1741 NUMVAL (prop) > 0)
1742 height = FONT_HEIGHT (font) * NUMVAL (prop);
1743 else
1744 height = FONT_HEIGHT (font);
1746 /* Compute percentage of height used for ascent. If
1747 `:ascent ASCENT' is present and valid, use that. Otherwise,
1748 derive the ascent from the font in use. */
1749 if (prop = Fplist_get (plist, QCascent),
1750 NUMVAL (prop) > 0 && NUMVAL (prop) <= 100)
1751 ascent = NUMVAL (prop) / 100.0;
1752 else
1753 ascent = (double) FONT_BASE (font) / FONT_HEIGHT (font);
1755 if (width <= 0)
1756 width = 1;
1757 if (height <= 0)
1758 height = 1;
1760 if (it->glyph_row)
1762 Lisp_Object object = it->stack[it->sp - 1].string;
1763 if (!STRINGP (object))
1764 object = it->w->buffer;
1765 x_append_stretch_glyph (it, object, width, height, ascent);
1768 it->pixel_width = width;
1769 it->ascent = it->phys_ascent = height * ascent;
1770 it->descent = it->phys_descent = height - it->ascent;
1771 it->nglyphs = 1;
1773 if (face->box != FACE_NO_BOX)
1775 it->ascent += face->box_line_width;
1776 it->descent += face->box_line_width;
1778 if (it->start_of_box_run_p)
1779 it->pixel_width += face->box_line_width;
1780 if (it->end_of_box_run_p)
1781 it->pixel_width += face->box_line_width;
1784 take_vertical_position_into_account (it);
1787 /* Return proper value to be used as baseline offset of font that has
1788 ASCENT and DESCENT to draw characters by the font at the vertical
1789 center of the line of frame F.
1791 Here, out task is to find the value of BOFF in the following figure;
1793 -------------------------+-----------+-
1794 -+-+---------+-+ | |
1795 | | | | | |
1796 | | | | F_ASCENT F_HEIGHT
1797 | | | ASCENT | |
1798 HEIGHT | | | | |
1799 | | |-|-+------+-----------|------- baseline
1800 | | | | BOFF | |
1801 | |---------|-+-+ | |
1802 | | | DESCENT | |
1803 -+-+---------+-+ F_DESCENT |
1804 -------------------------+-----------+-
1806 -BOFF + DESCENT + (F_HEIGHT - HEIGHT) / 2 = F_DESCENT
1807 BOFF = DESCENT + (F_HEIGHT - HEIGHT) / 2 - F_DESCENT
1808 DESCENT = FONT->descent
1809 HEIGHT = FONT_HEIGHT (FONT)
1810 F_DESCENT = (F->output_data.x->font->descent
1811 - F->output_data.x->baseline_offset)
1812 F_HEIGHT = FRAME_LINE_HEIGHT (F)
1815 #define VCENTER_BASELINE_OFFSET(FONT, F) \
1816 (FONT_DESCENT (FONT) \
1817 + (FRAME_LINE_HEIGHT ((F)) - FONT_HEIGHT ((FONT))) / 2 \
1818 - (FONT_DESCENT (FRAME_FONT (F)) - FRAME_BASELINE_OFFSET (F)))
1820 /* Produce glyphs/get display metrics for the display element IT is
1821 loaded with. See the description of struct display_iterator in
1822 dispextern.h for an overview of struct display_iterator. */
1824 static void
1825 x_produce_glyphs (it)
1826 struct it *it;
1828 it->glyph_not_available_p = 0;
1830 if (it->what == IT_CHARACTER)
1832 wchar_t char2b;
1833 XFontStruct *font;
1834 struct face *face = FACE_FROM_ID (it->f, it->face_id);
1835 XCharStruct *pcm;
1836 int font_not_found_p;
1837 struct font_info *font_info;
1838 int boff; /* baseline offset */
1839 HDC hdc;
1841 hdc = get_frame_dc (it->f);
1843 /* Maybe translate single-byte characters to multibyte, or the
1844 other way. */
1845 it->char_to_display = it->c;
1846 if (!ASCII_BYTE_P (it->c))
1848 if (unibyte_display_via_language_environment
1849 && SINGLE_BYTE_CHAR_P (it->c)
1850 && (it->c >= 0240
1851 || !NILP (Vnonascii_translation_table)))
1853 it->char_to_display = unibyte_char_to_multibyte (it->c);
1854 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
1855 face = FACE_FROM_ID (it->f, it->face_id);
1857 else if (!SINGLE_BYTE_CHAR_P (it->c)
1858 && !it->multibyte_p)
1860 it->char_to_display = multibyte_char_to_unibyte (it->c, Qnil);
1861 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
1862 face = FACE_FROM_ID (it->f, it->face_id);
1866 /* Get font to use. Encode IT->char_to_display. */
1867 x_get_char_face_and_encoding (it->f, it->char_to_display,
1868 it->face_id, &char2b,
1869 it->multibyte_p);
1870 font = face->font;
1872 /* When no suitable font found, use the default font. */
1873 font_not_found_p = font == NULL;
1874 if (font_not_found_p)
1876 font = FRAME_FONT (it->f);
1877 boff = it->f->output_data.w32->baseline_offset;
1878 font_info = NULL;
1880 else
1882 font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
1883 boff = font_info->baseline_offset;
1884 if (font_info->vertical_centering)
1885 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
1888 if (font->hfont)
1889 SelectObject (hdc, font->hfont);
1891 if (it->char_to_display >= ' '
1892 && (!it->multibyte_p || it->char_to_display < 128))
1894 /* Either unibyte or ASCII. */
1895 int stretched_p;
1897 it->nglyphs = 1;
1899 pcm = w32_per_char_metric (hdc, font, &char2b,
1900 font->bdf ? BDF_FONT : ANSI_FONT);
1901 it->ascent = FONT_BASE (font) + boff;
1902 it->descent = FONT_DESCENT (font) - boff;
1904 if (pcm)
1906 it->phys_ascent = pcm->ascent + boff;
1907 it->phys_descent = pcm->descent - boff;
1908 it->pixel_width = pcm->width;
1910 else
1912 it->glyph_not_available_p = 1;
1913 it->phys_ascent = FONT_BASE(font) + boff;
1914 it->phys_descent = FONT_DESCENT(font) - boff;
1915 it->pixel_width = FONT_WIDTH(font);
1918 /* If this is a space inside a region of text with
1919 `space-width' property, change its width. */
1920 stretched_p = it->char_to_display == ' ' && !NILP (it->space_width);
1921 if (stretched_p)
1922 it->pixel_width *= XFLOATINT (it->space_width);
1924 /* If face has a box, add the box thickness to the character
1925 height. If character has a box line to the left and/or
1926 right, add the box line width to the character's width. */
1927 if (face->box != FACE_NO_BOX)
1929 int thick = face->box_line_width;
1931 it->ascent += thick;
1932 it->descent += thick;
1934 if (it->start_of_box_run_p)
1935 it->pixel_width += thick;
1936 if (it->end_of_box_run_p)
1937 it->pixel_width += thick;
1940 /* If face has an overline, add the height of the overline
1941 (1 pixel) and a 1 pixel margin to the character height. */
1942 if (face->overline_p)
1943 it->ascent += 2;
1945 take_vertical_position_into_account (it);
1947 /* If we have to actually produce glyphs, do it. */
1948 if (it->glyph_row)
1950 if (stretched_p)
1952 /* Translate a space with a `space-width' property
1953 into a stretch glyph. */
1954 double ascent = (double) FONT_BASE (font)
1955 / FONT_HEIGHT (font);
1956 x_append_stretch_glyph (it, it->object, it->pixel_width,
1957 it->ascent + it->descent, ascent);
1959 else
1960 x_append_glyph (it);
1962 /* If characters with lbearing or rbearing are displayed
1963 in this line, record that fact in a flag of the
1964 glyph row. This is used to optimize X output code. */
1965 if (pcm && (pcm->lbearing < 0 || pcm->rbearing > pcm->width))
1966 it->glyph_row->contains_overlapping_glyphs_p = 1;
1967 if (pcm)
1968 xfree (pcm);
1971 else if (it->char_to_display == '\n')
1973 /* A newline has no width but we need the height of the line. */
1974 it->pixel_width = 0;
1975 it->nglyphs = 0;
1976 it->ascent = it->phys_ascent = FONT_BASE (font) + boff;
1977 it->descent = it->phys_descent = FONT_DESCENT (font) - boff;
1979 if (face->box != FACE_NO_BOX)
1981 int thick = face->box_line_width;
1982 it->ascent += thick;
1983 it->descent += thick;
1986 else if (it->char_to_display == '\t')
1988 int tab_width = it->tab_width * CANON_X_UNIT (it->f);
1989 int x = it->current_x + it->continuation_lines_width;
1990 int next_tab_x = ((1 + x + tab_width - 1) / tab_width) * tab_width;
1992 it->pixel_width = next_tab_x - x;
1993 it->nglyphs = 1;
1994 it->ascent = it->phys_ascent = FONT_BASE (font) + boff;
1995 it->descent = it->phys_descent = FONT_DESCENT (font) - boff;
1997 if (it->glyph_row)
1999 double ascent = (double) it->ascent / (it->ascent + it->descent);
2000 x_append_stretch_glyph (it, it->object, it->pixel_width,
2001 it->ascent + it->descent, ascent);
2004 else
2006 /* A multi-byte character.
2007 If we found a font, this font should give us the right
2008 metrics. If we didn't find a font, use the frame's
2009 default font and calculate the width of the character
2010 from the charset width; this is what old redisplay code
2011 did. */
2012 pcm = w32_per_char_metric (hdc, font, &char2b,
2013 font->bdf ? BDF_FONT : UNICODE_FONT);
2015 if (font_not_found_p || !pcm)
2017 int charset = CHAR_CHARSET (it->char_to_display);
2019 it->glyph_not_available_p = 1;
2020 it->pixel_width = (FONT_WIDTH (FRAME_FONT (it->f))
2021 * CHARSET_WIDTH (charset));
2022 it->phys_ascent = FONT_BASE (font) + boff;
2023 it->phys_descent = FONT_DESCENT (font) - boff;
2025 else
2027 it->pixel_width = pcm->width;
2028 it->phys_ascent = pcm->ascent + boff;
2029 it->phys_descent = pcm->descent - boff;
2030 if (it->glyph_row
2031 && (pcm->lbearing < 0
2032 || pcm->rbearing > pcm->width))
2033 it->glyph_row->contains_overlapping_glyphs_p = 1;
2035 it->nglyphs = 1;
2036 it->ascent = FONT_BASE (font) + boff;
2037 it->descent = FONT_DESCENT (font) - boff;
2039 if (face->box != FACE_NO_BOX)
2041 int thick = face->box_line_width;
2042 it->ascent += thick;
2043 it->descent += thick;
2045 if (it->start_of_box_run_p)
2046 it->pixel_width += thick;
2047 if (it->end_of_box_run_p)
2048 it->pixel_width += thick;
2051 /* If face has an overline, add the height of the overline
2052 (1 pixel) and a 1 pixel margin to the character height. */
2053 if (face->overline_p)
2054 it->ascent += 2;
2056 take_vertical_position_into_account (it);
2058 if (it->glyph_row)
2059 x_append_glyph (it);
2061 if (pcm)
2062 xfree (pcm);
2064 release_frame_dc (it->f, hdc);
2066 else if (it->what == IT_COMPOSITION)
2068 /* NTEMACS_TODO: Composite glyphs. */
2070 else if (it->what == IT_IMAGE)
2071 x_produce_image_glyph (it);
2072 else if (it->what == IT_STRETCH)
2073 x_produce_stretch_glyph (it);
2075 /* Accumulate dimensions. */
2076 xassert (it->ascent >= 0 && it->descent > 0);
2077 if (it->area == TEXT_AREA)
2078 it->current_x += it->pixel_width;
2080 it->descent += it->extra_line_spacing;
2082 it->max_ascent = max (it->max_ascent, it->ascent);
2083 it->max_descent = max (it->max_descent, it->descent);
2084 it->max_phys_ascent = max (it->max_phys_ascent, it->phys_ascent);
2085 it->max_phys_descent = max (it->max_phys_descent, it->phys_descent);
2089 /* Estimate the pixel height of the mode or top line on frame F.
2090 FACE_ID specifies what line's height to estimate. */
2093 x_estimate_mode_line_height (f, face_id)
2094 struct frame *f;
2095 enum face_id face_id;
2097 int height = 1;
2099 /* This function is called so early when Emacs starts that the face
2100 cache and mode line face are not yet initialized. */
2101 if (FRAME_FACE_CACHE (f))
2103 struct face *face = FACE_FROM_ID (f, face_id);
2104 if (face)
2105 height = FONT_HEIGHT (face->font) + 2 * face->box_line_width;
2108 return height;
2113 BOOL
2114 w32_use_unicode_for_codepage (codepage)
2115 int codepage;
2117 /* If the current codepage is supported, use Unicode for output. */
2118 return (w32_enable_unicode_output
2119 && codepage != CP_DEFAULT && IsValidCodePage (codepage));
2123 /***********************************************************************
2124 Glyph display
2125 ***********************************************************************/
2127 /* A sequence of glyphs to be drawn in the same face.
2129 This data structure is not really completely X specific, so it
2130 could possibly, at least partially, be useful for other systems. It
2131 is currently not part of the external redisplay interface because
2132 it's not clear what other systems will need. */
2134 struct glyph_string
2136 /* X-origin of the string. */
2137 int x;
2139 /* Y-origin and y-position of the base line of this string. */
2140 int y, ybase;
2142 /* The width of the string, not including a face extension. */
2143 int width;
2145 /* The width of the string, including a face extension. */
2146 int background_width;
2148 /* The height of this string. This is the height of the line this
2149 string is drawn in, and can be different from the height of the
2150 font the string is drawn in. */
2151 int height;
2153 /* Number of pixels this string overwrites in front of its x-origin.
2154 This number is zero if the string has an lbearing >= 0; it is
2155 -lbearing, if the string has an lbearing < 0. */
2156 int left_overhang;
2158 /* Number of pixels this string overwrites past its right-most
2159 nominal x-position, i.e. x + width. Zero if the string's
2160 rbearing is <= its nominal width, rbearing - width otherwise. */
2161 int right_overhang;
2163 /* The frame on which the glyph string is drawn. */
2164 struct frame *f;
2166 /* The window on which the glyph string is drawn. */
2167 struct window *w;
2169 /* X display and window for convenience. */
2170 Window window;
2172 /* The glyph row for which this string was built. It determines the
2173 y-origin and height of the string. */
2174 struct glyph_row *row;
2176 /* The area within row. */
2177 enum glyph_row_area area;
2179 /* Characters to be drawn, and number of characters. */
2180 wchar_t *char2b;
2181 int nchars;
2183 /* A face-override for drawing cursors, mouse face and similar. */
2184 enum draw_glyphs_face hl;
2186 /* Face in which this string is to be drawn. */
2187 struct face *face;
2189 /* Font in which this string is to be drawn. */
2190 XFontStruct *font;
2192 /* Font info for this string. */
2193 struct font_info *font_info;
2195 /* Non-null means this string describes (part of) a composition.
2196 All characters from char2b are drawn composed. */
2197 struct composition *cmp;
2199 /* Index of this glyph string's first character in the glyph
2200 definition of CMP. If this is zero, this glyph string describes
2201 the first character of a composition. */
2202 int gidx;
2204 /* 1 means this glyph strings face has to be drawn to the right end
2205 of the window's drawing area. */
2206 unsigned extends_to_end_of_line_p : 1;
2208 /* 1 means the background of this string has been drawn. */
2209 unsigned background_filled_p : 1;
2211 /* 1 means glyph string must be drawn with 16-bit functions. */
2212 unsigned two_byte_p : 1;
2214 /* 1 means that the original font determined for drawing this glyph
2215 string could not be loaded. The member `font' has been set to
2216 the frame's default font in this case. */
2217 unsigned font_not_found_p : 1;
2219 /* 1 means that the face in which this glyph string is drawn has a
2220 stipple pattern. */
2221 unsigned stippled_p : 1;
2223 /* 1 means only the foreground of this glyph string must be drawn,
2224 and we should use the physical height of the line this glyph
2225 string appears in as clip rect. */
2226 unsigned for_overlaps_p : 1;
2228 /* The GC to use for drawing this glyph string. */
2229 XGCValues *gc;
2231 HDC hdc;
2233 /* A pointer to the first glyph in the string. This glyph
2234 corresponds to char2b[0]. Needed to draw rectangles if
2235 font_not_found_p is 1. */
2236 struct glyph *first_glyph;
2238 /* Image, if any. */
2239 struct image *img;
2241 struct glyph_string *next, *prev;
2245 /* Encapsulate the different ways of displaying text under W32. */
2247 void W32_TEXTOUT(s, x, y,chars,nchars)
2248 struct glyph_string * s;
2249 int x, y;
2250 wchar_t * chars;
2251 int nchars;
2253 int charset_dim = w32_font_is_double_byte (s->gc->font) ? 2 : 1;
2254 if (s->gc->font->bdf)
2255 w32_BDF_TextOut (s->gc->font->bdf, s->hdc,
2256 x, y, (char *) chars, charset_dim, nchars, 0);
2257 else if (s->first_glyph->w32_font_type == UNICODE_FONT)
2258 ExtTextOutW (s->hdc, x, y, 0, NULL, chars, nchars, NULL);
2259 else
2260 ExtTextOut (s->hdc, x, y, 0, NULL, (char *) chars,
2261 nchars * charset_dim, NULL);
2264 #if 0
2266 static void
2267 x_dump_glyph_string (s)
2268 struct glyph_string *s;
2270 fprintf (stderr, "glyph string\n");
2271 fprintf (stderr, " x, y, w, h = %d, %d, %d, %d\n",
2272 s->x, s->y, s->width, s->height);
2273 fprintf (stderr, " ybase = %d\n", s->ybase);
2274 fprintf (stderr, " hl = %d\n", s->hl);
2275 fprintf (stderr, " left overhang = %d, right = %d\n",
2276 s->left_overhang, s->right_overhang);
2277 fprintf (stderr, " nchars = %d\n", s->nchars);
2278 fprintf (stderr, " extends to end of line = %d\n",
2279 s->extends_to_end_of_line_p);
2280 fprintf (stderr, " font height = %d\n", FONT_HEIGHT (s->font));
2281 fprintf (stderr, " bg width = %d\n", s->background_width);
2284 #endif /* GLYPH_DEBUG */
2288 static void x_append_glyph_string_lists P_ ((struct glyph_string **,
2289 struct glyph_string **,
2290 struct glyph_string *,
2291 struct glyph_string *));
2292 static void x_prepend_glyph_string_lists P_ ((struct glyph_string **,
2293 struct glyph_string **,
2294 struct glyph_string *,
2295 struct glyph_string *));
2296 static void x_append_glyph_string P_ ((struct glyph_string **,
2297 struct glyph_string **,
2298 struct glyph_string *));
2299 static int x_left_overwritten P_ ((struct glyph_string *));
2300 static int x_left_overwriting P_ ((struct glyph_string *));
2301 static int x_right_overwritten P_ ((struct glyph_string *));
2302 static int x_right_overwriting P_ ((struct glyph_string *));
2303 static int x_fill_glyph_string P_ ((struct glyph_string *, int, int,
2304 int, int));
2305 static void w32_init_glyph_string P_ ((struct glyph_string *, HDC hdc,
2306 wchar_t *, struct window *,
2307 struct glyph_row *,
2308 enum glyph_row_area, int,
2309 enum draw_glyphs_face));
2310 static int x_draw_glyphs P_ ((struct window *, int , struct glyph_row *,
2311 enum glyph_row_area, int, int,
2312 enum draw_glyphs_face, int *, int *, int));
2313 static void x_set_glyph_string_clipping P_ ((struct glyph_string *));
2314 static void x_set_glyph_string_gc P_ ((struct glyph_string *));
2315 static void x_draw_glyph_string_background P_ ((struct glyph_string *,
2316 int));
2317 static void x_draw_glyph_string_foreground P_ ((struct glyph_string *));
2318 static void x_draw_composite_glyph_string_foreground P_ ((struct glyph_string *));
2319 static void x_draw_glyph_string_box P_ ((struct glyph_string *));
2320 static void x_draw_glyph_string P_ ((struct glyph_string *));
2321 static void x_compute_glyph_string_overhangs P_ ((struct glyph_string *));
2322 static void x_set_cursor_gc P_ ((struct glyph_string *));
2323 static void x_set_mode_line_face_gc P_ ((struct glyph_string *));
2324 static void x_set_mouse_face_gc P_ ((struct glyph_string *));
2325 static void w32_get_glyph_overhangs P_ ((HDC hdc, struct glyph *,
2326 struct frame *,
2327 int *, int *));
2328 static void x_compute_overhangs_and_x P_ ((struct glyph_string *, int, int));
2329 static int w32_alloc_lighter_color (struct frame *, COLORREF *, double, int);
2330 static void w32_setup_relief_color P_ ((struct frame *, struct relief *,
2331 double, int, COLORREF));
2332 static void x_setup_relief_colors P_ ((struct glyph_string *));
2333 static void x_draw_image_glyph_string P_ ((struct glyph_string *));
2334 static void x_draw_image_relief P_ ((struct glyph_string *));
2335 static void x_draw_image_foreground P_ ((struct glyph_string *));
2336 static void w32_draw_image_foreground_1 P_ ((struct glyph_string *, HBITMAP));
2337 static void x_fill_image_glyph_string P_ ((struct glyph_string *));
2338 static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int,
2339 int, int, int));
2340 static void w32_draw_relief_rect P_ ((struct frame *, int, int, int, int,
2341 int, int, int, int, RECT *));
2342 static void w32_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,
2343 int, int, int, RECT *));
2344 static void x_fix_overlapping_area P_ ((struct window *, struct glyph_row *,
2345 enum glyph_row_area));
2348 /* Append the list of glyph strings with head H and tail T to the list
2349 with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the result. */
2351 static INLINE void
2352 x_append_glyph_string_lists (head, tail, h, t)
2353 struct glyph_string **head, **tail;
2354 struct glyph_string *h, *t;
2356 if (h)
2358 if (*head)
2359 (*tail)->next = h;
2360 else
2361 *head = h;
2362 h->prev = *tail;
2363 *tail = t;
2368 /* Prepend the list of glyph strings with head H and tail T to the
2369 list with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the
2370 result. */
2372 static INLINE void
2373 x_prepend_glyph_string_lists (head, tail, h, t)
2374 struct glyph_string **head, **tail;
2375 struct glyph_string *h, *t;
2377 if (h)
2379 if (*head)
2380 (*head)->prev = t;
2381 else
2382 *tail = t;
2383 t->next = *head;
2384 *head = h;
2389 /* Append glyph string S to the list with head *HEAD and tail *TAIL.
2390 Set *HEAD and *TAIL to the resulting list. */
2392 static INLINE void
2393 x_append_glyph_string (head, tail, s)
2394 struct glyph_string **head, **tail;
2395 struct glyph_string *s;
2397 s->next = s->prev = NULL;
2398 x_append_glyph_string_lists (head, tail, s, s);
2402 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
2403 face. */
2405 static void
2406 x_set_cursor_gc (s)
2407 struct glyph_string *s;
2409 if (s->font == FRAME_FONT (s->f)
2410 && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
2411 && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
2412 && !s->cmp)
2413 s->gc = s->f->output_data.w32->cursor_gc;
2414 else
2416 /* Cursor on non-default face: must merge. */
2417 XGCValues xgcv;
2418 unsigned long mask;
2420 xgcv.background = s->f->output_data.w32->cursor_pixel;
2421 xgcv.foreground = s->face->background;
2423 /* If the glyph would be invisible, try a different foreground. */
2424 if (xgcv.foreground == xgcv.background)
2425 xgcv.foreground = s->face->foreground;
2426 if (xgcv.foreground == xgcv.background)
2427 xgcv.foreground = s->f->output_data.w32->cursor_foreground_pixel;
2428 if (xgcv.foreground == xgcv.background)
2429 xgcv.foreground = s->face->foreground;
2431 /* Make sure the cursor is distinct from text in this face. */
2432 if (xgcv.background == s->face->background
2433 && xgcv.foreground == s->face->foreground)
2435 xgcv.background = s->face->foreground;
2436 xgcv.foreground = s->face->background;
2439 IF_DEBUG (x_check_font (s->f, s->font));
2440 xgcv.font = s->font;
2441 mask = GCForeground | GCBackground | GCFont;
2443 if (FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc)
2444 XChangeGC (NULL, FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc,
2445 mask, &xgcv);
2446 else
2447 FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc
2448 = XCreateGC (NULL, s->window, mask, &xgcv);
2450 s->gc = FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc;
2455 /* Set up S->gc of glyph string S for drawing text in mouse face. */
2457 static void
2458 x_set_mouse_face_gc (s)
2459 struct glyph_string *s;
2461 int face_id;
2462 struct face *face;
2464 /* What face has to be used for the mouse face? */
2465 face_id = FRAME_W32_DISPLAY_INFO (s->f)->mouse_face_face_id;
2466 face = FACE_FROM_ID (s->f, face_id);
2467 face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch);
2468 s->face = FACE_FROM_ID (s->f, face_id);
2469 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
2471 /* If font in this face is same as S->font, use it. */
2472 if (s->font == s->face->font)
2473 s->gc = s->face->gc;
2474 else
2476 /* Otherwise construct scratch_cursor_gc with values from FACE
2477 but font FONT. */
2478 XGCValues xgcv;
2479 unsigned long mask;
2481 xgcv.background = s->face->background;
2482 xgcv.foreground = s->face->foreground;
2483 IF_DEBUG (x_check_font (s->f, s->font));
2484 xgcv.font = s->font;
2485 mask = GCForeground | GCBackground | GCFont;
2487 if (FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc)
2488 XChangeGC (NULL, FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc,
2489 mask, &xgcv);
2490 else
2491 FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc
2492 = XCreateGC (NULL, s->window, mask, &xgcv);
2494 s->gc = FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc;
2497 xassert (s->gc != 0);
2501 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
2502 Faces to use in the mode line have already been computed when the
2503 matrix was built, so there isn't much to do, here. */
2505 static INLINE void
2506 x_set_mode_line_face_gc (s)
2507 struct glyph_string *s;
2509 s->gc = s->face->gc;
2513 /* Set S->gc of glyph string S for drawing that glyph string. Set
2514 S->stippled_p to a non-zero value if the face of S has a stipple
2515 pattern. */
2517 static INLINE void
2518 x_set_glyph_string_gc (s)
2519 struct glyph_string *s;
2521 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
2523 if (s->hl == DRAW_NORMAL_TEXT)
2525 s->gc = s->face->gc;
2526 s->stippled_p = s->face->stipple != 0;
2528 else if (s->hl == DRAW_INVERSE_VIDEO)
2530 x_set_mode_line_face_gc (s);
2531 s->stippled_p = s->face->stipple != 0;
2533 else if (s->hl == DRAW_CURSOR)
2535 x_set_cursor_gc (s);
2536 s->stippled_p = 0;
2538 else if (s->hl == DRAW_MOUSE_FACE)
2540 x_set_mouse_face_gc (s);
2541 s->stippled_p = s->face->stipple != 0;
2543 else if (s->hl == DRAW_IMAGE_RAISED
2544 || s->hl == DRAW_IMAGE_SUNKEN)
2546 s->gc = s->face->gc;
2547 s->stippled_p = s->face->stipple != 0;
2549 else
2551 s->gc = s->face->gc;
2552 s->stippled_p = s->face->stipple != 0;
2555 /* GC must have been set. */
2556 xassert (s->gc != 0);
2560 /* Return in *R the clipping rectangle for glyph string S. */
2562 static void
2563 w32_get_glyph_string_clip_rect (s, r)
2564 struct glyph_string *s;
2565 RECT *r;
2567 int r_height, r_width;
2569 if (s->row->full_width_p)
2571 /* Draw full-width. X coordinates are relative to S->w->left. */
2572 int canon_x = CANON_X_UNIT (s->f);
2574 r->left = WINDOW_LEFT_MARGIN (s->w) * canon_x;
2575 r_width = XFASTINT (s->w->width) * canon_x;
2577 if (FRAME_HAS_VERTICAL_SCROLL_BARS (s->f))
2579 int width = FRAME_SCROLL_BAR_WIDTH (s->f) * canon_x;
2580 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (s->f))
2581 r->left -= width;
2584 r->left += FRAME_INTERNAL_BORDER_WIDTH (s->f);
2586 /* Unless displaying a mode or menu bar line, which are always
2587 fully visible, clip to the visible part of the row. */
2588 if (s->w->pseudo_window_p)
2589 r_height = s->row->visible_height;
2590 else
2591 r_height = s->height;
2593 else
2595 /* This is a text line that may be partially visible. */
2596 r->left = WINDOW_AREA_TO_FRAME_PIXEL_X (s->w, s->area, 0);
2597 r_width = window_box_width (s->w, s->area);
2598 r_height = s->row->visible_height;
2601 /* Don't use S->y for clipping because it doesn't take partially
2602 visible lines into account. For example, it can be negative for
2603 partially visible lines at the top of a window. */
2604 if (!s->row->full_width_p
2605 && MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (s->w, s->row))
2606 r->top = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
2607 else
2608 r->top = max (0, s->row->y);
2610 /* If drawing a tool-bar window, draw it over the internal border
2611 at the top of the window. */
2612 if (s->w == XWINDOW (s->f->tool_bar_window))
2613 r->top -= s->f->output_data.w32->internal_border_width;
2615 /* If S draws overlapping rows, it's sufficient to use the top and
2616 bottom of the window for clipping because this glyph string
2617 intentionally draws over other lines. */
2618 if (s->for_overlaps_p)
2620 r->top = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
2621 r_height = window_text_bottom_y (s->w) - r->top;
2624 r->top = WINDOW_TO_FRAME_PIXEL_Y (s->w, r->top);
2626 r->bottom = r->top + r_height;
2627 r->right = r->left + r_width;
2631 /* Set clipping for output of glyph string S. S may be part of a mode
2632 line or menu if we don't have X toolkit support. */
2634 static INLINE void
2635 x_set_glyph_string_clipping (s)
2636 struct glyph_string *s;
2638 RECT r;
2639 w32_get_glyph_string_clip_rect (s, &r);
2640 w32_set_clip_rectangle (s->hdc, &r);
2644 /* Compute left and right overhang of glyph string S. If S is a glyph
2645 string for a composition, assume overhangs don't exist. */
2647 static INLINE void
2648 x_compute_glyph_string_overhangs (s)
2649 struct glyph_string *s;
2651 if (s->cmp == NULL
2652 && s->first_glyph->type == CHAR_GLYPH)
2654 XCharStruct cs;
2655 int direction, font_ascent, font_descent;
2656 XTextExtents16 (s->font, s->char2b, s->nchars, &direction,
2657 &font_ascent, &font_descent, &cs);
2658 s->right_overhang = cs.rbearing > cs.width ? cs.rbearing - cs.width : 0;
2659 s->left_overhang = cs.lbearing < 0 ? -cs.lbearing : 0;
2664 /* Compute overhangs and x-positions for glyph string S and its
2665 predecessors, or successors. X is the starting x-position for S.
2666 BACKWARD_P non-zero means process predecessors. */
2668 static void
2669 x_compute_overhangs_and_x (s, x, backward_p)
2670 struct glyph_string *s;
2671 int x;
2672 int backward_p;
2674 if (backward_p)
2676 while (s)
2678 x_compute_glyph_string_overhangs (s);
2679 x -= s->width;
2680 s->x = x;
2681 s = s->prev;
2684 else
2686 while (s)
2688 x_compute_glyph_string_overhangs (s);
2689 s->x = x;
2690 x += s->width;
2691 s = s->next;
2697 /* Set *LEFT and *RIGHT to the left and right overhang of GLYPH on
2698 frame F. Overhangs of glyphs other than type CHAR_GLYPH are
2699 assumed to be zero. */
2701 static void
2702 w32_get_glyph_overhangs (hdc, glyph, f, left, right)
2703 HDC hdc;
2704 struct glyph *glyph;
2705 struct frame *f;
2706 int *left, *right;
2708 int c;
2710 *left = *right = 0;
2712 if (glyph->type == CHAR_GLYPH)
2714 XFontStruct *font;
2715 struct face *face;
2716 wchar_t char2b;
2717 XCharStruct *pcm;
2719 face = x_get_glyph_face_and_encoding (f, glyph, &char2b, NULL);
2720 font = face->font;
2722 if (font
2723 && (pcm = w32_per_char_metric (hdc, font, &char2b,
2724 glyph->w32_font_type)))
2726 if (pcm->rbearing > pcm->width)
2727 *right = pcm->rbearing - pcm->width;
2728 if (pcm->lbearing < 0)
2729 *left = -pcm->lbearing;
2730 xfree (pcm);
2736 static void
2737 x_get_glyph_overhangs (glyph, f, left, right)
2738 struct glyph *glyph;
2739 struct frame *f;
2740 int *left, *right;
2742 HDC hdc = get_frame_dc (f);
2743 /* Convert to unicode! */
2744 w32_get_glyph_overhangs (hdc, glyph, f, left, right);
2745 release_frame_dc (f, hdc);
2749 /* Return the index of the first glyph preceding glyph string S that
2750 is overwritten by S because of S's left overhang. Value is -1
2751 if no glyphs are overwritten. */
2753 static int
2754 x_left_overwritten (s)
2755 struct glyph_string *s;
2757 int k;
2759 if (s->left_overhang)
2761 int x = 0, i;
2762 struct glyph *glyphs = s->row->glyphs[s->area];
2763 int first = s->first_glyph - glyphs;
2765 for (i = first - 1; i >= 0 && x > -s->left_overhang; --i)
2766 x -= glyphs[i].pixel_width;
2768 k = i + 1;
2770 else
2771 k = -1;
2773 return k;
2777 /* Return the index of the first glyph preceding glyph string S that
2778 is overwriting S because of its right overhang. Value is -1 if no
2779 glyph in front of S overwrites S. */
2781 static int
2782 x_left_overwriting (s)
2783 struct glyph_string *s;
2785 int i, k, x;
2786 struct glyph *glyphs = s->row->glyphs[s->area];
2787 int first = s->first_glyph - glyphs;
2789 k = -1;
2790 x = 0;
2791 for (i = first - 1; i >= 0; --i)
2793 int left, right;
2794 w32_get_glyph_overhangs (s->hdc, glyphs + i, s->f, &left, &right);
2795 if (x + right > 0)
2796 k = i;
2797 x -= glyphs[i].pixel_width;
2800 return k;
2804 /* Return the index of the last glyph following glyph string S that is
2805 not overwritten by S because of S's right overhang. Value is -1 if
2806 no such glyph is found. */
2808 static int
2809 x_right_overwritten (s)
2810 struct glyph_string *s;
2812 int k = -1;
2814 if (s->right_overhang)
2816 int x = 0, i;
2817 struct glyph *glyphs = s->row->glyphs[s->area];
2818 int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
2819 int end = s->row->used[s->area];
2821 for (i = first; i < end && s->right_overhang > x; ++i)
2822 x += glyphs[i].pixel_width;
2824 k = i;
2827 return k;
2831 /* Return the index of the last glyph following glyph string S that
2832 overwrites S because of its left overhang. Value is negative
2833 if no such glyph is found. */
2835 static int
2836 x_right_overwriting (s)
2837 struct glyph_string *s;
2839 int i, k, x;
2840 int end = s->row->used[s->area];
2841 struct glyph *glyphs = s->row->glyphs[s->area];
2842 int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
2844 k = -1;
2845 x = 0;
2846 for (i = first; i < end; ++i)
2848 int left, right;
2849 w32_get_glyph_overhangs (s->hdc, glyphs + i, s->f, &left, &right);
2850 if (x - left < 0)
2851 k = i;
2852 x += glyphs[i].pixel_width;
2855 return k;
2859 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
2861 static INLINE void
2862 x_clear_glyph_string_rect (s, x, y, w, h)
2863 struct glyph_string *s;
2864 int x, y, w, h;
2866 int real_x = x;
2867 int real_y = y;
2868 int real_w = w;
2869 int real_h = h;
2870 #if 0
2871 /* Take clipping into account. */
2872 if (s->gc->clip_mask == Rect)
2874 real_x = max (real_x, s->gc->clip_rectangle.left);
2875 real_y = max (real_y, s->gc->clip_rectangle.top);
2876 real_w = min (real_w, s->gc->clip_rectangle.right
2877 - s->gc->clip_rectangle.left);
2878 real_h = min (real_h, s->gc->clip_rectangle.bottom
2879 - s->gc->clip_rectangle.top);
2881 #endif
2882 w32_fill_area (s->f, s->hdc, s->gc->background, real_x, real_y,
2883 real_w, real_h);
2887 /* Draw the background of glyph_string S. If S->background_filled_p
2888 is non-zero don't draw it. FORCE_P non-zero means draw the
2889 background even if it wouldn't be drawn normally. This is used
2890 when a string preceding S draws into the background of S, or S
2891 contains the first component of a composition. */
2893 static void
2894 x_draw_glyph_string_background (s, force_p)
2895 struct glyph_string *s;
2896 int force_p;
2898 /* Nothing to do if background has already been drawn or if it
2899 shouldn't be drawn in the first place. */
2900 if (!s->background_filled_p)
2902 #if 0 /* NTEMACS_TODO: stipple */
2903 if (s->stippled_p)
2905 /* Fill background with a stipple pattern. */
2906 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
2907 XFillRectangle (s->display, s->window, s->gc, s->x,
2908 s->y + s->face->box_line_width,
2909 s->background_width,
2910 s->height - 2 * s->face->box_line_width);
2911 XSetFillStyle (s->display, s->gc, FillSolid);
2912 s->background_filled_p = 1;
2914 else
2915 #endif
2916 if (FONT_HEIGHT (s->font) < s->height - 2 * s->face->box_line_width
2917 || s->font_not_found_p
2918 || s->extends_to_end_of_line_p
2919 || force_p)
2921 x_clear_glyph_string_rect (s, s->x, s->y + s->face->box_line_width,
2922 s->background_width,
2923 s->height - 2 * s->face->box_line_width);
2924 s->background_filled_p = 1;
2930 /* Draw the foreground of glyph string S. */
2932 static void
2933 x_draw_glyph_string_foreground (s)
2934 struct glyph_string *s;
2936 int i, x;
2938 /* If first glyph of S has a left box line, start drawing the text
2939 of S to the right of that box line. */
2940 if (s->face->box != FACE_NO_BOX
2941 && s->first_glyph->left_box_line_p)
2942 x = s->x + s->face->box_line_width;
2943 else
2944 x = s->x;
2946 if (s->for_overlaps_p || (s->background_filled_p && s->hl != DRAW_CURSOR))
2947 SetBkMode (s->hdc, TRANSPARENT);
2948 else
2949 SetBkMode (s->hdc, OPAQUE);
2951 SetTextColor (s->hdc, s->gc->foreground);
2952 SetBkColor (s->hdc, s->gc->background);
2953 SetTextAlign (s->hdc, TA_BASELINE | TA_LEFT);
2955 if (s->font && s->font->hfont)
2956 SelectObject (s->hdc, s->font->hfont);
2958 /* Draw characters of S as rectangles if S's font could not be
2959 loaded. */
2960 if (s->font_not_found_p)
2962 for (i = 0; i < s->nchars; ++i)
2964 struct glyph *g = s->first_glyph + i;
2966 w32_draw_rectangle (s->hdc, s->gc, x, s->y, g->pixel_width - 1,
2967 s->height - 1);
2968 x += g->pixel_width;
2971 else
2973 char *char1b = (char *) s->char2b;
2974 int boff = s->font_info->baseline_offset;
2976 if (s->font_info->vertical_centering)
2977 boff = VCENTER_BASELINE_OFFSET (s->font, s->f) - boff;
2979 /* If we can use 8-bit functions, condense S->char2b. */
2980 if (!s->two_byte_p)
2981 for (i = 0; i < s->nchars; ++i)
2982 char1b[i] = BYTE2 (s->char2b[i]);
2984 /* Draw text with TextOut and friends. */
2985 W32_TEXTOUT (s, x, s->ybase - boff, s->char2b, s->nchars);
2989 /* Draw the foreground of composite glyph string S. */
2991 static void
2992 x_draw_composite_glyph_string_foreground (s)
2993 struct glyph_string *s;
2995 int i, x;
2997 /* If first glyph of S has a left box line, start drawing the text
2998 of S to the right of that box line. */
2999 if (s->face->box != FACE_NO_BOX
3000 && s->first_glyph->left_box_line_p)
3001 x = s->x + s->face->box_line_width;
3002 else
3003 x = s->x;
3005 /* S is a glyph string for a composition. S->gidx is the index of
3006 the first character drawn for glyphs of this composition.
3007 S->gidx == 0 means we are drawing the very first character of
3008 this composition. */
3010 SetTextColor (s->hdc, s->gc->foreground);
3011 SetBkColor (s->hdc, s->gc->background);
3012 SetBkMode (s->hdc, TRANSPARENT);
3013 SetTextAlign (s->hdc, TA_BASELINE | TA_LEFT);
3015 /* Draw a rectangle for the composition if the font for the very
3016 first character of the composition could not be loaded. */
3017 if (s->font_not_found_p)
3019 if (s->gidx == 0)
3020 w32_draw_rectangle (s->hdc, s->gc, x, s->y, s->width - 1,
3021 s->height - 1);
3023 else
3025 for (i = 0; i < s->nchars; i++, ++s->gidx)
3026 W32_TEXTOUT (s, x + s->cmp->offsets[s->gidx * 2],
3027 s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
3028 s->char2b + i, 1);
3032 /* Allocate a color which is lighter or darker than *COLOR by FACTOR
3033 or DELTA. Try a color with RGB values multiplied by FACTOR first.
3034 If this produces the same color as COLOR, try a color where all RGB
3035 values have DELTA added. Return the allocated color in *COLOR.
3036 DISPLAY is the X display, CMAP is the colormap to operate on.
3037 Value is non-zero if successful. */
3039 static int
3040 w32_alloc_lighter_color (f, color, factor, delta)
3041 struct frame *f;
3042 COLORREF *color;
3043 double factor;
3044 int delta;
3046 COLORREF new;
3048 /* Change RGB values by specified FACTOR. Avoid overflow! */
3049 xassert (factor >= 0);
3050 new = PALETTERGB (min (0xff, factor * GetRValue (*color)),
3051 min (0xff, factor * GetGValue (*color)),
3052 min (0xff, factor * GetBValue (*color)));
3053 if (new == *color)
3054 new = PALETTERGB (max (0, min (0xff, delta + GetRValue (*color))),
3055 max (0, min (0xff, delta + GetGValue (*color))),
3056 max (0, min (0xff, delta + GetBValue (*color))));
3058 /* NTEMACS_TODO: Map to palette and retry with delta if same? */
3059 /* NTEMACS_TODO: Free colors (if using palette)? */
3061 if (new == *color)
3062 return 0;
3064 *color = new;
3066 return 1;
3070 /* Set up the foreground color for drawing relief lines of glyph
3071 string S. RELIEF is a pointer to a struct relief containing the GC
3072 with which lines will be drawn. Use a color that is FACTOR or
3073 DELTA lighter or darker than the relief's background which is found
3074 in S->f->output_data.x->relief_background. If such a color cannot
3075 be allocated, use DEFAULT_PIXEL, instead. */
3077 static void
3078 w32_setup_relief_color (f, relief, factor, delta, default_pixel)
3079 struct frame *f;
3080 struct relief *relief;
3081 double factor;
3082 int delta;
3083 COLORREF default_pixel;
3085 XGCValues xgcv;
3086 struct w32_output *di = f->output_data.w32;
3087 unsigned long mask = GCForeground;
3088 COLORREF pixel;
3089 COLORREF background = di->relief_background;
3090 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
3092 /* NTEMACS_TODO: Free colors (if using palette)? */
3094 /* Allocate new color. */
3095 xgcv.foreground = default_pixel;
3096 pixel = background;
3097 if (w32_alloc_lighter_color (f, &pixel, factor, delta))
3099 relief->allocated_p = 1;
3100 xgcv.foreground = relief->pixel = pixel;
3103 if (relief->gc == 0)
3105 #if 0 /* NTEMACS_TODO: stipple */
3106 xgcv.stipple = dpyinfo->gray;
3107 mask |= GCStipple;
3108 #endif
3109 relief->gc = XCreateGC (NULL, FRAME_W32_WINDOW (f), mask, &xgcv);
3111 else
3112 XChangeGC (NULL, relief->gc, mask, &xgcv);
3116 /* Set up colors for the relief lines around glyph string S. */
3118 static void
3119 x_setup_relief_colors (s)
3120 struct glyph_string *s;
3122 struct w32_output *di = s->f->output_data.w32;
3123 COLORREF color;
3125 if (s->face->use_box_color_for_shadows_p)
3126 color = s->face->box_color;
3127 else
3128 color = s->gc->background;
3130 if (di->white_relief.gc == 0
3131 || color != di->relief_background)
3133 di->relief_background = color;
3134 w32_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
3135 WHITE_PIX_DEFAULT (s->f));
3136 w32_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
3137 BLACK_PIX_DEFAULT (s->f));
3142 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
3143 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
3144 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
3145 relief. LEFT_P non-zero means draw a relief on the left side of
3146 the rectangle. RIGHT_P non-zero means draw a relief on the right
3147 side of the rectangle. CLIP_RECT is the clipping rectangle to use
3148 when drawing. */
3150 static void
3151 w32_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
3152 raised_p, left_p, right_p, clip_rect)
3153 struct frame *f;
3154 int left_x, top_y, right_x, bottom_y, left_p, right_p, raised_p;
3155 RECT *clip_rect;
3157 int i;
3158 XGCValues gc;
3159 HDC hdc = get_frame_dc (f);
3161 if (raised_p)
3162 gc.foreground = PALETTERGB (255, 255, 255);
3163 else
3164 gc.foreground = PALETTERGB (0, 0, 0);
3166 w32_set_clip_rectangle (hdc, clip_rect);
3168 /* Top. */
3169 for (i = 0; i < width; ++i)
3171 w32_fill_area (f, hdc, gc.foreground,
3172 left_x + i * left_p, top_y + i,
3173 (right_x + 1 - i * right_p) - (left_x + i * left_p), 1);
3176 /* Left. */
3177 if (left_p)
3178 for (i = 0; i < width; ++i)
3180 w32_fill_area (f, hdc, gc.foreground,
3181 left_x + i, top_y + i, 1,
3182 (bottom_y - i) - (top_y + i));
3185 w32_set_clip_rectangle (hdc, NULL);
3187 if (raised_p)
3188 gc.foreground = PALETTERGB (0, 0, 0);
3189 else
3190 gc.foreground = PALETTERGB (255, 255, 255);
3192 w32_set_clip_rectangle (hdc, clip_rect);
3194 /* Bottom. */
3195 for (i = 0; i < width; ++i)
3197 w32_fill_area (f, hdc, gc.foreground,
3198 left_x + i * left_p, bottom_y - i,
3199 (right_x + 1 - i * right_p) - left_x + i * left_p, 1);
3202 /* Right. */
3203 if (right_p)
3204 for (i = 0; i < width; ++i)
3206 w32_fill_area (f, hdc, gc.foreground,
3207 right_x - i, top_y + i + 1, 1,
3208 (bottom_y - i) - (top_y + i + 1));
3211 w32_set_clip_rectangle (hdc, NULL);
3213 release_frame_dc (f, hdc);
3217 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
3218 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
3219 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
3220 left side of the rectangle. RIGHT_P non-zero means draw a line
3221 on the right side of the rectangle. CLIP_RECT is the clipping
3222 rectangle to use when drawing. */
3224 static void
3225 w32_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
3226 left_p, right_p, clip_rect)
3227 struct glyph_string *s;
3228 int left_x, top_y, right_x, bottom_y, width, left_p, right_p;
3229 RECT *clip_rect;
3231 w32_set_clip_rectangle (s->hdc, clip_rect);
3233 /* Top. */
3234 w32_fill_area (s->f, s->hdc, s->face->box_color,
3235 left_x, top_y, right_x - left_x, width);
3237 /* Left. */
3238 if (left_p)
3240 w32_fill_area (s->f, s->hdc, s->face->box_color,
3241 left_x, top_y, width, bottom_y - top_y);
3244 /* Bottom. */
3245 w32_fill_area (s->f, s->hdc, s->face->box_color,
3246 left_x, bottom_y - width, right_x - left_x, width);
3248 /* Right. */
3249 if (right_p)
3251 w32_fill_area (s->f, s->hdc, s->face->box_color,
3252 right_x - width, top_y, width, bottom_y - top_y);
3255 w32_set_clip_rectangle (s->hdc, NULL);
3259 /* Draw a box around glyph string S. */
3261 static void
3262 x_draw_glyph_string_box (s)
3263 struct glyph_string *s;
3265 int width, left_x, right_x, top_y, bottom_y, last_x, raised_p;
3266 int left_p, right_p;
3267 struct glyph *last_glyph;
3268 RECT clip_rect;
3270 last_x = window_box_right (s->w, s->area);
3271 if (s->row->full_width_p
3272 && !s->w->pseudo_window_p)
3274 last_x += FRAME_X_RIGHT_FLAGS_AREA_WIDTH (s->f);
3275 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (s->f))
3276 last_x += FRAME_SCROLL_BAR_WIDTH (s->f) * CANON_X_UNIT (s->f);
3279 /* The glyph that may have a right box line. */
3280 last_glyph = (s->cmp || s->img
3281 ? s->first_glyph
3282 : s->first_glyph + s->nchars - 1);
3284 width = s->face->box_line_width;
3285 raised_p = s->face->box == FACE_RAISED_BOX;
3286 left_x = s->x;
3287 right_x = ((s->row->full_width_p
3288 ? last_x - 1
3289 : min (last_x, s->x + s->background_width) - 1));
3290 top_y = s->y;
3291 bottom_y = top_y + s->height - 1;
3293 left_p = (s->first_glyph->left_box_line_p
3294 || (s->hl == DRAW_MOUSE_FACE
3295 && (s->prev == NULL
3296 || s->prev->hl != s->hl)));
3297 right_p = (last_glyph->right_box_line_p
3298 || (s->hl == DRAW_MOUSE_FACE
3299 && (s->next == NULL
3300 || s->next->hl != s->hl)));
3302 w32_get_glyph_string_clip_rect (s, &clip_rect);
3304 if (s->face->box == FACE_SIMPLE_BOX)
3305 w32_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
3306 left_p, right_p, &clip_rect);
3307 else
3309 x_setup_relief_colors (s);
3310 w32_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
3311 width, raised_p, left_p, right_p, &clip_rect);
3316 /* Draw foreground of image glyph string S. */
3318 static void
3319 x_draw_image_foreground (s)
3320 struct glyph_string *s;
3322 int x;
3323 int y = s->ybase - image_ascent (s->img, s->face);
3325 /* If first glyph of S has a left box line, start drawing it to the
3326 right of that line. */
3327 if (s->face->box != FACE_NO_BOX
3328 && s->first_glyph->left_box_line_p)
3329 x = s->x + s->face->box_line_width;
3330 else
3331 x = s->x;
3333 /* If there is a margin around the image, adjust x- and y-position
3334 by that margin. */
3335 if (s->img->margin)
3337 x += s->img->margin;
3338 y += s->img->margin;
3341 SaveDC (s->hdc);
3343 if (s->img->pixmap)
3345 #if 0 /* NTEMACS_TODO: image mask */
3346 if (s->img->mask)
3348 /* We can't set both a clip mask and use XSetClipRectangles
3349 because the latter also sets a clip mask. We also can't
3350 trust on the shape extension to be available
3351 (XShapeCombineRegion). So, compute the rectangle to draw
3352 manually. */
3353 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
3354 | GCFunction);
3355 XGCValues xgcv;
3356 XRectangle clip_rect, image_rect, r;
3358 xgcv.clip_mask = s->img->mask;
3359 xgcv.clip_x_origin = x;
3360 xgcv.clip_y_origin = y;
3361 xgcv.function = GXcopy;
3362 XChangeGC (s->display, s->gc, mask, &xgcv);
3364 w32_get_glyph_string_clip_rect (s, &clip_rect);
3365 image_rect.x = x;
3366 image_rect.y = y;
3367 image_rect.width = s->img->width;
3368 image_rect.height = s->img->height;
3369 if (w32_intersect_rectangles (&clip_rect, &image_rect, &r))
3370 XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
3371 r.x - x, r.y - y, r.width, r.height, r.x, r.y);
3373 else
3374 #endif
3376 HDC compat_hdc = CreateCompatibleDC (s->hdc);
3377 HBRUSH fg_brush = CreateSolidBrush (s->gc->foreground);
3378 HBRUSH orig_brush = SelectObject (s->hdc, fg_brush);
3379 HGDIOBJ orig_obj = SelectObject (compat_hdc, s->img->pixmap);
3381 SetTextColor (s->hdc, s->gc->foreground);
3382 SetBkColor (s->hdc, s->gc->background);
3383 #if 0 /* From w32bdf.c (which is from Meadow). */
3384 BitBlt (s->hdc, x, y, s->img->width, s->img->height,
3385 compat_hdc, 0, 0, SRCCOPY);
3386 #else
3387 BitBlt (s->hdc, x, y, s->img->width, s->img->height,
3388 compat_hdc, 0, 0, 0xB8074A);
3389 #endif
3390 SelectObject (s->hdc, orig_brush);
3391 DeleteObject (fg_brush);
3392 SelectObject (compat_hdc, orig_obj);
3393 DeleteDC (compat_hdc);
3395 /* When the image has a mask, we can expect that at
3396 least part of a mouse highlight or a block cursor will
3397 be visible. If the image doesn't have a mask, make
3398 a block cursor visible by drawing a rectangle around
3399 the image. I believe it's looking better if we do
3400 nothing here for mouse-face. */
3401 if (s->hl == DRAW_CURSOR)
3402 w32_draw_rectangle (s->hdc, s->gc, x, y, s->img->width - 1,
3403 s->img->height - 1);
3406 else
3407 w32_draw_rectangle (s->hdc, s->gc, x, y, s->img->width -1,
3408 s->img->height - 1);
3410 RestoreDC (s->hdc ,-1);
3415 /* Draw a relief around the image glyph string S. */
3417 static void
3418 x_draw_image_relief (s)
3419 struct glyph_string *s;
3421 int x0, y0, x1, y1, thick, raised_p;
3422 RECT r;
3423 int x;
3424 int y = s->ybase - image_ascent (s->img, s->face);
3426 /* If first glyph of S has a left box line, start drawing it to the
3427 right of that line. */
3428 if (s->face->box != FACE_NO_BOX
3429 && s->first_glyph->left_box_line_p)
3430 x = s->x + s->face->box_line_width;
3431 else
3432 x = s->x;
3434 /* If there is a margin around the image, adjust x- and y-position
3435 by that margin. */
3436 if (s->img->margin)
3438 x += s->img->margin;
3439 y += s->img->margin;
3442 if (s->hl == DRAW_IMAGE_SUNKEN
3443 || s->hl == DRAW_IMAGE_RAISED)
3445 thick = tool_bar_button_relief > 0 ? tool_bar_button_relief : 3;
3446 raised_p = s->hl == DRAW_IMAGE_RAISED;
3448 else
3450 thick = abs (s->img->relief);
3451 raised_p = s->img->relief > 0;
3454 x0 = x - thick;
3455 y0 = y - thick;
3456 x1 = x + s->img->width + thick - 1;
3457 y1 = y + s->img->height + thick - 1;
3459 x_setup_relief_colors (s);
3460 w32_get_glyph_string_clip_rect (s, &r);
3461 w32_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p, 1, 1, &r);
3465 /* Draw the foreground of image glyph string S to PIXMAP. */
3467 static void
3468 w32_draw_image_foreground_1 (s, pixmap)
3469 struct glyph_string *s;
3470 HBITMAP pixmap;
3472 HDC hdc = CreateCompatibleDC (s->hdc);
3473 HGDIOBJ orig_hdc_obj = SelectObject (hdc, pixmap);
3474 int x;
3475 int y = s->ybase - s->y - image_ascent (s->img, s->face);
3477 /* If first glyph of S has a left box line, start drawing it to the
3478 right of that line. */
3479 if (s->face->box != FACE_NO_BOX
3480 && s->first_glyph->left_box_line_p)
3481 x = s->face->box_line_width;
3482 else
3483 x = 0;
3485 /* If there is a margin around the image, adjust x- and y-position
3486 by that margin. */
3487 if (s->img->margin)
3489 x += s->img->margin;
3490 y += s->img->margin;
3493 if (s->img->pixmap)
3495 #if 0 /* NTEMACS_TODO: image mask */
3496 if (s->img->mask)
3498 /* We can't set both a clip mask and use XSetClipRectangles
3499 because the latter also sets a clip mask. We also can't
3500 trust on the shape extension to be available
3501 (XShapeCombineRegion). So, compute the rectangle to draw
3502 manually. */
3503 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
3504 | GCFunction);
3505 XGCValues xgcv;
3507 xgcv.clip_mask = s->img->mask;
3508 xgcv.clip_x_origin = x;
3509 xgcv.clip_y_origin = y;
3510 xgcv.function = GXcopy;
3511 XChangeGC (s->display, s->gc, mask, &xgcv);
3513 XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
3514 0, 0, s->img->width, s->img->height, x, y);
3515 XSetClipMask (s->display, s->gc, None);
3517 else
3518 #endif
3520 HDC compat_hdc = CreateCompatibleDC (hdc);
3521 HBRUSH fg_brush = CreateSolidBrush (s->gc->foreground);
3522 HBRUSH orig_brush = SelectObject (hdc, fg_brush);
3523 HGDIOBJ orig_obj = SelectObject (compat_hdc, s->img->pixmap);
3525 SetTextColor (hdc, s->gc->foreground);
3526 SetBkColor (hdc, s->gc->background);
3527 #if 0 /* From w32bdf.c (which is from Meadow). */
3528 BitBlt (hdc, x, y, s->img->width, s->img->height,
3529 compat_hdc, 0, 0, SRCCOPY);
3530 #else
3531 BitBlt (hdc, x, y, s->img->width, s->img->height,
3532 compat_hdc, 0, 0, 0xB8074A);
3533 #endif
3534 SelectObject (hdc, orig_brush);
3535 DeleteObject (fg_brush);
3536 SelectObject (compat_hdc, orig_obj);
3537 DeleteDC (compat_hdc);
3539 /* When the image has a mask, we can expect that at
3540 least part of a mouse highlight or a block cursor will
3541 be visible. If the image doesn't have a mask, make
3542 a block cursor visible by drawing a rectangle around
3543 the image. I believe it's looking better if we do
3544 nothing here for mouse-face. */
3545 if (s->hl == DRAW_CURSOR)
3546 w32_draw_rectangle (hdc, s->gc, x, y, s->img->width - 1,
3547 s->img->height - 1);
3550 else
3551 w32_draw_rectangle (hdc, s->gc, x, y, s->img->width - 1,
3552 s->img->height - 1);
3554 SelectObject (hdc, orig_hdc_obj);
3555 DeleteDC (hdc);
3559 /* Draw part of the background of glyph string S. X, Y, W, and H
3560 give the rectangle to draw. */
3562 static void
3563 x_draw_glyph_string_bg_rect (s, x, y, w, h)
3564 struct glyph_string *s;
3565 int x, y, w, h;
3567 #if 0 /* NTEMACS_TODO: stipple */
3568 if (s->stippled_p)
3570 /* Fill background with a stipple pattern. */
3571 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
3572 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
3573 XSetFillStyle (s->display, s->gc, FillSolid);
3575 else
3576 #endif
3577 x_clear_glyph_string_rect (s, x, y, w, h);
3581 /* Draw image glyph string S.
3583 s->y
3584 s->x +-------------------------
3585 | s->face->box
3587 | +-------------------------
3588 | | s->img->margin
3590 | | +-------------------
3591 | | | the image
3595 static void
3596 x_draw_image_glyph_string (s)
3597 struct glyph_string *s;
3599 int x, y;
3600 int box_line_width = s->face->box_line_width;
3601 int margin = s->img->margin;
3602 int height;
3603 HBITMAP pixmap = 0;
3605 height = s->height - 2 * box_line_width;
3607 /* Fill background with face under the image. Do it only if row is
3608 taller than image or if image has a clip mask to reduce
3609 flickering. */
3610 s->stippled_p = s->face->stipple != 0;
3611 if (height > s->img->height
3612 || margin
3613 #if 0 /* NTEMACS_TODO: image mask */
3614 || s->img->mask
3615 #endif
3616 || s->img->pixmap == 0
3617 || s->width != s->background_width)
3619 if (box_line_width && s->first_glyph->left_box_line_p)
3620 x = s->x + box_line_width;
3621 else
3622 x = s->x;
3624 y = s->y + box_line_width;
3625 #if 0 /* NTEMACS_TODO: image mask */
3626 if (s->img->mask)
3628 /* Create a pixmap as large as the glyph string Fill it with
3629 the background color. Copy the image to it, using its
3630 mask. Copy the temporary pixmap to the display. */
3631 Screen *screen = FRAME_X_SCREEN (s->f);
3632 int depth = DefaultDepthOfScreen (screen);
3634 /* Create a pixmap as large as the glyph string. */
3635 pixmap = XCreatePixmap (s->display, s->window,
3636 s->background_width,
3637 s->height, depth);
3639 /* Don't clip in the following because we're working on the
3640 pixmap. */
3641 XSetClipMask (s->display, s->gc, None);
3643 /* Fill the pixmap with the background color/stipple. */
3644 if (s->stippled_p)
3646 /* Fill background with a stipple pattern. */
3647 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
3648 XFillRectangle (s->display, pixmap, s->gc,
3649 0, 0, s->background_width, s->height);
3650 XSetFillStyle (s->display, s->gc, FillSolid);
3652 else
3654 XGCValues xgcv;
3655 XGetGCValues (s->display, s->gc, GCForeground | GCBackground,
3656 &xgcv);
3657 XSetForeground (s->display, s->gc, xgcv.background);
3658 XFillRectangle (s->display, pixmap, s->gc,
3659 0, 0, s->background_width, s->height);
3660 XSetForeground (s->display, s->gc, xgcv.foreground);
3663 else
3664 #endif
3665 /* Implementation idea: Is it possible to construct a mask?
3666 We could look at the color at the margins of the image, and
3667 say that this color is probably the background color of the
3668 image. */
3669 x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
3671 s->background_filled_p = 1;
3674 /* Draw the foreground. */
3675 if (pixmap != 0)
3677 w32_draw_image_foreground_1 (s, pixmap);
3678 x_set_glyph_string_clipping (s);
3680 HDC compat_hdc = CreateCompatibleDC (s->hdc);
3681 HBRUSH fg_brush = CreateSolidBrush (s->gc->foreground);
3682 HBRUSH orig_brush = SelectObject (s->hdc, fg_brush);
3683 HGDIOBJ orig_obj = SelectObject (compat_hdc, pixmap);
3685 SetTextColor (s->hdc, s->gc->foreground);
3686 SetBkColor (s->hdc, s->gc->background);
3687 #if 0 /* From w32bdf.c (which is from Meadow). */
3688 BitBlt (s->hdc, s->x, s->y, s->background_width, s->height,
3689 compat_hdc, 0, 0, SRCCOPY);
3690 #else
3691 BitBlt (s->hdc, s->x, s->y, s->background_width, s->height,
3692 compat_hdc, 0, 0, 0xB8074A);
3693 #endif
3694 SelectObject (s->hdc, orig_brush);
3695 DeleteObject (fg_brush);
3696 SelectObject (compat_hdc, orig_obj);
3697 DeleteDC (compat_hdc);
3699 DeleteObject (pixmap);
3700 pixmap = 0;
3702 else
3703 x_draw_image_foreground (s);
3705 /* If we must draw a relief around the image, do it. */
3706 if (s->img->relief
3707 || s->hl == DRAW_IMAGE_RAISED
3708 || s->hl == DRAW_IMAGE_SUNKEN)
3709 x_draw_image_relief (s);
3713 /* Draw stretch glyph string S. */
3715 static void
3716 x_draw_stretch_glyph_string (s)
3717 struct glyph_string *s;
3719 xassert (s->first_glyph->type == STRETCH_GLYPH);
3720 s->stippled_p = s->face->stipple != 0;
3722 if (s->hl == DRAW_CURSOR
3723 && !x_stretch_cursor_p)
3725 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
3726 as wide as the stretch glyph. */
3727 int width = min (CANON_X_UNIT (s->f), s->background_width);
3729 /* Draw cursor. */
3730 x_draw_glyph_string_bg_rect (s, s->x, s->y, width, s->height);
3732 /* Clear rest using the GC of the original non-cursor face. */
3733 if (width < s->background_width)
3735 XGCValues *gc = s->face->gc;
3736 int x = s->x + width, y = s->y;
3737 int w = s->background_width - width, h = s->height;
3738 RECT r;
3739 HDC hdc = s->hdc;
3740 w32_get_glyph_string_clip_rect (s, &r);
3741 w32_set_clip_rectangle (hdc, &r);
3743 #if 0 /* NTEMACS_TODO: stipple */
3744 if (s->face->stipple)
3746 /* Fill background with a stipple pattern. */
3747 XSetFillStyle (s->display, gc, FillOpaqueStippled);
3748 XFillRectangle (s->display, s->window, gc, x, y, w, h);
3749 XSetFillStyle (s->display, gc, FillSolid);
3751 else
3752 #endif
3754 w32_fill_area (s->f, s->hdc, gc->background, x, y, w, h);
3758 else
3759 x_draw_glyph_string_bg_rect (s, s->x, s->y, s->background_width,
3760 s->height);
3762 s->background_filled_p = 1;
3766 /* Draw glyph string S. */
3768 static void
3769 x_draw_glyph_string (s)
3770 struct glyph_string *s;
3772 /* If S draws into the background of its successor, draw the
3773 background of the successor first so that S can draw into it.
3774 This makes S->next use XDrawString instead of XDrawImageString. */
3775 if (s->next && s->right_overhang && !s->for_overlaps_p)
3777 xassert (s->next->img == NULL);
3778 x_set_glyph_string_gc (s->next);
3779 x_set_glyph_string_clipping (s->next);
3780 x_draw_glyph_string_background (s->next, 1);
3783 /* Set up S->gc, set clipping and draw S. */
3784 x_set_glyph_string_gc (s);
3785 x_set_glyph_string_clipping (s);
3787 switch (s->first_glyph->type)
3789 case IMAGE_GLYPH:
3790 x_draw_image_glyph_string (s);
3791 break;
3793 case STRETCH_GLYPH:
3794 x_draw_stretch_glyph_string (s);
3795 break;
3797 case CHAR_GLYPH:
3798 if (s->for_overlaps_p)
3799 s->background_filled_p = 1;
3800 else
3801 x_draw_glyph_string_background (s, 0);
3802 x_draw_glyph_string_foreground (s);
3803 break;
3805 case COMPOSITE_GLYPH:
3806 if (s->for_overlaps_p || s->gidx > 0)
3807 s->background_filled_p = 1;
3808 else
3809 x_draw_glyph_string_background (s, 1);
3810 x_draw_composite_glyph_string_foreground (s);
3811 break;
3813 default:
3814 abort ();
3817 if (!s->for_overlaps_p)
3819 /* Draw underline. */
3820 if (s->face->underline_p
3821 && (s->font->bdf || !s->font->tm.tmUnderlined))
3823 unsigned long h = 1;
3824 unsigned long dy = s->height - h;
3826 if (s->face->underline_defaulted_p)
3828 w32_fill_area (s->f, s->hdc, s->gc->foreground, s->x,
3829 s->y + dy, s->width, 1);
3831 else
3833 w32_fill_area (s->f, s->hdc, s->face->underline_color, s->x,
3834 s->y + dy, s->width, 1);
3838 /* Draw overline. */
3839 if (s->face->overline_p)
3841 unsigned long dy = 0, h = 1;
3843 if (s->face->overline_color_defaulted_p)
3845 w32_fill_area (s->f, s->hdc, s->gc->foreground, s->x,
3846 s->y + dy, s->width, h);
3848 else
3850 w32_fill_area (s->f, s->hdc, s->face->underline_color, s->x,
3851 s->y + dy, s->width, h);
3855 /* Draw strike-through. */
3856 if (s->face->strike_through_p
3857 && (s->font->bdf || !s->font->tm.tmStruckOut))
3859 unsigned long h = 1;
3860 unsigned long dy = (s->height - h) / 2;
3862 if (s->face->strike_through_color_defaulted_p)
3864 w32_fill_area (s->f, s->hdc, s->gc->foreground, s->x, s->y + dy,
3865 s->width, h);
3867 else
3869 w32_fill_area (s->f, s->hdc, s->face->underline_color, s->x,
3870 s->y + dy, s->width, h);
3874 /* Draw relief. */
3875 if (s->face->box != FACE_NO_BOX)
3876 x_draw_glyph_string_box (s);
3879 /* Reset clipping. */
3880 w32_set_clip_rectangle (s->hdc, NULL);
3884 static int x_fill_composite_glyph_string P_ ((struct glyph_string *,
3885 struct face **, int));
3888 /* Load glyph string S with a composition components specified by S->cmp.
3889 FACES is an array of faces for all components of this composition.
3890 S->gidx is the index of the first component for S.
3891 OVERLAPS_P non-zero means S should draw the foreground only, and
3892 use its lines physical height for clipping.
3894 Value is the index of a component not in S. */
3896 static int
3897 x_fill_composite_glyph_string (s, faces, overlaps_p)
3898 struct glyph_string *s;
3899 struct face **faces;
3900 int overlaps_p;
3902 int i;
3904 xassert (s);
3906 s->for_overlaps_p = overlaps_p;
3908 s->face = faces[s->gidx];
3909 s->font = s->face->font;
3910 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
3912 /* For all glyphs of this composition, starting at the offset
3913 S->gidx, until we reach the end of the definition or encounter a
3914 glyph that requires the different face, add it to S. */
3915 ++s->nchars;
3916 for (i = s->gidx + 1; i < s->cmp->glyph_len && faces[i] == s->face; ++i)
3917 ++s->nchars;
3919 /* All glyph strings for the same composition has the same width,
3920 i.e. the width set for the first component of the composition. */
3922 s->width = s->first_glyph->pixel_width;
3924 /* If the specified font could not be loaded, use the frame's
3925 default font, but record the fact that we couldn't load it in
3926 the glyph string so that we can draw rectangles for the
3927 characters of the glyph string. */
3928 if (s->font == NULL)
3930 s->font_not_found_p = 1;
3931 s->font = FRAME_FONT (s->f);
3934 /* Adjust base line for subscript/superscript text. */
3935 s->ybase += s->first_glyph->voffset;
3937 xassert (s->face && s->face->gc);
3939 /* This glyph string must always be drawn with 16-bit functions. */
3940 s->two_byte_p = 1;
3942 return s->gidx + s->nchars;
3946 /* Load glyph string S with a sequence of characters.
3947 FACE_ID is the face id of the string. START is the index of the
3948 first glyph to consider, END is the index of the last + 1.
3949 OVERLAPS_P non-zero means S should draw the foreground only, and
3950 use its lines physical height for clipping.
3952 Value is the index of the first glyph not in S. */
3954 static int
3955 x_fill_glyph_string (s, face_id, start, end, overlaps_p)
3956 struct glyph_string *s;
3957 int face_id;
3958 int start, end, overlaps_p;
3960 struct glyph *glyph, *last;
3961 int voffset;
3962 int glyph_not_available_p;
3964 xassert (s->f == XFRAME (s->w->frame));
3965 xassert (s->nchars == 0);
3966 xassert (start >= 0 && end > start);
3968 s->for_overlaps_p = overlaps_p;
3969 glyph = s->row->glyphs[s->area] + start;
3970 last = s->row->glyphs[s->area] + end;
3971 voffset = glyph->voffset;
3973 glyph_not_available_p = glyph->glyph_not_available_p;
3975 while (glyph < last
3976 && glyph->type == CHAR_GLYPH
3977 && glyph->voffset == voffset
3978 /* Same face id implies same font, nowadays. */
3979 && glyph->face_id == face_id
3980 && glyph->glyph_not_available_p == glyph_not_available_p)
3982 int two_byte_p;
3984 s->face = x_get_glyph_face_and_encoding (s->f, glyph,
3985 s->char2b + s->nchars,
3986 &two_byte_p);
3987 s->two_byte_p = two_byte_p;
3988 ++s->nchars;
3989 xassert (s->nchars <= end - start);
3990 s->width += glyph->pixel_width;
3991 ++glyph;
3994 s->font = s->face->font;
3995 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
3997 /* If the specified font could not be loaded, use the frame's font,
3998 but record the fact that we couldn't load it in
3999 S->font_not_found_p so that we can draw rectangles for the
4000 characters of the glyph string. */
4001 if (s->font == NULL || glyph_not_available_p)
4003 s->font_not_found_p = 1;
4004 s->font = FRAME_FONT (s->f);
4007 /* Adjust base line for subscript/superscript text. */
4008 s->ybase += voffset;
4010 xassert (s->face && s->face->gc);
4011 return glyph - s->row->glyphs[s->area];
4015 /* Fill glyph string S from image glyph S->first_glyph. */
4017 static void
4018 x_fill_image_glyph_string (s)
4019 struct glyph_string *s;
4021 xassert (s->first_glyph->type == IMAGE_GLYPH);
4022 s->img = IMAGE_FROM_ID (s->f, s->first_glyph->u.img_id);
4023 xassert (s->img);
4024 s->face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
4025 s->font = s->face->font;
4026 s->width = s->first_glyph->pixel_width;
4028 /* Adjust base line for subscript/superscript text. */
4029 s->ybase += s->first_glyph->voffset;
4033 /* Fill glyph string S from a sequence of stretch glyphs.
4035 ROW is the glyph row in which the glyphs are found, AREA is the
4036 area within the row. START is the index of the first glyph to
4037 consider, END is the index of the last + 1.
4039 Value is the index of the first glyph not in S. */
4041 static int
4042 x_fill_stretch_glyph_string (s, row, area, start, end)
4043 struct glyph_string *s;
4044 struct glyph_row *row;
4045 enum glyph_row_area area;
4046 int start, end;
4048 struct glyph *glyph, *last;
4049 int voffset, face_id;
4051 xassert (s->first_glyph->type == STRETCH_GLYPH);
4053 glyph = s->row->glyphs[s->area] + start;
4054 last = s->row->glyphs[s->area] + end;
4055 face_id = glyph->face_id;
4056 s->face = FACE_FROM_ID (s->f, face_id);
4057 s->font = s->face->font;
4058 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
4059 s->width = glyph->pixel_width;
4060 voffset = glyph->voffset;
4062 for (++glyph;
4063 (glyph < last
4064 && glyph->type == STRETCH_GLYPH
4065 && glyph->voffset == voffset
4066 && glyph->face_id == face_id);
4067 ++glyph)
4068 s->width += glyph->pixel_width;
4070 /* Adjust base line for subscript/superscript text. */
4071 s->ybase += voffset;
4073 xassert (s->face && s->face->gc);
4074 return glyph - s->row->glyphs[s->area];
4078 /* Initialize glyph string S. CHAR2B is a suitably allocated vector
4079 of XChar2b structures for S; it can't be allocated in
4080 x_init_glyph_string because it must be allocated via `alloca'. W
4081 is the window on which S is drawn. ROW and AREA are the glyph row
4082 and area within the row from which S is constructed. START is the
4083 index of the first glyph structure covered by S. HL is a
4084 face-override for drawing S. */
4086 static void
4087 w32_init_glyph_string (s, hdc, char2b, w, row, area, start, hl)
4088 struct glyph_string *s;
4089 HDC hdc;
4090 wchar_t *char2b;
4091 struct window *w;
4092 struct glyph_row *row;
4093 enum glyph_row_area area;
4094 int start;
4095 enum draw_glyphs_face hl;
4097 bzero (s, sizeof *s);
4098 s->w = w;
4099 s->f = XFRAME (w->frame);
4100 s->hdc = hdc;
4101 s->window = FRAME_W32_WINDOW (s->f);
4102 s->char2b = char2b;
4103 s->hl = hl;
4104 s->row = row;
4105 s->area = area;
4106 s->first_glyph = row->glyphs[area] + start;
4107 s->height = row->height;
4108 s->y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
4110 /* Display the internal border below the tool-bar window. */
4111 if (s->w == XWINDOW (s->f->tool_bar_window))
4112 s->y -= s->f->output_data.w32->internal_border_width;
4114 s->ybase = s->y + row->ascent;
4118 /* Set background width of glyph string S. START is the index of the
4119 first glyph following S. LAST_X is the right-most x-position + 1
4120 in the drawing area. */
4122 static INLINE void
4123 x_set_glyph_string_background_width (s, start, last_x)
4124 struct glyph_string *s;
4125 int start;
4126 int last_x;
4128 /* If the face of this glyph string has to be drawn to the end of
4129 the drawing area, set S->extends_to_end_of_line_p. */
4130 struct face *default_face = FACE_FROM_ID (s->f, DEFAULT_FACE_ID);
4132 if (start == s->row->used[s->area]
4133 && s->hl == DRAW_NORMAL_TEXT
4134 && ((s->area == TEXT_AREA && s->row->fill_line_p)
4135 || s->face->background != default_face->background
4136 || s->face->stipple != default_face->stipple))
4137 s->extends_to_end_of_line_p = 1;
4139 /* If S extends its face to the end of the line, set its
4140 background_width to the distance to the right edge of the drawing
4141 area. */
4142 if (s->extends_to_end_of_line_p)
4143 s->background_width = last_x - s->x + 1;
4144 else
4145 s->background_width = s->width;
4149 /* Add a glyph string for a stretch glyph to the list of strings
4150 between HEAD and TAIL. START is the index of the stretch glyph in
4151 row area AREA of glyph row ROW. END is the index of the last glyph
4152 in that glyph row area. X is the current output position assigned
4153 to the new glyph string constructed. HL overrides that face of the
4154 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
4155 is the right-most x-position of the drawing area. */
4157 #define BUILD_STRETCH_GLYPH_STRING(hdc, W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
4158 do \
4160 s = (struct glyph_string *) alloca (sizeof *s); \
4161 w32_init_glyph_string (s, hdc, NULL, W, ROW, AREA, START, HL); \
4162 START = x_fill_stretch_glyph_string (s, ROW, AREA, START, END); \
4163 x_append_glyph_string (&HEAD, &TAIL, s); \
4164 s->x = (X); \
4166 while (0)
4169 /* Add a glyph string for an image glyph to the list of strings
4170 between HEAD and TAIL. START is the index of the image glyph in
4171 row area AREA of glyph row ROW. END is the index of the last glyph
4172 in that glyph row area. X is the current output position assigned
4173 to the new glyph string constructed. HL overrides that face of the
4174 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
4175 is the right-most x-position of the drawing area. */
4177 #define BUILD_IMAGE_GLYPH_STRING(hdc, W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
4178 do \
4180 s = (struct glyph_string *) alloca (sizeof *s); \
4181 w32_init_glyph_string (s, hdc, NULL, W, ROW, AREA, START, HL); \
4182 x_fill_image_glyph_string (s); \
4183 x_append_glyph_string (&HEAD, &TAIL, s); \
4184 ++START; \
4185 s->x = (X); \
4187 while (0)
4190 /* Add a glyph string for a sequence of character glyphs to the list
4191 of strings between HEAD and TAIL. START is the index of the first
4192 glyph in row area AREA of glyph row ROW that is part of the new
4193 glyph string. END is the index of the last glyph in that glyph row
4194 area. X is the current output position assigned to the new glyph
4195 string constructed. HL overrides that face of the glyph; e.g. it
4196 is DRAW_CURSOR if a cursor has to be drawn. LAST_X is the
4197 right-most x-position of the drawing area. */
4199 #define BUILD_CHAR_GLYPH_STRINGS(hdc, W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
4200 do \
4202 int c, face_id; \
4203 wchar_t *char2b; \
4205 c = (ROW)->glyphs[AREA][START].u.ch; \
4206 face_id = (ROW)->glyphs[AREA][START].face_id; \
4208 s = (struct glyph_string *) alloca (sizeof *s); \
4209 char2b = (wchar_t *) alloca ((END - START) * sizeof *char2b); \
4210 w32_init_glyph_string (s, hdc, char2b, W, ROW, AREA, START, HL); \
4211 x_append_glyph_string (&HEAD, &TAIL, s); \
4212 s->x = (X); \
4213 START = x_fill_glyph_string (s, face_id, START, END, \
4214 OVERLAPS_P); \
4216 while (0)
4219 /* Add a glyph string for a composite sequence to the list of strings
4220 between HEAD and TAIL. START is the index of the first glyph in
4221 row area AREA of glyph row ROW that is part of the new glyph
4222 string. END is the index of the last glyph in that glyph row area.
4223 X is the current output position assigned to the new glyph string
4224 constructed. HL overrides that face of the glyph; e.g. it is
4225 DRAW_CURSOR if a cursor has to be drawn. LAST_X is the right-most
4226 x-position of the drawing area. */
4228 #define BUILD_COMPOSITE_GLYPH_STRING(hdc, W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
4229 do { \
4230 int cmp_id = (ROW)->glyphs[AREA][START].u.cmp_id; \
4231 int face_id = (ROW)->glyphs[AREA][START].face_id; \
4232 struct face *base_face = FACE_FROM_ID (XFRAME (w->frame), face_id); \
4233 struct composition *cmp = composition_table[cmp_id]; \
4234 int glyph_len = cmp->glyph_len; \
4235 wchar_t *char2b; \
4236 struct face **faces; \
4237 struct glyph_string *first_s = NULL; \
4238 int n; \
4240 base_face = base_face->ascii_face; \
4241 char2b = (wchar_t *) alloca ((sizeof *char2b) * glyph_len); \
4242 faces = (struct face **) alloca ((sizeof *faces) * glyph_len); \
4243 /* At first, fill in `char2b' and `faces'. */ \
4244 for (n = 0; n < glyph_len; n++) \
4246 int c = COMPOSITION_GLYPH (cmp, n); \
4247 int this_face_id = FACE_FOR_CHAR (XFRAME (w->frame), base_face, c); \
4248 faces[n] = FACE_FROM_ID (XFRAME (w->frame), this_face_id); \
4249 x_get_char_face_and_encoding (XFRAME (w->frame), c, \
4250 this_face_id, char2b + n, 1); \
4253 /* Make glyph_strings for each glyph sequence that is drawable by \
4254 the same face, and append them to HEAD/TAIL. */ \
4255 for (n = 0; n < cmp->glyph_len;) \
4257 s = (struct glyph_string *) alloca (sizeof *s); \
4258 w32_init_glyph_string (s, hdc, char2b + n, W, ROW, AREA, START, HL); \
4259 x_append_glyph_string (&(HEAD), &(TAIL), s); \
4260 s->cmp = cmp; \
4261 s->gidx = n; \
4262 s->x = (X); \
4264 if (n == 0) \
4265 first_s = s; \
4267 n = x_fill_composite_glyph_string (s, faces, OVERLAPS_P); \
4270 ++START; \
4271 s = first_s; \
4272 } while (0)
4275 /* Build a list of glyph strings between HEAD and TAIL for the glyphs
4276 of AREA of glyph row ROW on window W between indices START and END.
4277 HL overrides the face for drawing glyph strings, e.g. it is
4278 DRAW_CURSOR to draw a cursor. X and LAST_X are start and end
4279 x-positions of the drawing area.
4281 This is an ugly monster macro construct because we must use alloca
4282 to allocate glyph strings (because x_draw_glyphs can be called
4283 asynchronously). */
4285 #define BUILD_GLYPH_STRINGS(hdc, W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
4286 do \
4288 HEAD = TAIL = NULL; \
4289 while (START < END) \
4291 struct glyph *first_glyph = (ROW)->glyphs[AREA] + START; \
4292 switch (first_glyph->type) \
4294 case CHAR_GLYPH: \
4295 BUILD_CHAR_GLYPH_STRINGS (hdc, W, ROW, AREA, START, END, \
4296 HEAD, TAIL, HL, X, LAST_X, \
4297 OVERLAPS_P); \
4298 break; \
4300 case COMPOSITE_GLYPH: \
4301 BUILD_COMPOSITE_GLYPH_STRING (hdc, W, ROW, AREA, START, \
4302 END, HEAD, TAIL, HL, X, \
4303 LAST_X, OVERLAPS_P); \
4304 break; \
4306 case STRETCH_GLYPH: \
4307 BUILD_STRETCH_GLYPH_STRING (hdc, W, ROW, AREA, START, END,\
4308 HEAD, TAIL, HL, X, LAST_X); \
4309 break; \
4311 case IMAGE_GLYPH: \
4312 BUILD_IMAGE_GLYPH_STRING (hdc, W, ROW, AREA, START, END, \
4313 HEAD, TAIL, HL, X, LAST_X); \
4314 break; \
4316 default: \
4317 abort (); \
4320 x_set_glyph_string_background_width (s, START, LAST_X); \
4321 (X) += s->width; \
4324 while (0)
4327 /* Draw glyphs between START and END in AREA of ROW on window W,
4328 starting at x-position X. X is relative to AREA in W. HL is a
4329 face-override with the following meaning:
4331 DRAW_NORMAL_TEXT draw normally
4332 DRAW_CURSOR draw in cursor face
4333 DRAW_MOUSE_FACE draw in mouse face.
4334 DRAW_INVERSE_VIDEO draw in mode line face
4335 DRAW_IMAGE_SUNKEN draw an image with a sunken relief around it
4336 DRAW_IMAGE_RAISED draw an image with a raised relief around it
4338 If REAL_START is non-null, return in *REAL_START the real starting
4339 position for display. This can be different from START in case
4340 overlapping glyphs must be displayed. If REAL_END is non-null,
4341 return in *REAL_END the real end position for display. This can be
4342 different from END in case overlapping glyphs must be displayed.
4344 If OVERLAPS_P is non-zero, draw only the foreground of characters
4345 and clip to the physical height of ROW.
4347 Value is the x-position reached, relative to AREA of W. */
4349 static int
4350 x_draw_glyphs (w, x, row, area, start, end, hl, real_start, real_end,
4351 overlaps_p)
4352 struct window *w;
4353 int x;
4354 struct glyph_row *row;
4355 enum glyph_row_area area;
4356 int start, end;
4357 enum draw_glyphs_face hl;
4358 int *real_start, *real_end;
4359 int overlaps_p;
4361 struct glyph_string *head, *tail;
4362 struct glyph_string *s;
4363 int last_x, area_width;
4364 int x_reached;
4365 int i, j;
4366 HDC hdc = get_frame_dc (XFRAME (WINDOW_FRAME (w)));
4368 /* Let's rather be paranoid than getting a SEGV. */
4369 start = max (0, start);
4370 end = min (end, row->used[area]);
4371 if (real_start)
4372 *real_start = start;
4373 if (real_end)
4374 *real_end = end;
4376 /* Translate X to frame coordinates. Set last_x to the right
4377 end of the drawing area. */
4378 if (row->full_width_p)
4380 /* X is relative to the left edge of W, without scroll bars
4381 or flag areas. */
4382 struct frame *f = XFRAME (WINDOW_FRAME (w));
4383 /* int width = FRAME_FLAGS_AREA_WIDTH (f); */
4384 int window_left_x = WINDOW_LEFT_MARGIN (w) * CANON_X_UNIT (f);
4386 x += window_left_x;
4387 area_width = XFASTINT (w->width) * CANON_X_UNIT (f);
4388 last_x = window_left_x + area_width;
4390 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
4392 int width = FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
4393 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
4394 last_x += width;
4395 else
4396 x -= width;
4399 x += FRAME_INTERNAL_BORDER_WIDTH (f);
4400 last_x -= FRAME_INTERNAL_BORDER_WIDTH (f);
4402 else
4404 x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, x);
4405 area_width = window_box_width (w, area);
4406 last_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, area_width);
4409 /* Build a doubly-linked list of glyph_string structures between
4410 head and tail from what we have to draw. Note that the macro
4411 BUILD_GLYPH_STRINGS will modify its start parameter. That's
4412 the reason we use a separate variable `i'. */
4413 i = start;
4414 BUILD_GLYPH_STRINGS (hdc, w, row, area, i, end, head, tail, hl, x, last_x,
4415 overlaps_p);
4416 if (tail)
4417 x_reached = tail->x + tail->background_width;
4418 else
4419 x_reached = x;
4421 /* If there are any glyphs with lbearing < 0 or rbearing > width in
4422 the row, redraw some glyphs in front or following the glyph
4423 strings built above. */
4424 if (!overlaps_p && row->contains_overlapping_glyphs_p)
4426 int dummy_x = 0;
4427 struct glyph_string *h, *t;
4429 /* Compute overhangs for all glyph strings. */
4430 for (s = head; s; s = s->next)
4431 x_compute_glyph_string_overhangs (s);
4433 /* Prepend glyph strings for glyphs in front of the first glyph
4434 string that are overwritten because of the first glyph
4435 string's left overhang. The background of all strings
4436 prepended must be drawn because the first glyph string
4437 draws over it. */
4438 i = x_left_overwritten (head);
4439 if (i >= 0)
4441 j = i;
4442 BUILD_GLYPH_STRINGS (hdc, w, row, area, j, start, h, t,
4443 DRAW_NORMAL_TEXT, dummy_x, last_x,
4444 overlaps_p);
4445 start = i;
4446 if (real_start)
4447 *real_start = start;
4448 x_compute_overhangs_and_x (t, head->x, 1);
4449 x_prepend_glyph_string_lists (&head, &tail, h, t);
4452 /* Prepend glyph strings for glyphs in front of the first glyph
4453 string that overwrite that glyph string because of their
4454 right overhang. For these strings, only the foreground must
4455 be drawn, because it draws over the glyph string at `head'.
4456 The background must not be drawn because this would overwrite
4457 right overhangs of preceding glyphs for which no glyph
4458 strings exist. */
4459 i = x_left_overwriting (head);
4460 if (i >= 0)
4462 BUILD_GLYPH_STRINGS (hdc, w, row, area, i, start, h, t,
4463 DRAW_NORMAL_TEXT, dummy_x, last_x,
4464 overlaps_p);
4465 for (s = h; s; s = s->next)
4466 s->background_filled_p = 1;
4467 if (real_start)
4468 *real_start = i;
4469 x_compute_overhangs_and_x (t, head->x, 1);
4470 x_prepend_glyph_string_lists (&head, &tail, h, t);
4473 /* Append glyphs strings for glyphs following the last glyph
4474 string tail that are overwritten by tail. The background of
4475 these strings has to be drawn because tail's foreground draws
4476 over it. */
4477 i = x_right_overwritten (tail);
4478 if (i >= 0)
4480 BUILD_GLYPH_STRINGS (hdc, w, row, area, end, i, h, t,
4481 DRAW_NORMAL_TEXT, x, last_x,
4482 overlaps_p);
4483 x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
4484 x_append_glyph_string_lists (&head, &tail, h, t);
4485 if (real_end)
4486 *real_end = i;
4489 /* Append glyph strings for glyphs following the last glyph
4490 string tail that overwrite tail. The foreground of such
4491 glyphs has to be drawn because it writes into the background
4492 of tail. The background must not be drawn because it could
4493 paint over the foreground of following glyphs. */
4494 i = x_right_overwriting (tail);
4495 if (i >= 0)
4497 BUILD_GLYPH_STRINGS (hdc, w, row, area, end, i, h, t,
4498 DRAW_NORMAL_TEXT, x, last_x,
4499 overlaps_p);
4500 for (s = h; s; s = s->next)
4501 s->background_filled_p = 1;
4502 x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
4503 x_append_glyph_string_lists (&head, &tail, h, t);
4504 if (real_end)
4505 *real_end = i;
4509 /* Draw all strings. */
4510 for (s = head; s; s = s->next)
4511 x_draw_glyph_string (s);
4513 /* Value is the x-position up to which drawn, relative to AREA of W.
4514 This doesn't include parts drawn because of overhangs. */
4515 x_reached = FRAME_TO_WINDOW_PIXEL_X (w, x_reached);
4516 if (!row->full_width_p)
4518 if (area > LEFT_MARGIN_AREA)
4519 x_reached -= window_box_width (w, LEFT_MARGIN_AREA);
4520 if (area > TEXT_AREA)
4521 x_reached -= window_box_width (w, TEXT_AREA);
4524 release_frame_dc (XFRAME (WINDOW_FRAME (w)), hdc);
4526 return x_reached;
4530 /* Fix the display of area AREA of overlapping row ROW in window W. */
4532 static void
4533 x_fix_overlapping_area (w, row, area)
4534 struct window *w;
4535 struct glyph_row *row;
4536 enum glyph_row_area area;
4538 int i, x;
4540 BLOCK_INPUT;
4542 if (area == LEFT_MARGIN_AREA)
4543 x = 0;
4544 else if (area == TEXT_AREA)
4545 x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
4546 else
4547 x = (window_box_width (w, LEFT_MARGIN_AREA)
4548 + window_box_width (w, TEXT_AREA));
4550 for (i = 0; i < row->used[area];)
4552 if (row->glyphs[area][i].overlaps_vertically_p)
4554 int start = i, start_x = x;
4558 x += row->glyphs[area][i].pixel_width;
4559 ++i;
4561 while (i < row->used[area]
4562 && row->glyphs[area][i].overlaps_vertically_p);
4564 x_draw_glyphs (w, start_x, row, area, start, i,
4565 (row->inverse_p
4566 ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT),
4567 NULL, NULL, 1);
4569 else
4571 x += row->glyphs[area][i].pixel_width;
4572 ++i;
4576 UNBLOCK_INPUT;
4580 /* Output LEN glyphs starting at START at the nominal cursor position.
4581 Advance the nominal cursor over the text. The global variable
4582 updated_window contains the window being updated, updated_row is
4583 the glyph row being updated, and updated_area is the area of that
4584 row being updated. */
4586 static void
4587 x_write_glyphs (start, len)
4588 struct glyph *start;
4589 int len;
4591 int x, hpos, real_start, real_end;
4593 xassert (updated_window && updated_row);
4594 BLOCK_INPUT;
4596 /* Write glyphs. */
4598 hpos = start - updated_row->glyphs[updated_area];
4599 x = x_draw_glyphs (updated_window, output_cursor.x,
4600 updated_row, updated_area,
4601 hpos, hpos + len,
4602 (updated_row->inverse_p
4603 ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT),
4604 &real_start, &real_end, 0);
4606 /* If we drew over the cursor, note that it is not visible any more. */
4607 note_overwritten_text_cursor (updated_window, real_start,
4608 real_end - real_start);
4610 UNBLOCK_INPUT;
4612 /* Advance the output cursor. */
4613 output_cursor.hpos += len;
4614 output_cursor.x = x;
4618 /* Insert LEN glyphs from START at the nominal cursor position. */
4620 static void
4621 x_insert_glyphs (start, len)
4622 struct glyph *start;
4623 register int len;
4625 struct frame *f;
4626 struct window *w;
4627 int line_height, shift_by_width, shifted_region_width;
4628 struct glyph_row *row;
4629 struct glyph *glyph;
4630 int frame_x, frame_y, hpos, real_start, real_end;
4631 HDC hdc;
4633 xassert (updated_window && updated_row);
4634 BLOCK_INPUT;
4635 w = updated_window;
4636 f = XFRAME (WINDOW_FRAME (w));
4637 hdc = get_frame_dc (f);
4639 /* Get the height of the line we are in. */
4640 row = updated_row;
4641 line_height = row->height;
4643 /* Get the width of the glyphs to insert. */
4644 shift_by_width = 0;
4645 for (glyph = start; glyph < start + len; ++glyph)
4646 shift_by_width += glyph->pixel_width;
4648 /* Get the width of the region to shift right. */
4649 shifted_region_width = (window_box_width (w, updated_area)
4650 - output_cursor.x
4651 - shift_by_width);
4653 /* Shift right. */
4654 frame_x = WINDOW_TO_FRAME_PIXEL_X (w, output_cursor.x);
4655 frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, output_cursor.y);
4656 BitBlt (hdc, frame_x + shift_by_width, frame_y,
4657 shifted_region_width, line_height,
4658 hdc, frame_x, frame_y, SRCCOPY);
4660 /* Write the glyphs. */
4661 hpos = start - row->glyphs[updated_area];
4662 x_draw_glyphs (w, output_cursor.x, row, updated_area, hpos, hpos + len,
4663 DRAW_NORMAL_TEXT, &real_start, &real_end, 0);
4664 note_overwritten_text_cursor (w, real_start, real_end - real_start);
4666 /* Advance the output cursor. */
4667 output_cursor.hpos += len;
4668 output_cursor.x += shift_by_width;
4669 release_frame_dc (f, hdc);
4671 UNBLOCK_INPUT;
4675 /* Delete N glyphs at the nominal cursor position. Not implemented
4676 for X frames. */
4678 static void
4679 x_delete_glyphs (n)
4680 register int n;
4682 abort ();
4686 /* Erase the current text line from the nominal cursor position
4687 (inclusive) to pixel column TO_X (exclusive). The idea is that
4688 everything from TO_X onward is already erased.
4690 TO_X is a pixel position relative to updated_area of
4691 updated_window. TO_X == -1 means clear to the end of this area. */
4693 static void
4694 x_clear_end_of_line (to_x)
4695 int to_x;
4697 struct frame *f;
4698 struct window *w = updated_window;
4699 int max_x, min_y, max_y;
4700 int from_x, from_y, to_y;
4702 xassert (updated_window && updated_row);
4703 f = XFRAME (w->frame);
4705 if (updated_row->full_width_p)
4707 max_x = XFASTINT (w->width) * CANON_X_UNIT (f);
4708 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f)
4709 && !w->pseudo_window_p)
4710 max_x += FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
4712 else
4713 max_x = window_box_width (w, updated_area);
4714 max_y = window_text_bottom_y (w);
4716 /* TO_X == 0 means don't do anything. TO_X < 0 means clear to end
4717 of window. For TO_X > 0, truncate to end of drawing area. */
4718 if (to_x == 0)
4719 return;
4720 else if (to_x < 0)
4721 to_x = max_x;
4722 else
4723 to_x = min (to_x, max_x);
4725 to_y = min (max_y, output_cursor.y + updated_row->height);
4727 /* Notice if the cursor will be cleared by this operation. */
4728 if (!updated_row->full_width_p)
4729 note_overwritten_text_cursor (w, output_cursor.hpos, -1);
4731 from_x = output_cursor.x;
4733 /* Translate to frame coordinates. */
4734 if (updated_row->full_width_p)
4736 from_x = WINDOW_TO_FRAME_PIXEL_X (w, from_x);
4737 to_x = WINDOW_TO_FRAME_PIXEL_X (w, to_x);
4739 else
4741 from_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, from_x);
4742 to_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, to_x);
4745 min_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
4746 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, max (min_y, output_cursor.y));
4747 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, to_y);
4749 /* Prevent inadvertently clearing to end of the X window. */
4750 if (to_x > from_x && to_y > from_y)
4752 HDC hdc;
4753 BLOCK_INPUT;
4754 hdc = get_frame_dc (f);
4756 w32_clear_area (f, hdc, from_x, from_y, to_x - from_x, to_y - from_y);
4757 release_frame_dc (f, hdc);
4758 UNBLOCK_INPUT;
4763 /* Clear entire frame. If updating_frame is non-null, clear that
4764 frame. Otherwise clear the selected frame. */
4766 static void
4767 x_clear_frame ()
4769 struct frame *f;
4771 if (updating_frame)
4772 f = updating_frame;
4773 else
4774 f = SELECTED_FRAME ();
4776 /* Clearing the frame will erase any cursor, so mark them all as no
4777 longer visible. */
4778 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
4779 output_cursor.hpos = output_cursor.vpos = 0;
4780 output_cursor.x = -1;
4782 /* We don't set the output cursor here because there will always
4783 follow an explicit cursor_to. */
4784 BLOCK_INPUT;
4786 w32_clear_window (f);
4788 /* We have to clear the scroll bars, too. If we have changed
4789 colors or something like that, then they should be notified. */
4790 x_scroll_bar_clear (f);
4792 UNBLOCK_INPUT;
4796 /* Make audible bell. */
4798 static void
4799 w32_ring_bell (void)
4801 BLOCK_INPUT;
4803 if (visible_bell)
4805 int i;
4806 HWND hwnd = FRAME_W32_WINDOW (SELECTED_FRAME ());
4808 for (i = 0; i < 5; i++)
4810 FlashWindow (hwnd, TRUE);
4811 Sleep (10);
4813 FlashWindow (hwnd, FALSE);
4815 else
4816 w32_sys_ring_bell ();
4818 UNBLOCK_INPUT;
4822 /* Specify how many text lines, from the top of the window,
4823 should be affected by insert-lines and delete-lines operations.
4824 This, and those operations, are used only within an update
4825 that is bounded by calls to x_update_begin and x_update_end. */
4827 static void
4828 w32_set_terminal_window (n)
4829 register int n;
4831 /* This function intentionally left blank. */
4836 /***********************************************************************
4837 Line Dance
4838 ***********************************************************************/
4840 /* Perform an insert-lines or delete-lines operation, inserting N
4841 lines or deleting -N lines at vertical position VPOS. */
4843 static void
4844 x_ins_del_lines (vpos, n)
4845 int vpos, n;
4847 abort ();
4851 /* Scroll part of the display as described by RUN. */
4853 static void
4854 x_scroll_run (w, run)
4855 struct window *w;
4856 struct run *run;
4858 struct frame *f = XFRAME (w->frame);
4859 int x, y, width, height, from_y, to_y, bottom_y;
4860 HDC hdc = get_frame_dc (f);
4862 /* Get frame-relative bounding box of the text display area of W,
4863 without mode lines. Include in this box the flags areas to the
4864 left and right of W. */
4865 window_box (w, -1, &x, &y, &width, &height);
4866 width += FRAME_X_FLAGS_AREA_WIDTH (f);
4867 x -= FRAME_X_LEFT_FLAGS_AREA_WIDTH (f);
4869 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
4870 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
4871 bottom_y = y + height;
4873 if (to_y < from_y)
4875 /* Scrolling up. Make sure we don't copy part of the mode
4876 line at the bottom. */
4877 if (from_y + run->height > bottom_y)
4878 height = bottom_y - from_y;
4879 else
4880 height = run->height;
4882 else
4884 /* Scolling down. Make sure we don't copy over the mode line.
4885 at the bottom. */
4886 if (to_y + run->height > bottom_y)
4887 height = bottom_y - to_y;
4888 else
4889 height = run->height;
4892 BLOCK_INPUT;
4894 /* Cursor off. Will be switched on again in x_update_window_end. */
4895 updated_window = w;
4896 x_clear_cursor (w);
4898 BitBlt (hdc, x, to_y, width, height, hdc, x, from_y, SRCCOPY);
4900 UNBLOCK_INPUT;
4901 release_frame_dc (f, hdc);
4906 /***********************************************************************
4907 Exposure Events
4908 ***********************************************************************/
4910 /* Redisplay an exposed area of frame F. X and Y are the upper-left
4911 corner of the exposed rectangle. W and H are width and height of
4912 the exposed area. All are pixel values. W or H zero means redraw
4913 the entire frame. */
4915 static void
4916 expose_frame (f, x, y, w, h)
4917 struct frame *f;
4918 int x, y, w, h;
4920 RECT r;
4922 TRACE ((stderr, "expose_frame "));
4924 /* No need to redraw if frame will be redrawn soon. */
4925 if (FRAME_GARBAGED_P (f))
4927 TRACE ((stderr, " garbaged\n"));
4928 return;
4931 /* If basic faces haven't been realized yet, there is no point in
4932 trying to redraw anything. This can happen when we get an expose
4933 event while Emacs is starting, e.g. by moving another window. */
4934 if (FRAME_FACE_CACHE (f) == NULL
4935 || FRAME_FACE_CACHE (f)->used < BASIC_FACE_ID_SENTINEL)
4937 TRACE ((stderr, " no faces\n"));
4938 return;
4941 if (w == 0 || h == 0)
4943 r.left = r.top = 0;
4944 r.right = CANON_X_UNIT (f) * f->width;
4945 r.bottom = CANON_Y_UNIT (f) * f->height;
4947 else
4949 r.left = x;
4950 r.top = y;
4951 r.right = x + w;
4952 r.bottom = y + h;
4955 TRACE ((stderr, "(%d, %d, %d, %d)\n", r.left, r.top, r.right, r.bottom));
4956 expose_window_tree (XWINDOW (f->root_window), &r);
4958 if (WINDOWP (f->tool_bar_window))
4960 struct window *w = XWINDOW (f->tool_bar_window);
4961 RECT window_rect;
4962 RECT intersection_rect;
4963 int window_x, window_y, window_width, window_height;
4965 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
4966 window_rect.left = window_x;
4967 window_rect.top = window_y;
4968 window_rect.right = window_x + window_width;
4969 window_rect.bottom = window_y + window_height;
4971 if (w32_intersect_rectangles (&r, &window_rect, &intersection_rect))
4972 expose_window (w, &intersection_rect);
4977 /* Redraw (parts) of all windows in the window tree rooted at W that
4978 intersect R. R contains frame pixel coordinates. */
4980 static void
4981 expose_window_tree (w, r)
4982 struct window *w;
4983 RECT *r;
4985 while (w)
4987 if (!NILP (w->hchild))
4988 expose_window_tree (XWINDOW (w->hchild), r);
4989 else if (!NILP (w->vchild))
4990 expose_window_tree (XWINDOW (w->vchild), r);
4991 else
4993 RECT window_rect;
4994 RECT intersection_rect;
4995 struct frame *f = XFRAME (w->frame);
4996 int window_x, window_y, window_width, window_height;
4998 /* Frame-relative pixel rectangle of W. */
4999 window_box (w, -1, &window_x, &window_y, &window_width,
5000 &window_height);
5001 window_rect.left
5002 = (window_x
5003 - FRAME_X_LEFT_FLAGS_AREA_WIDTH (f)
5004 - FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_Y_UNIT (f));
5005 window_rect.top = window_y;
5006 window_rect.right = window_rect.left
5007 + (window_width
5008 + FRAME_X_FLAGS_AREA_WIDTH (f)
5009 + FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f));
5010 window_rect.bottom = window_rect.top
5011 + window_height + CURRENT_MODE_LINE_HEIGHT (w);
5013 if (w32_intersect_rectangles (r, &window_rect, &intersection_rect))
5014 expose_window (w, &intersection_rect);
5017 w = NILP (w->next) ? 0 : XWINDOW (w->next);
5022 /* Redraw the part of glyph row area AREA of glyph row ROW on window W
5023 which intersects rectangle R. R is in window-relative coordinates. */
5025 static void
5026 expose_area (w, row, r, area)
5027 struct window *w;
5028 struct glyph_row *row;
5029 RECT *r;
5030 enum glyph_row_area area;
5032 int x;
5033 struct glyph *first = row->glyphs[area];
5034 struct glyph *end = row->glyphs[area] + row->used[area];
5035 struct glyph *last;
5036 int first_x;
5038 /* Set x to the window-relative start position for drawing glyphs of
5039 AREA. The first glyph of the text area can be partially visible.
5040 The first glyphs of other areas cannot. */
5041 if (area == LEFT_MARGIN_AREA)
5042 x = 0;
5043 else if (area == TEXT_AREA)
5044 x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
5045 else
5046 x = (window_box_width (w, LEFT_MARGIN_AREA)
5047 + window_box_width (w, TEXT_AREA));
5049 if (area == TEXT_AREA && row->fill_line_p)
5050 /* If row extends face to end of line write the whole line. */
5051 x_draw_glyphs (w, x, row, area,
5052 0, row->used[area],
5053 row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT,
5054 NULL, NULL, 0);
5055 else
5057 /* Find the first glyph that must be redrawn. */
5058 while (first < end
5059 && x + first->pixel_width < r->left)
5061 x += first->pixel_width;
5062 ++first;
5065 /* Find the last one. */
5066 last = first;
5067 first_x = x;
5068 while (last < end
5069 && x < r->right)
5071 x += last->pixel_width;
5072 ++last;
5075 /* Repaint. */
5076 if (last > first)
5077 x_draw_glyphs (w, first_x, row, area,
5078 first - row->glyphs[area],
5079 last - row->glyphs[area],
5080 row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT,
5081 NULL, NULL, 0);
5086 /* Redraw the parts of the glyph row ROW on window W intersecting
5087 rectangle R. R is in window-relative coordinates. */
5089 static void
5090 expose_line (w, row, r)
5091 struct window *w;
5092 struct glyph_row *row;
5093 RECT *r;
5095 xassert (row->enabled_p);
5097 if (row->mode_line_p || w->pseudo_window_p)
5098 x_draw_glyphs (w, 0, row, TEXT_AREA, 0, row->used[TEXT_AREA],
5099 row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT,
5100 NULL, NULL, 0);
5101 else
5103 if (row->used[LEFT_MARGIN_AREA])
5104 expose_area (w, row, r, LEFT_MARGIN_AREA);
5105 if (row->used[TEXT_AREA])
5106 expose_area (w, row, r, TEXT_AREA);
5107 if (row->used[RIGHT_MARGIN_AREA])
5108 expose_area (w, row, r, RIGHT_MARGIN_AREA);
5109 x_draw_row_bitmaps (w, row);
5114 /* Return non-zero if W's cursor intersects rectangle R. */
5116 static int
5117 x_phys_cursor_in_rect_p (w, r)
5118 struct window *w;
5119 RECT *r;
5121 RECT cr, result;
5122 struct glyph *cursor_glyph;
5124 cursor_glyph = get_phys_cursor_glyph (w);
5125 if (cursor_glyph)
5127 cr.left = w->phys_cursor.x;
5128 cr.top = w->phys_cursor.y;
5129 cr.right = cr.left + cursor_glyph->pixel_width;
5130 cr.bottom = cr.top + w->phys_cursor_height;
5131 return w32_intersect_rectangles (&cr, r, &result);
5133 else
5134 return 0;
5138 /* Redraw a rectangle of window W. R is a rectangle in window
5139 relative coordinates. Call this function with input blocked. */
5141 static void
5142 expose_window (w, r)
5143 struct window *w;
5144 RECT *r;
5146 struct glyph_row *row;
5147 int y;
5148 int yb = window_text_bottom_y (w);
5149 int cursor_cleared_p;
5151 /* If window is not yet fully initialized, do nothing. This can
5152 happen when toolkit scroll bars are used and a window is split.
5153 Reconfiguring the scroll bar will generate an expose for a newly
5154 created window. */
5155 if (w->current_matrix == NULL)
5156 return;
5158 TRACE ((stderr, "expose_window (%d, %d, %d, %d)\n",
5159 r->left, r->top, r->right, r->bottom));
5161 /* Convert to window coordinates. */
5162 r->left = FRAME_TO_WINDOW_PIXEL_X (w, r->left);
5163 r->top = FRAME_TO_WINDOW_PIXEL_Y (w, r->top);
5164 r->right = FRAME_TO_WINDOW_PIXEL_X (w, r->right);
5165 r->bottom = FRAME_TO_WINDOW_PIXEL_Y (w, r->bottom);
5167 /* Turn off the cursor. */
5168 if (!w->pseudo_window_p
5169 && x_phys_cursor_in_rect_p (w, r))
5171 x_clear_cursor (w);
5172 cursor_cleared_p = 1;
5174 else
5175 cursor_cleared_p = 0;
5177 /* Find the first row intersecting the rectangle R. */
5178 row = w->current_matrix->rows;
5179 y = 0;
5180 while (row->enabled_p
5181 && y < yb
5182 && y + row->height < r->top)
5184 y += row->height;
5185 ++row;
5188 /* Display the text in the rectangle, one text line at a time. */
5189 while (row->enabled_p
5190 && y < yb
5191 && y < r->bottom)
5193 expose_line (w, row, r);
5194 y += row->height;
5195 ++row;
5198 /* Display the mode line if there is one. */
5199 if (WINDOW_WANTS_MODELINE_P (w)
5200 && (row = MATRIX_MODE_LINE_ROW (w->current_matrix),
5201 row->enabled_p)
5202 && row->y < r->bottom)
5203 expose_line (w, row, r);
5205 if (!w->pseudo_window_p)
5207 /* Draw border between windows. */
5208 x_draw_vertical_border (w);
5210 /* Turn the cursor on again. */
5211 if (cursor_cleared_p)
5212 x_update_window_cursor (w, 1);
5217 /* Determine the intersection of two rectangles R1 and R2. Return
5218 the intersection in *RESULT. Value is non-zero if RESULT is not
5219 empty. */
5221 static int
5222 w32_intersect_rectangles (r1, r2, result)
5223 RECT *r1, *r2, *result;
5225 RECT *left, *right;
5226 RECT *upper, *lower;
5227 int intersection_p = 0;
5229 /* Rerrange so that R1 is the left-most rectangle. */
5230 if (r1->left < r2->left)
5231 left = r1, right = r2;
5232 else
5233 left = r2, right = r1;
5235 /* X0 of the intersection is right.x0, if this is inside R1,
5236 otherwise there is no intersection. */
5237 if (right->left <= left->right)
5239 result->left = right->left;
5241 /* The right end of the intersection is the minimum of the
5242 the right ends of left and right. */
5243 result->right = min (left->right, right->right);
5245 /* Same game for Y. */
5246 if (r1->top < r2->top)
5247 upper = r1, lower = r2;
5248 else
5249 upper = r2, lower = r1;
5251 /* The upper end of the intersection is lower.y0, if this is inside
5252 of upper. Otherwise, there is no intersection. */
5253 if (lower->top <= upper->bottom)
5255 result->top = lower->top;
5257 /* The lower end of the intersection is the minimum of the lower
5258 ends of upper and lower. */
5259 result->bottom = min (lower->bottom, upper->bottom);
5260 intersection_p = 1;
5264 return intersection_p;
5271 static void
5272 frame_highlight (f)
5273 struct frame *f;
5275 x_update_cursor (f, 1);
5278 static void
5279 frame_unhighlight (f)
5280 struct frame *f;
5282 x_update_cursor (f, 1);
5285 /* The focus has changed. Update the frames as necessary to reflect
5286 the new situation. Note that we can't change the selected frame
5287 here, because the Lisp code we are interrupting might become confused.
5288 Each event gets marked with the frame in which it occurred, so the
5289 Lisp code can tell when the switch took place by examining the events. */
5291 static void
5292 x_new_focus_frame (dpyinfo, frame)
5293 struct w32_display_info *dpyinfo;
5294 struct frame *frame;
5296 struct frame *old_focus = dpyinfo->w32_focus_frame;
5298 if (frame != dpyinfo->w32_focus_frame)
5300 /* Set this before calling other routines, so that they see
5301 the correct value of w32_focus_frame. */
5302 dpyinfo->w32_focus_frame = frame;
5304 if (old_focus && old_focus->auto_lower)
5305 x_lower_frame (old_focus);
5307 if (dpyinfo->w32_focus_frame && dpyinfo->w32_focus_frame->auto_raise)
5308 pending_autoraise_frame = dpyinfo->w32_focus_frame;
5309 else
5310 pending_autoraise_frame = 0;
5313 x_frame_rehighlight (dpyinfo);
5316 /* Handle an event saying the mouse has moved out of an Emacs frame. */
5318 void
5319 x_mouse_leave (dpyinfo)
5320 struct w32_display_info *dpyinfo;
5322 x_new_focus_frame (dpyinfo, dpyinfo->w32_focus_event_frame);
5325 /* The focus has changed, or we have redirected a frame's focus to
5326 another frame (this happens when a frame uses a surrogate
5327 mini-buffer frame). Shift the highlight as appropriate.
5329 The FRAME argument doesn't necessarily have anything to do with which
5330 frame is being highlighted or un-highlighted; we only use it to find
5331 the appropriate X display info. */
5333 static void
5334 w32_frame_rehighlight (frame)
5335 struct frame *frame;
5337 x_frame_rehighlight (FRAME_W32_DISPLAY_INFO (frame));
5340 static void
5341 x_frame_rehighlight (dpyinfo)
5342 struct w32_display_info *dpyinfo;
5344 struct frame *old_highlight = dpyinfo->w32_highlight_frame;
5346 if (dpyinfo->w32_focus_frame)
5348 dpyinfo->w32_highlight_frame
5349 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->w32_focus_frame)))
5350 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->w32_focus_frame))
5351 : dpyinfo->w32_focus_frame);
5352 if (! FRAME_LIVE_P (dpyinfo->w32_highlight_frame))
5354 FRAME_FOCUS_FRAME (dpyinfo->w32_focus_frame) = Qnil;
5355 dpyinfo->w32_highlight_frame = dpyinfo->w32_focus_frame;
5358 else
5359 dpyinfo->w32_highlight_frame = 0;
5361 if (dpyinfo->w32_highlight_frame != old_highlight)
5363 if (old_highlight)
5364 frame_unhighlight (old_highlight);
5365 if (dpyinfo->w32_highlight_frame)
5366 frame_highlight (dpyinfo->w32_highlight_frame);
5370 /* Keyboard processing - modifier keys, etc. */
5372 /* Convert a keysym to its name. */
5374 char *
5375 x_get_keysym_name (keysym)
5376 int keysym;
5378 /* Make static so we can always return it */
5379 static char value[100];
5381 BLOCK_INPUT;
5382 GetKeyNameText(keysym, value, 100);
5383 UNBLOCK_INPUT;
5385 return value;
5390 /* Mouse clicks and mouse movement. Rah. */
5392 /* Given a pixel position (PIX_X, PIX_Y) on frame F, return glyph
5393 co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle that the
5394 glyph at X, Y occupies, if BOUNDS != 0. If NOCLIP is non-zero, do
5395 not force the value into range. */
5397 void
5398 pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds, noclip)
5399 FRAME_PTR f;
5400 register int pix_x, pix_y;
5401 register int *x, *y;
5402 RECT *bounds;
5403 int noclip;
5405 /* Support tty mode: if Vwindow_system is nil, behave correctly. */
5406 if (NILP (Vwindow_system))
5408 *x = pix_x;
5409 *y = pix_y;
5410 return;
5413 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
5414 even for negative values. */
5415 if (pix_x < 0)
5416 pix_x -= FONT_WIDTH (FRAME_FONT(f)) - 1;
5417 if (pix_y < 0)
5418 pix_y -= (f)->output_data.w32->line_height - 1;
5420 pix_x = PIXEL_TO_CHAR_COL (f, pix_x);
5421 pix_y = PIXEL_TO_CHAR_ROW (f, pix_y);
5423 if (bounds)
5425 bounds->left = CHAR_TO_PIXEL_COL (f, pix_x);
5426 bounds->top = CHAR_TO_PIXEL_ROW (f, pix_y);
5427 bounds->right = bounds->left + FONT_WIDTH (FRAME_FONT(f)) - 1;
5428 bounds->bottom = bounds->top + f->output_data.w32->line_height - 1;
5431 if (!noclip)
5433 if (pix_x < 0)
5434 pix_x = 0;
5435 else if (pix_x > FRAME_WINDOW_WIDTH (f))
5436 pix_x = FRAME_WINDOW_WIDTH (f);
5438 if (pix_y < 0)
5439 pix_y = 0;
5440 else if (pix_y > f->height)
5441 pix_y = f->height;
5444 *x = pix_x;
5445 *y = pix_y;
5449 /* Given HPOS/VPOS in the current matrix of W, return corresponding
5450 frame-relative pixel positions in *FRAME_X and *FRAME_Y. If we
5451 can't tell the positions because W's display is not up to date,
5452 return 0. */
5455 glyph_to_pixel_coords (w, hpos, vpos, frame_x, frame_y)
5456 struct window *w;
5457 int hpos, vpos;
5458 int *frame_x, *frame_y;
5460 int success_p;
5462 xassert (hpos >= 0 && hpos < w->current_matrix->matrix_w);
5463 xassert (vpos >= 0 && vpos < w->current_matrix->matrix_h);
5465 if (display_completed)
5467 struct glyph_row *row = MATRIX_ROW (w->current_matrix, vpos);
5468 struct glyph *glyph = row->glyphs[TEXT_AREA];
5469 struct glyph *end = glyph + min (hpos, row->used[TEXT_AREA]);
5471 *frame_y = row->y;
5472 *frame_x = row->x;
5473 while (glyph < end)
5475 *frame_x += glyph->pixel_width;
5476 ++glyph;
5479 success_p = 1;
5481 else
5483 *frame_y = *frame_x = 0;
5484 success_p = 0;
5487 *frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, *frame_y);
5488 *frame_x = WINDOW_TO_FRAME_PIXEL_X (w, *frame_x);
5489 return success_p;
5492 BOOL
5493 parse_button (message, pbutton, pup)
5494 int message;
5495 int * pbutton;
5496 int * pup;
5498 int button = 0;
5499 int up = 0;
5501 switch (message)
5503 case WM_LBUTTONDOWN:
5504 button = 0;
5505 up = 0;
5506 break;
5507 case WM_LBUTTONUP:
5508 button = 0;
5509 up = 1;
5510 break;
5511 case WM_MBUTTONDOWN:
5512 if (NILP (Vw32_swap_mouse_buttons))
5513 button = 1;
5514 else
5515 button = 2;
5516 up = 0;
5517 break;
5518 case WM_MBUTTONUP:
5519 if (NILP (Vw32_swap_mouse_buttons))
5520 button = 1;
5521 else
5522 button = 2;
5523 up = 1;
5524 break;
5525 case WM_RBUTTONDOWN:
5526 if (NILP (Vw32_swap_mouse_buttons))
5527 button = 2;
5528 else
5529 button = 1;
5530 up = 0;
5531 break;
5532 case WM_RBUTTONUP:
5533 if (NILP (Vw32_swap_mouse_buttons))
5534 button = 2;
5535 else
5536 button = 1;
5537 up = 1;
5538 break;
5539 default:
5540 return (FALSE);
5543 if (pup) *pup = up;
5544 if (pbutton) *pbutton = button;
5546 return (TRUE);
5550 /* Prepare a mouse-event in *RESULT for placement in the input queue.
5552 If the event is a button press, then note that we have grabbed
5553 the mouse. */
5555 static Lisp_Object
5556 construct_mouse_click (result, msg, f)
5557 struct input_event *result;
5558 W32Msg *msg;
5559 struct frame *f;
5561 int button;
5562 int up;
5564 parse_button (msg->msg.message, &button, &up);
5566 /* Make the event type no_event; we'll change that when we decide
5567 otherwise. */
5568 result->kind = mouse_click;
5569 result->code = button;
5570 result->timestamp = msg->msg.time;
5571 result->modifiers = (msg->dwModifiers
5572 | (up
5573 ? up_modifier
5574 : down_modifier));
5576 XSETINT (result->x, LOWORD (msg->msg.lParam));
5577 XSETINT (result->y, HIWORD (msg->msg.lParam));
5578 XSETFRAME (result->frame_or_window, f);
5579 result->arg = Qnil;
5580 return Qnil;
5583 static Lisp_Object
5584 construct_mouse_wheel (result, msg, f)
5585 struct input_event *result;
5586 W32Msg *msg;
5587 struct frame *f;
5589 POINT p;
5590 result->kind = mouse_wheel;
5591 result->code = (short) HIWORD (msg->msg.wParam);
5592 result->timestamp = msg->msg.time;
5593 result->modifiers = msg->dwModifiers;
5594 p.x = LOWORD (msg->msg.lParam);
5595 p.y = HIWORD (msg->msg.lParam);
5596 ScreenToClient(msg->msg.hwnd, &p);
5597 XSETINT (result->x, p.x);
5598 XSETINT (result->y, p.y);
5599 XSETFRAME (result->frame_or_window, f);
5600 result->arg = Qnil;
5601 return Qnil;
5604 static Lisp_Object
5605 construct_drag_n_drop (result, msg, f)
5606 struct input_event *result;
5607 W32Msg *msg;
5608 struct frame *f;
5610 Lisp_Object files;
5611 Lisp_Object frame;
5612 HDROP hdrop;
5613 POINT p;
5614 WORD num_files;
5615 char *name;
5616 int i, len;
5618 result->kind = drag_n_drop;
5619 result->code = 0;
5620 result->timestamp = msg->msg.time;
5621 result->modifiers = msg->dwModifiers;
5623 hdrop = (HDROP) msg->msg.wParam;
5624 DragQueryPoint (hdrop, &p);
5626 #if 0
5627 p.x = LOWORD (msg->msg.lParam);
5628 p.y = HIWORD (msg->msg.lParam);
5629 ScreenToClient (msg->msg.hwnd, &p);
5630 #endif
5632 XSETINT (result->x, p.x);
5633 XSETINT (result->y, p.y);
5635 num_files = DragQueryFile (hdrop, 0xFFFFFFFF, NULL, 0);
5636 files = Qnil;
5638 for (i = 0; i < num_files; i++)
5640 len = DragQueryFile (hdrop, i, NULL, 0);
5641 if (len <= 0)
5642 continue;
5643 name = alloca (len + 1);
5644 DragQueryFile (hdrop, i, name, len + 1);
5645 files = Fcons (build_string (name), files);
5648 DragFinish (hdrop);
5650 XSETFRAME (frame, f);
5651 result->frame_or_window = Fcons (frame, files);
5652 result->arg = Qnil;
5653 return Qnil;
5657 /* Function to report a mouse movement to the mainstream Emacs code.
5658 The input handler calls this.
5660 We have received a mouse movement event, which is given in *event.
5661 If the mouse is over a different glyph than it was last time, tell
5662 the mainstream emacs code by setting mouse_moved. If not, ask for
5663 another motion event, so we can check again the next time it moves. */
5665 static MSG last_mouse_motion_event;
5666 static Lisp_Object last_mouse_motion_frame;
5668 static void
5669 note_mouse_movement (frame, msg)
5670 FRAME_PTR frame;
5671 MSG *msg;
5673 last_mouse_movement_time = msg->time;
5674 memcpy (&last_mouse_motion_event, msg, sizeof (last_mouse_motion_event));
5675 XSETFRAME (last_mouse_motion_frame, frame);
5677 if (msg->hwnd != FRAME_W32_WINDOW (frame))
5679 frame->mouse_moved = 1;
5680 last_mouse_scroll_bar = Qnil;
5681 note_mouse_highlight (frame, -1, -1);
5684 /* Has the mouse moved off the glyph it was on at the last sighting? */
5685 else if (LOWORD (msg->lParam) < last_mouse_glyph.left
5686 || LOWORD (msg->lParam) > last_mouse_glyph.right
5687 || HIWORD (msg->lParam) < last_mouse_glyph.top
5688 || HIWORD (msg->lParam) > last_mouse_glyph.bottom)
5690 frame->mouse_moved = 1;
5691 last_mouse_scroll_bar = Qnil;
5693 note_mouse_highlight (frame, LOWORD (msg->lParam), HIWORD (msg->lParam));
5697 /* This is used for debugging, to turn off note_mouse_highlight. */
5699 int disable_mouse_highlight;
5703 /************************************************************************
5704 Mouse Face
5705 ************************************************************************/
5707 /* Find the glyph under window-relative coordinates X/Y in window W.
5708 Consider only glyphs from buffer text, i.e. no glyphs from overlay
5709 strings. Return in *HPOS and *VPOS the row and column number of
5710 the glyph found. Return in *AREA the glyph area containing X.
5711 Value is a pointer to the glyph found or null if X/Y is not on
5712 text, or we can't tell because W's current matrix is not up to
5713 date. */
5715 static struct glyph *
5716 x_y_to_hpos_vpos (w, x, y, hpos, vpos, area)
5717 struct window *w;
5718 int x, y;
5719 int *hpos, *vpos, *area;
5721 struct glyph *glyph, *end;
5722 struct glyph_row *row = NULL;
5723 int x0, i, left_area_width;
5725 /* Find row containing Y. Give up if some row is not enabled. */
5726 for (i = 0; i < w->current_matrix->nrows; ++i)
5728 row = MATRIX_ROW (w->current_matrix, i);
5729 if (!row->enabled_p)
5730 return NULL;
5731 if (y >= row->y && y < MATRIX_ROW_BOTTOM_Y (row))
5732 break;
5735 *vpos = i;
5736 *hpos = 0;
5738 /* Give up if Y is not in the window. */
5739 if (i == w->current_matrix->nrows)
5740 return NULL;
5742 /* Get the glyph area containing X. */
5743 if (w->pseudo_window_p)
5745 *area = TEXT_AREA;
5746 x0 = 0;
5748 else
5750 left_area_width = window_box_width (w, LEFT_MARGIN_AREA);
5751 if (x < left_area_width)
5753 *area = LEFT_MARGIN_AREA;
5754 x0 = 0;
5756 else if (x < left_area_width + window_box_width (w, TEXT_AREA))
5758 *area = TEXT_AREA;
5759 x0 = row->x + left_area_width;
5761 else
5763 *area = RIGHT_MARGIN_AREA;
5764 x0 = left_area_width + window_box_width (w, TEXT_AREA);
5768 /* Find glyph containing X. */
5769 glyph = row->glyphs[*area];
5770 end = glyph + row->used[*area];
5771 while (glyph < end)
5773 if (x < x0 + glyph->pixel_width)
5775 if (w->pseudo_window_p)
5776 break;
5777 else if (BUFFERP (glyph->object))
5778 break;
5781 x0 += glyph->pixel_width;
5782 ++glyph;
5785 if (glyph == end)
5786 return NULL;
5788 *hpos = glyph - row->glyphs[*area];
5789 return glyph;
5793 /* Convert frame-relative x/y to coordinates relative to window W.
5794 Takes pseudo-windows into account. */
5796 static void
5797 frame_to_window_pixel_xy (w, x, y)
5798 struct window *w;
5799 int *x, *y;
5801 if (w->pseudo_window_p)
5803 /* A pseudo-window is always full-width, and starts at the
5804 left edge of the frame, plus a frame border. */
5805 struct frame *f = XFRAME (w->frame);
5806 *x -= FRAME_INTERNAL_BORDER_WIDTH_SAFE (f);
5807 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
5809 else
5811 *x = FRAME_TO_WINDOW_PIXEL_X (w, *x);
5812 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
5817 /* Take proper action when mouse has moved to the mode or top line of
5818 window W, x-position X. MODE_LINE_P non-zero means mouse is on the
5819 mode line. X is relative to the start of the text display area of
5820 W, so the width of bitmap areas and scroll bars must be subtracted
5821 to get a position relative to the start of the mode line. */
5823 static void
5824 note_mode_line_highlight (w, x, mode_line_p)
5825 struct window *w;
5826 int x, mode_line_p;
5828 struct frame *f = XFRAME (w->frame);
5829 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
5830 Cursor cursor = dpyinfo->vertical_scroll_bar_cursor;
5831 struct glyph_row *row;
5833 if (mode_line_p)
5834 row = MATRIX_MODE_LINE_ROW (w->current_matrix);
5835 else
5836 row = MATRIX_HEADER_LINE_ROW (w->current_matrix);
5838 if (row->enabled_p)
5840 struct glyph *glyph, *end;
5841 Lisp_Object help, map;
5842 int x0;
5844 /* Find the glyph under X. */
5845 glyph = row->glyphs[TEXT_AREA];
5846 end = glyph + row->used[TEXT_AREA];
5847 x0 = - (FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f)
5848 + FRAME_X_LEFT_FLAGS_AREA_WIDTH (f));
5849 while (glyph < end
5850 && x >= x0 + glyph->pixel_width)
5852 x0 += glyph->pixel_width;
5853 ++glyph;
5856 if (glyph < end
5857 && STRINGP (glyph->object)
5858 && XSTRING (glyph->object)->intervals
5859 && glyph->charpos >= 0
5860 && glyph->charpos < XSTRING (glyph->object)->size)
5862 /* If we're on a string with `help-echo' text property,
5863 arrange for the help to be displayed. This is done by
5864 setting the global variable help_echo to the help string. */
5865 help = Fget_text_property (make_number (glyph->charpos),
5866 Qhelp_echo, glyph->object);
5867 if (!NILP (help))
5869 help_echo = help;
5870 help_echo_object = glyph->object;
5871 help_echo_pos = glyph->charpos;
5874 /* Change the mouse pointer according to what is under X/Y. */
5875 map = Fget_text_property (make_number (glyph->charpos),
5876 Qlocal_map, glyph->object);
5877 if (!NILP (Fkeymapp (map)))
5878 cursor = f->output_data.w32->nontext_cursor;
5882 #if 0 /* NTEMACS_TODO: mouse cursor */
5883 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);
5884 #endif
5888 /* Take proper action when the mouse has moved to position X, Y on
5889 frame F as regards highlighting characters that have mouse-face
5890 properties. Also de-highlighting chars where the mouse was before.
5891 X and Y can be negative or out of range. */
5893 static void
5894 note_mouse_highlight (f, x, y)
5895 struct frame *f;
5896 int x, y;
5898 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
5899 int portion;
5900 Lisp_Object window;
5901 struct window *w;
5903 /* When a menu is active, don't highlight because this looks odd. */
5904 if (popup_activated ())
5905 return;
5907 if (disable_mouse_highlight
5908 || !f->glyphs_initialized_p)
5909 return;
5911 dpyinfo->mouse_face_mouse_x = x;
5912 dpyinfo->mouse_face_mouse_y = y;
5913 dpyinfo->mouse_face_mouse_frame = f;
5915 if (dpyinfo->mouse_face_defer)
5916 return;
5918 if (gc_in_progress)
5920 dpyinfo->mouse_face_deferred_gc = 1;
5921 return;
5924 /* Which window is that in? */
5925 window = window_from_coordinates (f, x, y, &portion, 1);
5927 /* If we were displaying active text in another window, clear that. */
5928 if (! EQ (window, dpyinfo->mouse_face_window))
5929 clear_mouse_face (dpyinfo);
5931 /* Not on a window -> return. */
5932 if (!WINDOWP (window))
5933 return;
5935 /* Convert to window-relative pixel coordinates. */
5936 w = XWINDOW (window);
5937 frame_to_window_pixel_xy (w, &x, &y);
5939 /* Handle tool-bar window differently since it doesn't display a
5940 buffer. */
5941 if (EQ (window, f->tool_bar_window))
5943 note_tool_bar_highlight (f, x, y);
5944 return;
5947 if (portion == 1 || portion == 3)
5949 /* Mouse is on the mode or top line. */
5950 note_mode_line_highlight (w, x, portion == 1);
5951 return;
5953 #if 0 /* NTEMACS_TODO: mouse cursor */
5954 else
5955 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5956 f->output_data.x->text_cursor);
5957 #endif
5959 /* Are we in a window whose display is up to date?
5960 And verify the buffer's text has not changed. */
5961 if (/* Within text portion of the window. */
5962 portion == 0
5963 && EQ (w->window_end_valid, w->buffer)
5964 && XFASTINT (w->last_modified) == BUF_MODIFF (XBUFFER (w->buffer))
5965 && (XFASTINT (w->last_overlay_modified)
5966 == BUF_OVERLAY_MODIFF (XBUFFER (w->buffer))))
5968 int hpos, vpos, pos, i, area;
5969 struct glyph *glyph;
5971 /* Find the glyph under X/Y. */
5972 glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, &area);
5974 /* Clear mouse face if X/Y not over text. */
5975 if (glyph == NULL
5976 || area != TEXT_AREA
5977 || !MATRIX_ROW (w->current_matrix, vpos)->displays_text_p)
5979 clear_mouse_face (dpyinfo);
5980 return;
5983 pos = glyph->charpos;
5984 xassert (w->pseudo_window_p || BUFFERP (glyph->object));
5986 /* Check for mouse-face and help-echo. */
5988 Lisp_Object mouse_face, overlay, position;
5989 Lisp_Object *overlay_vec;
5990 int len, noverlays;
5991 struct buffer *obuf;
5992 int obegv, ozv;
5994 /* If we get an out-of-range value, return now; avoid an error. */
5995 if (pos > BUF_Z (XBUFFER (w->buffer)))
5996 return;
5998 /* Make the window's buffer temporarily current for
5999 overlays_at and compute_char_face. */
6000 obuf = current_buffer;
6001 current_buffer = XBUFFER (w->buffer);
6002 obegv = BEGV;
6003 ozv = ZV;
6004 BEGV = BEG;
6005 ZV = Z;
6007 /* Is this char mouse-active or does it have help-echo? */
6008 XSETINT (position, pos);
6010 /* Put all the overlays we want in a vector in overlay_vec.
6011 Store the length in len. If there are more than 10, make
6012 enough space for all, and try again. */
6013 len = 10;
6014 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
6015 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL, 0);
6016 if (noverlays > len)
6018 len = noverlays;
6019 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
6020 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL,0);
6023 noverlays = sort_overlays (overlay_vec, noverlays, w);
6025 /* Check mouse-face highlighting. */
6026 if (! (EQ (window, dpyinfo->mouse_face_window)
6027 && vpos >= dpyinfo->mouse_face_beg_row
6028 && vpos <= dpyinfo->mouse_face_end_row
6029 && (vpos > dpyinfo->mouse_face_beg_row
6030 || hpos >= dpyinfo->mouse_face_beg_col)
6031 && (vpos < dpyinfo->mouse_face_end_row
6032 || hpos < dpyinfo->mouse_face_end_col
6033 || dpyinfo->mouse_face_past_end)))
6035 /* Clear the display of the old active region, if any. */
6036 clear_mouse_face (dpyinfo);
6038 /* Find the highest priority overlay that has a mouse-face prop. */
6039 overlay = Qnil;
6040 for (i = 0; i < noverlays; i++)
6042 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
6043 if (!NILP (mouse_face))
6045 overlay = overlay_vec[i];
6046 break;
6050 /* If no overlay applies, get a text property. */
6051 if (NILP (overlay))
6052 mouse_face = Fget_text_property (position, Qmouse_face, w->buffer);
6054 /* Handle the overlay case. */
6055 if (! NILP (overlay))
6057 /* Find the range of text around this char that
6058 should be active. */
6059 Lisp_Object before, after;
6060 int ignore;
6062 before = Foverlay_start (overlay);
6063 after = Foverlay_end (overlay);
6064 /* Record this as the current active region. */
6065 fast_find_position (w, XFASTINT (before),
6066 &dpyinfo->mouse_face_beg_col,
6067 &dpyinfo->mouse_face_beg_row,
6068 &dpyinfo->mouse_face_beg_x,
6069 &dpyinfo->mouse_face_beg_y);
6070 dpyinfo->mouse_face_past_end
6071 = !fast_find_position (w, XFASTINT (after),
6072 &dpyinfo->mouse_face_end_col,
6073 &dpyinfo->mouse_face_end_row,
6074 &dpyinfo->mouse_face_end_x,
6075 &dpyinfo->mouse_face_end_y);
6076 dpyinfo->mouse_face_window = window;
6077 dpyinfo->mouse_face_face_id
6078 = face_at_buffer_position (w, pos, 0, 0,
6079 &ignore, pos + 1, 1);
6081 /* Display it as active. */
6082 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
6084 /* Handle the text property case. */
6085 else if (! NILP (mouse_face))
6087 /* Find the range of text around this char that
6088 should be active. */
6089 Lisp_Object before, after, beginning, end;
6090 int ignore;
6092 beginning = Fmarker_position (w->start);
6093 XSETINT (end, (BUF_Z (XBUFFER (w->buffer))
6094 - XFASTINT (w->window_end_pos)));
6095 before
6096 = Fprevious_single_property_change (make_number (pos + 1),
6097 Qmouse_face,
6098 w->buffer, beginning);
6099 after
6100 = Fnext_single_property_change (position, Qmouse_face,
6101 w->buffer, end);
6102 /* Record this as the current active region. */
6103 fast_find_position (w, XFASTINT (before),
6104 &dpyinfo->mouse_face_beg_col,
6105 &dpyinfo->mouse_face_beg_row,
6106 &dpyinfo->mouse_face_beg_x,
6107 &dpyinfo->mouse_face_beg_y);
6108 dpyinfo->mouse_face_past_end
6109 = !fast_find_position (w, XFASTINT (after),
6110 &dpyinfo->mouse_face_end_col,
6111 &dpyinfo->mouse_face_end_row,
6112 &dpyinfo->mouse_face_end_x,
6113 &dpyinfo->mouse_face_end_y);
6114 dpyinfo->mouse_face_window = window;
6115 dpyinfo->mouse_face_face_id
6116 = face_at_buffer_position (w, pos, 0, 0,
6117 &ignore, pos + 1, 1);
6119 /* Display it as active. */
6120 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
6124 /* Look for a `help-echo' property. */
6126 Lisp_Object help;
6128 /* Check overlays first. */
6129 help = Qnil;
6130 for (i = 0; i < noverlays && NILP (help); ++i)
6131 help = Foverlay_get (overlay_vec[i], Qhelp_echo);
6133 if (!NILP (help))
6135 help_echo = help;
6136 help_echo_object = w->buffer;
6137 help_echo_pos = pos;
6139 else
6141 /* Try text properties. */
6142 if ((STRINGP (glyph->object)
6143 && glyph->charpos >= 0
6144 && glyph->charpos < XSTRING (glyph->object)->size)
6145 || (BUFFERP (glyph->object)
6146 && glyph->charpos >= BEGV
6147 && glyph->charpos < ZV))
6148 help = Fget_text_property (make_number (glyph->charpos),
6149 Qhelp_echo, glyph->object);
6151 if (!NILP (help))
6153 help_echo = help;
6154 help_echo_object = glyph->object;
6155 help_echo_pos = glyph->charpos;
6160 BEGV = obegv;
6161 ZV = ozv;
6162 current_buffer = obuf;
6167 static void
6168 redo_mouse_highlight ()
6170 if (!NILP (last_mouse_motion_frame)
6171 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame)))
6172 note_mouse_highlight (XFRAME (last_mouse_motion_frame),
6173 LOWORD (last_mouse_motion_event.lParam),
6174 HIWORD (last_mouse_motion_event.lParam));
6179 /***********************************************************************
6180 Tool-bars
6181 ***********************************************************************/
6183 static int x_tool_bar_item P_ ((struct frame *, int, int,
6184 struct glyph **, int *, int *, int *));
6186 /* Tool-bar item index of the item on which a mouse button was pressed
6187 or -1. */
6189 static int last_tool_bar_item;
6192 /* Get information about the tool-bar item at position X/Y on frame F.
6193 Return in *GLYPH a pointer to the glyph of the tool-bar item in
6194 the current matrix of the tool-bar window of F, or NULL if not
6195 on a tool-bar item. Return in *PROP_IDX the index of the tool-bar
6196 item in F->current_tool_bar_items. Value is
6198 -1 if X/Y is not on a tool-bar item
6199 0 if X/Y is on the same item that was highlighted before.
6200 1 otherwise. */
6202 static int
6203 x_tool_bar_item (f, x, y, glyph, hpos, vpos, prop_idx)
6204 struct frame *f;
6205 int x, y;
6206 struct glyph **glyph;
6207 int *hpos, *vpos, *prop_idx;
6209 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
6210 struct window *w = XWINDOW (f->tool_bar_window);
6211 int area;
6213 /* Find the glyph under X/Y. */
6214 *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, &area);
6215 if (*glyph == NULL)
6216 return -1;
6218 /* Get the start of this tool-bar item's properties in
6219 f->current_tool_bar_items. */
6220 if (!tool_bar_item_info (f, *glyph, prop_idx))
6221 return -1;
6223 /* Is mouse on the highlighted item? */
6224 if (EQ (f->tool_bar_window, dpyinfo->mouse_face_window)
6225 && *vpos >= dpyinfo->mouse_face_beg_row
6226 && *vpos <= dpyinfo->mouse_face_end_row
6227 && (*vpos > dpyinfo->mouse_face_beg_row
6228 || *hpos >= dpyinfo->mouse_face_beg_col)
6229 && (*vpos < dpyinfo->mouse_face_end_row
6230 || *hpos < dpyinfo->mouse_face_end_col
6231 || dpyinfo->mouse_face_past_end))
6232 return 0;
6234 return 1;
6238 /* Handle mouse button event on the tool-bar of frame F, at
6239 frame-relative coordinates X/Y. EVENT_TYPE is either ButtionPress
6240 or ButtonRelase. */
6242 static void
6243 w32_handle_tool_bar_click (f, button_event)
6244 struct frame *f;
6245 struct input_event *button_event;
6247 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
6248 struct window *w = XWINDOW (f->tool_bar_window);
6249 int hpos, vpos, prop_idx;
6250 struct glyph *glyph;
6251 Lisp_Object enabled_p;
6252 int x = XFASTINT (button_event->x);
6253 int y = XFASTINT (button_event->y);
6255 /* If not on the highlighted tool-bar item, return. */
6256 frame_to_window_pixel_xy (w, &x, &y);
6257 if (x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx) != 0)
6258 return;
6260 /* If item is disabled, do nothing. */
6261 enabled_p = (XVECTOR (f->current_tool_bar_items)
6262 ->contents[prop_idx + TOOL_BAR_ITEM_ENABLED_P]);
6263 if (NILP (enabled_p))
6264 return;
6266 if (button_event->kind == mouse_click)
6268 /* Show item in pressed state. */
6269 show_mouse_face (dpyinfo, DRAW_IMAGE_SUNKEN);
6270 dpyinfo->mouse_face_image_state = DRAW_IMAGE_SUNKEN;
6271 last_tool_bar_item = prop_idx;
6273 else
6275 Lisp_Object key, frame;
6276 struct input_event event;
6278 /* Show item in released state. */
6279 show_mouse_face (dpyinfo, DRAW_IMAGE_RAISED);
6280 dpyinfo->mouse_face_image_state = DRAW_IMAGE_RAISED;
6282 key = (XVECTOR (f->current_tool_bar_items)
6283 ->contents[prop_idx + TOOL_BAR_ITEM_KEY]);
6285 XSETFRAME (frame, f);
6286 event.kind = TOOL_BAR_EVENT;
6287 event.frame_or_window = frame;
6288 event.arg = frame;
6289 kbd_buffer_store_event (&event);
6291 event.kind = TOOL_BAR_EVENT;
6292 event.frame_or_window = frame;
6293 event.arg = key;
6294 event.modifiers = button_event->modifiers;
6295 kbd_buffer_store_event (&event);
6296 last_tool_bar_item = -1;
6301 /* Possibly highlight a tool-bar item on frame F when mouse moves to
6302 tool-bar window-relative coordinates X/Y. Called from
6303 note_mouse_highlight. */
6305 static void
6306 note_tool_bar_highlight (f, x, y)
6307 struct frame *f;
6308 int x, y;
6310 Lisp_Object window = f->tool_bar_window;
6311 struct window *w = XWINDOW (window);
6312 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
6313 int hpos, vpos;
6314 struct glyph *glyph;
6315 struct glyph_row *row;
6316 int i;
6317 Lisp_Object enabled_p;
6318 int prop_idx;
6319 enum draw_glyphs_face draw = DRAW_IMAGE_RAISED;
6320 int mouse_down_p, rc;
6322 /* Function note_mouse_highlight is called with negative x(y
6323 values when mouse moves outside of the frame. */
6324 if (x <= 0 || y <= 0)
6326 clear_mouse_face (dpyinfo);
6327 return;
6330 rc = x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx);
6331 if (rc < 0)
6333 /* Not on tool-bar item. */
6334 clear_mouse_face (dpyinfo);
6335 return;
6337 else if (rc == 0)
6338 /* On same tool-bar item as before. */
6339 goto set_help_echo;
6341 clear_mouse_face (dpyinfo);
6343 /* Mouse is down, but on different tool-bar item? */
6344 mouse_down_p = (dpyinfo->grabbed
6345 && f == last_mouse_frame
6346 && FRAME_LIVE_P (f));
6347 if (mouse_down_p
6348 && last_tool_bar_item != prop_idx)
6349 return;
6351 dpyinfo->mouse_face_image_state = DRAW_NORMAL_TEXT;
6352 draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
6354 /* If tool-bar item is not enabled, don't highlight it. */
6355 enabled_p = (XVECTOR (f->current_tool_bar_items)
6356 ->contents[prop_idx + TOOL_BAR_ITEM_ENABLED_P]);
6357 if (!NILP (enabled_p))
6359 /* Compute the x-position of the glyph. In front and past the
6360 image is a space. We include this is the highlighted area. */
6361 row = MATRIX_ROW (w->current_matrix, vpos);
6362 for (i = x = 0; i < hpos; ++i)
6363 x += row->glyphs[TEXT_AREA][i].pixel_width;
6365 /* Record this as the current active region. */
6366 dpyinfo->mouse_face_beg_col = hpos;
6367 dpyinfo->mouse_face_beg_row = vpos;
6368 dpyinfo->mouse_face_beg_x = x;
6369 dpyinfo->mouse_face_beg_y = row->y;
6370 dpyinfo->mouse_face_past_end = 0;
6372 dpyinfo->mouse_face_end_col = hpos + 1;
6373 dpyinfo->mouse_face_end_row = vpos;
6374 dpyinfo->mouse_face_end_x = x + glyph->pixel_width;
6375 dpyinfo->mouse_face_end_y = row->y;
6376 dpyinfo->mouse_face_window = window;
6377 dpyinfo->mouse_face_face_id = TOOL_BAR_FACE_ID;
6379 /* Display it as active. */
6380 show_mouse_face (dpyinfo, draw);
6381 dpyinfo->mouse_face_image_state = draw;
6384 set_help_echo:
6386 /* Set help_echo to a help string.to display for this tool-bar item.
6387 w32_read_socket does the rest. */
6388 help_echo_object = Qnil;
6389 help_echo_pos = -1;
6390 help_echo = (XVECTOR (f->current_tool_bar_items)
6391 ->contents[prop_idx + TOOL_BAR_ITEM_HELP]);
6392 if (NILP (help_echo))
6393 help_echo = (XVECTOR (f->current_tool_bar_items)
6394 ->contents[prop_idx + TOOL_BAR_ITEM_CAPTION]);
6399 /* Find the glyph matrix position of buffer position POS in window W.
6400 *HPOS, *VPOS, *X, and *Y are set to the positions found. W's
6401 current glyphs must be up to date. If POS is above window start
6402 return (0, 0, 0, 0). If POS is after end of W, return end of
6403 last line in W. */
6405 static int
6406 fast_find_position (w, pos, hpos, vpos, x, y)
6407 struct window *w;
6408 int pos;
6409 int *hpos, *vpos, *x, *y;
6411 int i;
6412 int lastcol;
6413 int maybe_next_line_p = 0;
6414 int line_start_position;
6415 int yb = window_text_bottom_y (w);
6416 struct glyph_row *row = MATRIX_ROW (w->current_matrix, 0);
6417 struct glyph_row *best_row = row;
6418 int row_vpos = 0, best_row_vpos = 0;
6419 int current_x;
6421 while (row->y < yb)
6423 if (row->used[TEXT_AREA])
6424 line_start_position = row->glyphs[TEXT_AREA]->charpos;
6425 else
6426 line_start_position = 0;
6428 if (line_start_position > pos)
6429 break;
6430 /* If the position sought is the end of the buffer,
6431 don't include the blank lines at the bottom of the window. */
6432 else if (line_start_position == pos
6433 && pos == BUF_ZV (XBUFFER (w->buffer)))
6435 maybe_next_line_p = 1;
6436 break;
6438 else if (line_start_position > 0)
6440 best_row = row;
6441 best_row_vpos = row_vpos;
6444 if (row->y + row->height >= yb)
6445 break;
6447 ++row;
6448 ++row_vpos;
6451 /* Find the right column within BEST_ROW. */
6452 lastcol = 0;
6453 current_x = best_row->x;
6454 for (i = 0; i < best_row->used[TEXT_AREA]; i++)
6456 struct glyph *glyph = best_row->glyphs[TEXT_AREA] + i;
6457 int charpos;
6459 charpos = glyph->charpos;
6460 if (charpos == pos)
6462 *hpos = i;
6463 *vpos = best_row_vpos;
6464 *x = current_x;
6465 *y = best_row->y;
6466 return 1;
6468 else if (charpos > pos)
6469 break;
6470 else if (charpos > 0)
6471 lastcol = i;
6473 current_x += glyph->pixel_width;
6476 /* If we're looking for the end of the buffer,
6477 and we didn't find it in the line we scanned,
6478 use the start of the following line. */
6479 if (maybe_next_line_p)
6481 ++best_row;
6482 ++best_row_vpos;
6483 lastcol = 0;
6484 current_x = best_row->x;
6487 *vpos = best_row_vpos;
6488 *hpos = lastcol + 1;
6489 *x = current_x;
6490 *y = best_row->y;
6491 return 0;
6495 /* Display the active region described by mouse_face_*
6496 in its mouse-face if HL > 0, in its normal face if HL = 0. */
6498 static void
6499 show_mouse_face (dpyinfo, draw)
6500 struct w32_display_info *dpyinfo;
6501 enum draw_glyphs_face draw;
6503 struct window *w = XWINDOW (dpyinfo->mouse_face_window);
6504 struct frame *f = XFRAME (WINDOW_FRAME (w));
6505 int i;
6506 int cursor_off_p = 0;
6507 struct cursor_pos saved_cursor;
6509 saved_cursor = output_cursor;
6511 /* If window is in the process of being destroyed, don't bother
6512 to do anything. */
6513 if (w->current_matrix == NULL)
6514 goto set_x_cursor;
6516 /* Recognize when we are called to operate on rows that don't exist
6517 anymore. This can happen when a window is split. */
6518 if (dpyinfo->mouse_face_end_row >= w->current_matrix->nrows)
6519 goto set_x_cursor;
6521 set_output_cursor (&w->phys_cursor);
6523 /* Note that mouse_face_beg_row etc. are window relative. */
6524 for (i = dpyinfo->mouse_face_beg_row;
6525 i <= dpyinfo->mouse_face_end_row;
6526 i++)
6528 int start_hpos, end_hpos, start_x;
6529 struct glyph_row *row = MATRIX_ROW (w->current_matrix, i);
6531 /* Don't do anything if row doesn't have valid contents. */
6532 if (!row->enabled_p)
6533 continue;
6535 /* For all but the first row, the highlight starts at column 0. */
6536 if (i == dpyinfo->mouse_face_beg_row)
6538 start_hpos = dpyinfo->mouse_face_beg_col;
6539 start_x = dpyinfo->mouse_face_beg_x;
6541 else
6543 start_hpos = 0;
6544 start_x = 0;
6547 if (i == dpyinfo->mouse_face_end_row)
6548 end_hpos = dpyinfo->mouse_face_end_col;
6549 else
6550 end_hpos = row->used[TEXT_AREA];
6552 /* If the cursor's in the text we are about to rewrite, turn the
6553 cursor off. */
6554 if (!w->pseudo_window_p
6555 && i == output_cursor.vpos
6556 && output_cursor.hpos >= start_hpos - 1
6557 && output_cursor.hpos <= end_hpos)
6559 x_update_window_cursor (w, 0);
6560 cursor_off_p = 1;
6563 if (end_hpos > start_hpos)
6565 row->mouse_face_p = draw == DRAW_MOUSE_FACE;
6566 x_draw_glyphs (w, start_x, row, TEXT_AREA,
6567 start_hpos, end_hpos, draw, NULL, NULL, 0);
6571 /* If we turned the cursor off, turn it back on. */
6572 if (cursor_off_p)
6573 x_display_cursor (w, 1,
6574 output_cursor.hpos, output_cursor.vpos,
6575 output_cursor.x, output_cursor.y);
6577 output_cursor = saved_cursor;
6579 set_x_cursor:
6580 #if 0 /* NTEMACS_TODO: mouse cursor */
6581 /* Change the mouse cursor. */
6582 if (draw == DRAW_NORMAL_TEXT)
6583 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
6584 f->output_data.x->text_cursor);
6585 else if (draw == DRAW_MOUSE_FACE)
6586 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
6587 f->output_data.x->cross_cursor);
6588 else
6589 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
6590 f->output_data.x->nontext_cursor);
6591 #endif
6595 /* Clear out the mouse-highlighted active region.
6596 Redraw it un-highlighted first. */
6598 void
6599 clear_mouse_face (dpyinfo)
6600 struct w32_display_info *dpyinfo;
6602 if (tip_frame)
6603 return;
6605 if (! NILP (dpyinfo->mouse_face_window))
6606 show_mouse_face (dpyinfo, DRAW_NORMAL_TEXT);
6608 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
6609 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
6610 dpyinfo->mouse_face_window = Qnil;
6614 /* Clear any mouse-face on window W. This function is part of the
6615 redisplay interface, and is called from try_window_id and similar
6616 functions to ensure the mouse-highlight is off. */
6618 static void
6619 x_clear_mouse_face (w)
6620 struct window *w;
6622 struct w32_display_info *dpyinfo
6623 = FRAME_W32_DISPLAY_INFO (XFRAME (w->frame));
6624 Lisp_Object window;
6626 XSETWINDOW (window, w);
6627 if (EQ (window, dpyinfo->mouse_face_window))
6628 clear_mouse_face (dpyinfo);
6632 /* Just discard the mouse face information for frame F, if any.
6633 This is used when the size of F is changed. */
6635 void
6636 cancel_mouse_face (f)
6637 FRAME_PTR f;
6639 Lisp_Object window;
6640 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
6642 window = dpyinfo->mouse_face_window;
6643 if (! NILP (window) && XFRAME (XWINDOW (window)->frame) == f)
6645 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
6646 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
6647 dpyinfo->mouse_face_window = Qnil;
6651 static struct scroll_bar *x_window_to_scroll_bar ();
6652 static void x_scroll_bar_report_motion ();
6654 /* Return the current position of the mouse.
6655 *fp should be a frame which indicates which display to ask about.
6657 If the mouse movement started in a scroll bar, set *fp, *bar_window,
6658 and *part to the frame, window, and scroll bar part that the mouse
6659 is over. Set *x and *y to the portion and whole of the mouse's
6660 position on the scroll bar.
6662 If the mouse movement started elsewhere, set *fp to the frame the
6663 mouse is on, *bar_window to nil, and *x and *y to the character cell
6664 the mouse is over.
6666 Set *time to the server time-stamp for the time at which the mouse
6667 was at this position.
6669 Don't store anything if we don't have a valid set of values to report.
6671 This clears the mouse_moved flag, so we can wait for the next mouse
6672 movement. */
6674 static void
6675 w32_mouse_position (fp, insist, bar_window, part, x, y, time)
6676 FRAME_PTR *fp;
6677 int insist;
6678 Lisp_Object *bar_window;
6679 enum scroll_bar_part *part;
6680 Lisp_Object *x, *y;
6681 unsigned long *time;
6683 FRAME_PTR f1;
6685 BLOCK_INPUT;
6687 if (! NILP (last_mouse_scroll_bar) && insist == 0)
6688 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
6689 else
6691 POINT pt;
6693 Lisp_Object frame, tail;
6695 /* Clear the mouse-moved flag for every frame on this display. */
6696 FOR_EACH_FRAME (tail, frame)
6697 XFRAME (frame)->mouse_moved = 0;
6699 last_mouse_scroll_bar = Qnil;
6701 GetCursorPos (&pt);
6703 /* Now we have a position on the root; find the innermost window
6704 containing the pointer. */
6706 if (FRAME_W32_DISPLAY_INFO (*fp)->grabbed && last_mouse_frame
6707 && FRAME_LIVE_P (last_mouse_frame))
6709 /* If mouse was grabbed on a frame, give coords for that frame
6710 even if the mouse is now outside it. */
6711 f1 = last_mouse_frame;
6713 else
6715 /* Is window under mouse one of our frames? */
6716 f1 = x_window_to_frame (FRAME_W32_DISPLAY_INFO (*fp), WindowFromPoint(pt));
6719 /* If not, is it one of our scroll bars? */
6720 if (! f1)
6722 struct scroll_bar *bar = x_window_to_scroll_bar (WindowFromPoint(pt));
6724 if (bar)
6726 f1 = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
6730 if (f1 == 0 && insist > 0)
6731 f1 = SELECTED_FRAME ();
6733 if (f1)
6735 /* Ok, we found a frame. Store all the values.
6736 last_mouse_glyph is a rectangle used to reduce the
6737 generation of mouse events. To not miss any motion
6738 events, we must divide the frame into rectangles of the
6739 size of the smallest character that could be displayed
6740 on it, i.e. into the same rectangles that matrices on
6741 the frame are divided into. */
6743 #if OLD_REDISPLAY_CODE
6744 int ignore1, ignore2;
6746 ScreenToClient (FRAME_W32_WINDOW (f1), &pt);
6748 pixel_to_glyph_coords (f1, pt.x, pt.y, &ignore1, &ignore2,
6749 &last_mouse_glyph,
6750 FRAME_W32_DISPLAY_INFO (f1)->grabbed
6751 || insist);
6752 #else
6753 ScreenToClient (FRAME_W32_WINDOW (f1), &pt);
6755 int width = FRAME_SMALLEST_CHAR_WIDTH (f1);
6756 int height = FRAME_SMALLEST_FONT_HEIGHT (f1);
6757 int x = pt.x;
6758 int y = pt.y;
6760 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to
6761 round down even for negative values. */
6762 if (x < 0)
6763 x -= width - 1;
6764 if (y < 0)
6765 y -= height - 1;
6767 last_mouse_glyph.left = (x + width - 1) / width * width;
6768 last_mouse_glyph.top = (y + height - 1) / height * height;
6769 last_mouse_glyph.right = last_mouse_glyph.left + width;
6770 last_mouse_glyph.bottom = last_mouse_glyph.top + height;
6772 #endif
6774 *bar_window = Qnil;
6775 *part = 0;
6776 *fp = f1;
6777 XSETINT (*x, pt.x);
6778 XSETINT (*y, pt.y);
6779 *time = last_mouse_movement_time;
6784 UNBLOCK_INPUT;
6788 /* Scroll bar support. */
6790 /* Given a window ID, find the struct scroll_bar which manages it.
6791 This can be called in GC, so we have to make sure to strip off mark
6792 bits. */
6794 static struct scroll_bar *
6795 x_window_to_scroll_bar (window_id)
6796 Window window_id;
6798 Lisp_Object tail;
6800 for (tail = Vframe_list;
6801 XGCTYPE (tail) == Lisp_Cons;
6802 tail = XCDR (tail))
6804 Lisp_Object frame, bar, condemned;
6806 frame = XCAR (tail);
6807 /* All elements of Vframe_list should be frames. */
6808 if (! GC_FRAMEP (frame))
6809 abort ();
6811 /* Scan this frame's scroll bar list for a scroll bar with the
6812 right window ID. */
6813 condemned = FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame));
6814 for (bar = FRAME_SCROLL_BARS (XFRAME (frame));
6815 /* This trick allows us to search both the ordinary and
6816 condemned scroll bar lists with one loop. */
6817 ! GC_NILP (bar) || (bar = condemned,
6818 condemned = Qnil,
6819 ! GC_NILP (bar));
6820 bar = XSCROLL_BAR (bar)->next)
6821 if (SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar)) == window_id)
6822 return XSCROLL_BAR (bar);
6825 return 0;
6830 /* Set the thumb size and position of scroll bar BAR. We are currently
6831 displaying PORTION out of a whole WHOLE, and our position POSITION. */
6833 static void
6834 w32_set_scroll_bar_thumb (bar, portion, position, whole)
6835 struct scroll_bar *bar;
6836 int portion, position, whole;
6838 Window w = SCROLL_BAR_W32_WINDOW (bar);
6839 int range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
6840 int sb_page, sb_pos;
6841 BOOL draggingp = !NILP (bar->dragging) ? TRUE : FALSE;
6843 if (whole)
6845 /* Position scroll bar at rock bottom if the bottom of the
6846 buffer is visible. This avoids shinking the thumb away
6847 to nothing if it is held at the bottom of the buffer. */
6848 if (position + portion >= whole)
6850 sb_page = range * (whole - position) / whole
6851 + VERTICAL_SCROLL_BAR_MIN_HANDLE;
6852 sb_pos = range;
6855 sb_page = portion * range / whole + VERTICAL_SCROLL_BAR_MIN_HANDLE;
6856 sb_pos = position * range / whole;
6858 else
6860 sb_page = range;
6861 sb_pos = 0;
6864 BLOCK_INPUT;
6866 if (pfnSetScrollInfo)
6868 SCROLLINFO si;
6870 si.cbSize = sizeof (si);
6871 /* Only update page size if currently dragging, to reduce
6872 flicker effects. */
6873 if (draggingp)
6874 si.fMask = SIF_PAGE;
6875 else
6876 si.fMask = SIF_PAGE | SIF_POS;
6877 si.nPage = sb_page;
6878 si.nPos = sb_pos;
6880 pfnSetScrollInfo (w, SB_CTL, &si, !draggingp);
6882 else
6883 SetScrollPos (w, SB_CTL, sb_pos, !draggingp);
6885 UNBLOCK_INPUT;
6889 /************************************************************************
6890 Scroll bars, general
6891 ************************************************************************/
6893 HWND
6894 my_create_scrollbar (f, bar)
6895 struct frame * f;
6896 struct scroll_bar * bar;
6898 return (HWND) SendMessage (FRAME_W32_WINDOW (f),
6899 WM_EMACS_CREATESCROLLBAR, (WPARAM) f,
6900 (LPARAM) bar);
6903 //#define ATTACH_THREADS
6905 BOOL
6906 my_show_window (FRAME_PTR f, HWND hwnd, int how)
6908 #ifndef ATTACH_THREADS
6909 return SendMessage (FRAME_W32_WINDOW (f), WM_EMACS_SHOWWINDOW,
6910 (WPARAM) hwnd, (LPARAM) how);
6911 #else
6912 return ShowWindow (hwnd, how);
6913 #endif
6916 void
6917 my_set_window_pos (HWND hwnd, HWND hwndAfter,
6918 int x, int y, int cx, int cy, UINT flags)
6920 #ifndef ATTACH_THREADS
6921 WINDOWPOS pos;
6922 pos.hwndInsertAfter = hwndAfter;
6923 pos.x = x;
6924 pos.y = y;
6925 pos.cx = cx;
6926 pos.cy = cy;
6927 pos.flags = flags;
6928 SendMessage (hwnd, WM_EMACS_SETWINDOWPOS, (WPARAM) &pos, 0);
6929 #else
6930 SetWindowPos (hwnd, hwndAfter, x, y, cx, cy, flags);
6931 #endif
6934 void
6935 my_set_focus (f, hwnd)
6936 struct frame * f;
6937 HWND hwnd;
6939 SendMessage (FRAME_W32_WINDOW (f), WM_EMACS_SETFOCUS,
6940 (WPARAM) hwnd, 0);
6943 void
6944 my_set_foreground_window (hwnd)
6945 HWND hwnd;
6947 SendMessage (hwnd, WM_EMACS_SETFOREGROUND, (WPARAM) hwnd, 0);
6950 void
6951 my_destroy_window (f, hwnd)
6952 struct frame * f;
6953 HWND hwnd;
6955 SendMessage (FRAME_W32_WINDOW (f), WM_EMACS_DESTROYWINDOW,
6956 (WPARAM) hwnd, 0);
6959 /* Create a scroll bar and return the scroll bar vector for it. W is
6960 the Emacs window on which to create the scroll bar. TOP, LEFT,
6961 WIDTH and HEIGHT are.the pixel coordinates and dimensions of the
6962 scroll bar. */
6964 static struct scroll_bar *
6965 x_scroll_bar_create (w, top, left, width, height)
6966 struct window *w;
6967 int top, left, width, height;
6969 struct frame *f = XFRAME (WINDOW_FRAME (w));
6970 HWND hwnd;
6971 struct scroll_bar *bar
6972 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
6974 BLOCK_INPUT;
6976 XSETWINDOW (bar->window, w);
6977 XSETINT (bar->top, top);
6978 XSETINT (bar->left, left);
6979 XSETINT (bar->width, width);
6980 XSETINT (bar->height, height);
6981 XSETINT (bar->start, 0);
6982 XSETINT (bar->end, 0);
6983 bar->dragging = Qnil;
6985 /* Requires geometry to be set before call to create the real window */
6987 hwnd = my_create_scrollbar (f, bar);
6989 if (pfnSetScrollInfo)
6991 SCROLLINFO si;
6993 si.cbSize = sizeof (si);
6994 si.fMask = SIF_ALL;
6995 si.nMin = 0;
6996 si.nMax = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height)
6997 + VERTICAL_SCROLL_BAR_MIN_HANDLE;
6998 si.nPage = si.nMax;
6999 si.nPos = 0;
7001 pfnSetScrollInfo (hwnd, SB_CTL, &si, FALSE);
7003 else
7005 SetScrollRange (hwnd, SB_CTL, 0,
7006 VERTICAL_SCROLL_BAR_TOP_RANGE (f, height), FALSE);
7007 SetScrollPos (hwnd, SB_CTL, 0, FALSE);
7010 SET_SCROLL_BAR_W32_WINDOW (bar, hwnd);
7012 /* Add bar to its frame's list of scroll bars. */
7013 bar->next = FRAME_SCROLL_BARS (f);
7014 bar->prev = Qnil;
7015 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
7016 if (! NILP (bar->next))
7017 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
7019 UNBLOCK_INPUT;
7021 return bar;
7025 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
7026 nil. */
7028 static void
7029 x_scroll_bar_remove (bar)
7030 struct scroll_bar *bar;
7032 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
7034 BLOCK_INPUT;
7036 /* Destroy the window. */
7037 my_destroy_window (f, SCROLL_BAR_W32_WINDOW (bar));
7039 /* Disassociate this scroll bar from its window. */
7040 XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
7042 UNBLOCK_INPUT;
7045 /* Set the handle of the vertical scroll bar for WINDOW to indicate
7046 that we are displaying PORTION characters out of a total of WHOLE
7047 characters, starting at POSITION. If WINDOW has no scroll bar,
7048 create one. */
7049 static void
7050 w32_set_vertical_scroll_bar (w, portion, whole, position)
7051 struct window *w;
7052 int portion, whole, position;
7054 struct frame *f = XFRAME (w->frame);
7055 struct scroll_bar *bar;
7056 int top, height, left, sb_left, width, sb_width;
7057 int window_x, window_y, window_width, window_height;
7059 /* Get window dimensions. */
7060 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
7061 top = window_y;
7062 width = FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f);
7063 height = window_height;
7065 /* Compute the left edge of the scroll bar area. */
7066 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
7067 left = XINT (w->left) + XINT (w->width) - FRAME_SCROLL_BAR_COLS (f);
7068 else
7069 left = XFASTINT (w->left);
7070 left *= CANON_X_UNIT (f);
7071 left += FRAME_INTERNAL_BORDER_WIDTH (f);
7073 /* Compute the width of the scroll bar which might be less than
7074 the width of the area reserved for the scroll bar. */
7075 if (FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0)
7076 sb_width = FRAME_SCROLL_BAR_PIXEL_WIDTH (f);
7077 else
7078 sb_width = width;
7080 /* Compute the left edge of the scroll bar. */
7081 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
7082 sb_left = left + width - sb_width - (width - sb_width) / 2;
7083 else
7084 sb_left = left + (width - sb_width) / 2;
7086 /* Does the scroll bar exist yet? */
7087 if (NILP (w->vertical_scroll_bar))
7089 HDC hdc;
7090 BLOCK_INPUT;
7091 hdc = get_frame_dc (f);
7092 w32_clear_area (f, hdc, left, top, width, height);
7093 release_frame_dc (f, hdc);
7094 UNBLOCK_INPUT;
7096 bar = x_scroll_bar_create (w, top, sb_left, sb_width, height);
7098 else
7100 /* It may just need to be moved and resized. */
7101 HWND hwnd;
7103 bar = XSCROLL_BAR (w->vertical_scroll_bar);
7104 hwnd = SCROLL_BAR_W32_WINDOW (bar);
7106 /* If already correctly positioned, do nothing. */
7107 if ( XINT (bar->left) == sb_left
7108 && XINT (bar->top) == top
7109 && XINT (bar->width) == sb_width
7110 && XINT (bar->height) == height )
7112 /* Redraw after clear_frame. */
7113 if (!my_show_window (f, hwnd, SW_NORMAL))
7114 InvalidateRect (hwnd, NULL, FALSE);
7116 else
7118 HDC hdc;
7119 BLOCK_INPUT;
7121 hdc = get_frame_dc (f);
7122 /* Since Windows scroll bars are smaller than the space reserved
7123 for them on the frame, we have to clear "under" them. */
7124 w32_clear_area (f, hdc,
7125 left,
7126 top,
7127 width,
7128 height);
7129 release_frame_dc (f, hdc);
7131 /* Make sure scroll bar is "visible" before moving, to ensure the
7132 area of the parent window now exposed will be refreshed. */
7133 my_show_window (f, hwnd, SW_HIDE);
7134 MoveWindow (hwnd, sb_left, top,
7135 sb_width, height, TRUE);
7136 if (pfnSetScrollInfo)
7138 SCROLLINFO si;
7140 si.cbSize = sizeof (si);
7141 si.fMask = SIF_RANGE;
7142 si.nMin = 0;
7143 si.nMax = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height)
7144 + VERTICAL_SCROLL_BAR_MIN_HANDLE;
7146 pfnSetScrollInfo (hwnd, SB_CTL, &si, FALSE);
7148 else
7149 SetScrollRange (hwnd, SB_CTL, 0,
7150 VERTICAL_SCROLL_BAR_TOP_RANGE (f, height), FALSE);
7151 my_show_window (f, hwnd, SW_NORMAL);
7152 // InvalidateRect (w, NULL, FALSE);
7154 /* Remember new settings. */
7155 XSETINT (bar->left, sb_left);
7156 XSETINT (bar->top, top);
7157 XSETINT (bar->width, sb_width);
7158 XSETINT (bar->height, height);
7160 UNBLOCK_INPUT;
7163 w32_set_scroll_bar_thumb (bar, portion, position, whole);
7165 XSETVECTOR (w->vertical_scroll_bar, bar);
7169 /* The following three hooks are used when we're doing a thorough
7170 redisplay of the frame. We don't explicitly know which scroll bars
7171 are going to be deleted, because keeping track of when windows go
7172 away is a real pain - "Can you say set-window-configuration, boys
7173 and girls?" Instead, we just assert at the beginning of redisplay
7174 that *all* scroll bars are to be removed, and then save a scroll bar
7175 from the fiery pit when we actually redisplay its window. */
7177 /* Arrange for all scroll bars on FRAME to be removed at the next call
7178 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
7179 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
7181 static void
7182 w32_condemn_scroll_bars (frame)
7183 FRAME_PTR frame;
7185 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
7186 while (! NILP (FRAME_SCROLL_BARS (frame)))
7188 Lisp_Object bar;
7189 bar = FRAME_SCROLL_BARS (frame);
7190 FRAME_SCROLL_BARS (frame) = XSCROLL_BAR (bar)->next;
7191 XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
7192 XSCROLL_BAR (bar)->prev = Qnil;
7193 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
7194 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
7195 FRAME_CONDEMNED_SCROLL_BARS (frame) = bar;
7199 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
7200 Note that WINDOW isn't necessarily condemned at all. */
7201 static void
7202 w32_redeem_scroll_bar (window)
7203 struct window *window;
7205 struct scroll_bar *bar;
7207 /* We can't redeem this window's scroll bar if it doesn't have one. */
7208 if (NILP (window->vertical_scroll_bar))
7209 abort ();
7211 bar = XSCROLL_BAR (window->vertical_scroll_bar);
7213 /* Unlink it from the condemned list. */
7215 FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
7217 if (NILP (bar->prev))
7219 /* If the prev pointer is nil, it must be the first in one of
7220 the lists. */
7221 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
7222 /* It's not condemned. Everything's fine. */
7223 return;
7224 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
7225 window->vertical_scroll_bar))
7226 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
7227 else
7228 /* If its prev pointer is nil, it must be at the front of
7229 one or the other! */
7230 abort ();
7232 else
7233 XSCROLL_BAR (bar->prev)->next = bar->next;
7235 if (! NILP (bar->next))
7236 XSCROLL_BAR (bar->next)->prev = bar->prev;
7238 bar->next = FRAME_SCROLL_BARS (f);
7239 bar->prev = Qnil;
7240 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
7241 if (! NILP (bar->next))
7242 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
7246 /* Remove all scroll bars on FRAME that haven't been saved since the
7247 last call to `*condemn_scroll_bars_hook'. */
7249 static void
7250 w32_judge_scroll_bars (f)
7251 FRAME_PTR f;
7253 Lisp_Object bar, next;
7255 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
7257 /* Clear out the condemned list now so we won't try to process any
7258 more events on the hapless scroll bars. */
7259 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
7261 for (; ! NILP (bar); bar = next)
7263 struct scroll_bar *b = XSCROLL_BAR (bar);
7265 x_scroll_bar_remove (b);
7267 next = b->next;
7268 b->next = b->prev = Qnil;
7271 /* Now there should be no references to the condemned scroll bars,
7272 and they should get garbage-collected. */
7275 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
7276 is set to something other than no_event, it is enqueued.
7278 This may be called from a signal handler, so we have to ignore GC
7279 mark bits. */
7281 static int
7282 x_scroll_bar_handle_click (bar, msg, emacs_event)
7283 struct scroll_bar *bar;
7284 W32Msg *msg;
7285 struct input_event *emacs_event;
7287 if (! GC_WINDOWP (bar->window))
7288 abort ();
7290 emacs_event->kind = w32_scroll_bar_click;
7291 emacs_event->code = 0;
7292 /* not really meaningful to distinguish up/down */
7293 emacs_event->modifiers = msg->dwModifiers;
7294 emacs_event->frame_or_window = bar->window;
7295 emacs_event->arg = Qnil;
7296 emacs_event->timestamp = msg->msg.time;
7299 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
7300 int y;
7301 int dragging = !NILP (bar->dragging);
7303 if (pfnGetScrollInfo)
7305 SCROLLINFO si;
7307 si.cbSize = sizeof (si);
7308 si.fMask = SIF_POS;
7310 pfnGetScrollInfo ((HWND) msg->msg.lParam, SB_CTL, &si);
7311 y = si.nPos;
7313 else
7314 y = GetScrollPos ((HWND) msg->msg.lParam, SB_CTL);
7316 bar->dragging = Qnil;
7319 last_mouse_scroll_bar_pos = msg->msg.wParam;
7321 switch (LOWORD (msg->msg.wParam))
7323 case SB_LINEDOWN:
7324 emacs_event->part = scroll_bar_down_arrow;
7325 break;
7326 case SB_LINEUP:
7327 emacs_event->part = scroll_bar_up_arrow;
7328 break;
7329 case SB_PAGEUP:
7330 emacs_event->part = scroll_bar_above_handle;
7331 break;
7332 case SB_PAGEDOWN:
7333 emacs_event->part = scroll_bar_below_handle;
7334 break;
7335 case SB_TOP:
7336 emacs_event->part = scroll_bar_handle;
7337 y = 0;
7338 break;
7339 case SB_BOTTOM:
7340 emacs_event->part = scroll_bar_handle;
7341 y = top_range;
7342 break;
7343 case SB_THUMBTRACK:
7344 case SB_THUMBPOSITION:
7345 if (VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height)) <= 0xffff)
7346 y = HIWORD (msg->msg.wParam);
7347 bar->dragging = Qt;
7348 emacs_event->part = scroll_bar_handle;
7350 /* "Silently" update current position. */
7351 if (pfnSetScrollInfo)
7353 SCROLLINFO si;
7355 si.cbSize = sizeof (si);
7356 si.fMask = SIF_POS;
7357 si.nPos = y;
7358 /* Remember apparent position (we actually lag behind the real
7359 position, so don't set that directly. */
7360 last_scroll_bar_drag_pos = y;
7362 pfnSetScrollInfo (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, &si, FALSE);
7364 else
7365 SetScrollPos (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, y, FALSE);
7366 break;
7367 case SB_ENDSCROLL:
7368 /* If this is the end of a drag sequence, then reset the scroll
7369 handle size to normal and do a final redraw. Otherwise do
7370 nothing. */
7371 if (dragging)
7373 if (pfnSetScrollInfo)
7375 SCROLLINFO si;
7376 int start = XINT (bar->start);
7377 int end = XINT (bar->end);
7379 si.cbSize = sizeof (si);
7380 si.fMask = SIF_PAGE | SIF_POS;
7381 si.nPage = end - start + VERTICAL_SCROLL_BAR_MIN_HANDLE;
7382 si.nPos = last_scroll_bar_drag_pos;
7383 pfnSetScrollInfo (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, &si, TRUE);
7385 else
7386 SetScrollPos (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, y, TRUE);
7388 /* fall through */
7389 default:
7390 emacs_event->kind = no_event;
7391 return FALSE;
7394 XSETINT (emacs_event->x, y);
7395 XSETINT (emacs_event->y, top_range);
7397 return TRUE;
7401 /* Return information to the user about the current position of the mouse
7402 on the scroll bar. */
7404 static void
7405 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
7406 FRAME_PTR *fp;
7407 Lisp_Object *bar_window;
7408 enum scroll_bar_part *part;
7409 Lisp_Object *x, *y;
7410 unsigned long *time;
7412 struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
7413 Window w = SCROLL_BAR_W32_WINDOW (bar);
7414 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
7415 int pos;
7416 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
7418 BLOCK_INPUT;
7420 *fp = f;
7421 *bar_window = bar->window;
7423 if (pfnGetScrollInfo)
7425 SCROLLINFO si;
7427 si.cbSize = sizeof (si);
7428 si.fMask = SIF_POS | SIF_PAGE | SIF_RANGE;
7430 pfnGetScrollInfo (w, SB_CTL, &si);
7431 pos = si.nPos;
7432 top_range = si.nMax - si.nPage + 1;
7434 else
7435 pos = GetScrollPos (w, SB_CTL);
7437 switch (LOWORD (last_mouse_scroll_bar_pos))
7439 case SB_THUMBPOSITION:
7440 case SB_THUMBTRACK:
7441 *part = scroll_bar_handle;
7442 if (VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height)) <= 0xffff)
7443 pos = HIWORD (last_mouse_scroll_bar_pos);
7444 break;
7445 case SB_LINEDOWN:
7446 *part = scroll_bar_handle;
7447 pos++;
7448 break;
7449 default:
7450 *part = scroll_bar_handle;
7451 break;
7454 XSETINT(*x, pos);
7455 XSETINT(*y, top_range);
7457 f->mouse_moved = 0;
7458 last_mouse_scroll_bar = Qnil;
7460 *time = last_mouse_movement_time;
7462 UNBLOCK_INPUT;
7466 /* The screen has been cleared so we may have changed foreground or
7467 background colors, and the scroll bars may need to be redrawn.
7468 Clear out the scroll bars, and ask for expose events, so we can
7469 redraw them. */
7471 void
7472 x_scroll_bar_clear (f)
7473 FRAME_PTR f;
7475 Lisp_Object bar;
7477 /* We can have scroll bars even if this is 0,
7478 if we just turned off scroll bar mode.
7479 But in that case we should not clear them. */
7480 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
7481 for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar);
7482 bar = XSCROLL_BAR (bar)->next)
7484 HWND window = SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar));
7485 HDC hdc = GetDC (window);
7486 RECT rect;
7488 /* Hide scroll bar until ready to repaint. x_scroll_bar_move
7489 arranges to refresh the scroll bar if hidden. */
7490 my_show_window (f, window, SW_HIDE);
7492 GetClientRect (window, &rect);
7493 select_palette (f, hdc);
7494 w32_clear_rect (f, hdc, &rect);
7495 deselect_palette (f, hdc);
7497 ReleaseDC (window, hdc);
7501 show_scroll_bars (f, how)
7502 FRAME_PTR f;
7503 int how;
7505 Lisp_Object bar;
7507 for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar);
7508 bar = XSCROLL_BAR (bar)->next)
7510 HWND window = SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar));
7511 my_show_window (f, window, how);
7516 /* The main W32 event-reading loop - w32_read_socket. */
7518 /* Time stamp of enter window event. This is only used by w32_read_socket,
7519 but we have to put it out here, since static variables within functions
7520 sometimes don't work. */
7522 static Time enter_timestamp;
7524 /* Record the last 100 characters stored
7525 to help debug the loss-of-chars-during-GC problem. */
7527 static int temp_index;
7528 static short temp_buffer[100];
7531 /* Read events coming from the W32 shell.
7532 This routine is called by the SIGIO handler.
7533 We return as soon as there are no more events to be read.
7535 Events representing keys are stored in buffer BUFP,
7536 which can hold up to NUMCHARS characters.
7537 We return the number of characters stored into the buffer,
7538 thus pretending to be `read'.
7540 EXPECTED is nonzero if the caller knows input is available.
7542 Some of these messages are reposted back to the message queue since the
7543 system calls the windows proc directly in a context where we cannot return
7544 the data nor can we guarantee the state we are in. So if we dispatch them
7545 we will get into an infinite loop. To prevent this from ever happening we
7546 will set a variable to indicate we are in the read_socket call and indicate
7547 which message we are processing since the windows proc gets called
7548 recursively with different messages by the system.
7552 w32_read_socket (sd, bufp, numchars, expected)
7553 register int sd;
7554 /* register */ struct input_event *bufp;
7555 /* register */ int numchars;
7556 int expected;
7558 int count = 0;
7559 int check_visibility = 0;
7560 W32Msg msg;
7561 struct frame *f;
7562 struct w32_display_info *dpyinfo = &one_w32_display_info;
7564 if (interrupt_input_blocked)
7566 interrupt_input_pending = 1;
7567 return -1;
7570 interrupt_input_pending = 0;
7571 BLOCK_INPUT;
7573 /* So people can tell when we have read the available input. */
7574 input_signal_count++;
7576 if (numchars <= 0)
7577 abort (); /* Don't think this happens. */
7579 /* NTEMACS_TODO: tooltips, tool-bars, ghostscript integration, mouse
7580 cursors. */
7581 while (get_next_msg (&msg, FALSE))
7583 switch (msg.msg.message)
7585 case WM_PAINT:
7586 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
7588 if (f)
7590 if (msg.rect.right == msg.rect.left ||
7591 msg.rect.bottom == msg.rect.top)
7593 /* We may get paint messages even though the client
7594 area is clipped - these are not expose events. */
7595 DebPrint (("clipped frame %04x (%s) got WM_PAINT\n", f,
7596 XSTRING (f->name)->data));
7598 else if (f->async_visible != 1)
7600 /* Definitely not obscured, so mark as visible. */
7601 f->async_visible = 1;
7602 f->async_iconified = 0;
7603 SET_FRAME_GARBAGED (f);
7604 DebPrint (("frame %04x (%s) reexposed\n", f,
7605 XSTRING (f->name)->data));
7607 /* WM_PAINT serves as MapNotify as well, so report
7608 visibility changes properly. */
7609 if (f->iconified)
7611 bufp->kind = deiconify_event;
7612 XSETFRAME (bufp->frame_or_window, f);
7613 bufp->arg = Qnil;
7614 bufp++;
7615 count++;
7616 numchars--;
7618 else if (! NILP(Vframe_list)
7619 && ! NILP (XCDR (Vframe_list)))
7620 /* Force a redisplay sooner or later to update the
7621 frame titles in case this is the second frame. */
7622 record_asynch_buffer_change ();
7624 else
7626 HDC hdc = get_frame_dc (f);
7628 /* Erase background again for safety. */
7629 w32_clear_rect (f, hdc, &msg.rect);
7630 release_frame_dc (f, hdc);
7631 expose_frame (f,
7632 msg.rect.left,
7633 msg.rect.top,
7634 msg.rect.right - msg.rect.left,
7635 msg.rect.bottom - msg.rect.top);
7638 break;
7640 case WM_INPUTLANGCHANGE:
7641 /* Generate a language change event. */
7642 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
7644 if (f)
7646 if (numchars == 0)
7647 abort ();
7649 bufp->kind = language_change_event;
7650 XSETFRAME (bufp->frame_or_window, f);
7651 bufp->arg = Qnil;
7652 bufp->code = msg.msg.wParam;
7653 bufp->modifiers = msg.msg.lParam & 0xffff;
7654 bufp++;
7655 count++;
7656 numchars--;
7658 break;
7660 case WM_KEYDOWN:
7661 case WM_SYSKEYDOWN:
7662 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
7664 if (f && !f->iconified)
7666 if (temp_index == sizeof temp_buffer / sizeof (short))
7667 temp_index = 0;
7668 temp_buffer[temp_index++] = msg.msg.wParam;
7669 bufp->kind = non_ascii_keystroke;
7670 bufp->code = msg.msg.wParam;
7671 bufp->modifiers = msg.dwModifiers;
7672 XSETFRAME (bufp->frame_or_window, f);
7673 bufp->arg = Qnil;
7674 bufp->timestamp = msg.msg.time;
7675 bufp++;
7676 numchars--;
7677 count++;
7679 break;
7681 case WM_SYSCHAR:
7682 case WM_CHAR:
7683 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
7685 if (f && !f->iconified)
7687 if (temp_index == sizeof temp_buffer / sizeof (short))
7688 temp_index = 0;
7689 temp_buffer[temp_index++] = msg.msg.wParam;
7690 bufp->kind = ascii_keystroke;
7691 bufp->code = msg.msg.wParam;
7692 bufp->modifiers = msg.dwModifiers;
7693 XSETFRAME (bufp->frame_or_window, f);
7694 bufp->arg = Qnil;
7695 bufp->timestamp = msg.msg.time;
7696 bufp++;
7697 numchars--;
7698 count++;
7700 break;
7702 case WM_MOUSEMOVE:
7703 previous_help_echo = help_echo;
7704 help_echo = Qnil;
7706 if (dpyinfo->grabbed && last_mouse_frame
7707 && FRAME_LIVE_P (last_mouse_frame))
7708 f = last_mouse_frame;
7709 else
7710 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
7712 if (f)
7713 note_mouse_movement (f, &msg.msg);
7714 else
7716 /* If we move outside the frame, then we're
7717 certainly no longer on any text in the frame. */
7718 clear_mouse_face (FRAME_W32_DISPLAY_INFO (f));
7721 /* If the contents of the global variable help_echo
7722 has changed, generate a HELP_EVENT. */
7723 if (!NILP (help_echo)
7724 || !NILP (previous_help_echo))
7726 Lisp_Object frame;
7727 int n;
7729 if (f)
7730 XSETFRAME (frame, f);
7731 else
7732 frame = Qnil;
7734 any_help_event_p = 1;
7735 n = gen_help_event (bufp, help_echo, frame,
7736 help_echo_object, help_echo_pos);
7737 bufp += n, count += n, numchars -= n;
7739 break;
7741 case WM_LBUTTONDOWN:
7742 case WM_LBUTTONUP:
7743 case WM_MBUTTONDOWN:
7744 case WM_MBUTTONUP:
7745 case WM_RBUTTONDOWN:
7746 case WM_RBUTTONUP:
7748 /* If we decide we want to generate an event to be seen
7749 by the rest of Emacs, we put it here. */
7750 struct input_event emacs_event;
7751 int tool_bar_p = 0;
7752 int button;
7753 int up;
7755 emacs_event.kind = no_event;
7757 if (dpyinfo->grabbed && last_mouse_frame
7758 && FRAME_LIVE_P (last_mouse_frame))
7759 f = last_mouse_frame;
7760 else
7761 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
7763 if (f)
7765 construct_mouse_click (&emacs_event, &msg, f);
7767 /* Is this in the tool-bar? */
7768 if (WINDOWP (f->tool_bar_window)
7769 && XFASTINT (XWINDOW (f->tool_bar_window)->height))
7771 Lisp_Object window;
7772 int p, x, y;
7774 /* Set x and y. */
7775 window = window_from_coordinates (f,
7776 emacs_event.x,
7777 emacs_event.y,
7778 &p, 1);
7779 if (EQ (window, f->tool_bar_window))
7781 w32_handle_tool_bar_click (f, &emacs_event);
7782 tool_bar_p = 1;
7786 if (!tool_bar_p)
7787 if (!dpyinfo->w32_focus_frame
7788 || f == dpyinfo->w32_focus_frame
7789 && (numchars >= 1))
7791 construct_mouse_click (bufp, &msg, f);
7792 bufp++;
7793 count++;
7794 numchars--;
7798 parse_button (msg.msg.message, &button, &up);
7800 if (up)
7802 dpyinfo->grabbed &= ~ (1 << button);
7804 else
7806 dpyinfo->grabbed |= (1 << button);
7807 last_mouse_frame = f;
7808 /* Ignore any mouse motion that happened
7809 before this event; any subsequent mouse-movement
7810 Emacs events should reflect only motion after
7811 the ButtonPress. */
7812 if (f != 0)
7813 f->mouse_moved = 0;
7815 if (!tool_bar_p)
7816 last_tool_bar_item = -1;
7818 break;
7821 case WM_MOUSEWHEEL:
7822 if (dpyinfo->grabbed && last_mouse_frame
7823 && FRAME_LIVE_P (last_mouse_frame))
7824 f = last_mouse_frame;
7825 else
7826 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
7828 if (f)
7830 if ((!dpyinfo->w32_focus_frame
7831 || f == dpyinfo->w32_focus_frame)
7832 && (numchars >= 1))
7834 construct_mouse_wheel (bufp, &msg, f);
7835 bufp++;
7836 count++;
7837 numchars--;
7840 break;
7842 case WM_MENUSELECT:
7844 HMENU menu = (HMENU) msg.msg.lParam;
7845 UINT menu_item = (UINT) LOWORD (msg.msg.wParam);
7846 UINT flags = (UINT) HIWORD (msg.msg.wParam);
7848 w32_menu_display_help (menu, menu_item, flags);
7850 break;
7852 case WM_DROPFILES:
7853 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
7855 if (f)
7857 construct_drag_n_drop (bufp, &msg, f);
7858 bufp++;
7859 count++;
7860 numchars--;
7862 break;
7864 case WM_VSCROLL:
7866 struct scroll_bar *bar =
7867 x_window_to_scroll_bar ((HWND)msg.msg.lParam);
7869 if (bar && numchars >= 1)
7871 if (x_scroll_bar_handle_click (bar, &msg, bufp))
7873 bufp++;
7874 count++;
7875 numchars--;
7878 break;
7881 case WM_WINDOWPOSCHANGED:
7882 case WM_ACTIVATE:
7883 case WM_ACTIVATEAPP:
7884 check_visibility = 1;
7885 break;
7887 case WM_MOVE:
7888 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
7890 if (f && !f->async_iconified)
7892 int x, y;
7894 x_real_positions (f, &x, &y);
7895 f->output_data.w32->left_pos = x;
7896 f->output_data.w32->top_pos = y;
7899 check_visibility = 1;
7900 break;
7902 case WM_SHOWWINDOW:
7903 /* If window has been obscured or exposed by another window
7904 being maximised or minimised/restored, then recheck
7905 visibility of all frames. Direct changes to our own
7906 windows get handled by WM_SIZE. */
7907 #if 0
7908 if (msg.msg.lParam != 0)
7909 check_visibility = 1;
7910 else
7912 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
7913 f->async_visible = msg.msg.wParam;
7915 #endif
7917 check_visibility = 1;
7918 break;
7920 case WM_SIZE:
7921 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
7923 /* Inform lisp of whether frame has been iconified etc. */
7924 if (f)
7926 switch (msg.msg.wParam)
7928 case SIZE_MINIMIZED:
7929 f->async_visible = 0;
7930 f->async_iconified = 1;
7932 bufp->kind = iconify_event;
7933 XSETFRAME (bufp->frame_or_window, f);
7934 bufp->arg = Qnil;
7935 bufp++;
7936 count++;
7937 numchars--;
7938 break;
7940 case SIZE_MAXIMIZED:
7941 case SIZE_RESTORED:
7942 f->async_visible = 1;
7943 f->async_iconified = 0;
7945 /* wait_reading_process_input will notice this and update
7946 the frame's display structures. */
7947 SET_FRAME_GARBAGED (f);
7949 if (f->iconified)
7951 int x, y;
7953 /* Reset top and left positions of the Window
7954 here since Windows sends a WM_MOVE message
7955 BEFORE telling us the Window is minimized
7956 when the Window is iconified, with 3000,3000
7957 as the co-ords. */
7958 x_real_positions (f, &x, &y);
7959 f->output_data.w32->left_pos = x;
7960 f->output_data.w32->top_pos = y;
7962 bufp->kind = deiconify_event;
7963 XSETFRAME (bufp->frame_or_window, f);
7964 bufp->arg = Qnil;
7965 bufp++;
7966 count++;
7967 numchars--;
7969 else if (! NILP (Vframe_list)
7970 && ! NILP (XCDR (Vframe_list)))
7971 /* Force a redisplay sooner or later
7972 to update the frame titles
7973 in case this is the second frame. */
7974 record_asynch_buffer_change ();
7975 break;
7979 if (f && !f->async_iconified && msg.msg.wParam != SIZE_MINIMIZED)
7981 RECT rect;
7982 int rows;
7983 int columns;
7984 int width;
7985 int height;
7987 GetClientRect(msg.msg.hwnd, &rect);
7989 height = rect.bottom - rect.top;
7990 width = rect.right - rect.left;
7992 rows = PIXEL_TO_CHAR_HEIGHT (f, height);
7993 columns = PIXEL_TO_CHAR_WIDTH (f, width);
7995 /* TODO: Clip size to the screen dimensions. */
7997 /* Even if the number of character rows and columns has
7998 not changed, the font size may have changed, so we need
7999 to check the pixel dimensions as well. */
8001 if (columns != f->width
8002 || rows != f->height
8003 || width != f->output_data.w32->pixel_width
8004 || height != f->output_data.w32->pixel_height)
8006 change_frame_size (f, rows, columns, 0, 1, 0);
8007 SET_FRAME_GARBAGED (f);
8008 cancel_mouse_face (f);
8009 f->output_data.w32->pixel_width = width;
8010 f->output_data.w32->pixel_height = height;
8011 f->output_data.w32->win_gravity = NorthWestGravity;
8015 check_visibility = 1;
8016 break;
8018 case WM_SETFOCUS:
8019 f = x_any_window_to_frame (dpyinfo, msg.msg.hwnd);
8021 dpyinfo->w32_focus_event_frame = f;
8023 if (f)
8024 x_new_focus_frame (dpyinfo, f);
8027 dpyinfo->grabbed = 0;
8028 check_visibility = 1;
8029 break;
8031 case WM_KILLFOCUS:
8032 /* NTEMACS_TODO: some of this belongs in MOUSE_LEAVE */
8033 f = x_top_window_to_frame (dpyinfo, msg.msg.hwnd);
8035 if (f)
8037 Lisp_Object frame;
8039 if (f == dpyinfo->w32_focus_event_frame)
8040 dpyinfo->w32_focus_event_frame = 0;
8042 if (f == dpyinfo->w32_focus_frame)
8043 x_new_focus_frame (dpyinfo, 0);
8045 if (f == dpyinfo->mouse_face_mouse_frame)
8047 /* If we move outside the frame, then we're
8048 certainly no longer on any text in the frame. */
8049 clear_mouse_face (dpyinfo);
8050 dpyinfo->mouse_face_mouse_frame = 0;
8053 /* Generate a nil HELP_EVENT to cancel a help-echo.
8054 Do it only if there's something to cancel.
8055 Otherwise, the startup message is cleared when
8056 the mouse leaves the frame. */
8057 if (any_help_event_p)
8059 int n;
8061 XSETFRAME (frame, f);
8062 n = gen_help_event (bufp, Qnil, frame, Qnil, 0);
8063 bufp += n, count += n, numchars -=n;
8067 dpyinfo->grabbed = 0;
8068 check_visibility = 1;
8069 break;
8071 case WM_CLOSE:
8072 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
8074 if (f)
8076 if (numchars == 0)
8077 abort ();
8079 bufp->kind = delete_window_event;
8080 XSETFRAME (bufp->frame_or_window, f);
8081 bufp->arg = Qnil;
8082 bufp++;
8083 count++;
8084 numchars--;
8086 break;
8088 case WM_INITMENU:
8089 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
8091 if (f)
8093 if (numchars == 0)
8094 abort ();
8096 bufp->kind = menu_bar_activate_event;
8097 XSETFRAME (bufp->frame_or_window, f);
8098 bufp->arg = Qnil;
8099 bufp++;
8100 count++;
8101 numchars--;
8103 break;
8105 case WM_COMMAND:
8106 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
8108 if (f)
8110 extern void menubar_selection_callback
8111 (FRAME_PTR f, void * client_data);
8112 menubar_selection_callback (f, (void *)msg.msg.wParam);
8115 check_visibility = 1;
8116 break;
8118 case WM_DISPLAYCHANGE:
8119 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
8121 if (f)
8123 dpyinfo->width = (short) LOWORD (msg.msg.lParam);
8124 dpyinfo->height = (short) HIWORD (msg.msg.lParam);
8125 dpyinfo->n_cbits = msg.msg.wParam;
8126 DebPrint (("display change: %d %d\n", dpyinfo->width,
8127 dpyinfo->height));
8130 check_visibility = 1;
8131 break;
8133 default:
8134 /* Check for messages registered at runtime. */
8135 if (msg.msg.message == msh_mousewheel)
8137 if (dpyinfo->grabbed && last_mouse_frame
8138 && FRAME_LIVE_P (last_mouse_frame))
8139 f = last_mouse_frame;
8140 else
8141 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
8143 if (f)
8145 if ((!dpyinfo->w32_focus_frame
8146 || f == dpyinfo->w32_focus_frame)
8147 && (numchars >= 1))
8149 construct_mouse_wheel (bufp, &msg, f);
8150 bufp++;
8151 count++;
8152 numchars--;
8156 break;
8160 /* If the focus was just given to an autoraising frame,
8161 raise it now. */
8162 /* ??? This ought to be able to handle more than one such frame. */
8163 if (pending_autoraise_frame)
8165 x_raise_frame (pending_autoraise_frame);
8166 pending_autoraise_frame = 0;
8169 /* Check which frames are still visisble, if we have enqueued any user
8170 events or been notified of events that may affect visibility. We
8171 do this here because there doesn't seem to be any direct
8172 notification from Windows that the visibility of a window has
8173 changed (at least, not in all cases). */
8174 if (count > 0 || check_visibility)
8176 Lisp_Object tail, frame;
8178 FOR_EACH_FRAME (tail, frame)
8180 FRAME_PTR f = XFRAME (frame);
8181 /* Check "visible" frames and mark each as obscured or not.
8182 Note that async_visible is nonzero for unobscured and
8183 obscured frames, but zero for hidden and iconified frames. */
8184 if (FRAME_W32_P (f) && f->async_visible)
8186 RECT clipbox;
8187 HDC hdc = get_frame_dc (f);
8188 GetClipBox (hdc, &clipbox);
8189 release_frame_dc (f, hdc);
8191 if (clipbox.right == clipbox.left
8192 || clipbox.bottom == clipbox.top)
8194 /* Frame has become completely obscured so mark as
8195 such (we do this by setting async_visible to 2 so
8196 that FRAME_VISIBLE_P is still true, but redisplay
8197 will skip it). */
8198 f->async_visible = 2;
8200 if (!FRAME_OBSCURED_P (f))
8202 DebPrint (("frame %04x (%s) obscured\n", f,
8203 XSTRING (f->name)->data));
8206 else
8208 /* Frame is not obscured, so mark it as such. */
8209 f->async_visible = 1;
8211 if (FRAME_OBSCURED_P (f))
8213 SET_FRAME_GARBAGED (f);
8214 DebPrint (("frame %04x (%s) reexposed\n", f,
8215 XSTRING (f->name)->data));
8217 /* Force a redisplay sooner or later. */
8218 record_asynch_buffer_change ();
8225 UNBLOCK_INPUT;
8226 return count;
8232 /***********************************************************************
8233 Text Cursor
8234 ***********************************************************************/
8236 /* Note if the text cursor of window W has been overwritten by a
8237 drawing operation that outputs N glyphs starting at HPOS in the
8238 line given by output_cursor.vpos. N < 0 means all the rest of the
8239 line after HPOS has been written. */
8241 static void
8242 note_overwritten_text_cursor (w, hpos, n)
8243 struct window *w;
8244 int hpos, n;
8246 if (updated_area == TEXT_AREA
8247 && output_cursor.vpos == w->phys_cursor.vpos
8248 && hpos <= w->phys_cursor.hpos
8249 && (n < 0
8250 || hpos + n > w->phys_cursor.hpos))
8251 w->phys_cursor_on_p = 0;
8255 /* Set clipping for output in glyph row ROW. W is the window in which
8256 we operate. GC is the graphics context to set clipping in.
8257 WHOLE_LINE_P non-zero means include the areas used for truncation
8258 mark display and alike in the clipping rectangle.
8260 ROW may be a text row or, e.g., a mode line. Text rows must be
8261 clipped to the interior of the window dedicated to text display,
8262 mode lines must be clipped to the whole window. */
8264 static void
8265 w32_clip_to_row (w, row, hdc, whole_line_p)
8266 struct window *w;
8267 struct glyph_row *row;
8268 HDC hdc;
8269 int whole_line_p;
8271 struct frame *f = XFRAME (WINDOW_FRAME (w));
8272 RECT clip_rect;
8273 int window_x, window_y, window_width, window_height;
8275 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
8277 clip_rect.left = WINDOW_TO_FRAME_PIXEL_X (w, 0);
8278 clip_rect.top = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
8279 clip_rect.top = max (clip_rect.top, window_y);
8280 clip_rect.right = clip_rect.left + window_width;
8281 clip_rect.bottom = clip_rect.top + row->visible_height;
8283 /* If clipping to the whole line, including trunc marks, extend
8284 the rectangle to the left and increase its width. */
8285 if (whole_line_p)
8287 clip_rect.left -= FRAME_X_LEFT_FLAGS_AREA_WIDTH (f);
8288 clip_rect.right += FRAME_X_FLAGS_AREA_WIDTH (f);
8291 w32_set_clip_rectangle (hdc, &clip_rect);
8295 /* Draw a hollow box cursor on window W in glyph row ROW. */
8297 static void
8298 x_draw_hollow_cursor (w, row)
8299 struct window *w;
8300 struct glyph_row *row;
8302 struct frame *f = XFRAME (WINDOW_FRAME (w));
8303 HDC hdc = get_frame_dc (f);
8304 RECT rect;
8305 int wd;
8306 struct glyph *cursor_glyph;
8307 HBRUSH hb = CreateSolidBrush (f->output_data.w32->cursor_pixel);
8309 /* Compute frame-relative coordinates from window-relative
8310 coordinates. */
8311 rect.left = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
8312 rect.top = (WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y)
8313 + row->ascent - w->phys_cursor_ascent);
8314 rect.bottom = rect.top + row->height - 1;
8316 /* Get the glyph the cursor is on. If we can't tell because
8317 the current matrix is invalid or such, give up. */
8318 cursor_glyph = get_phys_cursor_glyph (w);
8319 if (cursor_glyph == NULL)
8320 return;
8322 /* Compute the width of the rectangle to draw. If on a stretch
8323 glyph, and `x-stretch-block-cursor' is nil, don't draw a
8324 rectangle as wide as the glyph, but use a canonical character
8325 width instead. */
8326 wd = cursor_glyph->pixel_width - 1;
8327 if (cursor_glyph->type == STRETCH_GLYPH
8328 && !x_stretch_cursor_p)
8329 wd = min (CANON_X_UNIT (f), wd);
8331 rect.right = rect.left + wd;
8333 FrameRect (hdc, &rect, hb);
8334 DeleteObject (hb);
8336 release_frame_dc (f, hdc);
8340 /* Draw a bar cursor on window W in glyph row ROW.
8342 Implementation note: One would like to draw a bar cursor with an
8343 angle equal to the one given by the font property XA_ITALIC_ANGLE.
8344 Unfortunately, I didn't find a font yet that has this property set.
8345 --gerd. */
8347 static void
8348 x_draw_bar_cursor (w, row, width)
8349 struct window *w;
8350 struct glyph_row *row;
8351 int width;
8353 /* If cursor hpos is out of bounds, don't draw garbage. This can
8354 happen in mini-buffer windows when switching between echo area
8355 glyphs and mini-buffer. */
8356 if (w->phys_cursor.hpos < row->used[TEXT_AREA])
8358 struct frame *f = XFRAME (w->frame);
8359 struct glyph *cursor_glyph;
8360 int x;
8361 HDC hdc;
8363 cursor_glyph = get_phys_cursor_glyph (w);
8364 if (cursor_glyph == NULL)
8365 return;
8367 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
8369 if (width < 0)
8370 width = f->output_data.w32->cursor_width;
8372 hdc = get_frame_dc (f);
8373 w32_fill_area (f, hdc, f->output_data.w32->cursor_pixel,
8375 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
8376 min (cursor_glyph->pixel_width, width),
8377 row->height);
8378 release_frame_dc (f, hdc);
8383 /* Clear the cursor of window W to background color, and mark the
8384 cursor as not shown. This is used when the text where the cursor
8385 is is about to be rewritten. */
8387 static void
8388 x_clear_cursor (w)
8389 struct window *w;
8391 if (FRAME_VISIBLE_P (XFRAME (w->frame)) && w->phys_cursor_on_p)
8392 x_update_window_cursor (w, 0);
8396 /* Draw the cursor glyph of window W in glyph row ROW. See the
8397 comment of x_draw_glyphs for the meaning of HL. */
8399 static void
8400 x_draw_phys_cursor_glyph (w, row, hl)
8401 struct window *w;
8402 struct glyph_row *row;
8403 enum draw_glyphs_face hl;
8405 /* If cursor hpos is out of bounds, don't draw garbage. This can
8406 happen in mini-buffer windows when switching between echo area
8407 glyphs and mini-buffer. */
8408 if (w->phys_cursor.hpos < row->used[TEXT_AREA])
8410 x_draw_glyphs (w, w->phys_cursor.x, row, TEXT_AREA,
8411 w->phys_cursor.hpos, w->phys_cursor.hpos + 1,
8412 hl, 0, 0, 0);
8414 /* When we erase the cursor, and ROW is overlapped by other
8415 rows, make sure that these overlapping parts of other rows
8416 are redrawn. */
8417 if (hl == DRAW_NORMAL_TEXT && row->overlapped_p)
8419 if (row > w->current_matrix->rows
8420 && MATRIX_ROW_OVERLAPS_SUCC_P (row - 1))
8421 x_fix_overlapping_area (w, row - 1, TEXT_AREA);
8423 if (MATRIX_ROW_BOTTOM_Y (row) < window_text_bottom_y (w)
8424 && MATRIX_ROW_OVERLAPS_PRED_P (row + 1))
8425 x_fix_overlapping_area (w, row + 1, TEXT_AREA);
8431 /* Erase the image of a cursor of window W from the screen. */
8433 static void
8434 x_erase_phys_cursor (w)
8435 struct window *w;
8437 struct frame *f = XFRAME (w->frame);
8438 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
8439 int hpos = w->phys_cursor.hpos;
8440 int vpos = w->phys_cursor.vpos;
8441 int mouse_face_here_p = 0;
8442 struct glyph_matrix *active_glyphs = w->current_matrix;
8443 struct glyph_row *cursor_row;
8444 struct glyph *cursor_glyph;
8445 enum draw_glyphs_face hl;
8447 /* No cursor displayed or row invalidated => nothing to do on the
8448 screen. */
8449 if (w->phys_cursor_type == NO_CURSOR)
8450 goto mark_cursor_off;
8452 /* VPOS >= active_glyphs->nrows means that window has been resized.
8453 Don't bother to erase the cursor. */
8454 if (vpos >= active_glyphs->nrows)
8455 goto mark_cursor_off;
8457 /* If row containing cursor is marked invalid, there is nothing we
8458 can do. */
8459 cursor_row = MATRIX_ROW (active_glyphs, vpos);
8460 if (!cursor_row->enabled_p)
8461 goto mark_cursor_off;
8463 /* This can happen when the new row is shorter than the old one.
8464 In this case, either x_draw_glyphs or clear_end_of_line
8465 should have cleared the cursor. Note that we wouldn't be
8466 able to erase the cursor in this case because we don't have a
8467 cursor glyph at hand. */
8468 if (w->phys_cursor.hpos >= cursor_row->used[TEXT_AREA])
8469 goto mark_cursor_off;
8471 /* If the cursor is in the mouse face area, redisplay that when
8472 we clear the cursor. */
8473 if (w == XWINDOW (dpyinfo->mouse_face_window)
8474 && (vpos > dpyinfo->mouse_face_beg_row
8475 || (vpos == dpyinfo->mouse_face_beg_row
8476 && hpos >= dpyinfo->mouse_face_beg_col))
8477 && (vpos < dpyinfo->mouse_face_end_row
8478 || (vpos == dpyinfo->mouse_face_end_row
8479 && hpos < dpyinfo->mouse_face_end_col))
8480 /* Don't redraw the cursor's spot in mouse face if it is at the
8481 end of a line (on a newline). The cursor appears there, but
8482 mouse highlighting does not. */
8483 && cursor_row->used[TEXT_AREA] > hpos)
8484 mouse_face_here_p = 1;
8486 /* Maybe clear the display under the cursor. */
8487 if (w->phys_cursor_type == HOLLOW_BOX_CURSOR)
8489 int x;
8490 int header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
8491 HDC hdc;
8493 cursor_glyph = get_phys_cursor_glyph (w);
8494 if (cursor_glyph == NULL)
8495 goto mark_cursor_off;
8497 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
8499 hdc = get_frame_dc (f);
8500 w32_clear_area (f, hdc, x,
8501 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
8502 cursor_row->y)),
8503 cursor_glyph->pixel_width,
8504 cursor_row->visible_height);
8505 release_frame_dc (f, hdc);
8508 /* Erase the cursor by redrawing the character underneath it. */
8509 if (mouse_face_here_p)
8510 hl = DRAW_MOUSE_FACE;
8511 else if (cursor_row->inverse_p)
8512 hl = DRAW_INVERSE_VIDEO;
8513 else
8514 hl = DRAW_NORMAL_TEXT;
8515 x_draw_phys_cursor_glyph (w, cursor_row, hl);
8517 mark_cursor_off:
8518 w->phys_cursor_on_p = 0;
8519 w->phys_cursor_type = NO_CURSOR;
8523 /* Display or clear cursor of window W. If ON is zero, clear the
8524 cursor. If it is non-zero, display the cursor. If ON is nonzero,
8525 where to put the cursor is specified by HPOS, VPOS, X and Y. */
8527 void
8528 x_display_and_set_cursor (w, on, hpos, vpos, x, y)
8529 struct window *w;
8530 int on, hpos, vpos, x, y;
8532 struct frame *f = XFRAME (w->frame);
8533 int new_cursor_type;
8534 int new_cursor_width;
8535 struct glyph_matrix *current_glyphs;
8536 struct glyph_row *glyph_row;
8537 struct glyph *glyph;
8539 /* This is pointless on invisible frames, and dangerous on garbaged
8540 windows and frames; in the latter case, the frame or window may
8541 be in the midst of changing its size, and x and y may be off the
8542 window. */
8543 if (! FRAME_VISIBLE_P (f)
8544 || FRAME_GARBAGED_P (f)
8545 || vpos >= w->current_matrix->nrows
8546 || hpos >= w->current_matrix->matrix_w)
8547 return;
8549 /* If cursor is off and we want it off, return quickly. */
8550 if (!on && !w->phys_cursor_on_p)
8551 return;
8553 current_glyphs = w->current_matrix;
8554 glyph_row = MATRIX_ROW (current_glyphs, vpos);
8555 glyph = glyph_row->glyphs[TEXT_AREA] + hpos;
8557 /* If cursor row is not enabled, we don't really know where to
8558 display the cursor. */
8559 if (!glyph_row->enabled_p)
8561 w->phys_cursor_on_p = 0;
8562 return;
8565 xassert (interrupt_input_blocked);
8567 /* Set new_cursor_type to the cursor we want to be displayed. In a
8568 mini-buffer window, we want the cursor only to appear if we are
8569 reading input from this window. For the selected window, we want
8570 the cursor type given by the frame parameter. If explicitly
8571 marked off, draw no cursor. In all other cases, we want a hollow
8572 box cursor. */
8573 new_cursor_width = -1;
8574 if (cursor_in_echo_area
8575 && FRAME_HAS_MINIBUF_P (f)
8576 && EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window))
8578 if (w == XWINDOW (echo_area_window))
8579 new_cursor_type = FRAME_DESIRED_CURSOR (f);
8580 else
8581 new_cursor_type = HOLLOW_BOX_CURSOR;
8583 else
8585 if (w != XWINDOW (selected_window)
8586 || f != FRAME_W32_DISPLAY_INFO (f)->w32_highlight_frame)
8588 extern int cursor_in_non_selected_windows;
8590 if (MINI_WINDOW_P (w) || !cursor_in_non_selected_windows)
8591 new_cursor_type = NO_CURSOR;
8592 else
8593 new_cursor_type = HOLLOW_BOX_CURSOR;
8595 else if (w->cursor_off_p)
8596 new_cursor_type = NO_CURSOR;
8597 else
8599 struct buffer *b = XBUFFER (w->buffer);
8601 if (EQ (b->cursor_type, Qt))
8602 new_cursor_type = FRAME_DESIRED_CURSOR (f);
8603 else
8604 new_cursor_type = x_specified_cursor_type (b->cursor_type,
8605 &new_cursor_width);
8609 /* If cursor is currently being shown and we don't want it to be or
8610 it is in the wrong place, or the cursor type is not what we want,
8611 erase it. */
8612 if (w->phys_cursor_on_p
8613 && (!on
8614 || w->phys_cursor.x != x
8615 || w->phys_cursor.y != y
8616 || new_cursor_type != w->phys_cursor_type))
8617 x_erase_phys_cursor (w);
8619 /* If the cursor is now invisible and we want it to be visible,
8620 display it. */
8621 if (on && !w->phys_cursor_on_p)
8623 w->phys_cursor_ascent = glyph_row->ascent;
8624 w->phys_cursor_height = glyph_row->height;
8626 /* Set phys_cursor_.* before x_draw_.* is called because some
8627 of them may need the information. */
8628 w->phys_cursor.x = x;
8629 w->phys_cursor.y = glyph_row->y;
8630 w->phys_cursor.hpos = hpos;
8631 w->phys_cursor.vpos = vpos;
8632 w->phys_cursor_type = new_cursor_type;
8633 w->phys_cursor_on_p = 1;
8635 switch (new_cursor_type)
8637 case HOLLOW_BOX_CURSOR:
8638 x_draw_hollow_cursor (w, glyph_row);
8639 break;
8641 case FILLED_BOX_CURSOR:
8642 x_draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
8643 break;
8645 case BAR_CURSOR:
8646 x_draw_bar_cursor (w, glyph_row, new_cursor_width);
8647 break;
8649 case NO_CURSOR:
8650 break;
8652 default:
8653 abort ();
8659 /* Display the cursor on window W, or clear it. X and Y are window
8660 relative pixel coordinates. HPOS and VPOS are glyph matrix
8661 positions. If W is not the selected window, display a hollow
8662 cursor. ON non-zero means display the cursor at X, Y which
8663 correspond to HPOS, VPOS, otherwise it is cleared. */
8665 void
8666 x_display_cursor (w, on, hpos, vpos, x, y)
8667 struct window *w;
8668 int on, hpos, vpos, x, y;
8670 BLOCK_INPUT;
8671 x_display_and_set_cursor (w, on, hpos, vpos, x, y);
8672 UNBLOCK_INPUT;
8676 /* Display the cursor on window W, or clear it, according to ON_P.
8677 Don't change the cursor's position. */
8679 void
8680 x_update_cursor (f, on_p)
8681 struct frame *f;
8682 int on_p;
8684 x_update_cursor_in_window_tree (XWINDOW (f->root_window), on_p);
8688 /* Call x_update_window_cursor with parameter ON_P on all leaf windows
8689 in the window tree rooted at W. */
8691 static void
8692 x_update_cursor_in_window_tree (w, on_p)
8693 struct window *w;
8694 int on_p;
8696 while (w)
8698 if (!NILP (w->hchild))
8699 x_update_cursor_in_window_tree (XWINDOW (w->hchild), on_p);
8700 else if (!NILP (w->vchild))
8701 x_update_cursor_in_window_tree (XWINDOW (w->vchild), on_p);
8702 else
8703 x_update_window_cursor (w, on_p);
8705 w = NILP (w->next) ? 0 : XWINDOW (w->next);
8710 /* Switch the display of W's cursor on or off, according to the value
8711 of ON. */
8713 static void
8714 x_update_window_cursor (w, on)
8715 struct window *w;
8716 int on;
8718 /* Don't update cursor in windows whose frame is in the process
8719 of being deleted. */
8720 if (w->current_matrix)
8722 BLOCK_INPUT;
8723 x_display_and_set_cursor (w, on, w->phys_cursor.hpos,
8724 w->phys_cursor.vpos, w->phys_cursor.x,
8725 w->phys_cursor.y);
8726 UNBLOCK_INPUT;
8733 /* Icons. */
8736 x_bitmap_icon (f, icon)
8737 struct frame *f;
8738 Lisp_Object icon;
8740 int mask, bitmap_id;
8741 Window icon_window;
8742 HANDLE hicon;
8744 if (FRAME_W32_WINDOW (f) == 0)
8745 return 1;
8747 if (NILP (icon))
8748 hicon = LoadIcon (hinst, EMACS_CLASS);
8749 else if (STRINGP (icon))
8750 hicon = LoadImage (NULL, (LPCTSTR) XSTRING (icon)->data, IMAGE_ICON, 0, 0,
8751 LR_DEFAULTSIZE | LR_LOADFROMFILE);
8752 else if (SYMBOLP (icon))
8754 LPCTSTR name;
8756 if (EQ (icon, intern ("application")))
8757 name = (LPCTSTR) IDI_APPLICATION;
8758 else if (EQ (icon, intern ("hand")))
8759 name = (LPCTSTR) IDI_HAND;
8760 else if (EQ (icon, intern ("question")))
8761 name = (LPCTSTR) IDI_QUESTION;
8762 else if (EQ (icon, intern ("exclamation")))
8763 name = (LPCTSTR) IDI_EXCLAMATION;
8764 else if (EQ (icon, intern ("asterisk")))
8765 name = (LPCTSTR) IDI_ASTERISK;
8766 else if (EQ (icon, intern ("winlogo")))
8767 name = (LPCTSTR) IDI_WINLOGO;
8768 else
8769 return 1;
8771 hicon = LoadIcon (NULL, name);
8773 else
8774 return 1;
8776 if (hicon == NULL)
8777 return 1;
8779 PostMessage (FRAME_W32_WINDOW (f), WM_SETICON, (WPARAM) ICON_BIG,
8780 (LPARAM) hicon);
8782 return 0;
8786 /* Changing the font of the frame. */
8788 /* Give frame F the font named FONTNAME as its default font, and
8789 return the full name of that font. FONTNAME may be a wildcard
8790 pattern; in that case, we choose some font that fits the pattern.
8791 The return value shows which font we chose. */
8793 Lisp_Object
8794 x_new_font (f, fontname)
8795 struct frame *f;
8796 register char *fontname;
8798 struct font_info *fontp
8799 = FS_LOAD_FONT (f, 0, fontname, -1);
8801 if (!fontp)
8802 return Qnil;
8804 FRAME_FONT (f) = (XFontStruct *) (fontp->font);
8805 FRAME_BASELINE_OFFSET (f) = fontp->baseline_offset;
8806 FRAME_FONTSET (f) = -1;
8808 /* Compute the scroll bar width in character columns. */
8809 if (f->scroll_bar_pixel_width > 0)
8811 int wid = FONT_WIDTH (FRAME_FONT (f));
8812 f->scroll_bar_cols = (f->scroll_bar_pixel_width + wid-1) / wid;
8814 else
8816 int wid = FONT_WIDTH (FRAME_FONT (f));
8817 f->scroll_bar_cols = (14 + wid - 1) / wid;
8820 /* Now make the frame display the given font. */
8821 if (FRAME_W32_WINDOW (f) != 0)
8823 frame_update_line_height (f);
8824 x_set_window_size (f, 0, f->width, f->height);
8826 else
8827 /* If we are setting a new frame's font for the first time,
8828 there are no faces yet, so this font's height is the line height. */
8829 f->output_data.w32->line_height = FONT_HEIGHT (FRAME_FONT (f));
8831 return build_string (fontp->full_name);
8834 /* Give frame F the fontset named FONTSETNAME as its default font, and
8835 return the full name of that fontset. FONTSETNAME may be a wildcard
8836 pattern; in that case, we choose some fontset that fits the pattern.
8837 The return value shows which fontset we chose. */
8839 Lisp_Object
8840 x_new_fontset (f, fontsetname)
8841 struct frame *f;
8842 char *fontsetname;
8844 int fontset = fs_query_fontset (build_string (fontsetname), 0);
8845 Lisp_Object result;
8846 char *fontname;
8848 if (fontset < 0)
8849 return Qnil;
8851 if (FRAME_FONTSET (f) == fontset)
8852 /* This fontset is already set in frame F. There's nothing more
8853 to do. */
8854 return fontset_name (fontset);
8856 result = x_new_font (f, (XSTRING (fontset_ascii (fontset))->data));
8858 if (!STRINGP (result))
8859 /* Can't load ASCII font. */
8860 return Qnil;
8862 /* Since x_new_font doesn't update any fontset information, do it now. */
8863 FRAME_FONTSET(f) = fontset;
8865 return build_string (fontsetname);
8869 #if GLYPH_DEBUG
8871 /* Check that FONT is valid on frame F. It is if it can be found in F's
8872 font table. */
8874 static void
8875 x_check_font (f, font)
8876 struct frame *f;
8877 XFontStruct *font;
8879 int i;
8880 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
8882 xassert (font != NULL);
8884 for (i = 0; i < dpyinfo->n_fonts; i++)
8885 if (dpyinfo->font_table[i].name
8886 && font == dpyinfo->font_table[i].font)
8887 break;
8889 xassert (i < dpyinfo->n_fonts);
8892 #endif /* GLYPH_DEBUG != 0 */
8894 /* Set *W to the minimum width, *H to the minimum font height of FONT.
8895 Note: There are (broken) X fonts out there with invalid XFontStruct
8896 min_bounds contents. For example, handa@etl.go.jp reports that
8897 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
8898 have font->min_bounds.width == 0. */
8900 static INLINE void
8901 x_font_min_bounds (font, w, h)
8902 XFontStruct *font;
8903 int *w, *h;
8905 *h = FONT_HEIGHT (font);
8906 *w = FONT_WIDTH (font);
8907 #if 0 /* NTEMACS_TODO: min/max bounds of Windows fonts */
8908 *w = font->min_bounds.width;
8910 /* Try to handle the case where FONT->min_bounds has invalid
8911 contents. Since the only font known to have invalid min_bounds
8912 is fixed-width, use max_bounds if min_bounds seems to be invalid. */
8913 if (*w <= 0)
8914 *w = font->max_bounds.width;
8915 #endif
8919 /* Compute the smallest character width and smallest font height over
8920 all fonts available on frame F. Set the members smallest_char_width
8921 and smallest_font_height in F's x_display_info structure to
8922 the values computed. Value is non-zero if smallest_font_height or
8923 smallest_char_width become smaller than they were before. */
8926 x_compute_min_glyph_bounds (f)
8927 struct frame *f;
8929 int i;
8930 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
8931 XFontStruct *font;
8932 int old_width = dpyinfo->smallest_char_width;
8933 int old_height = dpyinfo->smallest_font_height;
8935 dpyinfo->smallest_font_height = 100000;
8936 dpyinfo->smallest_char_width = 100000;
8938 for (i = 0; i < dpyinfo->n_fonts; ++i)
8939 if (dpyinfo->font_table[i].name)
8941 struct font_info *fontp = dpyinfo->font_table + i;
8942 int w, h;
8944 font = (XFontStruct *) fontp->font;
8945 xassert (font != (XFontStruct *) ~0);
8946 x_font_min_bounds (font, &w, &h);
8948 dpyinfo->smallest_font_height = min (dpyinfo->smallest_font_height, h);
8949 dpyinfo->smallest_char_width = min (dpyinfo->smallest_char_width, w);
8952 xassert (dpyinfo->smallest_char_width > 0
8953 && dpyinfo->smallest_font_height > 0);
8955 return (dpyinfo->n_fonts == 1
8956 || dpyinfo->smallest_char_width < old_width
8957 || dpyinfo->smallest_font_height < old_height);
8961 /* Calculate the absolute position in frame F
8962 from its current recorded position values and gravity. */
8964 void
8965 x_calc_absolute_position (f)
8966 struct frame *f;
8968 Window child;
8969 POINT pt;
8970 int flags = f->output_data.w32->size_hint_flags;
8972 pt.x = pt.y = 0;
8974 /* Find the position of the outside upper-left corner of
8975 the inner window, with respect to the outer window. */
8976 if (f->output_data.w32->parent_desc != FRAME_W32_DISPLAY_INFO (f)->root_window)
8978 BLOCK_INPUT;
8979 MapWindowPoints (FRAME_W32_WINDOW (f),
8980 f->output_data.w32->parent_desc,
8981 &pt, 1);
8982 UNBLOCK_INPUT;
8986 RECT rt;
8987 rt.left = rt.right = rt.top = rt.bottom = 0;
8989 BLOCK_INPUT;
8990 AdjustWindowRect(&rt, f->output_data.w32->dwStyle,
8991 FRAME_EXTERNAL_MENU_BAR (f));
8992 UNBLOCK_INPUT;
8994 pt.x += (rt.right - rt.left);
8995 pt.y += (rt.bottom - rt.top);
8998 /* Treat negative positions as relative to the leftmost bottommost
8999 position that fits on the screen. */
9000 if (flags & XNegative)
9001 f->output_data.w32->left_pos = (FRAME_W32_DISPLAY_INFO (f)->width
9002 - 2 * f->output_data.w32->border_width - pt.x
9003 - PIXEL_WIDTH (f)
9004 + f->output_data.w32->left_pos);
9005 /* NTEMACS_TODO: Subtract menubar height? */
9006 if (flags & YNegative)
9007 f->output_data.w32->top_pos = (FRAME_W32_DISPLAY_INFO (f)->height
9008 - 2 * f->output_data.w32->border_width - pt.y
9009 - PIXEL_HEIGHT (f)
9010 + f->output_data.w32->top_pos);
9011 /* The left_pos and top_pos
9012 are now relative to the top and left screen edges,
9013 so the flags should correspond. */
9014 f->output_data.w32->size_hint_flags &= ~ (XNegative | YNegative);
9017 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
9018 to really change the position, and 0 when calling from
9019 x_make_frame_visible (in that case, XOFF and YOFF are the current
9020 position values). It is -1 when calling from x_set_frame_parameters,
9021 which means, do adjust for borders but don't change the gravity. */
9023 void
9024 x_set_offset (f, xoff, yoff, change_gravity)
9025 struct frame *f;
9026 register int xoff, yoff;
9027 int change_gravity;
9029 int modified_top, modified_left;
9031 if (change_gravity > 0)
9033 f->output_data.w32->top_pos = yoff;
9034 f->output_data.w32->left_pos = xoff;
9035 f->output_data.w32->size_hint_flags &= ~ (XNegative | YNegative);
9036 if (xoff < 0)
9037 f->output_data.w32->size_hint_flags |= XNegative;
9038 if (yoff < 0)
9039 f->output_data.w32->size_hint_flags |= YNegative;
9040 f->output_data.w32->win_gravity = NorthWestGravity;
9042 x_calc_absolute_position (f);
9044 BLOCK_INPUT;
9045 x_wm_set_size_hint (f, (long) 0, 0);
9047 modified_left = f->output_data.w32->left_pos;
9048 modified_top = f->output_data.w32->top_pos;
9050 my_set_window_pos (FRAME_W32_WINDOW (f),
9051 NULL,
9052 modified_left, modified_top,
9053 0, 0,
9054 SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
9055 UNBLOCK_INPUT;
9058 /* Call this to change the size of frame F's x-window.
9059 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
9060 for this size change and subsequent size changes.
9061 Otherwise we leave the window gravity unchanged. */
9062 void
9063 x_set_window_size (f, change_gravity, cols, rows)
9064 struct frame *f;
9065 int change_gravity;
9066 int cols, rows;
9068 int pixelwidth, pixelheight;
9070 BLOCK_INPUT;
9072 check_frame_size (f, &rows, &cols);
9073 f->output_data.w32->vertical_scroll_bar_extra
9074 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
9076 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.w32->font)));
9077 f->output_data.w32->flags_areas_extra
9078 = FRAME_FLAGS_AREA_WIDTH (f);
9079 pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols);
9080 pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows);
9082 f->output_data.w32->win_gravity = NorthWestGravity;
9083 x_wm_set_size_hint (f, (long) 0, 0);
9086 RECT rect;
9088 rect.left = rect.top = 0;
9089 rect.right = pixelwidth;
9090 rect.bottom = pixelheight;
9092 AdjustWindowRect(&rect, f->output_data.w32->dwStyle,
9093 FRAME_EXTERNAL_MENU_BAR (f));
9095 my_set_window_pos (FRAME_W32_WINDOW (f),
9096 NULL,
9097 0, 0,
9098 rect.right - rect.left,
9099 rect.bottom - rect.top,
9100 SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE);
9103 /* Now, strictly speaking, we can't be sure that this is accurate,
9104 but the window manager will get around to dealing with the size
9105 change request eventually, and we'll hear how it went when the
9106 ConfigureNotify event gets here.
9108 We could just not bother storing any of this information here,
9109 and let the ConfigureNotify event set everything up, but that
9110 might be kind of confusing to the Lisp code, since size changes
9111 wouldn't be reported in the frame parameters until some random
9112 point in the future when the ConfigureNotify event arrives.
9114 We pass 1 for DELAY since we can't run Lisp code inside of
9115 a BLOCK_INPUT. */
9116 change_frame_size (f, rows, cols, 0, 1, 0);
9117 PIXEL_WIDTH (f) = pixelwidth;
9118 PIXEL_HEIGHT (f) = pixelheight;
9120 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
9121 receive in the ConfigureNotify event; if we get what we asked
9122 for, then the event won't cause the screen to become garbaged, so
9123 we have to make sure to do it here. */
9124 SET_FRAME_GARBAGED (f);
9126 /* If cursor was outside the new size, mark it as off. */
9127 mark_window_cursors_off (XWINDOW (f->root_window));
9129 /* Clear out any recollection of where the mouse highlighting was,
9130 since it might be in a place that's outside the new frame size.
9131 Actually checking whether it is outside is a pain in the neck,
9132 so don't try--just let the highlighting be done afresh with new size. */
9133 cancel_mouse_face (f);
9135 UNBLOCK_INPUT;
9138 /* Mouse warping. */
9140 void x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y);
9142 void
9143 x_set_mouse_position (f, x, y)
9144 struct frame *f;
9145 int x, y;
9147 int pix_x, pix_y;
9149 pix_x = CHAR_TO_PIXEL_COL (f, x) + FONT_WIDTH (f->output_data.w32->font) / 2;
9150 pix_y = CHAR_TO_PIXEL_ROW (f, y) + f->output_data.w32->line_height / 2;
9152 if (pix_x < 0) pix_x = 0;
9153 if (pix_x > PIXEL_WIDTH (f)) pix_x = PIXEL_WIDTH (f);
9155 if (pix_y < 0) pix_y = 0;
9156 if (pix_y > PIXEL_HEIGHT (f)) pix_y = PIXEL_HEIGHT (f);
9158 x_set_mouse_pixel_position (f, pix_x, pix_y);
9161 void
9162 x_set_mouse_pixel_position (f, pix_x, pix_y)
9163 struct frame *f;
9164 int pix_x, pix_y;
9166 RECT rect;
9167 POINT pt;
9169 BLOCK_INPUT;
9171 GetClientRect (FRAME_W32_WINDOW (f), &rect);
9172 pt.x = rect.left + pix_x;
9173 pt.y = rect.top + pix_y;
9174 ClientToScreen (FRAME_W32_WINDOW (f), &pt);
9176 SetCursorPos (pt.x, pt.y);
9178 UNBLOCK_INPUT;
9182 /* focus shifting, raising and lowering. */
9184 void
9185 x_focus_on_frame (f)
9186 struct frame *f;
9188 struct w32_display_info *dpyinfo = &one_w32_display_info;
9190 /* Give input focus to frame. */
9191 BLOCK_INPUT;
9192 #if 0
9193 /* Try not to change its Z-order if possible. */
9194 if (x_window_to_frame (dpyinfo, GetForegroundWindow ()))
9195 my_set_focus (f, FRAME_W32_WINDOW (f));
9196 else
9197 #endif
9198 my_set_foreground_window (FRAME_W32_WINDOW (f));
9199 UNBLOCK_INPUT;
9202 void
9203 x_unfocus_frame (f)
9204 struct frame *f;
9208 /* Raise frame F. */
9209 void
9210 x_raise_frame (f)
9211 struct frame *f;
9213 BLOCK_INPUT;
9215 /* Strictly speaking, raise-frame should only change the frame's Z
9216 order, leaving input focus unchanged. This is reasonable behaviour
9217 on X where the usual policy is point-to-focus. However, this
9218 behaviour would be very odd on Windows where the usual policy is
9219 click-to-focus.
9221 On X, if the mouse happens to be over the raised frame, it gets
9222 input focus anyway (so the window with focus will never be
9223 completely obscured) - if not, then just moving the mouse over it
9224 is sufficient to give it focus. On Windows, the user must actually
9225 click on the frame (preferrably the title bar so as not to move
9226 point), which is more awkward. Also, no other Windows program
9227 raises a window to the top but leaves another window (possibly now
9228 completely obscured) with input focus.
9230 Because there is a system setting on Windows that allows the user
9231 to choose the point to focus policy, we make the strict semantics
9232 optional, but by default we grab focus when raising. */
9234 if (NILP (Vw32_grab_focus_on_raise))
9236 /* The obvious call to my_set_window_pos doesn't work if Emacs is
9237 not already the foreground application: the frame is raised
9238 above all other frames belonging to us, but not above the
9239 current top window. To achieve that, we have to resort to this
9240 more cumbersome method. */
9242 HDWP handle = BeginDeferWindowPos (2);
9243 if (handle)
9245 DeferWindowPos (handle,
9246 FRAME_W32_WINDOW (f),
9247 HWND_TOP,
9248 0, 0, 0, 0,
9249 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
9251 DeferWindowPos (handle,
9252 GetForegroundWindow (),
9253 FRAME_W32_WINDOW (f),
9254 0, 0, 0, 0,
9255 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
9257 EndDeferWindowPos (handle);
9260 else
9262 my_set_foreground_window (FRAME_W32_WINDOW (f));
9265 UNBLOCK_INPUT;
9268 /* Lower frame F. */
9269 void
9270 x_lower_frame (f)
9271 struct frame *f;
9273 BLOCK_INPUT;
9274 my_set_window_pos (FRAME_W32_WINDOW (f),
9275 HWND_BOTTOM,
9276 0, 0, 0, 0,
9277 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
9278 UNBLOCK_INPUT;
9281 static void
9282 w32_frame_raise_lower (f, raise_flag)
9283 FRAME_PTR f;
9284 int raise_flag;
9286 if (raise_flag)
9287 x_raise_frame (f);
9288 else
9289 x_lower_frame (f);
9292 /* Change of visibility. */
9294 /* This tries to wait until the frame is really visible.
9295 However, if the window manager asks the user where to position
9296 the frame, this will return before the user finishes doing that.
9297 The frame will not actually be visible at that time,
9298 but it will become visible later when the window manager
9299 finishes with it. */
9301 void
9302 x_make_frame_visible (f)
9303 struct frame *f;
9305 Lisp_Object type;
9307 BLOCK_INPUT;
9309 type = x_icon_type (f);
9310 if (!NILP (type))
9311 x_bitmap_icon (f, type);
9313 if (! FRAME_VISIBLE_P (f))
9315 /* We test FRAME_GARBAGED_P here to make sure we don't
9316 call x_set_offset a second time
9317 if we get to x_make_frame_visible a second time
9318 before the window gets really visible. */
9319 if (! FRAME_ICONIFIED_P (f)
9320 && ! f->output_data.w32->asked_for_visible)
9321 x_set_offset (f, f->output_data.w32->left_pos, f->output_data.w32->top_pos, 0);
9323 f->output_data.w32->asked_for_visible = 1;
9325 // my_show_window (f, FRAME_W32_WINDOW (f), f->async_iconified ? SW_RESTORE : SW_SHOW);
9326 my_show_window (f, FRAME_W32_WINDOW (f), SW_SHOWNORMAL);
9329 /* Synchronize to ensure Emacs knows the frame is visible
9330 before we do anything else. We do this loop with input not blocked
9331 so that incoming events are handled. */
9333 Lisp_Object frame;
9334 int count;
9336 /* This must come after we set COUNT. */
9337 UNBLOCK_INPUT;
9339 XSETFRAME (frame, f);
9341 /* Wait until the frame is visible. Process X events until a
9342 MapNotify event has been seen, or until we think we won't get a
9343 MapNotify at all.. */
9344 for (count = input_signal_count + 10;
9345 input_signal_count < count && !FRAME_VISIBLE_P (f);)
9347 /* Force processing of queued events. */
9348 /* NTEMACS_TODO: x_sync equivalent? */
9350 /* Machines that do polling rather than SIGIO have been observed
9351 to go into a busy-wait here. So we'll fake an alarm signal
9352 to let the handler know that there's something to be read.
9353 We used to raise a real alarm, but it seems that the handler
9354 isn't always enabled here. This is probably a bug. */
9355 if (input_polling_used ())
9357 /* It could be confusing if a real alarm arrives while processing
9358 the fake one. Turn it off and let the handler reset it. */
9359 int old_poll_suppress_count = poll_suppress_count;
9360 poll_suppress_count = 1;
9361 poll_for_input_1 ();
9362 poll_suppress_count = old_poll_suppress_count;
9365 FRAME_SAMPLE_VISIBILITY (f);
9369 /* Change from mapped state to withdrawn state. */
9371 /* Make the frame visible (mapped and not iconified). */
9373 x_make_frame_invisible (f)
9374 struct frame *f;
9376 /* Don't keep the highlight on an invisible frame. */
9377 if (FRAME_W32_DISPLAY_INFO (f)->w32_highlight_frame == f)
9378 FRAME_W32_DISPLAY_INFO (f)->w32_highlight_frame = 0;
9380 BLOCK_INPUT;
9382 my_show_window (f, FRAME_W32_WINDOW (f), SW_HIDE);
9384 /* We can't distinguish this from iconification
9385 just by the event that we get from the server.
9386 So we can't win using the usual strategy of letting
9387 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
9388 and synchronize with the server to make sure we agree. */
9389 f->visible = 0;
9390 FRAME_ICONIFIED_P (f) = 0;
9391 f->async_visible = 0;
9392 f->async_iconified = 0;
9394 UNBLOCK_INPUT;
9397 /* Change window state from mapped to iconified. */
9399 void
9400 x_iconify_frame (f)
9401 struct frame *f;
9403 int result;
9404 Lisp_Object type;
9406 /* Don't keep the highlight on an invisible frame. */
9407 if (FRAME_W32_DISPLAY_INFO (f)->w32_highlight_frame == f)
9408 FRAME_W32_DISPLAY_INFO (f)->w32_highlight_frame = 0;
9410 if (f->async_iconified)
9411 return;
9413 BLOCK_INPUT;
9415 type = x_icon_type (f);
9416 if (!NILP (type))
9417 x_bitmap_icon (f, type);
9419 /* Simulate the user minimizing the frame. */
9420 SendMessage (FRAME_W32_WINDOW (f), WM_SYSCOMMAND, SC_MINIMIZE, 0);
9422 UNBLOCK_INPUT;
9425 /* Destroy the window of frame F. */
9427 x_destroy_window (f)
9428 struct frame *f;
9430 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
9432 BLOCK_INPUT;
9434 my_destroy_window (f, FRAME_W32_WINDOW (f));
9435 free_frame_menubar (f);
9436 free_frame_faces (f);
9438 xfree (f->output_data.w32);
9439 f->output_data.w32 = 0;
9440 if (f == dpyinfo->w32_focus_frame)
9441 dpyinfo->w32_focus_frame = 0;
9442 if (f == dpyinfo->w32_focus_event_frame)
9443 dpyinfo->w32_focus_event_frame = 0;
9444 if (f == dpyinfo->w32_highlight_frame)
9445 dpyinfo->w32_highlight_frame = 0;
9447 dpyinfo->reference_count--;
9449 if (f == dpyinfo->mouse_face_mouse_frame)
9451 dpyinfo->mouse_face_beg_row
9452 = dpyinfo->mouse_face_beg_col = -1;
9453 dpyinfo->mouse_face_end_row
9454 = dpyinfo->mouse_face_end_col = -1;
9455 dpyinfo->mouse_face_window = Qnil;
9458 UNBLOCK_INPUT;
9461 /* Setting window manager hints. */
9463 /* Set the normal size hints for the window manager, for frame F.
9464 FLAGS is the flags word to use--or 0 meaning preserve the flags
9465 that the window now has.
9466 If USER_POSITION is nonzero, we set the USPosition
9467 flag (this is useful when FLAGS is 0). */
9468 void
9469 x_wm_set_size_hint (f, flags, user_position)
9470 struct frame *f;
9471 long flags;
9472 int user_position;
9474 Window window = FRAME_W32_WINDOW (f);
9476 enter_crit ();
9478 SetWindowLong (window, WND_FONTWIDTH_INDEX, FONT_WIDTH (f->output_data.w32->font));
9479 SetWindowLong (window, WND_LINEHEIGHT_INDEX, f->output_data.w32->line_height);
9480 SetWindowLong (window, WND_BORDER_INDEX, f->output_data.w32->internal_border_width);
9481 SetWindowLong (window, WND_SCROLLBAR_INDEX, f->output_data.w32->vertical_scroll_bar_extra);
9483 leave_crit ();
9486 /* Window manager things */
9487 x_wm_set_icon_position (f, icon_x, icon_y)
9488 struct frame *f;
9489 int icon_x, icon_y;
9491 #if 0
9492 Window window = FRAME_W32_WINDOW (f);
9494 f->display.x->wm_hints.flags |= IconPositionHint;
9495 f->display.x->wm_hints.icon_x = icon_x;
9496 f->display.x->wm_hints.icon_y = icon_y;
9498 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->display.x->wm_hints);
9499 #endif
9504 /***********************************************************************
9505 Initialization
9506 ***********************************************************************/
9508 static int w32_initialized = 0;
9510 void
9511 w32_initialize_display_info (display_name)
9512 Lisp_Object display_name;
9514 struct w32_display_info *dpyinfo = &one_w32_display_info;
9516 bzero (dpyinfo, sizeof (*dpyinfo));
9518 /* Put it on w32_display_name_list. */
9519 w32_display_name_list = Fcons (Fcons (display_name, Qnil),
9520 w32_display_name_list);
9521 dpyinfo->name_list_element = XCAR (w32_display_name_list);
9523 dpyinfo->w32_id_name
9524 = (char *) xmalloc (XSTRING (Vinvocation_name)->size
9525 + XSTRING (Vsystem_name)->size
9526 + 2);
9527 sprintf (dpyinfo->w32_id_name, "%s@%s",
9528 XSTRING (Vinvocation_name)->data, XSTRING (Vsystem_name)->data);
9530 /* Default Console mode values - overridden when running in GUI mode
9531 with values obtained from system metrics. */
9532 dpyinfo->resx = 1;
9533 dpyinfo->resy = 1;
9534 dpyinfo->height_in = 1;
9535 dpyinfo->width_in = 1;
9536 dpyinfo->n_planes = 1;
9537 dpyinfo->n_cbits = 4;
9538 dpyinfo->n_fonts = 0;
9539 dpyinfo->smallest_font_height = 1;
9540 dpyinfo->smallest_char_width = 1;
9542 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
9543 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
9544 dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
9545 dpyinfo->mouse_face_window = Qnil;
9547 /* NTEMACS_TODO: dpyinfo->gray */
9551 struct w32_display_info *
9552 w32_term_init (display_name, xrm_option, resource_name)
9553 Lisp_Object display_name;
9554 char *xrm_option;
9555 char *resource_name;
9557 struct w32_display_info *dpyinfo;
9558 HDC hdc;
9560 BLOCK_INPUT;
9562 if (!w32_initialized)
9564 w32_initialize ();
9565 w32_initialized = 1;
9569 int argc = 0;
9570 char *argv[3];
9572 argv[0] = "";
9573 argc = 1;
9574 if (xrm_option)
9576 argv[argc++] = "-xrm";
9577 argv[argc++] = xrm_option;
9581 w32_initialize_display_info (display_name);
9583 dpyinfo = &one_w32_display_info;
9585 hdc = GetDC (GetDesktopWindow ());
9587 dpyinfo->height = GetDeviceCaps (hdc, VERTRES);
9588 dpyinfo->width = GetDeviceCaps (hdc, HORZRES);
9589 dpyinfo->root_window = GetDesktopWindow ();
9590 dpyinfo->n_planes = GetDeviceCaps (hdc, PLANES);
9591 dpyinfo->n_cbits = GetDeviceCaps (hdc, BITSPIXEL);
9592 dpyinfo->resx = GetDeviceCaps (hdc, LOGPIXELSX);
9593 dpyinfo->resy = GetDeviceCaps (hdc, LOGPIXELSY);
9594 dpyinfo->has_palette = GetDeviceCaps (hdc, RASTERCAPS) & RC_PALETTE;
9595 dpyinfo->image_cache = make_image_cache ();
9596 dpyinfo->height_in = dpyinfo->height / dpyinfo->resx;
9597 dpyinfo->width_in = dpyinfo->width / dpyinfo->resy;
9598 ReleaseDC (GetDesktopWindow (), hdc);
9600 /* initialise palette with white and black */
9602 COLORREF color;
9603 w32_defined_color (0, "white", &color, 1);
9604 w32_defined_color (0, "black", &color, 1);
9607 /* Create Row Bitmaps and store them for later use. */
9608 left_bmp = CreateBitmap (left_width, left_height, 1, 1, left_bits);
9609 ov_bmp = CreateBitmap (ov_width, ov_height, 1, 1, ov_bits);
9610 right_bmp = CreateBitmap (right_width, right_height, 1, 1, right_bits);
9611 continued_bmp = CreateBitmap (continued_width, continued_height, 1,
9612 1, continued_bits);
9613 continuation_bmp = CreateBitmap (continuation_width, continuation_height,
9614 1, 1, continuation_bits);
9615 zv_bmp = CreateBitmap (zv_width, zv_height, 1, 1, zv_bits);
9617 #ifndef F_SETOWN_BUG
9618 #ifdef F_SETOWN
9619 #ifdef F_SETOWN_SOCK_NEG
9620 /* stdin is a socket here */
9621 fcntl (connection, F_SETOWN, -getpid ());
9622 #else /* ! defined (F_SETOWN_SOCK_NEG) */
9623 fcntl (connection, F_SETOWN, getpid ());
9624 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
9625 #endif /* ! defined (F_SETOWN) */
9626 #endif /* F_SETOWN_BUG */
9628 #ifdef SIGIO
9629 if (interrupt_input)
9630 init_sigio (connection);
9631 #endif /* ! defined (SIGIO) */
9633 UNBLOCK_INPUT;
9635 return dpyinfo;
9638 /* Get rid of display DPYINFO, assuming all frames are already gone. */
9640 void
9641 x_delete_display (dpyinfo)
9642 struct w32_display_info *dpyinfo;
9644 /* Discard this display from w32_display_name_list and w32_display_list.
9645 We can't use Fdelq because that can quit. */
9646 if (! NILP (w32_display_name_list)
9647 && EQ (XCAR (w32_display_name_list), dpyinfo->name_list_element))
9648 w32_display_name_list = XCDR (w32_display_name_list);
9649 else
9651 Lisp_Object tail;
9653 tail = w32_display_name_list;
9654 while (CONSP (tail) && CONSP (XCDR (tail)))
9656 if (EQ (XCAR (XCDR (tail)), dpyinfo->name_list_element))
9658 XCDR (tail) = XCDR (XCDR (tail));
9659 break;
9661 tail = XCDR (tail);
9665 /* free palette table */
9667 struct w32_palette_entry * plist;
9669 plist = dpyinfo->color_list;
9670 while (plist)
9672 struct w32_palette_entry * pentry = plist;
9673 plist = plist->next;
9674 xfree(pentry);
9676 dpyinfo->color_list = NULL;
9677 if (dpyinfo->palette)
9678 DeleteObject(dpyinfo->palette);
9680 xfree (dpyinfo->font_table);
9681 xfree (dpyinfo->w32_id_name);
9683 /* Destroy row bitmaps. */
9684 DeleteObject (left_bmp);
9685 DeleteObject (ov_bmp);
9686 DeleteObject (right_bmp);
9687 DeleteObject (continued_bmp);
9688 DeleteObject (continuation_bmp);
9689 DeleteObject (zv_bmp);
9692 /* Set up use of W32. */
9694 DWORD w32_msg_worker ();
9696 void
9697 x_flush (struct frame * f)
9698 { /* Nothing to do */ }
9700 static struct redisplay_interface w32_redisplay_interface =
9702 x_produce_glyphs,
9703 x_write_glyphs,
9704 x_insert_glyphs,
9705 x_clear_end_of_line,
9706 x_scroll_run,
9707 x_after_update_window_line,
9708 x_update_window_begin,
9709 x_update_window_end,
9710 w32_cursor_to,
9711 x_flush,
9712 x_clear_mouse_face,
9713 x_get_glyph_overhangs,
9714 x_fix_overlapping_area
9717 void
9718 w32_initialize ()
9720 rif = &w32_redisplay_interface;
9722 /* MSVC does not type K&R functions with no arguments correctly, and
9723 so we must explicitly cast them. */
9724 clear_frame_hook = (void (*)(void)) x_clear_frame;
9725 ins_del_lines_hook = x_ins_del_lines;
9726 change_line_highlight_hook = x_change_line_highlight;
9727 delete_glyphs_hook = x_delete_glyphs;
9728 ring_bell_hook = (void (*)(void)) w32_ring_bell;
9729 reset_terminal_modes_hook = (void (*)(void)) w32_reset_terminal_modes;
9730 set_terminal_modes_hook = (void (*)(void)) w32_set_terminal_modes;
9731 update_begin_hook = x_update_begin;
9732 update_end_hook = x_update_end;
9733 set_terminal_window_hook = w32_set_terminal_window;
9734 read_socket_hook = w32_read_socket;
9735 frame_up_to_date_hook = w32_frame_up_to_date;
9736 reassert_line_highlight_hook = w32_reassert_line_highlight;
9737 mouse_position_hook = w32_mouse_position;
9738 frame_rehighlight_hook = w32_frame_rehighlight;
9739 frame_raise_lower_hook = w32_frame_raise_lower;
9740 set_vertical_scroll_bar_hook = w32_set_vertical_scroll_bar;
9741 condemn_scroll_bars_hook = w32_condemn_scroll_bars;
9742 redeem_scroll_bar_hook = w32_redeem_scroll_bar;
9743 judge_scroll_bars_hook = w32_judge_scroll_bars;
9744 estimate_mode_line_height_hook = x_estimate_mode_line_height;
9746 scroll_region_ok = 1; /* we'll scroll partial frames */
9747 char_ins_del_ok = 0; /* just as fast to write the line */
9748 line_ins_del_ok = 1; /* we'll just blt 'em */
9749 fast_clear_end_of_line = 1; /* X does this well */
9750 memory_below_frame = 0; /* we don't remember what scrolls
9751 off the bottom */
9752 baud_rate = 19200;
9754 last_tool_bar_item = -1;
9755 any_help_event_p = 0;
9757 /* Initialize input mode: interrupt_input off, no flow control, allow
9758 8 bit character input, standard quit char. */
9759 Fset_input_mode (Qnil, Qnil, make_number (2), Qnil);
9761 /* Create the window thread - it will terminate itself or when the app terminates */
9763 init_crit ();
9765 dwMainThreadId = GetCurrentThreadId ();
9766 DuplicateHandle (GetCurrentProcess (), GetCurrentThread (),
9767 GetCurrentProcess (), &hMainThread, 0, TRUE, DUPLICATE_SAME_ACCESS);
9769 /* Wait for thread to start */
9772 MSG msg;
9774 PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE);
9776 hWindowsThread = CreateThread (NULL, 0,
9777 (LPTHREAD_START_ROUTINE) w32_msg_worker,
9778 0, 0, &dwWindowsThreadId);
9780 GetMessage (&msg, NULL, WM_EMACS_DONE, WM_EMACS_DONE);
9783 /* It is desirable that mainThread should have the same notion of
9784 focus window and active window as windowsThread. Unfortunately, the
9785 following call to AttachThreadInput, which should do precisely what
9786 we need, causes major problems when Emacs is linked as a console
9787 program. Unfortunately, we have good reasons for doing that, so
9788 instead we need to send messages to windowsThread to make some API
9789 calls for us (ones that affect, or depend on, the active/focus
9790 window state. */
9791 #ifdef ATTACH_THREADS
9792 AttachThreadInput (dwMainThreadId, dwWindowsThreadId, TRUE);
9793 #endif
9795 /* Dynamically link to optional system components. */
9797 HANDLE user_lib = LoadLibrary ("user32.dll");
9799 #define LOAD_PROC(fn) pfn##fn = (void *) GetProcAddress (user_lib, #fn)
9801 /* New proportional scroll bar functions. */
9802 LOAD_PROC( SetScrollInfo );
9803 LOAD_PROC( GetScrollInfo );
9805 #undef LOAD_PROC
9807 FreeLibrary (user_lib);
9809 /* If using proportional scroll bars, ensure handle is at least 5 pixels;
9810 otherwise use the fixed height. */
9811 vertical_scroll_bar_min_handle = (pfnSetScrollInfo != NULL) ? 5 :
9812 GetSystemMetrics (SM_CYVTHUMB);
9814 /* For either kind of scroll bar, take account of the arrows; these
9815 effectively form the border of the main scroll bar range. */
9816 vertical_scroll_bar_top_border = vertical_scroll_bar_bottom_border
9817 = GetSystemMetrics (SM_CYVSCROLL);
9821 void
9822 syms_of_w32term ()
9824 Lisp_Object codepage;
9826 staticpro (&w32_display_name_list);
9827 w32_display_name_list = Qnil;
9829 staticpro (&last_mouse_scroll_bar);
9830 last_mouse_scroll_bar = Qnil;
9832 staticpro (&Qvendor_specific_keysyms);
9833 Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
9835 DEFVAR_INT ("w32-num-mouse-buttons",
9836 &Vw32_num_mouse_buttons,
9837 "Number of physical mouse buttons.");
9838 Vw32_num_mouse_buttons = Qnil;
9840 DEFVAR_LISP ("w32-swap-mouse-buttons",
9841 &Vw32_swap_mouse_buttons,
9842 "Swap the mapping of middle and right mouse buttons.\n\
9843 When nil, middle button is mouse-2 and right button is mouse-3.");
9844 Vw32_swap_mouse_buttons = Qnil;
9846 DEFVAR_LISP ("w32-grab-focus-on-raise",
9847 &Vw32_grab_focus_on_raise,
9848 "Raised frame grabs input focus.\n\
9849 When t, `raise-frame' grabs input focus as well. This fits well\n\
9850 with the normal Windows click-to-focus policy, but might not be\n\
9851 desirable when using a point-to-focus policy.");
9852 Vw32_grab_focus_on_raise = Qt;
9854 DEFVAR_LISP ("w32-capslock-is-shiftlock",
9855 &Vw32_capslock_is_shiftlock,
9856 "Apply CapsLock state to non character input keys.\n\
9857 When nil, CapsLock only affects normal character input keys.");
9858 Vw32_capslock_is_shiftlock = Qnil;
9860 DEFVAR_LISP ("w32-recognize-altgr",
9861 &Vw32_recognize_altgr,
9862 "Recognize right-alt and left-ctrl as AltGr.\n\
9863 When nil, the right-alt and left-ctrl key combination is\n\
9864 interpreted normally.");
9865 Vw32_recognize_altgr = Qt;
9867 DEFVAR_BOOL ("w32-enable-unicode-output",
9868 &w32_enable_unicode_output,
9869 "Enable the use of Unicode for text output if non-nil.\n\
9870 Unicode output may prevent some third party applications for displaying\n\
9871 Far-East Languages on Windows 95/98 from working properly.\n\
9872 NT uses Unicode internally anyway, so this flag will probably have no\n\
9873 affect on NT machines.");
9874 w32_enable_unicode_output = 1;
9876 help_echo = Qnil;
9877 staticpro (&help_echo);
9878 help_echo_object = Qnil;
9879 staticpro (&help_echo_object);
9880 previous_help_echo = Qnil;
9881 staticpro (&previous_help_echo);
9883 DEFVAR_BOOL ("x-stretch-cursor", &x_stretch_cursor_p,
9884 "*Non-nil means draw block cursor as wide as the glyph under it.\n\
9885 For example, if a block cursor is over a tab, it will be drawn as\n\
9886 wide as that tab on the display.");
9887 x_stretch_cursor_p = 0;
9889 DEFVAR_BOOL ("x-toolkit-scroll-bars-p", &x_toolkit_scroll_bars_p,
9890 "If not nil, Emacs uses toolkit scroll bars.");
9891 x_toolkit_scroll_bars_p = 1;
9893 staticpro (&last_mouse_motion_frame);
9894 last_mouse_motion_frame = Qnil;