Regenerated.
[emacs.git] / src / w32term.c
blobdd12c5b871ddbd8d6746fa407ef53570d4183290
1 /* Implementation of GUI terminal on the Microsoft W32 API.
2 Copyright (C) 1989, 93, 94, 95, 96, 1997, 1998, 1999, 2000, 2001
3 Free Software Foundation, Inc.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
22 #include <config.h>
23 #include <signal.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include "lisp.h"
27 #include "charset.h"
28 #include "blockinput.h"
30 #include "w32heap.h"
31 #include "w32term.h"
32 #include "w32bdf.h"
33 #include <shellapi.h>
35 #include "systty.h"
36 #include "systime.h"
37 #include "atimer.h"
38 #include "keymap.h"
40 #include <ctype.h>
41 #include <errno.h>
42 #include <setjmp.h>
43 #include <sys/stat.h>
45 #include "keyboard.h"
46 #include "frame.h"
47 #include "dispextern.h"
48 #include "fontset.h"
49 #include "termhooks.h"
50 #include "termopts.h"
51 #include "termchar.h"
52 #include "gnu.h"
53 #include "disptab.h"
54 #include "buffer.h"
55 #include "window.h"
56 #include "intervals.h"
57 #include "composite.h"
58 #include "coding.h"
60 #define abs(x) ((x) < 0 ? -(x) : (x))
62 #define BETWEEN(X, LOWER, UPPER) ((X) >= (LOWER) && (X) < (UPPER))
65 /* Fringe bitmaps. */
67 enum fringe_bitmap_type
69 NO_FRINGE_BITMAP,
70 LEFT_TRUNCATION_BITMAP,
71 RIGHT_TRUNCATION_BITMAP,
72 OVERLAY_ARROW_BITMAP,
73 CONTINUED_LINE_BITMAP,
74 CONTINUATION_LINE_BITMAP,
75 ZV_LINE_BITMAP
78 /* Bitmaps are all unsigned short, as Windows requires bitmap data to
79 be Word aligned. For some reason they are horizontally reflected
80 compared to how they appear on X, so changes in xterm.c should be
81 reflected here. */
83 /* Bitmap drawn to indicate lines not displaying text if
84 `indicate-empty-lines' is non-nil. */
86 #define zv_width 8
87 #define zv_height 72
88 #define zv_period 3
89 static unsigned short zv_bits[] = {
90 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
91 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
92 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
93 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
94 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
95 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
96 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
97 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00};
98 static HBITMAP zv_bmp;
100 /* An arrow like this: `<-'. */
102 #define left_width 8
103 #define left_height 8
104 static unsigned short left_bits[] = {
105 0x18, 0x30, 0x60, 0xfc, 0xfc, 0x60, 0x30, 0x18};
106 static HBITMAP left_bmp;
108 /* Right truncation arrow bitmap `->'. */
110 #define right_width 8
111 #define right_height 8
112 static unsigned short right_bits[] = {
113 0x18, 0x0c, 0x06, 0x3f, 0x3f, 0x06, 0x0c, 0x18};
114 static HBITMAP right_bmp;
116 /* Marker for continued lines. */
118 #define continued_width 8
119 #define continued_height 8
120 static unsigned short continued_bits[] = {
121 0x3c, 0x3e, 0x03, 0x27, 0x3f, 0x3e, 0x3c, 0x3e};
122 static HBITMAP continued_bmp;
124 /* Marker for continuation lines. */
126 #define continuation_width 8
127 #define continuation_height 8
128 static unsigned short continuation_bits[] = {
129 0x3c, 0x7c, 0xc0, 0xe4, 0xfc, 0x7c, 0x3c, 0x7c};
130 static HBITMAP continuation_bmp;
132 /* Overlay arrow bitmap. */
134 #if 0
135 /* A bomb. */
136 #define ov_width 8
137 #define ov_height 8
138 static unsigned short ov_bits[] = {
139 0x0c, 0x10, 0x3c, 0x7e, 0x5e, 0x5e, 0x46, 0x3c};
140 #else
141 /* A triangular arrow. */
142 #define ov_width 8
143 #define ov_height 8
144 static unsigned short ov_bits[] = {
145 0xc0, 0xf0, 0xf8, 0xfc, 0xfc, 0xf8, 0xf0, 0xc0};
146 #endif
147 static HBITMAP ov_bmp;
149 extern Lisp_Object Qhelp_echo;
152 /* Non-nil means Emacs uses toolkit scroll bars. */
154 Lisp_Object Vx_toolkit_scroll_bars;
156 /* If a string, w32_read_socket generates an event to display that string.
157 (The display is done in read_char.) */
159 static Lisp_Object help_echo;
160 static Lisp_Object help_echo_window;
161 static Lisp_Object help_echo_object;
162 static int help_echo_pos;
164 /* Temporary variables for w32_read_socket. */
166 static Lisp_Object previous_help_echo;
167 static int last_mousemove_x = 0;
168 static int last_mousemove_y = 0;
170 /* Non-zero means that a HELP_EVENT has been generated since Emacs
171 start. */
173 static int any_help_event_p;
175 /* Non-zero means autoselect window with the mouse cursor. */
177 int mouse_autoselect_window;
179 /* Non-zero means draw block and hollow cursor as wide as the glyph
180 under it. For example, if a block cursor is over a tab, it will be
181 drawn as wide as that tab on the display. */
183 int x_stretch_cursor_p;
185 /* Non-zero means make use of UNDERLINE_POSITION font properties. */
187 int x_use_underline_position_properties;
189 extern unsigned int msh_mousewheel;
191 extern void free_frame_menubar ();
193 extern int w32_codepage_for_font (char *fontname);
194 extern Cursor w32_load_cursor (LPCTSTR name);
196 extern glyph_metric *w32_BDF_TextMetric(bdffont *fontp,
197 unsigned char *text, int dim);
198 extern Lisp_Object Vwindow_system;
200 #define x_any_window_to_frame x_window_to_frame
201 #define x_top_window_to_frame x_window_to_frame
204 /* This is display since w32 does not support multiple ones. */
205 struct w32_display_info one_w32_display_info;
206 struct w32_display_info *x_display_list;
208 /* This is a list of cons cells, each of the form (NAME . FONT-LIST-CACHE),
209 one for each element of w32_display_list and in the same order.
210 NAME is the name of the frame.
211 FONT-LIST-CACHE records previous values returned by x-list-fonts. */
212 Lisp_Object w32_display_name_list;
214 /* Frame being updated by update_frame. This is declared in term.c.
215 This is set by update_begin and looked at by all the
216 w32 functions. It is zero while not inside an update.
217 In that case, the w32 functions assume that `SELECTED_FRAME ()'
218 is the frame to apply to. */
219 extern struct frame *updating_frame;
221 /* This is a frame waiting to be autoraised, within w32_read_socket. */
222 struct frame *pending_autoraise_frame;
224 /* Nominal cursor position -- where to draw output.
225 HPOS and VPOS are window relative glyph matrix coordinates.
226 X and Y are window relative pixel coordinates. */
228 struct cursor_pos output_cursor;
230 /* The handle of the frame that currently owns the system caret. */
231 HWND w32_system_caret_hwnd;
232 int w32_system_caret_height;
233 int w32_system_caret_x;
234 int w32_system_caret_y;
235 int w32_use_visible_system_caret;
237 /* Flag to enable Unicode output in case users wish to use programs
238 like Twinbridge on '95 rather than installed system level support
239 for Far East languages. */
240 int w32_enable_unicode_output;
242 DWORD dwWindowsThreadId = 0;
243 HANDLE hWindowsThread = NULL;
244 DWORD dwMainThreadId = 0;
245 HANDLE hMainThread = NULL;
247 #ifndef SIF_ALL
248 /* These definitions are new with Windows 95. */
249 #define SIF_RANGE 0x0001
250 #define SIF_PAGE 0x0002
251 #define SIF_POS 0x0004
252 #define SIF_DISABLENOSCROLL 0x0008
253 #define SIF_TRACKPOS 0x0010
254 #define SIF_ALL (SIF_RANGE | SIF_PAGE | SIF_POS | SIF_TRACKPOS)
256 typedef struct tagSCROLLINFO
258 UINT cbSize;
259 UINT fMask;
260 int nMin;
261 int nMax;
262 UINT nPage;
263 int nPos;
264 int nTrackPos;
265 } SCROLLINFO, FAR *LPSCROLLINFO;
266 typedef SCROLLINFO CONST FAR *LPCSCROLLINFO;
267 #endif /* SIF_ALL */
269 /* Dynamic linking to new proportional scroll bar functions. */
270 int (PASCAL *pfnSetScrollInfo) (HWND hwnd, int fnBar, LPSCROLLINFO lpsi, BOOL fRedraw);
271 BOOL (PASCAL *pfnGetScrollInfo) (HWND hwnd, int fnBar, LPSCROLLINFO lpsi);
273 int vertical_scroll_bar_min_handle;
274 int vertical_scroll_bar_top_border;
275 int vertical_scroll_bar_bottom_border;
277 int last_scroll_bar_drag_pos;
279 /* Mouse movement. */
281 /* Where the mouse was last time we reported a mouse event. */
283 FRAME_PTR last_mouse_frame;
284 static RECT last_mouse_glyph;
285 static Lisp_Object last_mouse_press_frame;
287 Lisp_Object Vw32_num_mouse_buttons;
289 Lisp_Object Vw32_swap_mouse_buttons;
291 /* Control whether x_raise_frame also sets input focus. */
292 Lisp_Object Vw32_grab_focus_on_raise;
294 /* Control whether Caps Lock affects non-ascii characters. */
295 Lisp_Object Vw32_capslock_is_shiftlock;
297 /* Control whether right-alt and left-ctrl should be recognized as AltGr. */
298 Lisp_Object Vw32_recognize_altgr;
300 /* The scroll bar in which the last motion event occurred.
302 If the last motion event occurred in a scroll bar, we set this
303 so w32_mouse_position can know whether to report a scroll bar motion or
304 an ordinary motion.
306 If the last motion event didn't occur in a scroll bar, we set this
307 to Qnil, to tell w32_mouse_position to return an ordinary motion event. */
308 static Lisp_Object last_mouse_scroll_bar;
309 static int last_mouse_scroll_bar_pos;
311 /* This is a hack. We would really prefer that w32_mouse_position would
312 return the time associated with the position it returns, but there
313 doesn't seem to be any way to wrest the time-stamp from the server
314 along with the position query. So, we just keep track of the time
315 of the last movement we received, and return that in hopes that
316 it's somewhat accurate. */
318 static Time last_mouse_movement_time;
320 /* Incremented by w32_read_socket whenever it really tries to read
321 events. */
323 #ifdef __STDC__
324 static int volatile input_signal_count;
325 #else
326 static int input_signal_count;
327 #endif
329 extern Lisp_Object Vcommand_line_args, Vsystem_name;
331 extern Lisp_Object Qface, Qmouse_face;
333 #ifndef USE_CRT_DLL
334 extern int errno;
335 #endif
337 /* A mask of extra modifier bits to put into every keyboard char. */
339 extern EMACS_INT extra_keyboard_modifiers;
341 /* Enumeration for overriding/changing the face to use for drawing
342 glyphs in x_draw_glyphs. */
344 enum draw_glyphs_face
346 DRAW_NORMAL_TEXT,
347 DRAW_INVERSE_VIDEO,
348 DRAW_CURSOR,
349 DRAW_MOUSE_FACE,
350 DRAW_IMAGE_RAISED,
351 DRAW_IMAGE_SUNKEN
354 static void x_update_window_end P_ ((struct window *, int, int));
355 static void frame_to_window_pixel_xy P_ ((struct window *, int *, int *));
356 void w32_delete_display P_ ((struct w32_display_info *));
357 static int fast_find_position P_ ((struct window *, int, int *, int *,
358 int *, int *, Lisp_Object));
359 static int fast_find_string_pos P_ ((struct window *, int, Lisp_Object,
360 int *, int *, int *, int *, int));
361 static void set_output_cursor P_ ((struct cursor_pos *));
362 static struct glyph *x_y_to_hpos_vpos P_ ((struct window *, int, int,
363 int *, int *, int *, int));
364 static void note_mode_line_highlight P_ ((struct window *, int, int));
365 static void note_mouse_highlight P_ ((struct frame *, int, int));
366 static void note_tool_bar_highlight P_ ((struct frame *f, int, int));
367 static void w32_handle_tool_bar_click P_ ((struct frame *,
368 struct input_event *));
369 static void show_mouse_face P_ ((struct w32_display_info *,
370 enum draw_glyphs_face));
371 static int cursor_in_mouse_face_p P_ ((struct window *));
372 static int clear_mouse_face P_ ((struct w32_display_info *));
373 void w32_define_cursor P_ ((Window, Cursor));
375 void x_lower_frame P_ ((struct frame *));
376 void x_scroll_bar_clear P_ ((struct frame *));
377 void x_wm_set_size_hint P_ ((struct frame *, long, int));
378 void x_raise_frame P_ ((struct frame *));
379 void x_set_window_size P_ ((struct frame *, int, int, int));
380 void x_wm_set_window_state P_ ((struct frame *, int));
381 void x_wm_set_icon_pixmap P_ ((struct frame *, int));
382 void w32_initialize P_ ((void));
383 static void x_font_min_bounds P_ ((XFontStruct *, int *, int *));
384 int x_compute_min_glyph_bounds P_ ((struct frame *));
385 static void x_draw_phys_cursor_glyph P_ ((struct window *,
386 struct glyph_row *,
387 enum draw_glyphs_face));
388 static void x_update_end P_ ((struct frame *));
389 static void w32_frame_up_to_date P_ ((struct frame *));
390 static void w32_set_terminal_modes P_ ((void));
391 static void w32_reset_terminal_modes P_ ((void));
392 static void w32_cursor_to P_ ((int, int, int, int));
393 static void x_write_glyphs P_ ((struct glyph *, int));
394 static void x_clear_end_of_line P_ ((int));
395 static void x_clear_frame P_ ((void));
396 static void x_clear_cursor P_ ((struct window *));
397 static void frame_highlight P_ ((struct frame *));
398 static void frame_unhighlight P_ ((struct frame *));
399 static void x_new_focus_frame P_ ((struct w32_display_info *,
400 struct frame *));
401 static void w32_frame_rehighlight P_ ((struct frame *));
402 static void x_frame_rehighlight P_ ((struct w32_display_info *));
403 static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *));
404 static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int,
405 enum text_cursor_kinds));
406 static void expose_frame P_ ((struct frame *, int, int, int, int));
407 static int expose_window_tree P_ ((struct window *, RECT *));
408 static void expose_overlaps P_ ((struct window *, struct glyph_row *,
409 struct glyph_row *));
410 static int expose_window P_ ((struct window *, RECT *));
411 static void expose_area P_ ((struct window *, struct glyph_row *,
412 RECT *, enum glyph_row_area));
413 static int expose_line P_ ((struct window *, struct glyph_row *,
414 RECT *));
415 void x_update_cursor P_ ((struct frame *, int));
416 static void x_update_cursor_in_window_tree P_ ((struct window *, int));
417 static void x_update_window_cursor P_ ((struct window *, int));
418 static void x_erase_phys_cursor P_ ((struct window *));
419 void x_display_cursor P_ ((struct window *w, int, int, int, int, int));
420 void x_display_and_set_cursor P_ ((struct window *, int, int, int, int, int));
421 static void w32_draw_fringe_bitmap P_ ((struct window *, HDC hdc,
422 struct glyph_row *,
423 enum fringe_bitmap_type, int left_p));
424 static void w32_clip_to_row P_ ((struct window *, struct glyph_row *,
425 HDC, int));
426 static int x_phys_cursor_in_rect_p P_ ((struct window *, RECT *));
427 static void x_draw_row_fringe_bitmaps P_ ((struct window *,
428 struct glyph_row *));
429 static void notice_overwritten_cursor P_ ((struct window *,
430 enum glyph_row_area,
431 int, int, int, int));
433 static Lisp_Object Qvendor_specific_keysyms;
436 /***********************************************************************
437 Debugging
438 ***********************************************************************/
440 #if 0
442 /* This is a function useful for recording debugging information about
443 the sequence of occurrences in this file. */
445 struct record
447 char *locus;
448 int type;
451 struct record event_record[100];
453 int event_record_index;
455 record_event (locus, type)
456 char *locus;
457 int type;
459 if (event_record_index == sizeof (event_record) / sizeof (struct record))
460 event_record_index = 0;
462 event_record[event_record_index].locus = locus;
463 event_record[event_record_index].type = type;
464 event_record_index++;
467 #endif /* 0 */
470 void XChangeGC (void * ignore, XGCValues* gc, unsigned long mask,
471 XGCValues *xgcv)
473 if (mask & GCForeground)
474 gc->foreground = xgcv->foreground;
475 if (mask & GCBackground)
476 gc->background = xgcv->background;
477 if (mask & GCFont)
478 gc->font = xgcv->font;
481 XGCValues *XCreateGC (void * ignore, Window window, unsigned long mask,
482 XGCValues *xgcv)
484 XGCValues *gc = (XGCValues *) xmalloc (sizeof (XGCValues));
485 bzero (gc, sizeof (XGCValues));
487 XChangeGC (ignore, gc, mask, xgcv);
489 return gc;
492 void XGetGCValues (void* ignore, XGCValues *gc,
493 unsigned long mask, XGCValues *xgcv)
495 XChangeGC (ignore, xgcv, mask, gc);
498 static void
499 w32_set_clip_rectangle (HDC hdc, RECT *rect)
501 if (rect)
503 HRGN clip_region = CreateRectRgnIndirect (rect);
504 SelectClipRgn (hdc, clip_region);
505 DeleteObject (clip_region);
507 else
508 SelectClipRgn (hdc, NULL);
512 /* Draw a hollow rectangle at the specified position. */
513 void
514 w32_draw_rectangle (HDC hdc, XGCValues *gc, int x, int y,
515 int width, int height)
517 HBRUSH hb, oldhb;
518 HPEN hp, oldhp;
520 hb = CreateSolidBrush (gc->background);
521 hp = CreatePen (PS_SOLID, 0, gc->foreground);
522 oldhb = SelectObject (hdc, hb);
523 oldhp = SelectObject (hdc, hp);
525 Rectangle (hdc, x, y, x + width, y + height);
527 SelectObject (hdc, oldhb);
528 SelectObject (hdc, oldhp);
529 DeleteObject (hb);
530 DeleteObject (hp);
533 /* Draw a filled rectangle at the specified position. */
534 void
535 w32_fill_rect (f, hdc, pix, lprect)
536 FRAME_PTR f;
537 HDC hdc;
538 COLORREF pix;
539 RECT * lprect;
541 HBRUSH hb;
543 hb = CreateSolidBrush (pix);
544 FillRect (hdc, lprect, hb);
545 DeleteObject (hb);
548 void
549 w32_clear_window (f)
550 FRAME_PTR f;
552 RECT rect;
553 HDC hdc = get_frame_dc (f);
555 /* Under certain conditions, this can be called at startup with
556 a console frame pointer before the GUI frame is created. An HDC
557 of 0 indicates this. */
558 if (hdc)
560 GetClientRect (FRAME_W32_WINDOW (f), &rect);
561 w32_clear_rect (f, hdc, &rect);
564 release_frame_dc (f, hdc);
568 /***********************************************************************
569 Starting and ending an update
570 ***********************************************************************/
572 /* Start an update of frame F. This function is installed as a hook
573 for update_begin, i.e. it is called when update_begin is called.
574 This function is called prior to calls to x_update_window_begin for
575 each window being updated. */
577 static void
578 x_update_begin (f)
579 struct frame *f;
581 struct w32_display_info *display_info = FRAME_W32_DISPLAY_INFO (f);
583 if (! FRAME_W32_P (f))
584 return;
586 /* Regenerate display palette before drawing if list of requested
587 colors has changed. */
588 if (display_info->regen_palette)
590 w32_regenerate_palette (f);
591 display_info->regen_palette = FALSE;
596 /* Start update of window W. Set the global variable updated_window
597 to the window being updated and set output_cursor to the cursor
598 position of W. */
600 static void
601 x_update_window_begin (w)
602 struct window *w;
604 struct frame *f = XFRAME (WINDOW_FRAME (w));
605 struct w32_display_info *display_info = FRAME_W32_DISPLAY_INFO (f);
607 /* Hide the system caret during an update. */
608 if (w32_use_visible_system_caret && w32_system_caret_hwnd)
610 SendMessage (w32_system_caret_hwnd, WM_EMACS_HIDE_CARET, 0, 0);
613 updated_window = w;
614 set_output_cursor (&w->cursor);
616 BLOCK_INPUT;
618 if (f == display_info->mouse_face_mouse_frame)
620 /* Don't do highlighting for mouse motion during the update. */
621 display_info->mouse_face_defer = 1;
623 /* If F needs to be redrawn, simply forget about any prior mouse
624 highlighting. */
625 if (FRAME_GARBAGED_P (f))
626 display_info->mouse_face_window = Qnil;
628 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
629 their mouse_face_p flag set, which means that they are always
630 unequal to rows in a desired matrix which never have that
631 flag set. So, rows containing mouse-face glyphs are never
632 scrolled, and we don't have to switch the mouse highlight off
633 here to prevent it from being scrolled. */
635 /* Can we tell that this update does not affect the window
636 where the mouse highlight is? If so, no need to turn off.
637 Likewise, don't do anything if the frame is garbaged;
638 in that case, the frame's current matrix that we would use
639 is all wrong, and we will redisplay that line anyway. */
640 if (!NILP (display_info->mouse_face_window)
641 && w == XWINDOW (display_info->mouse_face_window))
643 int i;
645 for (i = 0; i < w->desired_matrix->nrows; ++i)
646 if (MATRIX_ROW_ENABLED_P (w->desired_matrix, i))
647 break;
649 if (i < w->desired_matrix->nrows)
650 clear_mouse_face (display_info);
652 #endif /* 0 */
655 UNBLOCK_INPUT;
659 /* Draw a vertical window border to the right of window W if W doesn't
660 have vertical scroll bars. */
662 static void
663 x_draw_vertical_border (w)
664 struct window *w;
666 struct frame *f = XFRAME (WINDOW_FRAME (w));
668 /* Redraw borders between horizontally adjacent windows. Don't
669 do it for frames with vertical scroll bars because either the
670 right scroll bar of a window, or the left scroll bar of its
671 neighbor will suffice as a border. */
672 if (!WINDOW_RIGHTMOST_P (w)
673 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
675 RECT r;
676 HDC hdc;
678 window_box_edges (w, -1, (int *) &r.left, (int *) &r.top,
679 (int *) &r.right, (int *) &r.bottom);
680 r.left = r.right + FRAME_X_RIGHT_FRINGE_WIDTH (f);
681 r.right = r.left + 1;
682 r.bottom -= 1;
684 hdc = get_frame_dc (f);
685 w32_fill_rect (f, hdc, FRAME_FOREGROUND_PIXEL (f), &r);
686 release_frame_dc (f, hdc);
691 /* End update of window W (which is equal to updated_window).
693 Draw vertical borders between horizontally adjacent windows, and
694 display W's cursor if CURSOR_ON_P is non-zero.
696 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
697 glyphs in mouse-face were overwritten. In that case we have to
698 make sure that the mouse-highlight is properly redrawn.
700 W may be a menu bar pseudo-window in case we don't have X toolkit
701 support. Such windows don't have a cursor, so don't display it
702 here. */
704 static void
705 x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p)
706 struct window *w;
707 int cursor_on_p, mouse_face_overwritten_p;
709 struct w32_display_info *dpyinfo
710 = FRAME_W32_DISPLAY_INFO (XFRAME (w->frame));
712 if (!w->pseudo_window_p)
714 BLOCK_INPUT;
716 if (cursor_on_p)
717 x_display_and_set_cursor (w, 1, output_cursor.hpos,
718 output_cursor.vpos,
719 output_cursor.x, output_cursor.y);
721 x_draw_vertical_border (w);
722 UNBLOCK_INPUT;
725 /* If a row with mouse-face was overwritten, arrange for
726 XTframe_up_to_date to redisplay the mouse highlight. */
727 if (mouse_face_overwritten_p)
729 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
730 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
731 dpyinfo->mouse_face_window = Qnil;
734 /* Unhide the caret. This won't actually show the cursor, unless it
735 was visible before the corresponding call to HideCaret in
736 x_update_window_begin. */
737 if (w32_use_visible_system_caret && w32_system_caret_hwnd)
739 SendMessage (w32_system_caret_hwnd, WM_EMACS_SHOW_CARET, 0, 0);
742 updated_window = NULL;
746 /* End update of frame F. This function is installed as a hook in
747 update_end. */
749 static void
750 x_update_end (f)
751 struct frame *f;
753 if (! FRAME_W32_P (f))
754 return;
756 /* Mouse highlight may be displayed again. */
757 FRAME_W32_DISPLAY_INFO (f)->mouse_face_defer = 0;
761 /* This function is called from various places in xdisp.c whenever a
762 complete update has been performed. The global variable
763 updated_window is not available here. */
765 static void
766 w32_frame_up_to_date (f)
767 struct frame *f;
769 if (FRAME_W32_P (f))
771 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
772 if (dpyinfo->mouse_face_deferred_gc
773 || f == dpyinfo->mouse_face_mouse_frame)
775 BLOCK_INPUT;
776 if (dpyinfo->mouse_face_mouse_frame)
777 note_mouse_highlight (dpyinfo->mouse_face_mouse_frame,
778 dpyinfo->mouse_face_mouse_x,
779 dpyinfo->mouse_face_mouse_y);
780 dpyinfo->mouse_face_deferred_gc = 0;
781 UNBLOCK_INPUT;
787 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
788 arrow bitmaps, or clear the fringes if no bitmaps are required
789 before DESIRED_ROW is made current. The window being updated is
790 found in updated_window. This function is called from
791 update_window_line only if it is known that there are differences
792 between bitmaps to be drawn between current row and DESIRED_ROW. */
794 static void
795 x_after_update_window_line (desired_row)
796 struct glyph_row *desired_row;
798 struct window *w = updated_window;
799 struct frame *f;
800 int width, height;
802 xassert (w);
804 if (!desired_row->mode_line_p && !w->pseudo_window_p)
806 BLOCK_INPUT;
807 x_draw_row_fringe_bitmaps (w, desired_row);
808 UNBLOCK_INPUT;
811 /* When a window has disappeared, make sure that no rest of
812 full-width rows stays visible in the internal border. Could
813 check here if updated_window is the leftmost/rightmost window,
814 but I guess it's not worth doing since vertically split windows
815 are almost never used, internal border is rarely set, and the
816 overhead is very small. */
817 if (windows_or_buffers_changed
818 && desired_row->full_width_p
819 && (f = XFRAME (w->frame),
820 width = FRAME_INTERNAL_BORDER_WIDTH (f),
821 width != 0)
822 && (height = desired_row->visible_height,
823 height > 0))
825 int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
826 /* Internal border is drawn below the tool bar. */
827 if (WINDOWP (f->tool_bar_window)
828 && w == XWINDOW (f->tool_bar_window))
829 y -= width;
831 BLOCK_INPUT;
833 HDC hdc = get_frame_dc (f);
834 w32_clear_area (f, hdc, 0, y, width, height);
835 w32_clear_area (f, hdc, f->output_data.w32->pixel_width - width,
836 y, width, height);
837 release_frame_dc (f, hdc);
839 UNBLOCK_INPUT;
844 /* Draw the bitmap WHICH in one of the left or right fringes of
845 window W. ROW is the glyph row for which to display the bitmap; it
846 determines the vertical position at which the bitmap has to be
847 drawn. */
849 static void
850 w32_draw_fringe_bitmap (w, hdc, row, which, left_p)
851 struct window *w;
852 HDC hdc;
853 struct glyph_row *row;
854 enum fringe_bitmap_type which;
855 int left_p;
857 struct frame *f = XFRAME (WINDOW_FRAME (w));
858 HDC compat_hdc;
859 int x, y, wd, h, dy;
860 int b1, b2;
861 HBITMAP pixmap;
862 HANDLE horig_obj;
863 struct face *face;
865 /* Must clip because of partially visible lines. */
866 w32_clip_to_row (w, row, hdc, 1);
868 /* Convert row to frame coordinates. */
869 y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
871 switch (which)
873 case NO_FRINGE_BITMAP:
874 wd = 0;
875 h = 0;
876 break;
878 case LEFT_TRUNCATION_BITMAP:
879 wd = left_width;
880 h = left_height;
881 pixmap = left_bmp;
882 break;
884 case OVERLAY_ARROW_BITMAP:
885 wd = ov_width;
886 h = ov_height;
887 pixmap = ov_bmp;
888 break;
890 case RIGHT_TRUNCATION_BITMAP:
891 wd = right_width;
892 h = right_height;
893 pixmap = right_bmp;
894 break;
896 case CONTINUED_LINE_BITMAP:
897 wd = continued_width;
898 h = continued_height;
899 pixmap = continued_bmp;
900 break;
902 case CONTINUATION_LINE_BITMAP:
903 wd = continuation_width;
904 h = continuation_height;
905 pixmap = continuation_bmp;
906 break;
908 case ZV_LINE_BITMAP:
909 wd = zv_width;
910 h = zv_height - (y % zv_period);
911 pixmap = zv_bmp;
912 break;
914 default:
915 abort ();
918 /* Clip bitmap if too high. */
919 if (h > row->height)
920 h = row->height;
922 /* Set dy to the offset in the row to start drawing the bitmap. */
923 dy = (row->height - h) / 2;
925 /* Draw the bitmap. */
926 face = FACE_FROM_ID (f, FRINGE_FACE_ID);
927 PREPARE_FACE_FOR_DISPLAY (f, face);
929 /* Clear left fringe if no bitmap to draw or if bitmap doesn't fill
930 the fringe. */
931 b1 = -1;
932 if (left_p)
934 if (wd > FRAME_X_LEFT_FRINGE_WIDTH (f))
935 wd = FRAME_X_LEFT_FRINGE_WIDTH (f);
936 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
937 - wd
938 - (FRAME_X_LEFT_FRINGE_WIDTH (f) - wd) / 2);
939 if (wd < FRAME_X_LEFT_FRINGE_WIDTH (f) || row->height > h)
941 /* If W has a vertical border to its left, don't draw over it. */
942 int border = ((XFASTINT (w->left) > 0
943 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
944 ? 1 : 0);
945 b1 = (window_box_left (w, -1)
946 - FRAME_X_LEFT_FRINGE_WIDTH (f)
947 + border);
948 b2 = (FRAME_X_LEFT_FRINGE_WIDTH (f) - border);
951 else
953 if (wd > FRAME_X_RIGHT_FRINGE_WIDTH (f))
954 wd = FRAME_X_RIGHT_FRINGE_WIDTH (f);
955 x = (window_box_right (w, -1)
956 + (FRAME_X_RIGHT_FRINGE_WIDTH (f) - wd) / 2);
957 /* Clear right fringe if no bitmap to draw of if bitmap doesn't fill
958 the fringe. */
959 if (wd < FRAME_X_RIGHT_FRINGE_WIDTH (f) || row->height > h)
961 b1 = window_box_right (w, -1);
962 b2 = FRAME_X_RIGHT_FRINGE_WIDTH (f);
966 if (b1 >= 0)
968 int header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
970 w32_fill_area (f, hdc, face->background,
972 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
973 row->y)),
975 row->visible_height);
978 if (which == NO_FRINGE_BITMAP)
979 return;
981 compat_hdc = CreateCompatibleDC (hdc);
982 SaveDC (hdc);
984 horig_obj = SelectObject (compat_hdc, pixmap);
985 SetTextColor (hdc, face->background);
986 SetBkColor (hdc, face->foreground);
988 BitBlt (hdc, x, y + dy, wd, h, compat_hdc, 0,
989 (which == ZV_LINE_BITMAP ? (row->y % zv_period) : 0),
990 SRCCOPY);
992 SelectObject (compat_hdc, horig_obj);
993 DeleteDC (compat_hdc);
994 RestoreDC (hdc, -1);
998 /* Draw fringe bitmaps for glyph row ROW on window W. Call this
999 function with input blocked. */
1001 static void
1002 x_draw_row_fringe_bitmaps (w, row)
1003 struct window *w;
1004 struct glyph_row *row;
1006 struct frame *f = XFRAME (w->frame);
1007 enum fringe_bitmap_type bitmap;
1008 HDC hdc;
1010 xassert (interrupt_input_blocked);
1012 /* If row is completely invisible, because of vscrolling, we
1013 don't have to draw anything. */
1014 if (row->visible_height <= 0)
1015 return;
1017 hdc = get_frame_dc (f);
1019 if (FRAME_X_LEFT_FRINGE_WIDTH (f) != 0)
1021 /* Decide which bitmap to draw in the left fringe. */
1022 if (row->overlay_arrow_p)
1023 bitmap = OVERLAY_ARROW_BITMAP;
1024 else if (row->truncated_on_left_p)
1025 bitmap = LEFT_TRUNCATION_BITMAP;
1026 else if (MATRIX_ROW_CONTINUATION_LINE_P (row))
1027 bitmap = CONTINUATION_LINE_BITMAP;
1028 else if (row->indicate_empty_line_p)
1029 bitmap = ZV_LINE_BITMAP;
1030 else
1031 bitmap = NO_FRINGE_BITMAP;
1033 w32_draw_fringe_bitmap (w, hdc, row, bitmap, 1);
1036 if (FRAME_X_RIGHT_FRINGE_WIDTH (f) != 0)
1038 /* Decide which bitmap to draw in the right fringe. */
1039 if (row->truncated_on_right_p)
1040 bitmap = RIGHT_TRUNCATION_BITMAP;
1041 else if (row->continued_p)
1042 bitmap = CONTINUED_LINE_BITMAP;
1043 else if (row->indicate_empty_line_p && FRAME_X_LEFT_FRINGE_WIDTH (f) == 0)
1044 bitmap = ZV_LINE_BITMAP;
1045 else
1046 bitmap = NO_FRINGE_BITMAP;
1048 w32_draw_fringe_bitmap (w, hdc, row, bitmap, 0);
1051 release_frame_dc (f, hdc);
1055 /* This is called when starting Emacs and when restarting after
1056 suspend. When starting Emacs, no window is mapped. And nothing
1057 must be done to Emacs's own window if it is suspended (though that
1058 rarely happens). */
1060 static void
1061 w32_set_terminal_modes (void)
1065 /* This is called when exiting or suspending Emacs. Exiting will make
1066 the W32 windows go away, and suspending requires no action. */
1068 static void
1069 w32_reset_terminal_modes (void)
1075 /***********************************************************************
1076 Output Cursor
1077 ***********************************************************************/
1079 /* Set the global variable output_cursor to CURSOR. All cursor
1080 positions are relative to updated_window. */
1082 static void
1083 set_output_cursor (cursor)
1084 struct cursor_pos *cursor;
1086 output_cursor.hpos = cursor->hpos;
1087 output_cursor.vpos = cursor->vpos;
1088 output_cursor.x = cursor->x;
1089 output_cursor.y = cursor->y;
1093 /* Set a nominal cursor position.
1095 HPOS and VPOS are column/row positions in a window glyph matrix. X
1096 and Y are window text area relative pixel positions.
1098 If this is done during an update, updated_window will contain the
1099 window that is being updated and the position is the future output
1100 cursor position for that window. If updated_window is null, use
1101 selected_window and display the cursor at the given position. */
1103 static void
1104 w32_cursor_to (vpos, hpos, y, x)
1105 int vpos, hpos, y, x;
1107 struct window *w;
1109 /* If updated_window is not set, work on selected_window. */
1110 if (updated_window)
1111 w = updated_window;
1112 else
1113 w = XWINDOW (selected_window);
1115 /* Set the output cursor. */
1116 output_cursor.hpos = hpos;
1117 output_cursor.vpos = vpos;
1118 output_cursor.x = x;
1119 output_cursor.y = y;
1121 /* If not called as part of an update, really display the cursor.
1122 This will also set the cursor position of W. */
1123 if (updated_window == NULL)
1125 BLOCK_INPUT;
1126 x_display_cursor (w, 1, hpos, vpos, x, y);
1127 UNBLOCK_INPUT;
1133 /***********************************************************************
1134 Display Iterator
1135 ***********************************************************************/
1137 /* Function prototypes of this page. */
1139 static struct face *x_get_glyph_face_and_encoding P_ ((struct frame *,
1140 struct glyph *,
1141 wchar_t *,
1142 int *));
1143 static struct face *x_get_char_face_and_encoding P_ ((struct frame *, int,
1144 int, wchar_t *, int));
1145 static XCharStruct *w32_per_char_metric P_ ((XFontStruct *,
1146 wchar_t *,
1147 enum w32_char_font_type));
1148 static enum w32_char_font_type
1149 w32_encode_char P_ ((int, wchar_t *, struct font_info *, int *));
1150 static void x_append_glyph P_ ((struct it *));
1151 static void x_append_composite_glyph P_ ((struct it *));
1152 static void x_append_stretch_glyph P_ ((struct it *it, Lisp_Object,
1153 int, int, double));
1154 static void x_produce_glyphs P_ ((struct it *));
1155 static void x_produce_image_glyph P_ ((struct it *it));
1158 /* Dealing with bits of wchar_t as if they were an XChar2B. */
1159 #define BUILD_WCHAR_T(byte1, byte2) \
1160 ((wchar_t)((((byte1) & 0x00ff) << 8) | ((byte2) & 0x00ff)))
1163 #define BYTE1(ch) \
1164 (((ch) & 0xff00) >> 8)
1166 #define BYTE2(ch) \
1167 ((ch) & 0x00ff)
1170 /* Get metrics of character CHAR2B in FONT. Value is always non-null.
1171 If CHAR2B is not contained in FONT, the font's default character
1172 metric is returned. */
1174 static int
1175 w32_bdf_per_char_metric (font, char2b, dim, pcm)
1176 XFontStruct *font;
1177 wchar_t *char2b;
1178 int dim;
1179 XCharStruct * pcm;
1181 glyph_metric * bdf_metric;
1182 char buf[2];
1184 if (dim == 1)
1185 buf[0] = (char)(*char2b);
1186 else
1188 buf[0] = BYTE1 (*char2b);
1189 buf[1] = BYTE2 (*char2b);
1192 bdf_metric = w32_BDF_TextMetric (font->bdf, buf, dim);
1194 if (bdf_metric)
1196 pcm->width = bdf_metric->dwidth;
1197 pcm->lbearing = bdf_metric->bbox;
1198 pcm->rbearing = bdf_metric->dwidth
1199 - (bdf_metric->bbox + bdf_metric->bbw);
1200 pcm->ascent = bdf_metric->bboy + bdf_metric->bbh;
1201 pcm->descent = -bdf_metric->bboy;
1203 return 1;
1205 return 0;
1209 static int
1210 w32_native_per_char_metric (font, char2b, font_type, pcm)
1211 XFontStruct *font;
1212 wchar_t *char2b;
1213 enum w32_char_font_type font_type;
1214 XCharStruct * pcm;
1216 HDC hdc = GetDC (NULL);
1217 HFONT old_font;
1218 BOOL retval = FALSE;
1220 xassert (font && char2b);
1221 xassert (font->hfont);
1222 xassert (font_type == UNICODE_FONT || font_type == ANSI_FONT);
1224 old_font = SelectObject (hdc, font->hfont);
1226 if ((font->tm.tmPitchAndFamily & TMPF_TRUETYPE) != 0)
1228 ABC char_widths;
1230 if (font_type == UNICODE_FONT)
1231 retval = GetCharABCWidthsW (hdc, *char2b, *char2b, &char_widths);
1232 else
1233 retval = GetCharABCWidthsA (hdc, *char2b, *char2b, &char_widths);
1235 if (retval)
1237 #if 0
1238 /* Disabled until we can find a way to get the right results
1239 on all versions of Windows. */
1241 /* Don't trust the ABC widths. For synthesized fonts they are
1242 wrong, and so is the result of GetCharWidth()! */
1243 int real_width;
1244 GetCharWidth (hdc, *char2b, *char2b, &real_width);
1245 #endif
1246 pcm->width = char_widths.abcA + char_widths.abcB + char_widths.abcC;
1247 #if 0
1248 /* As far as I can tell, this is the best way to determine what
1249 ExtTextOut will do with the broken font. */
1250 if (pcm->width != real_width)
1251 pcm->width = (pcm->width + real_width) / 2;
1252 #endif
1253 pcm->lbearing = char_widths.abcA;
1254 pcm->rbearing = char_widths.abcA + char_widths.abcB;
1255 pcm->ascent = FONT_BASE (font);
1256 pcm->descent = FONT_DESCENT (font);
1260 if (!retval)
1262 /* Either font is not a True-type font, or GetCharABCWidthsW
1263 failed (it is not supported on Windows 9x for instance), so we
1264 can't determine the full info we would like. All is not lost
1265 though - we can call GetTextExtentPoint32 to get rbearing and
1266 deduce width based on the font's per-string overhang. lbearing
1267 is assumed to be zero. */
1269 /* TODO: Some Thai characters (and other composites if Windows
1270 supports them) do have lbearing, and report their total width
1271 as zero. Need some way of handling them when
1272 GetCharABCWidthsW fails. */
1273 SIZE sz;
1275 if (font_type == UNICODE_FONT)
1276 retval = GetTextExtentPoint32W (hdc, char2b, 1, &sz);
1277 else
1278 retval = GetTextExtentPoint32A (hdc, (char*)char2b, 1, &sz);
1280 if (retval)
1282 pcm->width = sz.cx - font->tm.tmOverhang;
1283 pcm->rbearing = sz.cx;
1284 pcm->lbearing = 0;
1285 pcm->ascent = FONT_BASE (font);
1286 pcm->descent = FONT_DESCENT (font);
1291 if (pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0)
1293 retval = FALSE;
1296 SelectObject (hdc, old_font);
1297 ReleaseDC (NULL, hdc);
1299 return retval;
1303 static XCharStruct *
1304 w32_per_char_metric (font, char2b, font_type)
1305 XFontStruct *font;
1306 wchar_t *char2b;
1307 enum w32_char_font_type font_type;
1309 /* The result metric information. */
1310 XCharStruct *pcm;
1311 BOOL retval;
1313 xassert (font && char2b);
1314 xassert (font_type != UNKNOWN_FONT);
1316 /* Handle the common cases quickly. */
1317 if (!font->bdf && font->per_char == NULL)
1318 /* TODO: determine whether char2b exists in font? */
1319 return &font->max_bounds;
1320 else if (!font->bdf && *char2b < 128)
1321 return &font->per_char[*char2b];
1323 pcm = &font->scratch;
1325 if (font_type == BDF_1D_FONT)
1326 retval = w32_bdf_per_char_metric (font, char2b, 1, pcm);
1327 else if (font_type == BDF_2D_FONT)
1328 retval = w32_bdf_per_char_metric (font, char2b, 2, pcm);
1329 else
1330 retval = w32_native_per_char_metric (font, char2b, font_type, pcm);
1332 if (retval)
1333 return pcm;
1335 return NULL;
1338 void
1339 w32_cache_char_metrics (font)
1340 XFontStruct *font;
1342 wchar_t char2b = L'x';
1344 /* Cache char metrics for the common cases. */
1345 if (font->bdf)
1347 /* TODO: determine whether font is fixed-pitch. */
1348 if (!w32_bdf_per_char_metric (font, &char2b, 1, &font->max_bounds))
1350 /* Use the font width and height as max bounds, as not all BDF
1351 fonts contain the letter 'x'. */
1352 font->max_bounds.width = FONT_MAX_WIDTH (font);
1353 font->max_bounds.lbearing = -font->bdf->llx;
1354 font->max_bounds.rbearing = FONT_MAX_WIDTH (font) - font->bdf->urx;
1355 font->max_bounds.ascent = FONT_BASE (font);
1356 font->max_bounds.descent = FONT_DESCENT (font);
1359 else
1361 if (((font->tm.tmPitchAndFamily & TMPF_FIXED_PITCH) != 0)
1362 /* Some fonts (eg DBCS fonts) are marked as fixed width even
1363 though they contain characters of different widths. */
1364 || (font->tm.tmMaxCharWidth != font->tm.tmAveCharWidth))
1366 /* Font is not fixed pitch, so cache per_char info for the
1367 ASCII characters. It would be much more work, and probably
1368 not worth it, to cache other chars, since we may change
1369 between using Unicode and ANSI text drawing functions at
1370 run-time. */
1371 int i;
1373 font->per_char = xmalloc (128 * sizeof(XCharStruct));
1374 for (i = 0; i < 128; i++)
1376 char2b = i;
1377 w32_native_per_char_metric (font, &char2b, ANSI_FONT,
1378 &font->per_char[i]);
1381 else
1382 w32_native_per_char_metric (font, &char2b, ANSI_FONT,
1383 &font->max_bounds);
1388 /* Determine if a font is double byte. */
1389 int w32_font_is_double_byte (XFontStruct *font)
1391 return font->double_byte_p;
1395 static BOOL
1396 w32_use_unicode_for_codepage (codepage)
1397 int codepage;
1399 /* If the current codepage is supported, use Unicode for output. */
1400 return (w32_enable_unicode_output
1401 && codepage != CP_8BIT
1402 && (codepage == CP_UNICODE || IsValidCodePage (codepage)));
1405 /* Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
1406 the two-byte form of C. Encoding is returned in *CHAR2B. */
1408 static INLINE enum w32_char_font_type
1409 w32_encode_char (c, char2b, font_info, two_byte_p)
1410 int c;
1411 wchar_t *char2b;
1412 struct font_info *font_info;
1413 int * two_byte_p;
1415 int charset = CHAR_CHARSET (c);
1416 int codepage;
1417 int unicode_p = 0;
1419 XFontStruct *font = font_info->font;
1421 xassert (two_byte_p);
1423 *two_byte_p = w32_font_is_double_byte (font);
1425 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
1426 This may be either a program in a special encoder language or a
1427 fixed encoding. */
1428 if (font_info->font_encoder)
1430 /* It's a program. */
1431 struct ccl_program *ccl = font_info->font_encoder;
1433 if (CHARSET_DIMENSION (charset) == 1)
1435 ccl->reg[0] = charset;
1436 ccl->reg[1] = BYTE2 (*char2b);
1437 ccl->reg[2] = -1;
1439 else
1441 ccl->reg[0] = charset;
1442 ccl->reg[1] = BYTE1 (*char2b);
1443 ccl->reg[2] = BYTE2 (*char2b);
1446 ccl_driver (ccl, NULL, NULL, 0, 0, NULL);
1448 /* We assume that MSBs are appropriately set/reset by CCL
1449 program. */
1450 if (!*two_byte_p) /* 1-byte font */
1451 *char2b = BUILD_WCHAR_T (0, ccl->reg[1]);
1452 else
1453 *char2b = BUILD_WCHAR_T (ccl->reg[1], ccl->reg[2]);
1455 else if (font_info->encoding[charset])
1457 /* Fixed encoding scheme. See fontset.h for the meaning of the
1458 encoding numbers. */
1459 int enc = font_info->encoding[charset];
1461 if ((enc == 1 || enc == 2)
1462 && CHARSET_DIMENSION (charset) == 2)
1463 *char2b = BUILD_WCHAR_T (BYTE1 (*char2b) | 0x80, BYTE2 (*char2b));
1465 if (enc == 1 || enc == 3
1466 || (enc == 4 && CHARSET_DIMENSION (charset) == 1))
1467 *char2b = BUILD_WCHAR_T (BYTE1 (*char2b), BYTE2 (*char2b) | 0x80);
1468 else if (enc == 4)
1470 int sjis1, sjis2;
1472 ENCODE_SJIS (BYTE1 (*char2b), BYTE2 (*char2b),
1473 sjis1, sjis2);
1474 *char2b = BUILD_WCHAR_T (sjis1, sjis2);
1477 codepage = font_info->codepage;
1479 /* If charset is not ASCII or Latin-1, may need to move it into
1480 Unicode space. */
1481 if ( font && !font->bdf && w32_use_unicode_for_codepage (codepage)
1482 && charset != CHARSET_ASCII && charset != charset_latin_iso8859_1
1483 && charset != CHARSET_8_BIT_CONTROL && charset != CHARSET_8_BIT_GRAPHIC)
1485 char temp[3];
1486 temp[0] = BYTE1 (*char2b);
1487 temp[1] = BYTE2 (*char2b);
1488 temp[2] = '\0';
1489 if (codepage != CP_UNICODE)
1491 if (temp[0])
1492 MultiByteToWideChar (codepage, 0, temp, 2, char2b, 1);
1493 else
1494 MultiByteToWideChar (codepage, 0, temp+1, 1, char2b, 1);
1496 unicode_p = 1;
1497 *two_byte_p = 1;
1499 if (!font)
1500 return UNKNOWN_FONT;
1501 else if (font->bdf && CHARSET_DIMENSION (charset) == 1)
1502 return BDF_1D_FONT;
1503 else if (font->bdf)
1504 return BDF_2D_FONT;
1505 else if (unicode_p)
1506 return UNICODE_FONT;
1507 else
1508 return ANSI_FONT;
1512 /* Get face and two-byte form of character C in face FACE_ID on frame
1513 F. The encoding of C is returned in *CHAR2B. MULTIBYTE_P non-zero
1514 means we want to display multibyte text. Value is a pointer to a
1515 realized face that is ready for display. */
1517 static INLINE struct face *
1518 x_get_char_face_and_encoding (f, c, face_id, char2b, multibyte_p)
1519 struct frame *f;
1520 int c, face_id;
1521 wchar_t *char2b;
1522 int multibyte_p;
1524 struct face *face = FACE_FROM_ID (f, face_id);
1526 if (!multibyte_p)
1528 /* Unibyte case. We don't have to encode, but we have to make
1529 sure to use a face suitable for unibyte. */
1530 *char2b = BUILD_WCHAR_T (0, c);
1531 face_id = FACE_FOR_CHAR (f, face, c);
1532 face = FACE_FROM_ID (f, face_id);
1534 else if (c < 128 && face_id < BASIC_FACE_ID_SENTINEL)
1536 /* Case of ASCII in a face known to fit ASCII. */
1537 *char2b = BUILD_WCHAR_T (0, c);
1539 else
1541 int c1, c2, charset;
1543 /* Split characters into bytes. If c2 is -1 afterwards, C is
1544 really a one-byte character so that byte1 is zero. */
1545 SPLIT_CHAR (c, charset, c1, c2);
1546 if (c2 > 0)
1547 *char2b = BUILD_WCHAR_T (c1, c2);
1548 else
1549 *char2b = BUILD_WCHAR_T (0, c1);
1551 /* Maybe encode the character in *CHAR2B. */
1552 if (face->font != NULL)
1554 struct font_info *font_info
1555 = FONT_INFO_FROM_ID (f, face->font_info_id);
1556 if (font_info)
1557 w32_encode_char (c, char2b, font_info, &multibyte_p);
1561 /* Make sure X resources of the face are allocated. */
1562 xassert (face != NULL);
1563 PREPARE_FACE_FOR_DISPLAY (f, face);
1565 return face;
1569 /* Get face and two-byte form of character glyph GLYPH on frame F.
1570 The encoding of GLYPH->u.ch is returned in *CHAR2B. Value is
1571 a pointer to a realized face that is ready for display. */
1573 static INLINE struct face *
1574 x_get_glyph_face_and_encoding (f, glyph, char2b, two_byte_p)
1575 struct frame *f;
1576 struct glyph *glyph;
1577 wchar_t *char2b;
1578 int *two_byte_p;
1580 struct face *face;
1581 int dummy = 0;
1583 xassert (glyph->type == CHAR_GLYPH);
1584 face = FACE_FROM_ID (f, glyph->face_id);
1586 if (two_byte_p)
1587 *two_byte_p = 0;
1588 else
1589 two_byte_p = &dummy;
1591 if (!glyph->multibyte_p)
1593 /* Unibyte case. We don't have to encode, but we have to make
1594 sure to use a face suitable for unibyte. */
1595 *char2b = BUILD_WCHAR_T (0, glyph->u.ch);
1597 else if (glyph->u.ch < 128
1598 && glyph->face_id < BASIC_FACE_ID_SENTINEL)
1600 /* Case of ASCII in a face known to fit ASCII. */
1601 *char2b = BUILD_WCHAR_T (0, glyph->u.ch);
1603 else
1605 int c1, c2, charset;
1607 /* Split characters into bytes. If c2 is -1 afterwards, C is
1608 really a one-byte character so that byte1 is zero. */
1609 SPLIT_CHAR (glyph->u.ch, charset, c1, c2);
1610 if (c2 > 0)
1611 *char2b = BUILD_WCHAR_T (c1, c2);
1612 else
1613 *char2b = BUILD_WCHAR_T (0, c1);
1615 /* Maybe encode the character in *CHAR2B. */
1616 if (charset != CHARSET_ASCII)
1618 struct font_info *font_info
1619 = FONT_INFO_FROM_ID (f, face->font_info_id);
1620 if (font_info)
1622 glyph->w32_font_type
1623 = w32_encode_char (glyph->u.ch, char2b, font_info, two_byte_p);
1628 /* Make sure X resources of the face are allocated. */
1629 xassert (face != NULL);
1630 PREPARE_FACE_FOR_DISPLAY (f, face);
1631 return face;
1635 /* Store one glyph for IT->char_to_display in IT->glyph_row.
1636 Called from x_produce_glyphs when IT->glyph_row is non-null. */
1638 static INLINE void
1639 x_append_glyph (it)
1640 struct it *it;
1642 struct glyph *glyph;
1643 enum glyph_row_area area = it->area;
1645 xassert (it->glyph_row);
1646 xassert (it->char_to_display != '\n' && it->char_to_display != '\t');
1648 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1649 if (glyph < it->glyph_row->glyphs[area + 1])
1651 glyph->charpos = CHARPOS (it->position);
1652 glyph->object = it->object;
1653 glyph->pixel_width = it->pixel_width;
1654 glyph->voffset = it->voffset;
1655 glyph->type = CHAR_GLYPH;
1656 glyph->multibyte_p = it->multibyte_p;
1657 glyph->left_box_line_p = it->start_of_box_run_p;
1658 glyph->right_box_line_p = it->end_of_box_run_p;
1659 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
1660 || it->phys_descent > it->descent);
1661 glyph->padding_p = 0;
1662 glyph->glyph_not_available_p = it->glyph_not_available_p;
1663 glyph->face_id = it->face_id;
1664 glyph->u.ch = it->char_to_display;
1665 glyph->w32_font_type = UNKNOWN_FONT;
1666 ++it->glyph_row->used[area];
1670 /* Store one glyph for the composition IT->cmp_id in IT->glyph_row.
1671 Called from x_produce_glyphs when IT->glyph_row is non-null. */
1673 static INLINE void
1674 x_append_composite_glyph (it)
1675 struct it *it;
1677 struct glyph *glyph;
1678 enum glyph_row_area area = it->area;
1680 xassert (it->glyph_row);
1682 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1683 if (glyph < it->glyph_row->glyphs[area + 1])
1685 glyph->charpos = CHARPOS (it->position);
1686 glyph->object = it->object;
1687 glyph->pixel_width = it->pixel_width;
1688 glyph->voffset = it->voffset;
1689 glyph->type = COMPOSITE_GLYPH;
1690 glyph->multibyte_p = it->multibyte_p;
1691 glyph->left_box_line_p = it->start_of_box_run_p;
1692 glyph->right_box_line_p = it->end_of_box_run_p;
1693 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
1694 || it->phys_descent > it->descent);
1695 glyph->padding_p = 0;
1696 glyph->glyph_not_available_p = 0;
1697 glyph->face_id = it->face_id;
1698 glyph->u.cmp_id = it->cmp_id;
1699 glyph->w32_font_type = UNKNOWN_FONT;
1700 ++it->glyph_row->used[area];
1705 /* Change IT->ascent and IT->height according to the setting of
1706 IT->voffset. */
1708 static INLINE void
1709 take_vertical_position_into_account (it)
1710 struct it *it;
1712 if (it->voffset)
1714 if (it->voffset < 0)
1715 /* Increase the ascent so that we can display the text higher
1716 in the line. */
1717 it->ascent += abs (it->voffset);
1718 else
1719 /* Increase the descent so that we can display the text lower
1720 in the line. */
1721 it->descent += it->voffset;
1726 /* Produce glyphs/get display metrics for the image IT is loaded with.
1727 See the description of struct display_iterator in dispextern.h for
1728 an overview of struct display_iterator. */
1730 static void
1731 x_produce_image_glyph (it)
1732 struct it *it;
1734 struct image *img;
1735 struct face *face;
1737 xassert (it->what == IT_IMAGE);
1739 face = FACE_FROM_ID (it->f, it->face_id);
1740 img = IMAGE_FROM_ID (it->f, it->image_id);
1741 xassert (img);
1743 /* Make sure X resources of the face and image are loaded. */
1744 PREPARE_FACE_FOR_DISPLAY (it->f, face);
1745 prepare_image_for_display (it->f, img);
1747 it->ascent = it->phys_ascent = image_ascent (img, face);
1748 it->descent = it->phys_descent = img->height + 2 * img->vmargin - it->ascent;
1749 it->pixel_width = img->width + 2 * img->hmargin;
1751 it->nglyphs = 1;
1753 if (face->box != FACE_NO_BOX)
1755 if (face->box_line_width > 0)
1757 it->ascent += face->box_line_width;
1758 it->descent += face->box_line_width;
1761 if (it->start_of_box_run_p)
1762 it->pixel_width += abs (face->box_line_width);
1763 if (it->end_of_box_run_p)
1764 it->pixel_width += abs (face->box_line_width);
1767 take_vertical_position_into_account (it);
1769 if (it->glyph_row)
1771 struct glyph *glyph;
1772 enum glyph_row_area area = it->area;
1774 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1775 if (glyph < it->glyph_row->glyphs[area + 1])
1777 glyph->charpos = CHARPOS (it->position);
1778 glyph->object = it->object;
1779 glyph->pixel_width = it->pixel_width;
1780 glyph->voffset = it->voffset;
1781 glyph->type = IMAGE_GLYPH;
1782 glyph->multibyte_p = it->multibyte_p;
1783 glyph->left_box_line_p = it->start_of_box_run_p;
1784 glyph->right_box_line_p = it->end_of_box_run_p;
1785 glyph->overlaps_vertically_p = 0;
1786 glyph->padding_p = 0;
1787 glyph->glyph_not_available_p = 0;
1788 glyph->face_id = it->face_id;
1789 glyph->u.img_id = img->id;
1790 glyph->w32_font_type = UNKNOWN_FONT;
1791 ++it->glyph_row->used[area];
1797 /* Append a stretch glyph to IT->glyph_row. OBJECT is the source
1798 of the glyph, WIDTH and HEIGHT are the width and height of the
1799 stretch. ASCENT is the percentage/100 of HEIGHT to use for the
1800 ascent of the glyph (0 <= ASCENT <= 1). */
1802 static void
1803 x_append_stretch_glyph (it, object, width, height, ascent)
1804 struct it *it;
1805 Lisp_Object object;
1806 int width, height;
1807 double ascent;
1809 struct glyph *glyph;
1810 enum glyph_row_area area = it->area;
1812 xassert (ascent >= 0 && ascent <= 1);
1814 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1815 if (glyph < it->glyph_row->glyphs[area + 1])
1817 glyph->charpos = CHARPOS (it->position);
1818 glyph->object = object;
1819 glyph->pixel_width = width;
1820 glyph->voffset = it->voffset;
1821 glyph->type = STRETCH_GLYPH;
1822 glyph->multibyte_p = it->multibyte_p;
1823 glyph->left_box_line_p = it->start_of_box_run_p;
1824 glyph->right_box_line_p = it->end_of_box_run_p;
1825 glyph->overlaps_vertically_p = 0;
1826 glyph->padding_p = 0;
1827 glyph->glyph_not_available_p = 0;
1828 glyph->face_id = it->face_id;
1829 glyph->u.stretch.ascent = height * ascent;
1830 glyph->u.stretch.height = height;
1831 glyph->w32_font_type = UNKNOWN_FONT;
1832 ++it->glyph_row->used[area];
1837 /* Produce a stretch glyph for iterator IT. IT->object is the value
1838 of the glyph property displayed. The value must be a list
1839 `(space KEYWORD VALUE ...)' with the following KEYWORD/VALUE pairs
1840 being recognized:
1842 1. `:width WIDTH' specifies that the space should be WIDTH *
1843 canonical char width wide. WIDTH may be an integer or floating
1844 point number.
1846 2. `:relative-width FACTOR' specifies that the width of the stretch
1847 should be computed from the width of the first character having the
1848 `glyph' property, and should be FACTOR times that width.
1850 3. `:align-to HPOS' specifies that the space should be wide enough
1851 to reach HPOS, a value in canonical character units.
1853 Exactly one of the above pairs must be present.
1855 4. `:height HEIGHT' specifies that the height of the stretch produced
1856 should be HEIGHT, measured in canonical character units.
1858 5. `:relative-height FACTOR' specifies that the height of the
1859 stretch should be FACTOR times the height of the characters having
1860 the glyph property.
1862 Either none or exactly one of 4 or 5 must be present.
1864 6. `:ascent ASCENT' specifies that ASCENT percent of the height
1865 of the stretch should be used for the ascent of the stretch.
1866 ASCENT must be in the range 0 <= ASCENT <= 100. */
1868 #define NUMVAL(X) \
1869 ((INTEGERP (X) || FLOATP (X)) \
1870 ? XFLOATINT (X) \
1871 : - 1)
1874 static void
1875 x_produce_stretch_glyph (it)
1876 struct it *it;
1878 /* (space :width WIDTH :height HEIGHT. */
1879 #if GLYPH_DEBUG
1880 extern Lisp_Object Qspace;
1881 #endif
1882 extern Lisp_Object QCwidth, QCheight, QCascent;
1883 extern Lisp_Object QCrelative_width, QCrelative_height;
1884 extern Lisp_Object QCalign_to;
1885 Lisp_Object prop, plist;
1886 double width = 0, height = 0, ascent = 0;
1887 struct face *face = FACE_FROM_ID (it->f, it->face_id);
1888 XFontStruct *font = face->font ? face->font : FRAME_FONT (it->f);
1890 PREPARE_FACE_FOR_DISPLAY (it->f, face);
1892 /* List should start with `space'. */
1893 xassert (CONSP (it->object) && EQ (XCAR (it->object), Qspace));
1894 plist = XCDR (it->object);
1896 /* Compute the width of the stretch. */
1897 if (prop = Fplist_get (plist, QCwidth),
1898 NUMVAL (prop) > 0)
1899 /* Absolute width `:width WIDTH' specified and valid. */
1900 width = NUMVAL (prop) * CANON_X_UNIT (it->f);
1901 else if (prop = Fplist_get (plist, QCrelative_width),
1902 NUMVAL (prop) > 0)
1904 /* Relative width `:relative-width FACTOR' specified and valid.
1905 Compute the width of the characters having the `glyph'
1906 property. */
1907 struct it it2;
1908 unsigned char *p = BYTE_POS_ADDR (IT_BYTEPOS (*it));
1910 it2 = *it;
1911 if (it->multibyte_p)
1913 int maxlen = ((IT_BYTEPOS (*it) >= GPT ? ZV : GPT)
1914 - IT_BYTEPOS (*it));
1915 it2.c = STRING_CHAR_AND_LENGTH (p, maxlen, it2.len);
1917 else
1918 it2.c = *p, it2.len = 1;
1920 it2.glyph_row = NULL;
1921 it2.what = IT_CHARACTER;
1922 x_produce_glyphs (&it2);
1923 width = NUMVAL (prop) * it2.pixel_width;
1925 else if (prop = Fplist_get (plist, QCalign_to),
1926 NUMVAL (prop) > 0)
1927 width = NUMVAL (prop) * CANON_X_UNIT (it->f) - it->current_x;
1928 else
1929 /* Nothing specified -> width defaults to canonical char width. */
1930 width = CANON_X_UNIT (it->f);
1932 /* Compute height. */
1933 if (prop = Fplist_get (plist, QCheight),
1934 NUMVAL (prop) > 0)
1935 height = NUMVAL (prop) * CANON_Y_UNIT (it->f);
1936 else if (prop = Fplist_get (plist, QCrelative_height),
1937 NUMVAL (prop) > 0)
1938 height = FONT_HEIGHT (font) * NUMVAL (prop);
1939 else
1940 height = FONT_HEIGHT (font);
1942 /* Compute percentage of height used for ascent. If
1943 `:ascent ASCENT' is present and valid, use that. Otherwise,
1944 derive the ascent from the font in use. */
1945 if (prop = Fplist_get (plist, QCascent),
1946 NUMVAL (prop) > 0 && NUMVAL (prop) <= 100)
1947 ascent = NUMVAL (prop) / 100.0;
1948 else
1949 ascent = (double) FONT_BASE (font) / FONT_HEIGHT (font);
1951 if (width <= 0)
1952 width = 1;
1953 if (height <= 0)
1954 height = 1;
1956 if (it->glyph_row)
1958 Lisp_Object object = it->stack[it->sp - 1].string;
1959 if (!STRINGP (object))
1960 object = it->w->buffer;
1961 x_append_stretch_glyph (it, object, width, height, ascent);
1964 it->pixel_width = width;
1965 it->ascent = it->phys_ascent = height * ascent;
1966 it->descent = it->phys_descent = height - it->ascent;
1967 it->nglyphs = 1;
1969 if (face->box != FACE_NO_BOX)
1971 if (face->box_line_width > 0)
1973 it->ascent += face->box_line_width;
1974 it->descent += face->box_line_width;
1977 if (it->start_of_box_run_p)
1978 it->pixel_width += abs (face->box_line_width);
1979 if (it->end_of_box_run_p)
1980 it->pixel_width += abs (face->box_line_width);
1983 take_vertical_position_into_account (it);
1986 /* Return proper value to be used as baseline offset of font that has
1987 ASCENT and DESCENT to draw characters by the font at the vertical
1988 center of the line of frame F.
1990 Here, out task is to find the value of BOFF in the following figure;
1992 -------------------------+-----------+-
1993 -+-+---------+-+ | |
1994 | | | | | |
1995 | | | | F_ASCENT F_HEIGHT
1996 | | | ASCENT | |
1997 HEIGHT | | | | |
1998 | | |-|-+------+-----------|------- baseline
1999 | | | | BOFF | |
2000 | |---------|-+-+ | |
2001 | | | DESCENT | |
2002 -+-+---------+-+ F_DESCENT |
2003 -------------------------+-----------+-
2005 -BOFF + DESCENT + (F_HEIGHT - HEIGHT) / 2 = F_DESCENT
2006 BOFF = DESCENT + (F_HEIGHT - HEIGHT) / 2 - F_DESCENT
2007 DESCENT = FONT->descent
2008 HEIGHT = FONT_HEIGHT (FONT)
2009 F_DESCENT = (F->output_data.x->font->descent
2010 - F->output_data.x->baseline_offset)
2011 F_HEIGHT = FRAME_LINE_HEIGHT (F)
2014 #define VCENTER_BASELINE_OFFSET(FONT, F) \
2015 (FONT_DESCENT (FONT) \
2016 + (FRAME_LINE_HEIGHT ((F)) - FONT_HEIGHT ((FONT)) \
2017 + (FRAME_LINE_HEIGHT ((F)) > FONT_HEIGHT ((FONT)))) / 2 \
2018 - (FONT_DESCENT (FRAME_FONT (F)) - FRAME_BASELINE_OFFSET (F)))
2020 /* Produce glyphs/get display metrics for the display element IT is
2021 loaded with. See the description of struct display_iterator in
2022 dispextern.h for an overview of struct display_iterator. */
2024 static void
2025 x_produce_glyphs (it)
2026 struct it *it;
2028 it->glyph_not_available_p = 0;
2030 if (it->what == IT_CHARACTER)
2032 wchar_t char2b;
2033 XFontStruct *font;
2034 struct face *face = FACE_FROM_ID (it->f, it->face_id);
2035 XCharStruct *pcm;
2036 int font_not_found_p;
2037 struct font_info *font_info;
2038 int boff; /* baseline offset */
2039 /* We may change it->multibyte_p upon unibyte<->multibyte
2040 conversion. So, save the current value now and restore it
2041 later.
2043 Note: It seems that we don't have to record multibyte_p in
2044 struct glyph because the character code itself tells if or
2045 not the character is multibyte. Thus, in the future, we must
2046 consider eliminating the field `multibyte_p' in the struct
2047 glyph.
2049 int saved_multibyte_p = it->multibyte_p;
2051 /* Maybe translate single-byte characters to multibyte, or the
2052 other way. */
2053 it->char_to_display = it->c;
2054 if (!ASCII_BYTE_P (it->c))
2056 if (unibyte_display_via_language_environment
2057 && SINGLE_BYTE_CHAR_P (it->c)
2058 && (it->c >= 0240
2059 || !NILP (Vnonascii_translation_table)))
2061 it->char_to_display = unibyte_char_to_multibyte (it->c);
2062 it->multibyte_p = 1;
2063 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
2064 face = FACE_FROM_ID (it->f, it->face_id);
2066 else if (!SINGLE_BYTE_CHAR_P (it->c)
2067 && !it->multibyte_p)
2069 it->multibyte_p = 1;
2070 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
2071 face = FACE_FROM_ID (it->f, it->face_id);
2075 /* Get font to use. Encode IT->char_to_display. */
2076 x_get_char_face_and_encoding (it->f, it->char_to_display,
2077 it->face_id, &char2b,
2078 it->multibyte_p);
2079 font = face->font;
2081 /* When no suitable font found, use the default font. */
2082 font_not_found_p = font == NULL;
2083 if (font_not_found_p)
2085 font = FRAME_FONT (it->f);
2086 boff = it->f->output_data.w32->baseline_offset;
2087 font_info = NULL;
2089 else
2091 font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
2092 boff = font_info->baseline_offset;
2093 if (font_info->vertical_centering)
2094 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
2097 if (it->char_to_display >= ' '
2098 && (!it->multibyte_p || it->char_to_display < 128))
2100 /* Either unibyte or ASCII. */
2101 int stretched_p;
2103 it->nglyphs = 1;
2105 pcm = w32_per_char_metric (font, &char2b,
2106 font->bdf ? BDF_1D_FONT : ANSI_FONT);
2107 it->ascent = FONT_BASE (font) + boff;
2108 it->descent = FONT_DESCENT (font) - boff;
2110 if (pcm)
2112 it->phys_ascent = pcm->ascent + boff;
2113 it->phys_descent = pcm->descent - boff;
2114 it->pixel_width = pcm->width;
2116 else
2118 it->glyph_not_available_p = 1;
2119 it->phys_ascent = FONT_BASE (font) + boff;
2120 it->phys_descent = FONT_DESCENT (font) - boff;
2121 it->pixel_width = FONT_WIDTH (font);
2124 /* If this is a space inside a region of text with
2125 `space-width' property, change its width. */
2126 stretched_p = it->char_to_display == ' ' && !NILP (it->space_width);
2127 if (stretched_p)
2128 it->pixel_width *= XFLOATINT (it->space_width);
2130 /* If face has a box, add the box thickness to the character
2131 height. If character has a box line to the left and/or
2132 right, add the box line width to the character's width. */
2133 if (face->box != FACE_NO_BOX)
2135 int thick = face->box_line_width;
2137 if (thick > 0)
2139 it->ascent += thick;
2140 it->descent += thick;
2142 else
2143 thick = -thick;
2145 if (it->start_of_box_run_p)
2146 it->pixel_width += thick;
2147 if (it->end_of_box_run_p)
2148 it->pixel_width += thick;
2151 /* If face has an overline, add the height of the overline
2152 (1 pixel) and a 1 pixel margin to the character height. */
2153 if (face->overline_p)
2154 it->ascent += 2;
2156 take_vertical_position_into_account (it);
2158 /* If we have to actually produce glyphs, do it. */
2159 if (it->glyph_row)
2161 if (stretched_p)
2163 /* Translate a space with a `space-width' property
2164 into a stretch glyph. */
2165 double ascent = (double) FONT_BASE (font)
2166 / FONT_HEIGHT (font);
2167 x_append_stretch_glyph (it, it->object, it->pixel_width,
2168 it->ascent + it->descent, ascent);
2170 else
2171 x_append_glyph (it);
2173 /* If characters with lbearing or rbearing are displayed
2174 in this line, record that fact in a flag of the
2175 glyph row. This is used to optimize X output code. */
2176 if (pcm && (pcm->lbearing < 0 || pcm->rbearing > pcm->width))
2177 it->glyph_row->contains_overlapping_glyphs_p = 1;
2180 else if (it->char_to_display == '\n')
2182 /* A newline has no width but we need the height of the line. */
2183 it->pixel_width = 0;
2184 it->nglyphs = 0;
2185 it->ascent = it->phys_ascent = FONT_BASE (font) + boff;
2186 it->descent = it->phys_descent = FONT_DESCENT (font) - boff;
2188 if (face->box != FACE_NO_BOX
2189 && face->box_line_width > 0)
2191 it->ascent += face->box_line_width;
2192 it->descent += face->box_line_width;
2195 else if (it->char_to_display == '\t')
2197 int tab_width = it->tab_width * CANON_X_UNIT (it->f);
2198 int x = it->current_x + it->continuation_lines_width;
2199 int next_tab_x = ((1 + x + tab_width - 1) / tab_width) * tab_width;
2201 /* If the distance from the current position to the next tab
2202 stop is less than a canonical character width, use the
2203 tab stop after that. */
2204 if (next_tab_x - x < CANON_X_UNIT (it->f))
2205 next_tab_x += tab_width;
2207 it->pixel_width = next_tab_x - x;
2208 it->nglyphs = 1;
2209 it->ascent = it->phys_ascent = FONT_BASE (font) + boff;
2210 it->descent = it->phys_descent = FONT_DESCENT (font) - boff;
2212 if (it->glyph_row)
2214 double ascent = (double) it->ascent / (it->ascent + it->descent);
2215 x_append_stretch_glyph (it, it->object, it->pixel_width,
2216 it->ascent + it->descent, ascent);
2219 else
2221 /* A multi-byte character.
2222 If we found a font, this font should give us the right
2223 metrics. If we didn't find a font, use the frame's
2224 default font and calculate the width of the character
2225 from the charset width; this is what old redisplay code
2226 did. */
2227 enum w32_char_font_type type;
2229 if (font->bdf && CHARSET_DIMENSION (CHAR_CHARSET (it->c)) == 1)
2230 type = BDF_1D_FONT;
2231 else if (font->bdf)
2232 type = BDF_2D_FONT;
2233 else
2234 type = UNICODE_FONT;
2236 pcm = w32_per_char_metric (font, &char2b, type);
2238 if (font_not_found_p || !pcm)
2240 int charset = CHAR_CHARSET (it->char_to_display);
2242 it->glyph_not_available_p = 1;
2243 it->pixel_width = (FONT_WIDTH (FRAME_FONT (it->f))
2244 * CHARSET_WIDTH (charset));
2245 it->phys_ascent = FONT_BASE (font) + boff;
2246 it->phys_descent = FONT_DESCENT (font) - boff;
2248 else
2250 it->pixel_width = pcm->width;
2251 it->phys_ascent = pcm->ascent + boff;
2252 it->phys_descent = pcm->descent - boff;
2253 if (it->glyph_row
2254 && (pcm->lbearing < 0
2255 || pcm->rbearing > pcm->width))
2256 it->glyph_row->contains_overlapping_glyphs_p = 1;
2258 it->nglyphs = 1;
2259 it->ascent = FONT_BASE (font) + boff;
2260 it->descent = FONT_DESCENT (font) - boff;
2261 if (face->box != FACE_NO_BOX)
2263 int thick = face->box_line_width;
2265 if (thick > 0)
2267 it->ascent += thick;
2268 it->descent += thick;
2270 else
2271 thick = - thick;
2273 if (it->start_of_box_run_p)
2274 it->pixel_width += thick;
2275 if (it->end_of_box_run_p)
2276 it->pixel_width += thick;
2279 /* If face has an overline, add the height of the overline
2280 (1 pixel) and a 1 pixel margin to the character height. */
2281 if (face->overline_p)
2282 it->ascent += 2;
2284 take_vertical_position_into_account (it);
2286 if (it->glyph_row)
2287 x_append_glyph (it);
2289 it->multibyte_p = saved_multibyte_p;
2291 else if (it->what == IT_COMPOSITION)
2293 /* Note: A composition is represented as one glyph in the
2294 glyph matrix. There are no padding glyphs. */
2295 wchar_t char2b;
2296 XFontStruct *font;
2297 struct face *face = FACE_FROM_ID (it->f, it->face_id);
2298 XCharStruct *pcm;
2299 int font_not_found_p;
2300 struct font_info *font_info;
2301 int boff; /* baseline offset */
2302 struct composition *cmp = composition_table[it->cmp_id];
2304 /* Maybe translate single-byte characters to multibyte. */
2305 it->char_to_display = it->c;
2306 if (unibyte_display_via_language_environment
2307 && SINGLE_BYTE_CHAR_P (it->c)
2308 && (it->c >= 0240
2309 || (it->c >= 0200
2310 && !NILP (Vnonascii_translation_table))))
2312 it->char_to_display = unibyte_char_to_multibyte (it->c);
2315 /* Get face and font to use. Encode IT->char_to_display. */
2316 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
2317 face = FACE_FROM_ID (it->f, it->face_id);
2318 x_get_char_face_and_encoding (it->f, it->char_to_display,
2319 it->face_id, &char2b, it->multibyte_p);
2320 font = face->font;
2322 /* When no suitable font found, use the default font. */
2323 font_not_found_p = font == NULL;
2324 if (font_not_found_p)
2326 font = FRAME_FONT (it->f);
2327 boff = it->f->output_data.w32->baseline_offset;
2328 font_info = NULL;
2330 else
2332 font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
2333 boff = font_info->baseline_offset;
2334 if (font_info->vertical_centering)
2335 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
2338 /* There are no padding glyphs, so there is only one glyph to
2339 produce for the composition. Important is that pixel_width,
2340 ascent and descent are the values of what is drawn by
2341 draw_glyphs (i.e. the values of the overall glyphs composed). */
2342 it->nglyphs = 1;
2344 /* If we have not yet calculated pixel size data of glyphs of
2345 the composition for the current face font, calculate them
2346 now. Theoretically, we have to check all fonts for the
2347 glyphs, but that requires much time and memory space. So,
2348 here we check only the font of the first glyph. This leads
2349 to incorrect display very rarely, and C-l (recenter) can
2350 correct the display anyway. */
2351 if (cmp->font != (void *) font)
2353 /* Ascent and descent of the font of the first character of
2354 this composition (adjusted by baseline offset). Ascent
2355 and descent of overall glyphs should not be less than
2356 them respectively. */
2357 int font_ascent = FONT_BASE (font) + boff;
2358 int font_descent = FONT_DESCENT (font) - boff;
2359 /* Bounding box of the overall glyphs. */
2360 int leftmost, rightmost, lowest, highest;
2361 int i, width, ascent, descent;
2362 enum w32_char_font_type font_type;
2364 cmp->font = (void *) font;
2366 if (font->bdf && CHARSET_DIMENSION (CHAR_CHARSET (it->c)) == 1)
2367 font_type = BDF_1D_FONT;
2368 else if (font->bdf)
2369 font_type = BDF_2D_FONT;
2370 else
2371 font_type = UNICODE_FONT;
2373 /* Initialize the bounding box. */
2374 if (font_info
2375 && (pcm = w32_per_char_metric (font, &char2b, font_type)))
2377 width = pcm->width;
2378 ascent = pcm->ascent;
2379 descent = pcm->descent;
2381 else
2383 width = FONT_WIDTH (font);
2384 ascent = FONT_BASE (font);
2385 descent = FONT_DESCENT (font);
2388 rightmost = width;
2389 lowest = - descent + boff;
2390 highest = ascent + boff;
2391 leftmost = 0;
2393 if (font_info
2394 && font_info->default_ascent
2395 && CHAR_TABLE_P (Vuse_default_ascent)
2396 && !NILP (Faref (Vuse_default_ascent,
2397 make_number (it->char_to_display))))
2398 highest = font_info->default_ascent + boff;
2400 /* Draw the first glyph at the normal position. It may be
2401 shifted to right later if some other glyphs are drawn at
2402 the left. */
2403 cmp->offsets[0] = 0;
2404 cmp->offsets[1] = boff;
2406 /* Set cmp->offsets for the remaining glyphs. */
2407 for (i = 1; i < cmp->glyph_len; i++)
2409 int left, right, btm, top;
2410 int ch = COMPOSITION_GLYPH (cmp, i);
2411 int face_id = FACE_FOR_CHAR (it->f, face, ch);
2413 face = FACE_FROM_ID (it->f, face_id);
2414 x_get_char_face_and_encoding (it->f, ch, face->id, &char2b,
2415 it->multibyte_p);
2416 font = face->font;
2417 if (font == NULL)
2419 font = FRAME_FONT (it->f);
2420 boff = it->f->output_data.w32->baseline_offset;
2421 font_info = NULL;
2423 else
2425 font_info
2426 = FONT_INFO_FROM_ID (it->f, face->font_info_id);
2427 boff = font_info->baseline_offset;
2428 if (font_info->vertical_centering)
2429 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
2432 if (font->bdf && CHARSET_DIMENSION (CHAR_CHARSET (ch)) == 1)
2433 font_type = BDF_1D_FONT;
2434 else if (font->bdf)
2435 font_type = BDF_2D_FONT;
2436 else
2437 font_type = UNICODE_FONT;
2439 if (font_info
2440 && (pcm = w32_per_char_metric (font, &char2b, font_type)))
2442 width = pcm->width;
2443 ascent = pcm->ascent;
2444 descent = pcm->descent;
2446 else
2448 width = FONT_WIDTH (font);
2449 ascent = 1;
2450 descent = 0;
2453 if (cmp->method != COMPOSITION_WITH_RULE_ALTCHARS)
2455 /* Relative composition with or without
2456 alternate chars. */
2457 left = (leftmost + rightmost - width) / 2;
2458 btm = - descent + boff;
2459 if (font_info && font_info->relative_compose
2460 && (! CHAR_TABLE_P (Vignore_relative_composition)
2461 || NILP (Faref (Vignore_relative_composition,
2462 make_number (ch)))))
2465 if (- descent >= font_info->relative_compose)
2466 /* One extra pixel between two glyphs. */
2467 btm = highest + 1;
2468 else if (ascent <= 0)
2469 /* One extra pixel between two glyphs. */
2470 btm = lowest - 1 - ascent - descent;
2473 else
2475 /* A composition rule is specified by an integer
2476 value that encodes global and new reference
2477 points (GREF and NREF). GREF and NREF are
2478 specified by numbers as below:
2480 0---1---2 -- ascent
2484 9--10--11 -- center
2486 ---3---4---5--- baseline
2488 6---7---8 -- descent
2490 int rule = COMPOSITION_RULE (cmp, i);
2491 int gref, nref, grefx, grefy, nrefx, nrefy;
2493 COMPOSITION_DECODE_RULE (rule, gref, nref);
2494 grefx = gref % 3, nrefx = nref % 3;
2495 grefy = gref / 3, nrefy = nref / 3;
2497 left = (leftmost
2498 + grefx * (rightmost - leftmost) / 2
2499 - nrefx * width / 2);
2500 btm = ((grefy == 0 ? highest
2501 : grefy == 1 ? 0
2502 : grefy == 2 ? lowest
2503 : (highest + lowest) / 2)
2504 - (nrefy == 0 ? ascent + descent
2505 : nrefy == 1 ? descent - boff
2506 : nrefy == 2 ? 0
2507 : (ascent + descent) / 2));
2510 cmp->offsets[i * 2] = left;
2511 cmp->offsets[i * 2 + 1] = btm + descent;
2513 /* Update the bounding box of the overall glyphs. */
2514 right = left + width;
2515 top = btm + descent + ascent;
2516 if (left < leftmost)
2517 leftmost = left;
2518 if (right > rightmost)
2519 rightmost = right;
2520 if (top > highest)
2521 highest = top;
2522 if (btm < lowest)
2523 lowest = btm;
2526 /* If there are glyphs whose x-offsets are negative,
2527 shift all glyphs to the right and make all x-offsets
2528 non-negative. */
2529 if (leftmost < 0)
2531 for (i = 0; i < cmp->glyph_len; i++)
2532 cmp->offsets[i * 2] -= leftmost;
2533 rightmost -= leftmost;
2536 cmp->pixel_width = rightmost;
2537 cmp->ascent = highest;
2538 cmp->descent = - lowest;
2539 if (cmp->ascent < font_ascent)
2540 cmp->ascent = font_ascent;
2541 if (cmp->descent < font_descent)
2542 cmp->descent = font_descent;
2545 it->pixel_width = cmp->pixel_width;
2546 it->ascent = it->phys_ascent = cmp->ascent;
2547 it->descent = it->phys_descent = cmp->descent;
2549 if (face->box != FACE_NO_BOX)
2551 int thick = face->box_line_width;
2553 if (thick > 0)
2555 it->ascent += thick;
2556 it->descent += thick;
2558 else
2559 thick = - thick;
2561 if (it->start_of_box_run_p)
2562 it->pixel_width += thick;
2563 if (it->end_of_box_run_p)
2564 it->pixel_width += thick;
2567 /* If face has an overline, add the height of the overline
2568 (1 pixel) and a 1 pixel margin to the character height. */
2569 if (face->overline_p)
2570 it->ascent += 2;
2572 take_vertical_position_into_account (it);
2574 if (it->glyph_row)
2575 x_append_composite_glyph (it);
2577 else if (it->what == IT_IMAGE)
2578 x_produce_image_glyph (it);
2579 else if (it->what == IT_STRETCH)
2580 x_produce_stretch_glyph (it);
2582 /* Accumulate dimensions. Note: can't assume that it->descent > 0
2583 because this isn't true for images with `:ascent 100'. */
2584 xassert (it->ascent >= 0 && it->descent >= 0);
2585 if (it->area == TEXT_AREA)
2586 it->current_x += it->pixel_width;
2588 it->descent += it->extra_line_spacing;
2590 it->max_ascent = max (it->max_ascent, it->ascent);
2591 it->max_descent = max (it->max_descent, it->descent);
2592 it->max_phys_ascent = max (it->max_phys_ascent, it->phys_ascent);
2593 it->max_phys_descent = max (it->max_phys_descent, it->phys_descent);
2597 /* Estimate the pixel height of the mode or top line on frame F.
2598 FACE_ID specifies what line's height to estimate. */
2601 x_estimate_mode_line_height (f, face_id)
2602 struct frame *f;
2603 enum face_id face_id;
2605 int height = FONT_HEIGHT (FRAME_FONT (f));
2607 /* This function is called so early when Emacs starts that the face
2608 cache and mode line face are not yet initialized. */
2609 if (FRAME_FACE_CACHE (f))
2611 struct face *face = FACE_FROM_ID (f, face_id);
2612 if (face)
2614 if (face->font)
2615 height = FONT_HEIGHT (face->font);
2616 if (face->box_line_width > 0)
2617 height += 2 * face->box_line_width;
2621 return height;
2625 /***********************************************************************
2626 Glyph display
2627 ***********************************************************************/
2629 /* A sequence of glyphs to be drawn in the same face.
2631 This data structure is not really completely X specific, so it
2632 could possibly, at least partially, be useful for other systems. It
2633 is currently not part of the external redisplay interface because
2634 it's not clear what other systems will need. */
2636 struct glyph_string
2638 /* X-origin of the string. */
2639 int x;
2641 /* Y-origin and y-position of the base line of this string. */
2642 int y, ybase;
2644 /* The width of the string, not including a face extension. */
2645 int width;
2647 /* The width of the string, including a face extension. */
2648 int background_width;
2650 /* The height of this string. This is the height of the line this
2651 string is drawn in, and can be different from the height of the
2652 font the string is drawn in. */
2653 int height;
2655 /* Number of pixels this string overwrites in front of its x-origin.
2656 This number is zero if the string has an lbearing >= 0; it is
2657 -lbearing, if the string has an lbearing < 0. */
2658 int left_overhang;
2660 /* Number of pixels this string overwrites past its right-most
2661 nominal x-position, i.e. x + width. Zero if the string's
2662 rbearing is <= its nominal width, rbearing - width otherwise. */
2663 int right_overhang;
2665 /* The frame on which the glyph string is drawn. */
2666 struct frame *f;
2668 /* The window on which the glyph string is drawn. */
2669 struct window *w;
2671 /* X display and window for convenience. */
2672 Window window;
2674 /* The glyph row for which this string was built. It determines the
2675 y-origin and height of the string. */
2676 struct glyph_row *row;
2678 /* The area within row. */
2679 enum glyph_row_area area;
2681 /* Characters to be drawn, and number of characters. */
2682 wchar_t *char2b;
2683 int nchars;
2685 /* A face-override for drawing cursors, mouse face and similar. */
2686 enum draw_glyphs_face hl;
2688 /* Face in which this string is to be drawn. */
2689 struct face *face;
2691 /* Font in which this string is to be drawn. */
2692 XFontStruct *font;
2694 /* Font info for this string. */
2695 struct font_info *font_info;
2697 /* Non-null means this string describes (part of) a composition.
2698 All characters from char2b are drawn composed. */
2699 struct composition *cmp;
2701 /* Index of this glyph string's first character in the glyph
2702 definition of CMP. If this is zero, this glyph string describes
2703 the first character of a composition. */
2704 int gidx;
2706 /* 1 means this glyph strings face has to be drawn to the right end
2707 of the window's drawing area. */
2708 unsigned extends_to_end_of_line_p : 1;
2710 /* 1 means the background of this string has been drawn. */
2711 unsigned background_filled_p : 1;
2713 /* 1 means glyph string must be drawn with 16-bit functions. */
2714 unsigned two_byte_p : 1;
2716 /* 1 means that the original font determined for drawing this glyph
2717 string could not be loaded. The member `font' has been set to
2718 the frame's default font in this case. */
2719 unsigned font_not_found_p : 1;
2721 /* 1 means that the face in which this glyph string is drawn has a
2722 stipple pattern. */
2723 unsigned stippled_p : 1;
2725 /* 1 means only the foreground of this glyph string must be drawn,
2726 and we should use the physical height of the line this glyph
2727 string appears in as clip rect. */
2728 unsigned for_overlaps_p : 1;
2730 /* The GC to use for drawing this glyph string. */
2731 XGCValues *gc;
2733 HDC hdc;
2735 /* A pointer to the first glyph in the string. This glyph
2736 corresponds to char2b[0]. Needed to draw rectangles if
2737 font_not_found_p is 1. */
2738 struct glyph *first_glyph;
2740 /* Image, if any. */
2741 struct image *img;
2743 struct glyph_string *next, *prev;
2747 /* Encapsulate the different ways of displaying text under W32. */
2749 static void
2750 w32_text_out (s, x, y,chars,nchars)
2751 struct glyph_string * s;
2752 int x, y;
2753 wchar_t * chars;
2754 int nchars;
2756 int charset_dim = w32_font_is_double_byte (s->gc->font) ? 2 : 1;
2757 if (s->gc->font->bdf)
2758 w32_BDF_TextOut (s->gc->font->bdf, s->hdc,
2759 x, y, (char *) chars, charset_dim,
2760 nchars * charset_dim, 0);
2761 else if (s->first_glyph->w32_font_type == UNICODE_FONT)
2762 ExtTextOutW (s->hdc, x, y, 0, NULL, chars, nchars, NULL);
2763 else
2764 ExtTextOutA (s->hdc, x, y, 0, NULL, (char *) chars,
2765 nchars * charset_dim, NULL);
2768 #if GLYPH_DEBUG
2770 static void
2771 x_dump_glyph_string (s)
2772 struct glyph_string *s;
2774 fprintf (stderr, "glyph string\n");
2775 fprintf (stderr, " x, y, w, h = %d, %d, %d, %d\n",
2776 s->x, s->y, s->width, s->height);
2777 fprintf (stderr, " ybase = %d\n", s->ybase);
2778 fprintf (stderr, " hl = %d\n", s->hl);
2779 fprintf (stderr, " left overhang = %d, right = %d\n",
2780 s->left_overhang, s->right_overhang);
2781 fprintf (stderr, " nchars = %d\n", s->nchars);
2782 fprintf (stderr, " extends to end of line = %d\n",
2783 s->extends_to_end_of_line_p);
2784 fprintf (stderr, " font height = %d\n", FONT_HEIGHT (s->font));
2785 fprintf (stderr, " bg width = %d\n", s->background_width);
2788 #endif /* GLYPH_DEBUG */
2792 static void x_append_glyph_string_lists P_ ((struct glyph_string **,
2793 struct glyph_string **,
2794 struct glyph_string *,
2795 struct glyph_string *));
2796 static void x_prepend_glyph_string_lists P_ ((struct glyph_string **,
2797 struct glyph_string **,
2798 struct glyph_string *,
2799 struct glyph_string *));
2800 static void x_append_glyph_string P_ ((struct glyph_string **,
2801 struct glyph_string **,
2802 struct glyph_string *));
2803 static int x_left_overwritten P_ ((struct glyph_string *));
2804 static int x_left_overwriting P_ ((struct glyph_string *));
2805 static int x_right_overwritten P_ ((struct glyph_string *));
2806 static int x_right_overwriting P_ ((struct glyph_string *));
2807 static int x_fill_glyph_string P_ ((struct glyph_string *, int, int, int,
2808 int));
2809 static void w32_init_glyph_string P_ ((struct glyph_string *, HDC hdc,
2810 wchar_t *, struct window *,
2811 struct glyph_row *,
2812 enum glyph_row_area, int,
2813 enum draw_glyphs_face));
2814 static int x_draw_glyphs P_ ((struct window *, int , struct glyph_row *,
2815 enum glyph_row_area, int, int,
2816 enum draw_glyphs_face, int));
2817 static void x_set_glyph_string_clipping P_ ((struct glyph_string *));
2818 static void x_set_glyph_string_gc P_ ((struct glyph_string *));
2819 static void x_draw_glyph_string_background P_ ((struct glyph_string *,
2820 int));
2821 static void x_draw_glyph_string_foreground P_ ((struct glyph_string *));
2822 static void x_draw_composite_glyph_string_foreground P_ ((struct glyph_string *));
2823 static void x_draw_glyph_string_box P_ ((struct glyph_string *));
2824 static void x_draw_glyph_string P_ ((struct glyph_string *));
2825 static void x_compute_glyph_string_overhangs P_ ((struct glyph_string *));
2826 static void x_set_cursor_gc P_ ((struct glyph_string *));
2827 static void x_set_mode_line_face_gc P_ ((struct glyph_string *));
2828 static void x_set_mouse_face_gc P_ ((struct glyph_string *));
2829 static void w32_get_glyph_overhangs P_ ((HDC hdc, struct glyph *,
2830 struct frame *,
2831 int *, int *));
2832 static void x_compute_overhangs_and_x P_ ((struct glyph_string *, int, int));
2833 static int w32_alloc_lighter_color (struct frame *, COLORREF *, double, int);
2834 static void w32_setup_relief_color P_ ((struct frame *, struct relief *,
2835 double, int, COLORREF));
2836 static void x_setup_relief_colors P_ ((struct glyph_string *));
2837 static void x_draw_image_glyph_string P_ ((struct glyph_string *));
2838 static void x_draw_image_relief P_ ((struct glyph_string *));
2839 static void x_draw_image_foreground P_ ((struct glyph_string *));
2840 static void w32_draw_image_foreground_1 P_ ((struct glyph_string *, HBITMAP));
2841 static void x_fill_image_glyph_string P_ ((struct glyph_string *));
2842 static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int,
2843 int, int, int));
2844 static void w32_draw_relief_rect P_ ((struct frame *, int, int, int, int,
2845 int, int, int, int, RECT *));
2846 static void w32_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,
2847 int, int, int, RECT *));
2848 static void x_fix_overlapping_area P_ ((struct window *, struct glyph_row *,
2849 enum glyph_row_area));
2850 static int x_fill_stretch_glyph_string P_ ((struct glyph_string *,
2851 struct glyph_row *,
2852 enum glyph_row_area, int, int));
2854 #if GLYPH_DEBUG
2855 static void x_check_font P_ ((struct frame *, XFontStruct *));
2856 #endif
2859 /* Append the list of glyph strings with head H and tail T to the list
2860 with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the result. */
2862 static INLINE void
2863 x_append_glyph_string_lists (head, tail, h, t)
2864 struct glyph_string **head, **tail;
2865 struct glyph_string *h, *t;
2867 if (h)
2869 if (*head)
2870 (*tail)->next = h;
2871 else
2872 *head = h;
2873 h->prev = *tail;
2874 *tail = t;
2879 /* Prepend the list of glyph strings with head H and tail T to the
2880 list with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the
2881 result. */
2883 static INLINE void
2884 x_prepend_glyph_string_lists (head, tail, h, t)
2885 struct glyph_string **head, **tail;
2886 struct glyph_string *h, *t;
2888 if (h)
2890 if (*head)
2891 (*head)->prev = t;
2892 else
2893 *tail = t;
2894 t->next = *head;
2895 *head = h;
2900 /* Append glyph string S to the list with head *HEAD and tail *TAIL.
2901 Set *HEAD and *TAIL to the resulting list. */
2903 static INLINE void
2904 x_append_glyph_string (head, tail, s)
2905 struct glyph_string **head, **tail;
2906 struct glyph_string *s;
2908 s->next = s->prev = NULL;
2909 x_append_glyph_string_lists (head, tail, s, s);
2913 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
2914 face. */
2916 static void
2917 x_set_cursor_gc (s)
2918 struct glyph_string *s;
2920 if (s->font == FRAME_FONT (s->f)
2921 && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
2922 && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
2923 && !s->cmp)
2924 s->gc = s->f->output_data.w32->cursor_gc;
2925 else
2927 /* Cursor on non-default face: must merge. */
2928 XGCValues xgcv;
2929 unsigned long mask;
2931 xgcv.background = s->f->output_data.w32->cursor_pixel;
2932 xgcv.foreground = s->face->background;
2934 /* If the glyph would be invisible, try a different foreground. */
2935 if (xgcv.foreground == xgcv.background)
2936 xgcv.foreground = s->face->foreground;
2937 if (xgcv.foreground == xgcv.background)
2938 xgcv.foreground = s->f->output_data.w32->cursor_foreground_pixel;
2939 if (xgcv.foreground == xgcv.background)
2940 xgcv.foreground = s->face->foreground;
2942 /* Make sure the cursor is distinct from text in this face. */
2943 if (xgcv.background == s->face->background
2944 && xgcv.foreground == s->face->foreground)
2946 xgcv.background = s->face->foreground;
2947 xgcv.foreground = s->face->background;
2950 IF_DEBUG (x_check_font (s->f, s->font));
2951 xgcv.font = s->font;
2952 mask = GCForeground | GCBackground | GCFont;
2954 if (FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc)
2955 XChangeGC (NULL, FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc,
2956 mask, &xgcv);
2957 else
2958 FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc
2959 = XCreateGC (NULL, s->window, mask, &xgcv);
2961 s->gc = FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc;
2966 /* Set up S->gc of glyph string S for drawing text in mouse face. */
2968 static void
2969 x_set_mouse_face_gc (s)
2970 struct glyph_string *s;
2972 int face_id;
2973 struct face *face;
2975 /* What face has to be used last for the mouse face? */
2976 face_id = FRAME_W32_DISPLAY_INFO (s->f)->mouse_face_face_id;
2977 face = FACE_FROM_ID (s->f, face_id);
2978 if (face == NULL)
2979 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
2981 if (s->first_glyph->type == CHAR_GLYPH)
2982 face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch);
2983 else
2984 face_id = FACE_FOR_CHAR (s->f, face, 0);
2985 s->face = FACE_FROM_ID (s->f, face_id);
2986 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
2988 /* If font in this face is same as S->font, use it. */
2989 if (s->font == s->face->font)
2990 s->gc = s->face->gc;
2991 else
2993 /* Otherwise construct scratch_cursor_gc with values from FACE
2994 but font FONT. */
2995 XGCValues xgcv;
2996 unsigned long mask;
2998 xgcv.background = s->face->background;
2999 xgcv.foreground = s->face->foreground;
3000 IF_DEBUG (x_check_font (s->f, s->font));
3001 xgcv.font = s->font;
3002 mask = GCForeground | GCBackground | GCFont;
3004 if (FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc)
3005 XChangeGC (NULL, FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc,
3006 mask, &xgcv);
3007 else
3008 FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc
3009 = XCreateGC (NULL, s->window, mask, &xgcv);
3011 s->gc = FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc;
3014 xassert (s->gc != 0);
3018 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
3019 Faces to use in the mode line have already been computed when the
3020 matrix was built, so there isn't much to do, here. */
3022 static INLINE void
3023 x_set_mode_line_face_gc (s)
3024 struct glyph_string *s;
3026 s->gc = s->face->gc;
3030 /* Set S->gc of glyph string S for drawing that glyph string. Set
3031 S->stippled_p to a non-zero value if the face of S has a stipple
3032 pattern. */
3034 static INLINE void
3035 x_set_glyph_string_gc (s)
3036 struct glyph_string *s;
3038 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
3040 if (s->hl == DRAW_NORMAL_TEXT)
3042 s->gc = s->face->gc;
3043 s->stippled_p = s->face->stipple != 0;
3045 else if (s->hl == DRAW_INVERSE_VIDEO)
3047 x_set_mode_line_face_gc (s);
3048 s->stippled_p = s->face->stipple != 0;
3050 else if (s->hl == DRAW_CURSOR)
3052 x_set_cursor_gc (s);
3053 s->stippled_p = 0;
3055 else if (s->hl == DRAW_MOUSE_FACE)
3057 x_set_mouse_face_gc (s);
3058 s->stippled_p = s->face->stipple != 0;
3060 else if (s->hl == DRAW_IMAGE_RAISED
3061 || s->hl == DRAW_IMAGE_SUNKEN)
3063 s->gc = s->face->gc;
3064 s->stippled_p = s->face->stipple != 0;
3066 else
3068 s->gc = s->face->gc;
3069 s->stippled_p = s->face->stipple != 0;
3072 /* GC must have been set. */
3073 xassert (s->gc != 0);
3077 /* Return in *R the clipping rectangle for glyph string S. */
3079 static void
3080 w32_get_glyph_string_clip_rect (s, r)
3081 struct glyph_string *s;
3082 RECT *r;
3084 int r_height, r_width;
3086 if (s->row->full_width_p)
3088 /* Draw full-width. X coordinates are relative to S->w->left. */
3089 int canon_x = CANON_X_UNIT (s->f);
3091 r->left = WINDOW_LEFT_MARGIN (s->w) * canon_x;
3092 r_width = XFASTINT (s->w->width) * canon_x;
3094 if (FRAME_HAS_VERTICAL_SCROLL_BARS (s->f))
3096 int width = FRAME_SCROLL_BAR_WIDTH (s->f) * canon_x;
3097 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (s->f))
3098 r->left -= width;
3101 r->left += FRAME_INTERNAL_BORDER_WIDTH (s->f);
3103 /* Unless displaying a mode or menu bar line, which are always
3104 fully visible, clip to the visible part of the row. */
3105 if (s->w->pseudo_window_p)
3106 r_height = s->row->visible_height;
3107 else
3108 r_height = s->height;
3110 else
3112 /* This is a text line that may be partially visible. */
3113 r->left = WINDOW_AREA_TO_FRAME_PIXEL_X (s->w, s->area, 0);
3114 r_width = window_box_width (s->w, s->area);
3115 r_height = s->row->visible_height;
3118 /* If S draws overlapping rows, it's sufficient to use the top and
3119 bottom of the window for clipping because this glyph string
3120 intentionally draws over other lines. */
3121 if (s->for_overlaps_p)
3123 r->top = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
3124 r_height = window_text_bottom_y (s->w) - r->top;
3126 else
3128 /* Don't use S->y for clipping because it doesn't take partially
3129 visible lines into account. For example, it can be negative for
3130 partially visible lines at the top of a window. */
3131 if (!s->row->full_width_p
3132 && MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (s->w, s->row))
3133 r->top = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
3134 else
3135 r->top = max (0, s->row->y);
3137 /* If drawing a tool-bar window, draw it over the internal border
3138 at the top of the window. */
3139 if (s->w == XWINDOW (s->f->tool_bar_window))
3140 r->top -= s->f->output_data.w32->internal_border_width;
3143 r->top = WINDOW_TO_FRAME_PIXEL_Y (s->w, r->top);
3145 /* If drawing the cursor, don't let glyph draw outside its
3146 advertised boundaries. Cleartype does this under some circumstances. */
3147 if (s->hl == DRAW_CURSOR)
3149 if (s->x > r->left)
3151 r_width -= s->x - r->left;
3152 r->left = s->x;
3154 r_width = min (r_width, s->first_glyph->pixel_width);
3157 r->bottom = r->top + r_height;
3158 r->right = r->left + r_width;
3162 /* Set clipping for output of glyph string S. S may be part of a mode
3163 line or menu if we don't have X toolkit support. */
3165 static INLINE void
3166 x_set_glyph_string_clipping (s)
3167 struct glyph_string *s;
3169 RECT r;
3170 w32_get_glyph_string_clip_rect (s, &r);
3171 w32_set_clip_rectangle (s->hdc, &r);
3175 /* Compute left and right overhang of glyph string S. If S is a glyph
3176 string for a composition, assume overhangs don't exist. */
3178 static INLINE void
3179 x_compute_glyph_string_overhangs (s)
3180 struct glyph_string *s;
3182 /* TODO: Windows does not appear to have a method for
3183 getting this info without getting the ABC widths for each
3184 individual character and working it out manually. */
3188 /* Compute overhangs and x-positions for glyph string S and its
3189 predecessors, or successors. X is the starting x-position for S.
3190 BACKWARD_P non-zero means process predecessors. */
3192 static void
3193 x_compute_overhangs_and_x (s, x, backward_p)
3194 struct glyph_string *s;
3195 int x;
3196 int backward_p;
3198 if (backward_p)
3200 while (s)
3202 x_compute_glyph_string_overhangs (s);
3203 x -= s->width;
3204 s->x = x;
3205 s = s->prev;
3208 else
3210 while (s)
3212 x_compute_glyph_string_overhangs (s);
3213 s->x = x;
3214 x += s->width;
3215 s = s->next;
3221 /* Set *LEFT and *RIGHT to the left and right overhang of GLYPH on
3222 frame F. Overhangs of glyphs other than type CHAR_GLYPH are
3223 assumed to be zero. */
3225 static void
3226 w32_get_glyph_overhangs (hdc, glyph, f, left, right)
3227 HDC hdc;
3228 struct glyph *glyph;
3229 struct frame *f;
3230 int *left, *right;
3232 *left = *right = 0;
3234 if (glyph->type == CHAR_GLYPH)
3236 XFontStruct *font;
3237 struct face *face;
3238 wchar_t char2b;
3239 XCharStruct *pcm;
3241 face = x_get_glyph_face_and_encoding (f, glyph, &char2b, NULL);
3242 font = face->font;
3244 if (font
3245 && (pcm = w32_per_char_metric (font, &char2b,
3246 glyph->w32_font_type)))
3248 if (pcm->rbearing > pcm->width)
3249 *right = pcm->rbearing - pcm->width;
3250 if (pcm->lbearing < 0)
3251 *left = -pcm->lbearing;
3257 static void
3258 x_get_glyph_overhangs (glyph, f, left, right)
3259 struct glyph *glyph;
3260 struct frame *f;
3261 int *left, *right;
3263 HDC hdc = get_frame_dc (f);
3264 /* Convert to unicode! */
3265 w32_get_glyph_overhangs (hdc, glyph, f, left, right);
3266 release_frame_dc (f, hdc);
3270 /* Return the index of the first glyph preceding glyph string S that
3271 is overwritten by S because of S's left overhang. Value is -1
3272 if no glyphs are overwritten. */
3274 static int
3275 x_left_overwritten (s)
3276 struct glyph_string *s;
3278 int k;
3280 if (s->left_overhang)
3282 int x = 0, i;
3283 struct glyph *glyphs = s->row->glyphs[s->area];
3284 int first = s->first_glyph - glyphs;
3286 for (i = first - 1; i >= 0 && x > -s->left_overhang; --i)
3287 x -= glyphs[i].pixel_width;
3289 k = i + 1;
3291 else
3292 k = -1;
3294 return k;
3298 /* Return the index of the first glyph preceding glyph string S that
3299 is overwriting S because of its right overhang. Value is -1 if no
3300 glyph in front of S overwrites S. */
3302 static int
3303 x_left_overwriting (s)
3304 struct glyph_string *s;
3306 int i, k, x;
3307 struct glyph *glyphs = s->row->glyphs[s->area];
3308 int first = s->first_glyph - glyphs;
3310 k = -1;
3311 x = 0;
3312 for (i = first - 1; i >= 0; --i)
3314 int left, right;
3315 w32_get_glyph_overhangs (s->hdc, glyphs + i, s->f, &left, &right);
3316 if (x + right > 0)
3317 k = i;
3318 x -= glyphs[i].pixel_width;
3321 return k;
3325 /* Return the index of the last glyph following glyph string S that is
3326 not overwritten by S because of S's right overhang. Value is -1 if
3327 no such glyph is found. */
3329 static int
3330 x_right_overwritten (s)
3331 struct glyph_string *s;
3333 int k = -1;
3335 if (s->right_overhang)
3337 int x = 0, i;
3338 struct glyph *glyphs = s->row->glyphs[s->area];
3339 int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
3340 int end = s->row->used[s->area];
3342 for (i = first; i < end && s->right_overhang > x; ++i)
3343 x += glyphs[i].pixel_width;
3345 k = i;
3348 return k;
3352 /* Return the index of the last glyph following glyph string S that
3353 overwrites S because of its left overhang. Value is negative
3354 if no such glyph is found. */
3356 static int
3357 x_right_overwriting (s)
3358 struct glyph_string *s;
3360 int i, k, x;
3361 int end = s->row->used[s->area];
3362 struct glyph *glyphs = s->row->glyphs[s->area];
3363 int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
3365 k = -1;
3366 x = 0;
3367 for (i = first; i < end; ++i)
3369 int left, right;
3370 w32_get_glyph_overhangs (s->hdc, glyphs + i, s->f, &left, &right);
3371 if (x - left < 0)
3372 k = i;
3373 x += glyphs[i].pixel_width;
3376 return k;
3380 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
3382 static INLINE void
3383 x_clear_glyph_string_rect (s, x, y, w, h)
3384 struct glyph_string *s;
3385 int x, y, w, h;
3387 int real_x = x;
3388 int real_y = y;
3389 int real_w = w;
3390 int real_h = h;
3391 #if 0
3392 /* Take clipping into account. */
3393 if (s->gc->clip_mask == Rect)
3395 real_x = max (real_x, s->gc->clip_rectangle.left);
3396 real_y = max (real_y, s->gc->clip_rectangle.top);
3397 real_w = min (real_w, s->gc->clip_rectangle.right
3398 - s->gc->clip_rectangle.left);
3399 real_h = min (real_h, s->gc->clip_rectangle.bottom
3400 - s->gc->clip_rectangle.top);
3402 #endif
3403 w32_fill_area (s->f, s->hdc, s->gc->background, real_x, real_y,
3404 real_w, real_h);
3408 /* Draw the background of glyph_string S. If S->background_filled_p
3409 is non-zero don't draw it. FORCE_P non-zero means draw the
3410 background even if it wouldn't be drawn normally. This is used
3411 when a string preceding S draws into the background of S, or S
3412 contains the first component of a composition. */
3414 static void
3415 x_draw_glyph_string_background (s, force_p)
3416 struct glyph_string *s;
3417 int force_p;
3419 /* Nothing to do if background has already been drawn or if it
3420 shouldn't be drawn in the first place. */
3421 if (!s->background_filled_p)
3423 int box_line_width = max (s->face->box_line_width, 0);
3425 #if 0 /* TODO: stipple */
3426 if (s->stippled_p)
3428 /* Fill background with a stipple pattern. */
3429 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
3430 XFillRectangle (s->display, s->window, s->gc, s->x,
3431 s->y + box_line_width,
3432 s->background_width,
3433 s->height - 2 * box_line_width);
3434 XSetFillStyle (s->display, s->gc, FillSolid);
3435 s->background_filled_p = 1;
3437 else
3438 #endif
3439 if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
3440 || s->font_not_found_p
3441 || s->extends_to_end_of_line_p
3442 || s->font->bdf
3443 || force_p)
3445 x_clear_glyph_string_rect (s, s->x, s->y + box_line_width,
3446 s->background_width,
3447 s->height - 2 * box_line_width);
3448 s->background_filled_p = 1;
3454 /* Draw the foreground of glyph string S. */
3456 static void
3457 x_draw_glyph_string_foreground (s)
3458 struct glyph_string *s;
3460 int i, x;
3461 HFONT old_font;
3463 /* If first glyph of S has a left box line, start drawing the text
3464 of S to the right of that box line. */
3465 if (s->face->box != FACE_NO_BOX
3466 && s->first_glyph->left_box_line_p)
3467 x = s->x + abs (s->face->box_line_width);
3468 else
3469 x = s->x;
3471 if (s->for_overlaps_p || (s->background_filled_p && s->hl != DRAW_CURSOR))
3472 SetBkMode (s->hdc, TRANSPARENT);
3473 else
3474 SetBkMode (s->hdc, OPAQUE);
3476 SetTextColor (s->hdc, s->gc->foreground);
3477 SetBkColor (s->hdc, s->gc->background);
3478 SetTextAlign (s->hdc, TA_BASELINE | TA_LEFT);
3480 if (s->font && s->font->hfont)
3481 old_font = SelectObject (s->hdc, s->font->hfont);
3483 /* Draw characters of S as rectangles if S's font could not be
3484 loaded. */
3485 if (s->font_not_found_p)
3487 for (i = 0; i < s->nchars; ++i)
3489 struct glyph *g = s->first_glyph + i;
3491 w32_draw_rectangle (s->hdc, s->gc, x, s->y, g->pixel_width - 1,
3492 s->height - 1);
3493 x += g->pixel_width;
3496 else
3498 char *char1b = (char *) s->char2b;
3499 int boff = s->font_info->baseline_offset;
3501 if (s->font_info->vertical_centering)
3502 boff = VCENTER_BASELINE_OFFSET (s->font, s->f) - boff;
3504 /* If we can use 8-bit functions, condense S->char2b. */
3505 if (!s->two_byte_p)
3506 for (i = 0; i < s->nchars; ++i)
3507 char1b[i] = BYTE2 (s->char2b[i]);
3509 /* Draw text with TextOut and friends. */
3510 w32_text_out (s, x, s->ybase - boff, s->char2b, s->nchars);
3512 if (s->font && s->font->hfont)
3513 SelectObject (s->hdc, old_font);
3516 /* Draw the foreground of composite glyph string S. */
3518 static void
3519 x_draw_composite_glyph_string_foreground (s)
3520 struct glyph_string *s;
3522 int i, x;
3523 HFONT old_font;
3525 /* If first glyph of S has a left box line, start drawing the text
3526 of S to the right of that box line. */
3527 if (s->face->box != FACE_NO_BOX
3528 && s->first_glyph->left_box_line_p)
3529 x = s->x + abs (s->face->box_line_width);
3530 else
3531 x = s->x;
3533 /* S is a glyph string for a composition. S->gidx is the index of
3534 the first character drawn for glyphs of this composition.
3535 S->gidx == 0 means we are drawing the very first character of
3536 this composition. */
3538 SetTextColor (s->hdc, s->gc->foreground);
3539 SetBkColor (s->hdc, s->gc->background);
3540 SetBkMode (s->hdc, TRANSPARENT);
3541 SetTextAlign (s->hdc, TA_BASELINE | TA_LEFT);
3543 if (s->font && s->font->hfont)
3544 old_font = SelectObject (s->hdc, s->font->hfont);
3546 /* Draw a rectangle for the composition if the font for the very
3547 first character of the composition could not be loaded. */
3548 if (s->font_not_found_p)
3550 if (s->gidx == 0)
3551 w32_draw_rectangle (s->hdc, s->gc, x, s->y, s->width - 1,
3552 s->height - 1);
3554 else
3556 for (i = 0; i < s->nchars; i++, ++s->gidx)
3557 w32_text_out (s, x + s->cmp->offsets[s->gidx * 2],
3558 s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
3559 s->char2b + i, 1);
3561 if (s->font && s->font->hfont)
3562 SelectObject (s->hdc, old_font);
3566 /* Brightness beyond which a color won't have its highlight brightness
3567 boosted.
3569 Nominally, highlight colors for `3d' faces are calculated by
3570 brightening an object's color by a constant scale factor, but this
3571 doesn't yield good results for dark colors, so for colors who's
3572 brightness is less than this value (on a scale of 0-255) have to
3573 use an additional additive factor.
3575 The value here is set so that the default menu-bar/mode-line color
3576 (grey75) will not have its highlights changed at all. */
3577 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 187
3580 /* Allocate a color which is lighter or darker than *COLOR by FACTOR
3581 or DELTA. Try a color with RGB values multiplied by FACTOR first.
3582 If this produces the same color as COLOR, try a color where all RGB
3583 values have DELTA added. Return the allocated color in *COLOR.
3584 DISPLAY is the X display, CMAP is the colormap to operate on.
3585 Value is non-zero if successful. */
3587 static int
3588 w32_alloc_lighter_color (f, color, factor, delta)
3589 struct frame *f;
3590 COLORREF *color;
3591 double factor;
3592 int delta;
3594 COLORREF new;
3595 long bright;
3597 /* On Windows, RGB values are 0-255, not 0-65535, so scale delta. */
3598 delta /= 256;
3600 /* Change RGB values by specified FACTOR. Avoid overflow! */
3601 xassert (factor >= 0);
3602 new = PALETTERGB (min (0xff, factor * GetRValue (*color)),
3603 min (0xff, factor * GetGValue (*color)),
3604 min (0xff, factor * GetBValue (*color)));
3606 /* Calculate brightness of COLOR. */
3607 bright = (2 * GetRValue (*color) + 3 * GetGValue (*color)
3608 + GetBValue (*color)) / 6;
3610 /* We only boost colors that are darker than
3611 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
3612 if (bright < HIGHLIGHT_COLOR_DARK_BOOST_LIMIT)
3613 /* Make an additive adjustment to NEW, because it's dark enough so
3614 that scaling by FACTOR alone isn't enough. */
3616 /* How far below the limit this color is (0 - 1, 1 being darker). */
3617 double dimness = 1 - (double)bright / HIGHLIGHT_COLOR_DARK_BOOST_LIMIT;
3618 /* The additive adjustment. */
3619 int min_delta = delta * dimness * factor / 2;
3621 if (factor < 1)
3622 new = PALETTERGB (max (0, min (0xff, min_delta - GetRValue (*color))),
3623 max (0, min (0xff, min_delta - GetGValue (*color))),
3624 max (0, min (0xff, min_delta - GetBValue (*color))));
3625 else
3626 new = PALETTERGB (max (0, min (0xff, min_delta + GetRValue (*color))),
3627 max (0, min (0xff, min_delta + GetGValue (*color))),
3628 max (0, min (0xff, min_delta + GetBValue (*color))));
3631 if (new == *color)
3632 new = PALETTERGB (max (0, min (0xff, delta + GetRValue (*color))),
3633 max (0, min (0xff, delta + GetGValue (*color))),
3634 max (0, min (0xff, delta + GetBValue (*color))));
3636 /* TODO: Map to palette and retry with delta if same? */
3637 /* TODO: Free colors (if using palette)? */
3639 if (new == *color)
3640 return 0;
3642 *color = new;
3644 return 1;
3648 /* Set up the foreground color for drawing relief lines of glyph
3649 string S. RELIEF is a pointer to a struct relief containing the GC
3650 with which lines will be drawn. Use a color that is FACTOR or
3651 DELTA lighter or darker than the relief's background which is found
3652 in S->f->output_data.x->relief_background. If such a color cannot
3653 be allocated, use DEFAULT_PIXEL, instead. */
3655 static void
3656 w32_setup_relief_color (f, relief, factor, delta, default_pixel)
3657 struct frame *f;
3658 struct relief *relief;
3659 double factor;
3660 int delta;
3661 COLORREF default_pixel;
3663 XGCValues xgcv;
3664 struct w32_output *di = f->output_data.w32;
3665 unsigned long mask = GCForeground;
3666 COLORREF pixel;
3667 COLORREF background = di->relief_background;
3668 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
3670 /* TODO: Free colors (if using palette)? */
3672 /* Allocate new color. */
3673 xgcv.foreground = default_pixel;
3674 pixel = background;
3675 if (w32_alloc_lighter_color (f, &pixel, factor, delta))
3677 relief->allocated_p = 1;
3678 xgcv.foreground = relief->pixel = pixel;
3681 if (relief->gc == 0)
3683 #if 0 /* TODO: stipple */
3684 xgcv.stipple = dpyinfo->gray;
3685 mask |= GCStipple;
3686 #endif
3687 relief->gc = XCreateGC (NULL, FRAME_W32_WINDOW (f), mask, &xgcv);
3689 else
3690 XChangeGC (NULL, relief->gc, mask, &xgcv);
3694 /* Set up colors for the relief lines around glyph string S. */
3696 static void
3697 x_setup_relief_colors (s)
3698 struct glyph_string *s;
3700 struct w32_output *di = s->f->output_data.w32;
3701 COLORREF color;
3703 if (s->face->use_box_color_for_shadows_p)
3704 color = s->face->box_color;
3705 else if (s->first_glyph->type == IMAGE_GLYPH
3706 && s->img->pixmap
3707 && !IMAGE_BACKGROUND_TRANSPARENT (s->img, s->f, 0))
3708 color = IMAGE_BACKGROUND (s->img, s->f, 0);
3709 else
3710 color = s->gc->background;
3712 if (di->white_relief.gc == 0
3713 || color != di->relief_background)
3715 di->relief_background = color;
3716 w32_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
3717 WHITE_PIX_DEFAULT (s->f));
3718 w32_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
3719 BLACK_PIX_DEFAULT (s->f));
3724 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
3725 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
3726 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
3727 relief. LEFT_P non-zero means draw a relief on the left side of
3728 the rectangle. RIGHT_P non-zero means draw a relief on the right
3729 side of the rectangle. CLIP_RECT is the clipping rectangle to use
3730 when drawing. */
3732 static void
3733 w32_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
3734 raised_p, left_p, right_p, clip_rect)
3735 struct frame *f;
3736 int left_x, top_y, right_x, bottom_y, width, left_p, right_p, raised_p;
3737 RECT *clip_rect;
3739 int i;
3740 XGCValues gc;
3741 HDC hdc = get_frame_dc (f);
3743 if (raised_p)
3744 gc.foreground = f->output_data.w32->white_relief.gc->foreground;
3745 else
3746 gc.foreground = f->output_data.w32->black_relief.gc->foreground;
3748 w32_set_clip_rectangle (hdc, clip_rect);
3750 /* Top. */
3751 for (i = 0; i < width; ++i)
3752 w32_fill_area (f, hdc, gc.foreground,
3753 left_x + i * left_p, top_y + i,
3754 right_x - left_x - i * (left_p + right_p ) + 1, 1);
3756 /* Left. */
3757 if (left_p)
3758 for (i = 0; i < width; ++i)
3759 w32_fill_area (f, hdc, gc.foreground,
3760 left_x + i, top_y + i, 1,
3761 bottom_y - top_y - 2 * i + 1);
3763 if (raised_p)
3764 gc.foreground = f->output_data.w32->black_relief.gc->foreground;
3765 else
3766 gc.foreground = f->output_data.w32->white_relief.gc->foreground;
3768 /* Bottom. */
3769 for (i = 0; i < width; ++i)
3770 w32_fill_area (f, hdc, gc.foreground,
3771 left_x + i * left_p, bottom_y - i,
3772 right_x - left_x - i * (left_p + right_p) + 1, 1);
3774 /* Right. */
3775 if (right_p)
3776 for (i = 0; i < width; ++i)
3777 w32_fill_area (f, hdc, gc.foreground,
3778 right_x - i, top_y + i + 1, 1,
3779 bottom_y - top_y - 2 * i - 1);
3781 w32_set_clip_rectangle (hdc, NULL);
3783 release_frame_dc (f, hdc);
3787 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
3788 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
3789 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
3790 left side of the rectangle. RIGHT_P non-zero means draw a line
3791 on the right side of the rectangle. CLIP_RECT is the clipping
3792 rectangle to use when drawing. */
3794 static void
3795 w32_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
3796 left_p, right_p, clip_rect)
3797 struct glyph_string *s;
3798 int left_x, top_y, right_x, bottom_y, width, left_p, right_p;
3799 RECT *clip_rect;
3801 w32_set_clip_rectangle (s->hdc, clip_rect);
3803 /* Top. */
3804 w32_fill_area (s->f, s->hdc, s->face->box_color,
3805 left_x, top_y, right_x - left_x + 1, width);
3807 /* Left. */
3808 if (left_p)
3810 w32_fill_area (s->f, s->hdc, s->face->box_color,
3811 left_x, top_y, width, bottom_y - top_y + 1);
3814 /* Bottom. */
3815 w32_fill_area (s->f, s->hdc, s->face->box_color,
3816 left_x, bottom_y - width + 1, right_x - left_x + 1, width);
3818 /* Right. */
3819 if (right_p)
3821 w32_fill_area (s->f, s->hdc, s->face->box_color,
3822 right_x - width + 1, top_y, width, bottom_y - top_y + 1);
3825 w32_set_clip_rectangle (s->hdc, NULL);
3829 /* Draw a box around glyph string S. */
3831 static void
3832 x_draw_glyph_string_box (s)
3833 struct glyph_string *s;
3835 int width, left_x, right_x, top_y, bottom_y, last_x, raised_p;
3836 int left_p, right_p;
3837 struct glyph *last_glyph;
3838 RECT clip_rect;
3840 last_x = window_box_right (s->w, s->area);
3841 if (s->row->full_width_p
3842 && !s->w->pseudo_window_p)
3844 last_x += FRAME_X_RIGHT_FRINGE_WIDTH (s->f);
3845 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (s->f))
3846 last_x += FRAME_SCROLL_BAR_WIDTH (s->f) * CANON_X_UNIT (s->f);
3849 /* The glyph that may have a right box line. */
3850 last_glyph = (s->cmp || s->img
3851 ? s->first_glyph
3852 : s->first_glyph + s->nchars - 1);
3854 width = abs (s->face->box_line_width);
3855 raised_p = s->face->box == FACE_RAISED_BOX;
3856 left_x = s->x;
3857 right_x = ((s->row->full_width_p && s->extends_to_end_of_line_p
3858 ? last_x - 1
3859 : min (last_x, s->x + s->background_width) - 1));
3860 top_y = s->y;
3861 bottom_y = top_y + s->height - 1;
3863 left_p = (s->first_glyph->left_box_line_p
3864 || (s->hl == DRAW_MOUSE_FACE
3865 && (s->prev == NULL
3866 || s->prev->hl != s->hl)));
3867 right_p = (last_glyph->right_box_line_p
3868 || (s->hl == DRAW_MOUSE_FACE
3869 && (s->next == NULL
3870 || s->next->hl != s->hl)));
3872 w32_get_glyph_string_clip_rect (s, &clip_rect);
3874 if (s->face->box == FACE_SIMPLE_BOX)
3875 w32_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
3876 left_p, right_p, &clip_rect);
3877 else
3879 x_setup_relief_colors (s);
3880 w32_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
3881 width, raised_p, left_p, right_p, &clip_rect);
3886 /* Draw foreground of image glyph string S. */
3888 static void
3889 x_draw_image_foreground (s)
3890 struct glyph_string *s;
3892 int x;
3893 int y = s->ybase - image_ascent (s->img, s->face);
3895 /* If first glyph of S has a left box line, start drawing it to the
3896 right of that line. */
3897 if (s->face->box != FACE_NO_BOX
3898 && s->first_glyph->left_box_line_p)
3899 x = s->x + abs (s->face->box_line_width);
3900 else
3901 x = s->x;
3903 /* If there is a margin around the image, adjust x- and y-position
3904 by that margin. */
3905 x += s->img->hmargin;
3906 y += s->img->vmargin;
3908 SaveDC (s->hdc);
3910 if (s->img->pixmap)
3912 HDC compat_hdc = CreateCompatibleDC (s->hdc);
3913 HBRUSH fg_brush = CreateSolidBrush (s->gc->foreground);
3914 HBRUSH orig_brush = SelectObject (s->hdc, fg_brush);
3915 HGDIOBJ orig_obj = SelectObject (compat_hdc, s->img->pixmap);
3916 SetBkColor (compat_hdc, RGB (255, 255, 255));
3917 SetTextColor (s->hdc, RGB (0, 0, 0));
3918 x_set_glyph_string_clipping (s);
3920 if (s->img->mask)
3922 HDC mask_dc = CreateCompatibleDC (s->hdc);
3923 HGDIOBJ mask_orig_obj = SelectObject (mask_dc, s->img->mask);
3925 SetTextColor (s->hdc, RGB (255, 255, 255));
3926 SetBkColor (s->hdc, RGB (0, 0, 0));
3928 BitBlt (s->hdc, x, y, s->img->width, s->img->height,
3929 compat_hdc, 0, 0, SRCINVERT);
3930 BitBlt (s->hdc, x, y, s->img->width, s->img->height,
3931 mask_dc, 0, 0, SRCAND);
3932 BitBlt (s->hdc, x, y, s->img->width, s->img->height,
3933 compat_hdc, 0, 0, SRCINVERT);
3935 SelectObject (mask_dc, mask_orig_obj);
3936 DeleteDC (mask_dc);
3938 else
3940 SetTextColor (s->hdc, s->gc->foreground);
3941 SetBkColor (s->hdc, s->gc->background);
3943 BitBlt (s->hdc, x, y, s->img->width, s->img->height,
3944 compat_hdc, 0, 0, SRCCOPY);
3946 /* When the image has a mask, we can expect that at
3947 least part of a mouse highlight or a block cursor will
3948 be visible. If the image doesn't have a mask, make
3949 a block cursor visible by drawing a rectangle around
3950 the image. I believe it's looking better if we do
3951 nothing here for mouse-face. */
3952 if (s->hl == DRAW_CURSOR)
3954 int r = s->img->relief;
3955 if (r < 0) r = -r;
3956 w32_draw_rectangle (s->hdc, s->gc, x - r, y - r ,
3957 s->img->width + r*2 - 1, s->img->height + r*2 - 1);
3961 w32_set_clip_rectangle (s->hdc, NULL);
3962 SelectObject (s->hdc, orig_brush);
3963 DeleteObject (fg_brush);
3964 SelectObject (compat_hdc, orig_obj);
3965 DeleteDC (compat_hdc);
3967 else
3968 w32_draw_rectangle (s->hdc, s->gc, x, y, s->img->width -1,
3969 s->img->height - 1);
3971 RestoreDC (s->hdc ,-1);
3976 /* Draw a relief around the image glyph string S. */
3978 static void
3979 x_draw_image_relief (s)
3980 struct glyph_string *s;
3982 int x0, y0, x1, y1, thick, raised_p;
3983 RECT r;
3984 int x;
3985 int y = s->ybase - image_ascent (s->img, s->face);
3987 /* If first glyph of S has a left box line, start drawing it to the
3988 right of that line. */
3989 if (s->face->box != FACE_NO_BOX
3990 && s->first_glyph->left_box_line_p)
3991 x = s->x + abs (s->face->box_line_width);
3992 else
3993 x = s->x;
3995 /* If there is a margin around the image, adjust x- and y-position
3996 by that margin. */
3997 x += s->img->hmargin;
3998 y += s->img->vmargin;
4000 if (s->hl == DRAW_IMAGE_SUNKEN
4001 || s->hl == DRAW_IMAGE_RAISED)
4003 thick = tool_bar_button_relief >= 0 ? tool_bar_button_relief : DEFAULT_TOOL_BAR_BUTTON_RELIEF;
4004 raised_p = s->hl == DRAW_IMAGE_RAISED;
4006 else
4008 thick = abs (s->img->relief);
4009 raised_p = s->img->relief > 0;
4012 x0 = x - thick;
4013 y0 = y - thick;
4014 x1 = x + s->img->width + thick - 1;
4015 y1 = y + s->img->height + thick - 1;
4017 x_setup_relief_colors (s);
4018 w32_get_glyph_string_clip_rect (s, &r);
4019 w32_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p, 1, 1, &r);
4023 /* Draw the foreground of image glyph string S to PIXMAP. */
4025 static void
4026 w32_draw_image_foreground_1 (s, pixmap)
4027 struct glyph_string *s;
4028 HBITMAP pixmap;
4030 HDC hdc = CreateCompatibleDC (s->hdc);
4031 HGDIOBJ orig_hdc_obj = SelectObject (hdc, pixmap);
4032 int x;
4033 int y = s->ybase - s->y - image_ascent (s->img, s->face);
4035 /* If first glyph of S has a left box line, start drawing it to the
4036 right of that line. */
4037 if (s->face->box != FACE_NO_BOX
4038 && s->first_glyph->left_box_line_p)
4039 x = abs (s->face->box_line_width);
4040 else
4041 x = 0;
4043 /* If there is a margin around the image, adjust x- and y-position
4044 by that margin. */
4045 x += s->img->hmargin;
4046 y += s->img->vmargin;
4048 if (s->img->pixmap)
4050 HDC compat_hdc = CreateCompatibleDC (hdc);
4051 HBRUSH fg_brush = CreateSolidBrush (s->gc->foreground);
4052 HBRUSH orig_brush = SelectObject (hdc, fg_brush);
4053 HGDIOBJ orig_obj = SelectObject (compat_hdc, s->img->pixmap);
4055 if (s->img->mask)
4057 HDC mask_dc = CreateCompatibleDC (hdc);
4058 HGDIOBJ mask_orig_obj = SelectObject (mask_dc, s->img->mask);
4060 SetTextColor (hdc, RGB (0, 0, 0));
4061 SetBkColor (hdc, RGB (255, 255, 255));
4062 BitBlt (hdc, x, y, s->img->width, s->img->height,
4063 compat_hdc, 0, 0, SRCINVERT);
4064 BitBlt (hdc, x, y, s->img->width, s->img->height,
4065 mask_dc, 0, 0, SRCAND);
4066 BitBlt (hdc, x, y, s->img->width, s->img->height,
4067 compat_hdc, 0, 0, SRCINVERT);
4069 SelectObject (mask_dc, mask_orig_obj);
4070 DeleteDC (mask_dc);
4072 else
4074 SetTextColor (hdc, s->gc->foreground);
4075 SetBkColor (hdc, s->gc->background);
4077 BitBlt (hdc, x, y, s->img->width, s->img->height,
4078 compat_hdc, 0, 0, SRCCOPY);
4080 /* When the image has a mask, we can expect that at
4081 least part of a mouse highlight or a block cursor will
4082 be visible. If the image doesn't have a mask, make
4083 a block cursor visible by drawing a rectangle around
4084 the image. I believe it's looking better if we do
4085 nothing here for mouse-face. */
4086 if (s->hl == DRAW_CURSOR)
4088 int r = s->img->relief;
4089 if (r < 0) r = -r;
4090 w32_draw_rectangle (hdc, s->gc, x - r, y - r ,
4091 s->img->width + r*2 - 1, s->img->height + r*2 - 1);
4095 SelectObject (hdc, orig_brush);
4096 DeleteObject (fg_brush);
4097 SelectObject (compat_hdc, orig_obj);
4098 DeleteDC (compat_hdc);
4100 else
4101 w32_draw_rectangle (hdc, s->gc, x, y, s->img->width - 1,
4102 s->img->height - 1);
4104 SelectObject (hdc, orig_hdc_obj);
4105 DeleteDC (hdc);
4109 /* Draw part of the background of glyph string S. X, Y, W, and H
4110 give the rectangle to draw. */
4112 static void
4113 x_draw_glyph_string_bg_rect (s, x, y, w, h)
4114 struct glyph_string *s;
4115 int x, y, w, h;
4117 #if 0 /* TODO: stipple */
4118 if (s->stippled_p)
4120 /* Fill background with a stipple pattern. */
4121 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
4122 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
4123 XSetFillStyle (s->display, s->gc, FillSolid);
4125 else
4126 #endif
4127 x_clear_glyph_string_rect (s, x, y, w, h);
4131 /* Draw image glyph string S.
4133 s->y
4134 s->x +-------------------------
4135 | s->face->box
4137 | +-------------------------
4138 | | s->img->vmargin
4140 | | +-------------------
4141 | | | the image
4145 static void
4146 x_draw_image_glyph_string (s)
4147 struct glyph_string *s;
4149 int x, y;
4150 int box_line_hwidth = abs (s->face->box_line_width);
4151 int box_line_vwidth = max (s->face->box_line_width, 0);
4152 int height;
4153 HBITMAP pixmap = 0;
4155 height = s->height - 2 * box_line_vwidth;
4157 /* Fill background with face under the image. Do it only if row is
4158 taller than image or if image has a clip mask to reduce
4159 flickering. */
4160 s->stippled_p = s->face->stipple != 0;
4161 if (height > s->img->height
4162 || s->img->hmargin
4163 || s->img->vmargin
4164 || s->img->mask
4165 || s->img->pixmap == 0
4166 || s->width != s->background_width)
4168 if (box_line_hwidth && s->first_glyph->left_box_line_p)
4169 x = s->x + box_line_hwidth;
4170 else
4171 x = s->x;
4173 y = s->y + box_line_vwidth;
4174 #if 0 /* TODO: figure out if we need to do this on Windows. */
4175 if (s->img->mask)
4177 /* Create a pixmap as large as the glyph string. Fill it
4178 with the background color. Copy the image to it, using
4179 its mask. Copy the temporary pixmap to the display. */
4180 Screen *screen = FRAME_X_SCREEN (s->f);
4181 int depth = DefaultDepthOfScreen (screen);
4183 /* Create a pixmap as large as the glyph string. */
4184 pixmap = XCreatePixmap (s->display, s->window,
4185 s->background_width,
4186 s->height, depth);
4188 /* Don't clip in the following because we're working on the
4189 pixmap. */
4190 XSetClipMask (s->display, s->gc, None);
4192 /* Fill the pixmap with the background color/stipple. */
4193 if (s->stippled_p)
4195 /* Fill background with a stipple pattern. */
4196 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
4197 XFillRectangle (s->display, pixmap, s->gc,
4198 0, 0, s->background_width, s->height);
4199 XSetFillStyle (s->display, s->gc, FillSolid);
4201 else
4203 XGCValues xgcv;
4204 XGetGCValues (s->display, s->gc, GCForeground | GCBackground,
4205 &xgcv);
4206 XSetForeground (s->display, s->gc, xgcv.background);
4207 XFillRectangle (s->display, pixmap, s->gc,
4208 0, 0, s->background_width, s->height);
4209 XSetForeground (s->display, s->gc, xgcv.foreground);
4212 else
4213 #endif
4214 x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
4216 s->background_filled_p = 1;
4219 /* Draw the foreground. */
4220 if (pixmap != 0)
4222 w32_draw_image_foreground_1 (s, pixmap);
4223 x_set_glyph_string_clipping (s);
4225 HDC compat_hdc = CreateCompatibleDC (s->hdc);
4226 HBRUSH fg_brush = CreateSolidBrush (s->gc->foreground);
4227 HBRUSH orig_brush = SelectObject (s->hdc, fg_brush);
4228 HGDIOBJ orig_obj = SelectObject (compat_hdc, pixmap);
4230 SetTextColor (s->hdc, s->gc->foreground);
4231 SetBkColor (s->hdc, s->gc->background);
4232 BitBlt (s->hdc, s->x, s->y, s->background_width, s->height,
4233 compat_hdc, 0, 0, SRCCOPY);
4235 SelectObject (s->hdc, orig_brush);
4236 DeleteObject (fg_brush);
4237 SelectObject (compat_hdc, orig_obj);
4238 DeleteDC (compat_hdc);
4240 DeleteObject (pixmap);
4241 pixmap = 0;
4243 else
4244 x_draw_image_foreground (s);
4246 /* If we must draw a relief around the image, do it. */
4247 if (s->img->relief
4248 || s->hl == DRAW_IMAGE_RAISED
4249 || s->hl == DRAW_IMAGE_SUNKEN)
4250 x_draw_image_relief (s);
4254 /* Draw stretch glyph string S. */
4256 static void
4257 x_draw_stretch_glyph_string (s)
4258 struct glyph_string *s;
4260 xassert (s->first_glyph->type == STRETCH_GLYPH);
4261 s->stippled_p = s->face->stipple != 0;
4263 if (s->hl == DRAW_CURSOR
4264 && !x_stretch_cursor_p)
4266 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
4267 as wide as the stretch glyph. */
4268 int width = min (CANON_X_UNIT (s->f), s->background_width);
4270 /* Draw cursor. */
4271 x_draw_glyph_string_bg_rect (s, s->x, s->y, width, s->height);
4273 /* Clear rest using the GC of the original non-cursor face. */
4274 if (width < s->background_width)
4276 XGCValues *gc = s->face->gc;
4277 int x = s->x + width, y = s->y;
4278 int w = s->background_width - width, h = s->height;
4279 RECT r;
4280 HDC hdc = s->hdc;
4282 if (s->row->mouse_face_p
4283 && cursor_in_mouse_face_p (s->w))
4285 x_set_mouse_face_gc (s);
4286 gc = s->gc;
4288 else
4289 gc = s->face->gc;
4291 w32_get_glyph_string_clip_rect (s, &r);
4292 w32_set_clip_rectangle (hdc, &r);
4294 #if 0 /* TODO: stipple */
4295 if (s->face->stipple)
4297 /* Fill background with a stipple pattern. */
4298 XSetFillStyle (s->display, gc, FillOpaqueStippled);
4299 XFillRectangle (s->display, s->window, gc, x, y, w, h);
4300 XSetFillStyle (s->display, gc, FillSolid);
4302 else
4303 #endif
4305 w32_fill_area (s->f, s->hdc, gc->background, x, y, w, h);
4309 else if (!s->background_filled_p)
4310 x_draw_glyph_string_bg_rect (s, s->x, s->y, s->background_width,
4311 s->height);
4313 s->background_filled_p = 1;
4317 /* Draw glyph string S. */
4319 static void
4320 x_draw_glyph_string (s)
4321 struct glyph_string *s;
4323 int relief_drawn_p = 0;
4325 /* If S draws into the background of its successor, draw the
4326 background of the successor first so that S can draw into it.
4327 This makes S->next use XDrawString instead of XDrawImageString. */
4328 if (s->next && s->right_overhang && !s->for_overlaps_p)
4330 xassert (s->next->img == NULL);
4331 x_set_glyph_string_gc (s->next);
4332 x_set_glyph_string_clipping (s->next);
4333 x_draw_glyph_string_background (s->next, 1);
4336 /* Set up S->gc, set clipping and draw S. */
4337 x_set_glyph_string_gc (s);
4339 /* Draw relief (if any) in advance for char/composition so that the
4340 glyph string can be drawn over it. */
4341 if (!s->for_overlaps_p
4342 && s->face->box != FACE_NO_BOX
4343 && (s->first_glyph->type == CHAR_GLYPH
4344 || s->first_glyph->type == COMPOSITE_GLYPH))
4347 x_set_glyph_string_clipping (s);
4348 x_draw_glyph_string_background (s, 1);
4349 x_draw_glyph_string_box (s);
4350 x_set_glyph_string_clipping (s);
4351 relief_drawn_p = 1;
4353 else
4354 x_set_glyph_string_clipping (s);
4356 switch (s->first_glyph->type)
4358 case IMAGE_GLYPH:
4359 x_draw_image_glyph_string (s);
4360 break;
4362 case STRETCH_GLYPH:
4363 x_draw_stretch_glyph_string (s);
4364 break;
4366 case CHAR_GLYPH:
4367 if (s->for_overlaps_p)
4368 s->background_filled_p = 1;
4369 else
4370 x_draw_glyph_string_background (s, 0);
4371 x_draw_glyph_string_foreground (s);
4372 break;
4374 case COMPOSITE_GLYPH:
4375 if (s->for_overlaps_p || s->gidx > 0)
4376 s->background_filled_p = 1;
4377 else
4378 x_draw_glyph_string_background (s, 1);
4379 x_draw_composite_glyph_string_foreground (s);
4380 break;
4382 default:
4383 abort ();
4386 if (!s->for_overlaps_p)
4388 /* Draw underline. */
4389 if (s->face->underline_p
4390 && (s->font->bdf || !s->font->tm.tmUnderlined))
4392 unsigned long h = 1;
4393 unsigned long dy = s->height - h;
4395 /* TODO: Use font information for positioning and thickness
4396 of underline. See OUTLINETEXTMETRIC, and xterm.c. */
4397 if (s->face->underline_defaulted_p)
4399 w32_fill_area (s->f, s->hdc, s->gc->foreground, s->x,
4400 s->y + dy, s->width, 1);
4402 else
4404 w32_fill_area (s->f, s->hdc, s->face->underline_color, s->x,
4405 s->y + dy, s->width, 1);
4409 /* Draw overline. */
4410 if (s->face->overline_p)
4412 unsigned long dy = 0, h = 1;
4414 if (s->face->overline_color_defaulted_p)
4416 w32_fill_area (s->f, s->hdc, s->gc->foreground, s->x,
4417 s->y + dy, s->width, h);
4419 else
4421 w32_fill_area (s->f, s->hdc, s->face->underline_color, s->x,
4422 s->y + dy, s->width, h);
4426 /* Draw strike-through. */
4427 if (s->face->strike_through_p
4428 && (s->font->bdf || !s->font->tm.tmStruckOut))
4430 unsigned long h = 1;
4431 unsigned long dy = (s->height - h) / 2;
4433 if (s->face->strike_through_color_defaulted_p)
4435 w32_fill_area (s->f, s->hdc, s->gc->foreground, s->x, s->y + dy,
4436 s->width, h);
4438 else
4440 w32_fill_area (s->f, s->hdc, s->face->underline_color, s->x,
4441 s->y + dy, s->width, h);
4445 /* Draw relief. */
4446 if (!relief_drawn_p && s->face->box != FACE_NO_BOX)
4447 x_draw_glyph_string_box (s);
4450 /* Reset clipping. */
4451 w32_set_clip_rectangle (s->hdc, NULL);
4455 static int x_fill_composite_glyph_string P_ ((struct glyph_string *,
4456 struct face **, int));
4459 /* Fill glyph string S with composition components specified by S->cmp.
4461 FACES is an array of faces for all components of this composition.
4462 S->gidx is the index of the first component for S.
4463 OVERLAPS_P non-zero means S should draw the foreground only, and
4464 use its physical height for clipping.
4466 Value is the index of a component not in S. */
4468 static int
4469 x_fill_composite_glyph_string (s, faces, overlaps_p)
4470 struct glyph_string *s;
4471 struct face **faces;
4472 int overlaps_p;
4474 int i;
4476 xassert (s);
4478 s->for_overlaps_p = overlaps_p;
4480 s->face = faces[s->gidx];
4481 s->font = s->face->font;
4482 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
4484 /* For all glyphs of this composition, starting at the offset
4485 S->gidx, until we reach the end of the definition or encounter a
4486 glyph that requires the different face, add it to S. */
4487 ++s->nchars;
4488 for (i = s->gidx + 1; i < s->cmp->glyph_len && faces[i] == s->face; ++i)
4489 ++s->nchars;
4491 /* All glyph strings for the same composition has the same width,
4492 i.e. the width set for the first component of the composition. */
4494 s->width = s->first_glyph->pixel_width;
4496 /* If the specified font could not be loaded, use the frame's
4497 default font, but record the fact that we couldn't load it in
4498 the glyph string so that we can draw rectangles for the
4499 characters of the glyph string. */
4500 if (s->font == NULL)
4502 s->font_not_found_p = 1;
4503 s->font = FRAME_FONT (s->f);
4506 /* Adjust base line for subscript/superscript text. */
4507 s->ybase += s->first_glyph->voffset;
4509 xassert (s->face && s->face->gc);
4511 /* This glyph string must always be drawn with 16-bit functions. */
4512 s->two_byte_p = 1;
4514 return s->gidx + s->nchars;
4518 /* Fill glyph string S from a sequence of character glyphs.
4520 FACE_ID is the face id of the string. START is the index of the
4521 first glyph to consider, END is the index of the last + 1.
4522 OVERLAPS_P non-zero means S should draw the foreground only, and
4523 use its physical height for clipping.
4525 Value is the index of the first glyph not in S. */
4527 static int
4528 x_fill_glyph_string (s, face_id, start, end, overlaps_p)
4529 struct glyph_string *s;
4530 int face_id;
4531 int start, end, overlaps_p;
4533 struct glyph *glyph, *last;
4534 int voffset;
4535 int glyph_not_available_p;
4537 xassert (s->f == XFRAME (s->w->frame));
4538 xassert (s->nchars == 0);
4539 xassert (start >= 0 && end > start);
4541 s->for_overlaps_p = overlaps_p;
4542 glyph = s->row->glyphs[s->area] + start;
4543 last = s->row->glyphs[s->area] + end;
4544 voffset = glyph->voffset;
4546 glyph_not_available_p = glyph->glyph_not_available_p;
4548 while (glyph < last
4549 && glyph->type == CHAR_GLYPH
4550 && glyph->voffset == voffset
4551 /* Same face id implies same font, nowadays. */
4552 && glyph->face_id == face_id
4553 && glyph->glyph_not_available_p == glyph_not_available_p)
4555 int two_byte_p;
4557 s->face = x_get_glyph_face_and_encoding (s->f, glyph,
4558 s->char2b + s->nchars,
4559 &two_byte_p);
4560 s->two_byte_p = two_byte_p;
4561 ++s->nchars;
4562 xassert (s->nchars <= end - start);
4563 s->width += glyph->pixel_width;
4564 ++glyph;
4567 s->font = s->face->font;
4568 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
4570 /* If the specified font could not be loaded, use the frame's font,
4571 but record the fact that we couldn't load it in
4572 S->font_not_found_p so that we can draw rectangles for the
4573 characters of the glyph string. */
4574 if (s->font == NULL || glyph_not_available_p)
4576 s->font_not_found_p = 1;
4577 s->font = FRAME_FONT (s->f);
4580 /* Adjust base line for subscript/superscript text. */
4581 s->ybase += voffset;
4583 xassert (s->face && s->face->gc);
4584 return glyph - s->row->glyphs[s->area];
4588 /* Fill glyph string S from image glyph S->first_glyph. */
4590 static void
4591 x_fill_image_glyph_string (s)
4592 struct glyph_string *s;
4594 xassert (s->first_glyph->type == IMAGE_GLYPH);
4595 s->img = IMAGE_FROM_ID (s->f, s->first_glyph->u.img_id);
4596 xassert (s->img);
4597 s->face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
4598 s->font = s->face->font;
4599 s->width = s->first_glyph->pixel_width;
4601 /* Adjust base line for subscript/superscript text. */
4602 s->ybase += s->first_glyph->voffset;
4606 /* Fill glyph string S from a sequence of stretch glyphs.
4608 ROW is the glyph row in which the glyphs are found, AREA is the
4609 area within the row. START is the index of the first glyph to
4610 consider, END is the index of the last + 1.
4612 Value is the index of the first glyph not in S. */
4614 static int
4615 x_fill_stretch_glyph_string (s, row, area, start, end)
4616 struct glyph_string *s;
4617 struct glyph_row *row;
4618 enum glyph_row_area area;
4619 int start, end;
4621 struct glyph *glyph, *last;
4622 int voffset, face_id;
4624 xassert (s->first_glyph->type == STRETCH_GLYPH);
4626 glyph = s->row->glyphs[s->area] + start;
4627 last = s->row->glyphs[s->area] + end;
4628 face_id = glyph->face_id;
4629 s->face = FACE_FROM_ID (s->f, face_id);
4630 s->font = s->face->font;
4631 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
4632 s->width = glyph->pixel_width;
4633 voffset = glyph->voffset;
4635 for (++glyph;
4636 (glyph < last
4637 && glyph->type == STRETCH_GLYPH
4638 && glyph->voffset == voffset
4639 && glyph->face_id == face_id);
4640 ++glyph)
4641 s->width += glyph->pixel_width;
4643 /* Adjust base line for subscript/superscript text. */
4644 s->ybase += voffset;
4646 xassert (s->face);
4647 return glyph - s->row->glyphs[s->area];
4651 /* Initialize glyph string S. CHAR2B is a suitably allocated vector
4652 of XChar2b structures for S; it can't be allocated in
4653 x_init_glyph_string because it must be allocated via `alloca'. W
4654 is the window on which S is drawn. ROW and AREA are the glyph row
4655 and area within the row from which S is constructed. START is the
4656 index of the first glyph structure covered by S. HL is a
4657 face-override for drawing S. */
4659 static void
4660 w32_init_glyph_string (s, hdc, char2b, w, row, area, start, hl)
4661 struct glyph_string *s;
4662 HDC hdc;
4663 wchar_t *char2b;
4664 struct window *w;
4665 struct glyph_row *row;
4666 enum glyph_row_area area;
4667 int start;
4668 enum draw_glyphs_face hl;
4670 bzero (s, sizeof *s);
4671 s->w = w;
4672 s->f = XFRAME (w->frame);
4673 s->hdc = hdc;
4674 s->window = FRAME_W32_WINDOW (s->f);
4675 s->char2b = char2b;
4676 s->hl = hl;
4677 s->row = row;
4678 s->area = area;
4679 s->first_glyph = row->glyphs[area] + start;
4680 s->height = row->height;
4681 s->y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
4683 /* Display the internal border below the tool-bar window. */
4684 if (s->w == XWINDOW (s->f->tool_bar_window))
4685 s->y -= s->f->output_data.w32->internal_border_width;
4687 s->ybase = s->y + row->ascent;
4691 /* Set background width of glyph string S. START is the index of the
4692 first glyph following S. LAST_X is the right-most x-position + 1
4693 in the drawing area. */
4695 static INLINE void
4696 x_set_glyph_string_background_width (s, start, last_x)
4697 struct glyph_string *s;
4698 int start;
4699 int last_x;
4701 /* If the face of this glyph string has to be drawn to the end of
4702 the drawing area, set S->extends_to_end_of_line_p. */
4703 struct face *default_face = FACE_FROM_ID (s->f, DEFAULT_FACE_ID);
4705 if (start == s->row->used[s->area]
4706 && s->area == TEXT_AREA
4707 && ((s->hl == DRAW_NORMAL_TEXT
4708 && (s->row->fill_line_p
4709 || s->face->background != default_face->background
4710 || s->face->stipple != default_face->stipple
4711 || s->row->mouse_face_p))
4712 || s->hl == DRAW_MOUSE_FACE
4713 || ((s->hl == DRAW_IMAGE_RAISED || s->hl == DRAW_IMAGE_SUNKEN)
4714 && s->row->fill_line_p)))
4715 s->extends_to_end_of_line_p = 1;
4717 /* If S extends its face to the end of the line, set its
4718 background_width to the distance to the right edge of the drawing
4719 area. */
4720 if (s->extends_to_end_of_line_p)
4721 s->background_width = last_x - s->x + 1;
4722 else
4723 s->background_width = s->width;
4727 /* Add a glyph string for a stretch glyph to the list of strings
4728 between HEAD and TAIL. START is the index of the stretch glyph in
4729 row area AREA of glyph row ROW. END is the index of the last glyph
4730 in that glyph row area. X is the current output position assigned
4731 to the new glyph string constructed. HL overrides that face of the
4732 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
4733 is the right-most x-position of the drawing area. */
4735 #define BUILD_STRETCH_GLYPH_STRING(hdc, W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
4736 do \
4738 s = (struct glyph_string *) alloca (sizeof *s); \
4739 w32_init_glyph_string (s, hdc, NULL, W, ROW, AREA, START, HL); \
4740 START = x_fill_stretch_glyph_string (s, ROW, AREA, START, END); \
4741 x_append_glyph_string (&HEAD, &TAIL, s); \
4742 s->x = (X); \
4744 while (0)
4747 /* Add a glyph string for an image glyph to the list of strings
4748 between HEAD and TAIL. START is the index of the image glyph in
4749 row area AREA of glyph row ROW. END is the index of the last glyph
4750 in that glyph row area. X is the current output position assigned
4751 to the new glyph string constructed. HL overrides that face of the
4752 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
4753 is the right-most x-position of the drawing area. */
4755 #define BUILD_IMAGE_GLYPH_STRING(hdc, W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
4756 do \
4758 s = (struct glyph_string *) alloca (sizeof *s); \
4759 w32_init_glyph_string (s, hdc, NULL, W, ROW, AREA, START, HL); \
4760 x_fill_image_glyph_string (s); \
4761 x_append_glyph_string (&HEAD, &TAIL, s); \
4762 ++START; \
4763 s->x = (X); \
4765 while (0)
4768 /* Add a glyph string for a sequence of character glyphs to the list
4769 of strings between HEAD and TAIL. START is the index of the first
4770 glyph in row area AREA of glyph row ROW that is part of the new
4771 glyph string. END is the index of the last glyph in that glyph row
4772 area. X is the current output position assigned to the new glyph
4773 string constructed. HL overrides that face of the glyph; e.g. it
4774 is DRAW_CURSOR if a cursor has to be drawn. LAST_X is the
4775 right-most x-position of the drawing area. */
4777 #define BUILD_CHAR_GLYPH_STRINGS(hdc, W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
4778 do \
4780 int c, face_id; \
4781 wchar_t *char2b; \
4783 c = (ROW)->glyphs[AREA][START].u.ch; \
4784 face_id = (ROW)->glyphs[AREA][START].face_id; \
4786 s = (struct glyph_string *) alloca (sizeof *s); \
4787 char2b = (wchar_t *) alloca ((END - START) * sizeof *char2b); \
4788 w32_init_glyph_string (s, hdc, char2b, W, ROW, AREA, START, HL); \
4789 x_append_glyph_string (&HEAD, &TAIL, s); \
4790 s->x = (X); \
4791 START = x_fill_glyph_string (s, face_id, START, END, \
4792 OVERLAPS_P); \
4794 while (0)
4797 /* Add a glyph string for a composite sequence to the list of strings
4798 between HEAD and TAIL. START is the index of the first glyph in
4799 row area AREA of glyph row ROW that is part of the new glyph
4800 string. END is the index of the last glyph in that glyph row area.
4801 X is the current output position assigned to the new glyph string
4802 constructed. HL overrides that face of the glyph; e.g. it is
4803 DRAW_CURSOR if a cursor has to be drawn. LAST_X is the right-most
4804 x-position of the drawing area. */
4806 #define BUILD_COMPOSITE_GLYPH_STRING(hdc, W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
4807 do { \
4808 int cmp_id = (ROW)->glyphs[AREA][START].u.cmp_id; \
4809 int face_id = (ROW)->glyphs[AREA][START].face_id; \
4810 struct face *base_face = FACE_FROM_ID (XFRAME (w->frame), face_id); \
4811 struct composition *cmp = composition_table[cmp_id]; \
4812 int glyph_len = cmp->glyph_len; \
4813 wchar_t *char2b; \
4814 struct face **faces; \
4815 struct glyph_string *first_s = NULL; \
4816 int n; \
4818 base_face = base_face->ascii_face; \
4819 char2b = (wchar_t *) alloca ((sizeof *char2b) * glyph_len); \
4820 faces = (struct face **) alloca ((sizeof *faces) * glyph_len); \
4821 /* At first, fill in `char2b' and `faces'. */ \
4822 for (n = 0; n < glyph_len; n++) \
4824 int c = COMPOSITION_GLYPH (cmp, n); \
4825 int this_face_id = FACE_FOR_CHAR (XFRAME (w->frame), base_face, c); \
4826 faces[n] = FACE_FROM_ID (XFRAME (w->frame), this_face_id); \
4827 x_get_char_face_and_encoding (XFRAME (w->frame), c, \
4828 this_face_id, char2b + n, 1); \
4831 /* Make glyph_strings for each glyph sequence that is drawable by \
4832 the same face, and append them to HEAD/TAIL. */ \
4833 for (n = 0; n < cmp->glyph_len;) \
4835 s = (struct glyph_string *) alloca (sizeof *s); \
4836 w32_init_glyph_string (s, hdc, char2b + n, W, ROW, AREA, START, HL); \
4837 x_append_glyph_string (&(HEAD), &(TAIL), s); \
4838 s->cmp = cmp; \
4839 s->gidx = n; \
4840 s->x = (X); \
4842 if (n == 0) \
4843 first_s = s; \
4845 n = x_fill_composite_glyph_string (s, faces, OVERLAPS_P); \
4848 ++START; \
4849 s = first_s; \
4850 } while (0)
4853 /* Build a list of glyph strings between HEAD and TAIL for the glyphs
4854 of AREA of glyph row ROW on window W between indices START and END.
4855 HL overrides the face for drawing glyph strings, e.g. it is
4856 DRAW_CURSOR to draw a cursor. X and LAST_X are start and end
4857 x-positions of the drawing area.
4859 This is an ugly monster macro construct because we must use alloca
4860 to allocate glyph strings (because x_draw_glyphs can be called
4861 asynchronously). */
4863 #define BUILD_GLYPH_STRINGS(hdc, W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
4864 do \
4866 HEAD = TAIL = NULL; \
4867 while (START < END) \
4869 struct glyph *first_glyph = (ROW)->glyphs[AREA] + START; \
4870 switch (first_glyph->type) \
4872 case CHAR_GLYPH: \
4873 BUILD_CHAR_GLYPH_STRINGS (hdc, W, ROW, AREA, START, END, \
4874 HEAD, TAIL, HL, X, LAST_X, \
4875 OVERLAPS_P); \
4876 break; \
4878 case COMPOSITE_GLYPH: \
4879 BUILD_COMPOSITE_GLYPH_STRING (hdc, W, ROW, AREA, START, \
4880 END, HEAD, TAIL, HL, X, \
4881 LAST_X, OVERLAPS_P); \
4882 break; \
4884 case STRETCH_GLYPH: \
4885 BUILD_STRETCH_GLYPH_STRING (hdc, W, ROW, AREA, START, END,\
4886 HEAD, TAIL, HL, X, LAST_X); \
4887 break; \
4889 case IMAGE_GLYPH: \
4890 BUILD_IMAGE_GLYPH_STRING (hdc, W, ROW, AREA, START, END, \
4891 HEAD, TAIL, HL, X, LAST_X); \
4892 break; \
4894 default: \
4895 abort (); \
4898 x_set_glyph_string_background_width (s, START, LAST_X); \
4899 (X) += s->width; \
4902 while (0)
4905 /* Draw glyphs between START and END in AREA of ROW on window W,
4906 starting at x-position X. X is relative to AREA in W. HL is a
4907 face-override with the following meaning:
4909 DRAW_NORMAL_TEXT draw normally
4910 DRAW_CURSOR draw in cursor face
4911 DRAW_MOUSE_FACE draw in mouse face.
4912 DRAW_INVERSE_VIDEO draw in mode line face
4913 DRAW_IMAGE_SUNKEN draw an image with a sunken relief around it
4914 DRAW_IMAGE_RAISED draw an image with a raised relief around it
4916 If OVERLAPS_P is non-zero, draw only the foreground of characters
4917 and clip to the physical height of ROW.
4919 Value is the x-position reached, relative to AREA of W. */
4921 static int
4922 x_draw_glyphs (w, x, row, area, start, end, hl, overlaps_p)
4923 struct window *w;
4924 int x;
4925 struct glyph_row *row;
4926 enum glyph_row_area area;
4927 int start, end;
4928 enum draw_glyphs_face hl;
4929 int overlaps_p;
4931 struct glyph_string *head, *tail;
4932 struct glyph_string *s;
4933 int last_x, area_width;
4934 int x_reached;
4935 int i, j;
4936 HDC hdc = get_frame_dc (XFRAME (WINDOW_FRAME (w)));
4938 /* Let's rather be paranoid than getting a SEGV. */
4939 end = min (end, row->used[area]);
4940 start = max (0, start);
4941 start = min (end, start);
4943 /* Translate X to frame coordinates. Set last_x to the right
4944 end of the drawing area. */
4945 if (row->full_width_p)
4947 /* X is relative to the left edge of W, without scroll bars
4948 or fringes. */
4949 struct frame *f = XFRAME (WINDOW_FRAME (w));
4950 int window_left_x = WINDOW_LEFT_MARGIN (w) * CANON_X_UNIT (f);
4952 x += window_left_x;
4953 area_width = XFASTINT (w->width) * CANON_X_UNIT (f);
4954 last_x = window_left_x + area_width;
4956 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
4958 int width = FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
4959 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
4960 last_x += width;
4961 else
4962 x -= width;
4965 x += FRAME_INTERNAL_BORDER_WIDTH (f);
4966 last_x -= FRAME_INTERNAL_BORDER_WIDTH (f);
4968 else
4970 x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, x);
4971 area_width = window_box_width (w, area);
4972 last_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, area_width);
4975 /* Build a doubly-linked list of glyph_string structures between
4976 head and tail from what we have to draw. Note that the macro
4977 BUILD_GLYPH_STRINGS will modify its start parameter. That's
4978 the reason we use a separate variable `i'. */
4979 i = start;
4980 BUILD_GLYPH_STRINGS (hdc, w, row, area, i, end, head, tail, hl, x, last_x,
4981 overlaps_p);
4982 if (tail)
4983 x_reached = tail->x + tail->background_width;
4984 else
4985 x_reached = x;
4987 /* If there are any glyphs with lbearing < 0 or rbearing > width in
4988 the row, redraw some glyphs in front or following the glyph
4989 strings built above. */
4990 if (head && !overlaps_p && row->contains_overlapping_glyphs_p)
4992 int dummy_x = 0;
4993 struct glyph_string *h, *t;
4995 /* Compute overhangs for all glyph strings. */
4996 for (s = head; s; s = s->next)
4997 x_compute_glyph_string_overhangs (s);
4999 /* Prepend glyph strings for glyphs in front of the first glyph
5000 string that are overwritten because of the first glyph
5001 string's left overhang. The background of all strings
5002 prepended must be drawn because the first glyph string
5003 draws over it. */
5004 i = x_left_overwritten (head);
5005 if (i >= 0)
5007 j = i;
5008 BUILD_GLYPH_STRINGS (hdc, w, row, area, j, start, h, t,
5009 DRAW_NORMAL_TEXT, dummy_x, last_x,
5010 overlaps_p);
5011 start = i;
5012 x_compute_overhangs_and_x (t, head->x, 1);
5013 x_prepend_glyph_string_lists (&head, &tail, h, t);
5016 /* Prepend glyph strings for glyphs in front of the first glyph
5017 string that overwrite that glyph string because of their
5018 right overhang. For these strings, only the foreground must
5019 be drawn, because it draws over the glyph string at `head'.
5020 The background must not be drawn because this would overwrite
5021 right overhangs of preceding glyphs for which no glyph
5022 strings exist. */
5023 i = x_left_overwriting (head);
5024 if (i >= 0)
5026 BUILD_GLYPH_STRINGS (hdc, w, row, area, i, start, h, t,
5027 DRAW_NORMAL_TEXT, dummy_x, last_x,
5028 overlaps_p);
5029 for (s = h; s; s = s->next)
5030 s->background_filled_p = 1;
5031 x_compute_overhangs_and_x (t, head->x, 1);
5032 x_prepend_glyph_string_lists (&head, &tail, h, t);
5035 /* Append glyphs strings for glyphs following the last glyph
5036 string tail that are overwritten by tail. The background of
5037 these strings has to be drawn because tail's foreground draws
5038 over it. */
5039 i = x_right_overwritten (tail);
5040 if (i >= 0)
5042 BUILD_GLYPH_STRINGS (hdc, w, row, area, end, i, h, t,
5043 DRAW_NORMAL_TEXT, x, last_x,
5044 overlaps_p);
5045 x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
5046 x_append_glyph_string_lists (&head, &tail, h, t);
5049 /* Append glyph strings for glyphs following the last glyph
5050 string tail that overwrite tail. The foreground of such
5051 glyphs has to be drawn because it writes into the background
5052 of tail. The background must not be drawn because it could
5053 paint over the foreground of following glyphs. */
5054 i = x_right_overwriting (tail);
5055 if (i >= 0)
5057 BUILD_GLYPH_STRINGS (hdc, w, row, area, end, i, h, t,
5058 DRAW_NORMAL_TEXT, x, last_x,
5059 overlaps_p);
5060 for (s = h; s; s = s->next)
5061 s->background_filled_p = 1;
5062 x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
5063 x_append_glyph_string_lists (&head, &tail, h, t);
5067 /* Draw all strings. */
5068 for (s = head; s; s = s->next)
5069 x_draw_glyph_string (s);
5071 if (area == TEXT_AREA
5072 && !row->full_width_p
5073 /* When drawing overlapping rows, only the glyph strings'
5074 foreground is drawn, which doesn't erase a cursor
5075 completely. */
5076 && !overlaps_p)
5078 int x0 = head ? head->x : x;
5079 int x1 = tail ? tail->x + tail->background_width : x;
5081 x0 = FRAME_TO_WINDOW_PIXEL_X (w, x0);
5082 x1 = FRAME_TO_WINDOW_PIXEL_X (w, x1);
5084 if (!row->full_width_p && XFASTINT (w->left_margin_width) != 0)
5086 int left_area_width = window_box_width (w, LEFT_MARGIN_AREA);
5087 x0 -= left_area_width;
5088 x1 -= left_area_width;
5091 notice_overwritten_cursor (w, area, x0, x1,
5092 row->y, MATRIX_ROW_BOTTOM_Y (row));
5095 /* Value is the x-position up to which drawn, relative to AREA of W.
5096 This doesn't include parts drawn because of overhangs. */
5097 x_reached = FRAME_TO_WINDOW_PIXEL_X (w, x_reached);
5098 if (!row->full_width_p)
5100 if (area > LEFT_MARGIN_AREA)
5101 x_reached -= window_box_width (w, LEFT_MARGIN_AREA);
5102 if (area > TEXT_AREA)
5103 x_reached -= window_box_width (w, TEXT_AREA);
5106 release_frame_dc (XFRAME (WINDOW_FRAME (w)), hdc);
5108 return x_reached;
5112 /* Fix the display of area AREA of overlapping row ROW in window W. */
5114 static void
5115 x_fix_overlapping_area (w, row, area)
5116 struct window *w;
5117 struct glyph_row *row;
5118 enum glyph_row_area area;
5120 int i, x;
5122 BLOCK_INPUT;
5124 if (area == LEFT_MARGIN_AREA)
5125 x = 0;
5126 else if (area == TEXT_AREA)
5127 x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
5128 else
5129 x = (window_box_width (w, LEFT_MARGIN_AREA)
5130 + window_box_width (w, TEXT_AREA));
5132 for (i = 0; i < row->used[area];)
5134 if (row->glyphs[area][i].overlaps_vertically_p)
5136 int start = i, start_x = x;
5140 x += row->glyphs[area][i].pixel_width;
5141 ++i;
5143 while (i < row->used[area]
5144 && row->glyphs[area][i].overlaps_vertically_p);
5146 x_draw_glyphs (w, start_x, row, area, start, i,
5147 DRAW_NORMAL_TEXT, 1);
5149 else
5151 x += row->glyphs[area][i].pixel_width;
5152 ++i;
5156 UNBLOCK_INPUT;
5160 /* Output LEN glyphs starting at START at the nominal cursor position.
5161 Advance the nominal cursor over the text. The global variable
5162 updated_window contains the window being updated, updated_row is
5163 the glyph row being updated, and updated_area is the area of that
5164 row being updated. */
5166 static void
5167 x_write_glyphs (start, len)
5168 struct glyph *start;
5169 int len;
5171 int x, hpos;
5173 xassert (updated_window && updated_row);
5174 BLOCK_INPUT;
5176 /* Write glyphs. */
5178 hpos = start - updated_row->glyphs[updated_area];
5179 x = x_draw_glyphs (updated_window, output_cursor.x,
5180 updated_row, updated_area,
5181 hpos, hpos + len,
5182 DRAW_NORMAL_TEXT, 0);
5184 UNBLOCK_INPUT;
5186 /* Advance the output cursor. */
5187 output_cursor.hpos += len;
5188 output_cursor.x = x;
5192 /* Insert LEN glyphs from START at the nominal cursor position. */
5194 static void
5195 x_insert_glyphs (start, len)
5196 struct glyph *start;
5197 register int len;
5199 struct frame *f;
5200 struct window *w;
5201 int line_height, shift_by_width, shifted_region_width;
5202 struct glyph_row *row;
5203 struct glyph *glyph;
5204 int frame_x, frame_y, hpos;
5205 HDC hdc;
5207 xassert (updated_window && updated_row);
5208 BLOCK_INPUT;
5209 w = updated_window;
5210 f = XFRAME (WINDOW_FRAME (w));
5211 hdc = get_frame_dc (f);
5213 /* Get the height of the line we are in. */
5214 row = updated_row;
5215 line_height = row->height;
5217 /* Get the width of the glyphs to insert. */
5218 shift_by_width = 0;
5219 for (glyph = start; glyph < start + len; ++glyph)
5220 shift_by_width += glyph->pixel_width;
5222 /* Get the width of the region to shift right. */
5223 shifted_region_width = (window_box_width (w, updated_area)
5224 - output_cursor.x
5225 - shift_by_width);
5227 /* Shift right. */
5228 frame_x = window_box_left (w, updated_area) + output_cursor.x;
5229 frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, output_cursor.y);
5230 BitBlt (hdc, frame_x + shift_by_width, frame_y,
5231 shifted_region_width, line_height,
5232 hdc, frame_x, frame_y, SRCCOPY);
5234 /* Write the glyphs. */
5235 hpos = start - row->glyphs[updated_area];
5236 x_draw_glyphs (w, output_cursor.x, row, updated_area, hpos, hpos + len,
5237 DRAW_NORMAL_TEXT, 0);
5239 /* Advance the output cursor. */
5240 output_cursor.hpos += len;
5241 output_cursor.x += shift_by_width;
5242 release_frame_dc (f, hdc);
5244 UNBLOCK_INPUT;
5248 /* Delete N glyphs at the nominal cursor position. Not implemented
5249 for X frames. */
5251 static void
5252 x_delete_glyphs (n)
5253 register int n;
5255 struct frame *f;
5257 if (updating_frame)
5258 f = updating_frame;
5259 else
5260 f = SELECTED_FRAME ();
5262 if (! FRAME_W32_P (f))
5263 return;
5265 abort ();
5269 /* Erase the current text line from the nominal cursor position
5270 (inclusive) to pixel column TO_X (exclusive). The idea is that
5271 everything from TO_X onward is already erased.
5273 TO_X is a pixel position relative to updated_area of
5274 updated_window. TO_X == -1 means clear to the end of this area. */
5276 static void
5277 x_clear_end_of_line (to_x)
5278 int to_x;
5280 struct frame *f;
5281 struct window *w = updated_window;
5282 int max_x, min_y, max_y;
5283 int from_x, from_y, to_y;
5285 xassert (updated_window && updated_row);
5286 f = XFRAME (w->frame);
5288 if (updated_row->full_width_p)
5290 max_x = XFASTINT (w->width) * CANON_X_UNIT (f);
5291 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f)
5292 && !w->pseudo_window_p)
5293 max_x += FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
5295 else
5296 max_x = window_box_width (w, updated_area);
5297 max_y = window_text_bottom_y (w);
5299 /* TO_X == 0 means don't do anything. TO_X < 0 means clear to end
5300 of window. For TO_X > 0, truncate to end of drawing area. */
5301 if (to_x == 0)
5302 return;
5303 else if (to_x < 0)
5304 to_x = max_x;
5305 else
5306 to_x = min (to_x, max_x);
5308 to_y = min (max_y, output_cursor.y + updated_row->height);
5310 /* Notice if the cursor will be cleared by this operation. */
5311 if (!updated_row->full_width_p)
5312 notice_overwritten_cursor (w, updated_area,
5313 output_cursor.x, -1,
5314 updated_row->y,
5315 MATRIX_ROW_BOTTOM_Y (updated_row));
5317 from_x = output_cursor.x;
5319 /* Translate to frame coordinates. */
5320 if (updated_row->full_width_p)
5322 from_x = WINDOW_TO_FRAME_PIXEL_X (w, from_x);
5323 to_x = WINDOW_TO_FRAME_PIXEL_X (w, to_x);
5325 else
5327 from_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, from_x);
5328 to_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, to_x);
5331 min_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
5332 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, max (min_y, output_cursor.y));
5333 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, to_y);
5335 /* Prevent inadvertently clearing to end of the X window. */
5336 if (to_x > from_x && to_y > from_y)
5338 HDC hdc;
5339 BLOCK_INPUT;
5340 hdc = get_frame_dc (f);
5342 w32_clear_area (f, hdc, from_x, from_y, to_x - from_x, to_y - from_y);
5343 release_frame_dc (f, hdc);
5344 UNBLOCK_INPUT;
5349 /* Clear entire frame. If updating_frame is non-null, clear that
5350 frame. Otherwise clear the selected frame. */
5352 static void
5353 x_clear_frame ()
5355 struct frame *f;
5357 if (updating_frame)
5358 f = updating_frame;
5359 else
5360 f = SELECTED_FRAME ();
5362 if (! FRAME_W32_P (f))
5363 return;
5365 /* Clearing the frame will erase any cursor, so mark them all as no
5366 longer visible. */
5367 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
5368 output_cursor.hpos = output_cursor.vpos = 0;
5369 output_cursor.x = -1;
5371 /* We don't set the output cursor here because there will always
5372 follow an explicit cursor_to. */
5373 BLOCK_INPUT;
5375 w32_clear_window (f);
5377 /* We have to clear the scroll bars, too. If we have changed
5378 colors or something like that, then they should be notified. */
5379 x_scroll_bar_clear (f);
5381 UNBLOCK_INPUT;
5385 /* Make audible bell. */
5387 static void
5388 w32_ring_bell (void)
5390 struct frame *f;
5392 f = SELECTED_FRAME ();
5394 BLOCK_INPUT;
5396 if (FRAME_W32_P (f) && visible_bell)
5398 int i;
5399 HWND hwnd = FRAME_W32_WINDOW (SELECTED_FRAME ());
5401 for (i = 0; i < 5; i++)
5403 FlashWindow (hwnd, TRUE);
5404 Sleep (10);
5406 FlashWindow (hwnd, FALSE);
5408 else
5409 w32_sys_ring_bell ();
5411 UNBLOCK_INPUT;
5415 /* Specify how many text lines, from the top of the window,
5416 should be affected by insert-lines and delete-lines operations.
5417 This, and those operations, are used only within an update
5418 that is bounded by calls to x_update_begin and x_update_end. */
5420 static void
5421 w32_set_terminal_window (n)
5422 register int n;
5424 /* This function intentionally left blank. */
5429 /***********************************************************************
5430 Line Dance
5431 ***********************************************************************/
5433 /* Perform an insert-lines or delete-lines operation, inserting N
5434 lines or deleting -N lines at vertical position VPOS. */
5436 static void
5437 x_ins_del_lines (vpos, n)
5438 int vpos, n;
5440 struct frame *f;
5442 if (updating_frame)
5443 f = updating_frame;
5444 else
5445 f = SELECTED_FRAME ();
5447 if (! FRAME_W32_P (f))
5448 return;
5450 abort ();
5454 /* Scroll part of the display as described by RUN. */
5456 static void
5457 x_scroll_run (w, run)
5458 struct window *w;
5459 struct run *run;
5461 struct frame *f = XFRAME (w->frame);
5462 int x, y, width, height, from_y, to_y, bottom_y;
5463 HWND hwnd = FRAME_W32_WINDOW (f);
5464 HRGN expect_dirty;
5466 /* Get frame-relative bounding box of the text display area of W,
5467 without mode lines. Include in this box the left and right
5468 fringes of W. */
5469 window_box (w, -1, &x, &y, &width, &height);
5470 width += FRAME_X_FRINGE_WIDTH (f);
5471 x -= FRAME_X_LEFT_FRINGE_WIDTH (f);
5473 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
5474 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
5475 bottom_y = y + height;
5477 if (to_y < from_y)
5479 /* Scrolling up. Make sure we don't copy part of the mode
5480 line at the bottom. */
5481 if (from_y + run->height > bottom_y)
5482 height = bottom_y - from_y;
5483 else
5484 height = run->height;
5485 expect_dirty = CreateRectRgn (x, y + height, x + width, bottom_y);
5487 else
5489 /* Scolling down. Make sure we don't copy over the mode line.
5490 at the bottom. */
5491 if (to_y + run->height > bottom_y)
5492 height = bottom_y - to_y;
5493 else
5494 height = run->height;
5495 expect_dirty = CreateRectRgn (x, y, x + width, to_y);
5498 BLOCK_INPUT;
5500 /* Cursor off. Will be switched on again in x_update_window_end. */
5501 updated_window = w;
5502 x_clear_cursor (w);
5505 RECT from;
5506 RECT to;
5507 HRGN dirty = CreateRectRgn (0, 0, 0, 0);
5508 HRGN combined = CreateRectRgn (0, 0, 0, 0);
5510 from.left = to.left = x;
5511 from.right = to.right = x + width;
5512 from.top = from_y;
5513 from.bottom = from_y + height;
5514 to.top = y;
5515 to.bottom = bottom_y;
5517 ScrollWindowEx (hwnd, 0, to_y - from_y, &from, &to, dirty,
5518 NULL, SW_INVALIDATE);
5520 /* Combine this with what we expect to be dirty. This covers the
5521 case where not all of the region we expect is actually dirty. */
5522 CombineRgn (combined, dirty, expect_dirty, RGN_OR);
5524 /* If the dirty region is not what we expected, redraw the entire frame. */
5525 if (!EqualRgn (combined, expect_dirty))
5526 SET_FRAME_GARBAGED (f);
5529 UNBLOCK_INPUT;
5534 /***********************************************************************
5535 Exposure Events
5536 ***********************************************************************/
5538 /* Redisplay an exposed area of frame F. X and Y are the upper-left
5539 corner of the exposed rectangle. W and H are width and height of
5540 the exposed area. All are pixel values. W or H zero means redraw
5541 the entire frame. */
5543 static void
5544 expose_frame (f, x, y, w, h)
5545 struct frame *f;
5546 int x, y, w, h;
5548 RECT r;
5549 int mouse_face_overwritten_p = 0;
5551 TRACE ((stderr, "expose_frame "));
5553 /* No need to redraw if frame will be redrawn soon. */
5554 if (FRAME_GARBAGED_P (f))
5556 TRACE ((stderr, " garbaged\n"));
5557 return;
5560 /* If basic faces haven't been realized yet, there is no point in
5561 trying to redraw anything. This can happen when we get an expose
5562 event while Emacs is starting, e.g. by moving another window. */
5563 if (FRAME_FACE_CACHE (f) == NULL
5564 || FRAME_FACE_CACHE (f)->used < BASIC_FACE_ID_SENTINEL)
5566 TRACE ((stderr, " no faces\n"));
5567 return;
5570 if (w == 0 || h == 0)
5572 r.left = r.top = 0;
5573 r.right = CANON_X_UNIT (f) * f->width;
5574 r.bottom = CANON_Y_UNIT (f) * f->height;
5576 else
5578 r.left = x;
5579 r.top = y;
5580 r.right = x + w;
5581 r.bottom = y + h;
5584 TRACE ((stderr, "(%d, %d, %d, %d)\n", r.left, r.top, r.right, r.bottom));
5585 mouse_face_overwritten_p = expose_window_tree (XWINDOW (f->root_window), &r);
5587 if (WINDOWP (f->tool_bar_window))
5588 mouse_face_overwritten_p
5589 |= expose_window (XWINDOW (f->tool_bar_window), &r);
5591 /* Some window managers support a focus-follows-mouse style with
5592 delayed raising of frames. Imagine a partially obscured frame,
5593 and moving the mouse into partially obscured mouse-face on that
5594 frame. The visible part of the mouse-face will be highlighted,
5595 then the WM raises the obscured frame. With at least one WM, KDE
5596 2.1, Emacs is not getting any event for the raising of the frame
5597 (even tried with SubstructureRedirectMask), only Expose events.
5598 These expose events will draw text normally, i.e. not
5599 highlighted. Which means we must redo the highlight here.
5600 Subsume it under ``we love X''. --gerd 2001-08-15 */
5601 /* Included in Windows version because Windows most likely does not
5602 do the right thing if any third party tool offers
5603 focus-follows-mouse with delayed raise. --jason 2001-10-12 */
5604 if (mouse_face_overwritten_p && !FRAME_GARBAGED_P (f))
5606 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
5607 if (f == dpyinfo->mouse_face_mouse_frame)
5609 int x = dpyinfo->mouse_face_mouse_x;
5610 int y = dpyinfo->mouse_face_mouse_y;
5611 clear_mouse_face (dpyinfo);
5612 note_mouse_highlight (f, x, y);
5618 /* Redraw (parts) of all windows in the window tree rooted at W that
5619 intersect R. R contains frame pixel coordinates. */
5621 static int
5622 expose_window_tree (w, r)
5623 struct window *w;
5624 RECT *r;
5626 struct frame *f = XFRAME (w->frame);
5627 int mouse_face_overwritten_p = 0;
5629 while (w && !FRAME_GARBAGED_P (f))
5631 if (!NILP (w->hchild))
5632 mouse_face_overwritten_p
5633 |= expose_window_tree (XWINDOW (w->hchild), r);
5634 else if (!NILP (w->vchild))
5635 mouse_face_overwritten_p
5636 |= expose_window_tree (XWINDOW (w->vchild), r);
5637 else
5638 mouse_face_overwritten_p |= expose_window (w, r);
5640 w = NILP (w->next) ? NULL : XWINDOW (w->next);
5643 return mouse_face_overwritten_p;
5647 /* Redraw the part of glyph row area AREA of glyph row ROW on window W
5648 which intersects rectangle R. R is in window-relative coordinates. */
5650 static void
5651 expose_area (w, row, r, area)
5652 struct window *w;
5653 struct glyph_row *row;
5654 RECT *r;
5655 enum glyph_row_area area;
5657 struct glyph *first = row->glyphs[area];
5658 struct glyph *end = row->glyphs[area] + row->used[area];
5659 struct glyph *last;
5660 int first_x, start_x, x;
5662 if (area == TEXT_AREA && row->fill_line_p)
5663 /* If row extends face to end of line write the whole line. */
5664 x_draw_glyphs (w, 0, row, area,
5665 0, row->used[area],
5666 DRAW_NORMAL_TEXT, 0);
5667 else
5669 /* Set START_X to the window-relative start position for drawing glyphs of
5670 AREA. The first glyph of the text area can be partially visible.
5671 The first glyphs of other areas cannot. */
5672 if (area == LEFT_MARGIN_AREA)
5673 start_x = 0;
5674 else if (area == TEXT_AREA)
5675 start_x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
5676 else
5677 start_x = (window_box_width (w, LEFT_MARGIN_AREA)
5678 + window_box_width (w, TEXT_AREA));
5679 x = start_x;
5681 /* Find the first glyph that must be redrawn. */
5682 while (first < end
5683 && x + first->pixel_width < r->left)
5685 x += first->pixel_width;
5686 ++first;
5689 /* Find the last one. */
5690 last = first;
5691 first_x = x;
5692 while (last < end
5693 && x < r->right)
5695 x += last->pixel_width;
5696 ++last;
5699 /* Repaint. */
5700 if (last > first)
5701 x_draw_glyphs (w, first_x - start_x, row, area,
5702 first - row->glyphs[area],
5703 last - row->glyphs[area],
5704 DRAW_NORMAL_TEXT, 0);
5709 /* Redraw the parts of the glyph row ROW on window W intersecting
5710 rectangle R. R is in window-relative coordinates. Value is
5711 non-zero if mouse face was overwritten. */
5713 static int
5714 expose_line (w, row, r)
5715 struct window *w;
5716 struct glyph_row *row;
5717 RECT *r;
5719 xassert (row->enabled_p);
5721 if (row->mode_line_p || w->pseudo_window_p)
5722 x_draw_glyphs (w, 0, row, TEXT_AREA, 0, row->used[TEXT_AREA],
5723 DRAW_NORMAL_TEXT, 0);
5724 else
5726 if (row->used[LEFT_MARGIN_AREA])
5727 expose_area (w, row, r, LEFT_MARGIN_AREA);
5728 if (row->used[TEXT_AREA])
5729 expose_area (w, row, r, TEXT_AREA);
5730 if (row->used[RIGHT_MARGIN_AREA])
5731 expose_area (w, row, r, RIGHT_MARGIN_AREA);
5732 x_draw_row_fringe_bitmaps (w, row);
5735 return row->mouse_face_p;
5739 /* Return non-zero if W's cursor intersects rectangle R. */
5741 static int
5742 x_phys_cursor_in_rect_p (w, r)
5743 struct window *w;
5744 RECT *r;
5746 RECT cr, result;
5747 struct glyph *cursor_glyph;
5749 cursor_glyph = get_phys_cursor_glyph (w);
5750 if (cursor_glyph)
5752 cr.left = w->phys_cursor.x;
5753 cr.top = w->phys_cursor.y;
5754 cr.right = cr.left + cursor_glyph->pixel_width;
5755 cr.bottom = cr.top + w->phys_cursor_height;
5756 return IntersectRect (&result, &cr, r);
5758 else
5759 return 0;
5763 /* Redraw those parts of glyphs rows during expose event handling that
5764 overlap other rows. Redrawing of an exposed line writes over parts
5765 of lines overlapping that exposed line; this function fixes that.
5767 W is the window being exposed. FIRST_OVERLAPPING_ROW is the first
5768 row in W's current matrix that is exposed and overlaps other rows.
5769 LAST_OVERLAPPING_ROW is the last such row. */
5771 static void
5772 expose_overlaps (w, first_overlapping_row, last_overlapping_row)
5773 struct window *w;
5774 struct glyph_row *first_overlapping_row;
5775 struct glyph_row *last_overlapping_row;
5777 struct glyph_row *row;
5779 for (row = first_overlapping_row; row <= last_overlapping_row; ++row)
5780 if (row->overlapping_p)
5782 xassert (row->enabled_p && !row->mode_line_p);
5784 if (row->used[LEFT_MARGIN_AREA])
5785 x_fix_overlapping_area (w, row, LEFT_MARGIN_AREA);
5787 if (row->used[TEXT_AREA])
5788 x_fix_overlapping_area (w, row, TEXT_AREA);
5790 if (row->used[RIGHT_MARGIN_AREA])
5791 x_fix_overlapping_area (w, row, RIGHT_MARGIN_AREA);
5796 /* Redraw the part of window W intersection rectagle FR. Pixel
5797 coordinates in FR are frame relative. Call this function with
5798 input blocked. Value is non-zero if the exposure overwrites
5799 mouse-face. */
5801 static int
5802 expose_window (w, fr)
5803 struct window *w;
5804 RECT *fr;
5806 struct frame *f = XFRAME (w->frame);
5807 RECT wr, r;
5808 int mouse_face_overwritten_p = 0;
5810 /* If window is not yet fully initialized, do nothing. This can
5811 happen when toolkit scroll bars are used and a window is split.
5812 Reconfiguring the scroll bar will generate an expose for a newly
5813 created window. */
5814 if (w->current_matrix == NULL)
5815 return 0;
5817 /* When we're currently updating the window, display and current
5818 matrix usually don't agree. Arrange for a thorough display
5819 later. */
5820 if (w == updated_window)
5822 SET_FRAME_GARBAGED (f);
5823 return 0;
5826 /* Frame-relative pixel rectangle of W. */
5827 wr.left = XFASTINT (w->left) * CANON_X_UNIT (f);
5828 wr.top = XFASTINT (w->top) * CANON_Y_UNIT (f);
5829 wr.right = wr.left + XFASTINT (w->width) * CANON_X_UNIT (f);
5830 wr.bottom = wr.top + XFASTINT (w->height) * CANON_Y_UNIT (f);
5832 if (IntersectRect(&r, fr, &wr))
5834 int yb = window_text_bottom_y (w);
5835 struct glyph_row *row;
5836 int cursor_cleared_p;
5837 struct glyph_row *first_overlapping_row, *last_overlapping_row;
5839 TRACE ((stderr, "expose_window (%d, %d, %d, %d)\n",
5840 r.left, r.top, r.right, r.bottom));
5842 /* Convert to window coordinates. */
5843 r.left = FRAME_TO_WINDOW_PIXEL_X (w, r.left);
5844 r.right = FRAME_TO_WINDOW_PIXEL_X (w, r.right);
5845 r.top = FRAME_TO_WINDOW_PIXEL_Y (w, r.top);
5846 r.bottom = FRAME_TO_WINDOW_PIXEL_Y (w, r.bottom);
5848 /* Turn off the cursor. */
5849 if (!w->pseudo_window_p
5850 && x_phys_cursor_in_rect_p (w, &r))
5852 x_clear_cursor (w);
5853 cursor_cleared_p = 1;
5855 else
5856 cursor_cleared_p = 0;
5858 /* Update lines intersecting rectangle R. */
5859 first_overlapping_row = last_overlapping_row = NULL;
5860 for (row = w->current_matrix->rows;
5861 row->enabled_p;
5862 ++row)
5864 int y0 = row->y;
5865 int y1 = MATRIX_ROW_BOTTOM_Y (row);
5867 if ((y0 >= r.top && y0 < r.bottom)
5868 || (y1 > r.top && y1 < r.bottom)
5869 || (r.top >= y0 && r.top < y1)
5870 || (r.bottom > y0 && r.bottom < y1))
5872 if (row->overlapping_p)
5874 if (first_overlapping_row == NULL)
5875 first_overlapping_row = row;
5876 last_overlapping_row = row;
5879 if (expose_line (w, row, &r))
5880 mouse_face_overwritten_p = 1;
5883 if (y1 >= yb)
5884 break;
5887 /* Display the mode line if there is one. */
5888 if (WINDOW_WANTS_MODELINE_P (w)
5889 && (row = MATRIX_MODE_LINE_ROW (w->current_matrix),
5890 row->enabled_p)
5891 && row->y < r.bottom)
5893 if (expose_line (w, row, &r))
5894 mouse_face_overwritten_p = 1;
5897 if (!w->pseudo_window_p)
5899 /* Fix the display of overlapping rows. */
5900 if (first_overlapping_row)
5901 expose_overlaps (w, first_overlapping_row, last_overlapping_row);
5903 /* Draw border between windows. */
5904 x_draw_vertical_border (w);
5906 /* Turn the cursor on again. */
5907 if (cursor_cleared_p)
5908 x_update_window_cursor (w, 1);
5912 return mouse_face_overwritten_p;
5916 static void
5917 frame_highlight (f)
5918 struct frame *f;
5920 x_update_cursor (f, 1);
5923 static void
5924 frame_unhighlight (f)
5925 struct frame *f;
5927 x_update_cursor (f, 1);
5930 /* The focus has changed. Update the frames as necessary to reflect
5931 the new situation. Note that we can't change the selected frame
5932 here, because the Lisp code we are interrupting might become confused.
5933 Each event gets marked with the frame in which it occurred, so the
5934 Lisp code can tell when the switch took place by examining the events. */
5936 static void
5937 x_new_focus_frame (dpyinfo, frame)
5938 struct w32_display_info *dpyinfo;
5939 struct frame *frame;
5941 struct frame *old_focus = dpyinfo->w32_focus_frame;
5943 if (frame != dpyinfo->w32_focus_frame)
5945 /* Set this before calling other routines, so that they see
5946 the correct value of w32_focus_frame. */
5947 dpyinfo->w32_focus_frame = frame;
5949 if (old_focus && old_focus->auto_lower)
5950 x_lower_frame (old_focus);
5952 if (dpyinfo->w32_focus_frame && dpyinfo->w32_focus_frame->auto_raise)
5953 pending_autoraise_frame = dpyinfo->w32_focus_frame;
5954 else
5955 pending_autoraise_frame = 0;
5958 x_frame_rehighlight (dpyinfo);
5961 /* Handle an event saying the mouse has moved out of an Emacs frame. */
5963 void
5964 x_mouse_leave (dpyinfo)
5965 struct w32_display_info *dpyinfo;
5967 x_new_focus_frame (dpyinfo, dpyinfo->w32_focus_event_frame);
5970 /* The focus has changed, or we have redirected a frame's focus to
5971 another frame (this happens when a frame uses a surrogate
5972 mini-buffer frame). Shift the highlight as appropriate.
5974 The FRAME argument doesn't necessarily have anything to do with which
5975 frame is being highlighted or un-highlighted; we only use it to find
5976 the appropriate X display info. */
5978 static void
5979 w32_frame_rehighlight (frame)
5980 struct frame *frame;
5982 if (! FRAME_W32_P (frame))
5983 return;
5984 x_frame_rehighlight (FRAME_W32_DISPLAY_INFO (frame));
5987 static void
5988 x_frame_rehighlight (dpyinfo)
5989 struct w32_display_info *dpyinfo;
5991 struct frame *old_highlight = dpyinfo->x_highlight_frame;
5993 if (dpyinfo->w32_focus_frame)
5995 dpyinfo->x_highlight_frame
5996 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->w32_focus_frame)))
5997 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->w32_focus_frame))
5998 : dpyinfo->w32_focus_frame);
5999 if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame))
6001 FRAME_FOCUS_FRAME (dpyinfo->w32_focus_frame) = Qnil;
6002 dpyinfo->x_highlight_frame = dpyinfo->w32_focus_frame;
6005 else
6006 dpyinfo->x_highlight_frame = 0;
6008 if (dpyinfo->x_highlight_frame != old_highlight)
6010 if (old_highlight)
6011 frame_unhighlight (old_highlight);
6012 if (dpyinfo->x_highlight_frame)
6013 frame_highlight (dpyinfo->x_highlight_frame);
6017 /* Keyboard processing - modifier keys, etc. */
6019 /* Convert a keysym to its name. */
6021 char *
6022 x_get_keysym_name (keysym)
6023 int keysym;
6025 /* Make static so we can always return it */
6026 static char value[100];
6028 BLOCK_INPUT;
6029 GetKeyNameText (keysym, value, 100);
6030 UNBLOCK_INPUT;
6032 return value;
6037 /* Mouse clicks and mouse movement. Rah. */
6039 /* Given a pixel position (PIX_X, PIX_Y) on frame F, return glyph
6040 co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle that the
6041 glyph at X, Y occupies, if BOUNDS != 0. If NOCLIP is non-zero, do
6042 not force the value into range. */
6044 void
6045 pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds, noclip)
6046 FRAME_PTR f;
6047 register int pix_x, pix_y;
6048 register int *x, *y;
6049 RECT *bounds;
6050 int noclip;
6052 /* Support tty mode: if Vwindow_system is nil, behave correctly. */
6053 if (NILP (Vwindow_system))
6055 *x = pix_x;
6056 *y = pix_y;
6057 return;
6060 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
6061 even for negative values. */
6062 if (pix_x < 0)
6063 pix_x -= FONT_WIDTH (FRAME_FONT (f)) - 1;
6064 if (pix_y < 0)
6065 pix_y -= (f)->output_data.w32->line_height - 1;
6067 pix_x = PIXEL_TO_CHAR_COL (f, pix_x);
6068 pix_y = PIXEL_TO_CHAR_ROW (f, pix_y);
6070 if (bounds)
6072 bounds->left = CHAR_TO_PIXEL_COL (f, pix_x);
6073 bounds->top = CHAR_TO_PIXEL_ROW (f, pix_y);
6074 bounds->right = bounds->left + FONT_WIDTH (FRAME_FONT (f)) - 1;
6075 bounds->bottom = bounds->top + f->output_data.w32->line_height - 1;
6078 if (!noclip)
6080 if (pix_x < 0)
6081 pix_x = 0;
6082 else if (pix_x > FRAME_WINDOW_WIDTH (f))
6083 pix_x = FRAME_WINDOW_WIDTH (f);
6085 if (pix_y < 0)
6086 pix_y = 0;
6087 else if (pix_y > f->height)
6088 pix_y = f->height;
6091 *x = pix_x;
6092 *y = pix_y;
6096 /* Given HPOS/VPOS in the current matrix of W, return corresponding
6097 frame-relative pixel positions in *FRAME_X and *FRAME_Y. If we
6098 can't tell the positions because W's display is not up to date,
6099 return 0. */
6102 glyph_to_pixel_coords (w, hpos, vpos, frame_x, frame_y)
6103 struct window *w;
6104 int hpos, vpos;
6105 int *frame_x, *frame_y;
6107 int success_p;
6109 xassert (hpos >= 0 && hpos < w->current_matrix->matrix_w);
6110 xassert (vpos >= 0 && vpos < w->current_matrix->matrix_h);
6112 if (display_completed)
6114 struct glyph_row *row = MATRIX_ROW (w->current_matrix, vpos);
6115 struct glyph *glyph = row->glyphs[TEXT_AREA];
6116 struct glyph *end = glyph + min (hpos, row->used[TEXT_AREA]);
6118 *frame_y = row->y;
6119 *frame_x = row->x;
6120 while (glyph < end)
6122 *frame_x += glyph->pixel_width;
6123 ++glyph;
6126 success_p = 1;
6128 else
6130 *frame_y = *frame_x = 0;
6131 success_p = 0;
6134 *frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, *frame_y);
6135 *frame_x = WINDOW_TO_FRAME_PIXEL_X (w, *frame_x);
6136 return success_p;
6139 /* Parse a button MESSAGE. The button index is returned in PBUTTON, and
6140 the state in PUP. XBUTTON provides extra information for extended mouse
6141 button messages. Returns FALSE if unable to parse the message. */
6142 BOOL
6143 parse_button (message, xbutton, pbutton, pup)
6144 int message;
6145 int xbutton;
6146 int * pbutton;
6147 int * pup;
6149 int button = 0;
6150 int up = 0;
6152 switch (message)
6154 case WM_LBUTTONDOWN:
6155 button = 0;
6156 up = 0;
6157 break;
6158 case WM_LBUTTONUP:
6159 button = 0;
6160 up = 1;
6161 break;
6162 case WM_MBUTTONDOWN:
6163 if (NILP (Vw32_swap_mouse_buttons))
6164 button = 1;
6165 else
6166 button = 2;
6167 up = 0;
6168 break;
6169 case WM_MBUTTONUP:
6170 if (NILP (Vw32_swap_mouse_buttons))
6171 button = 1;
6172 else
6173 button = 2;
6174 up = 1;
6175 break;
6176 case WM_RBUTTONDOWN:
6177 if (NILP (Vw32_swap_mouse_buttons))
6178 button = 2;
6179 else
6180 button = 1;
6181 up = 0;
6182 break;
6183 case WM_RBUTTONUP:
6184 if (NILP (Vw32_swap_mouse_buttons))
6185 button = 2;
6186 else
6187 button = 1;
6188 up = 1;
6189 break;
6190 case WM_XBUTTONDOWN:
6191 button = xbutton + 2;
6192 up = 0;
6193 break;
6194 case WM_XBUTTONUP:
6195 button = xbutton + 2;
6196 up = 1;
6197 break;
6198 default:
6199 return (FALSE);
6202 if (pup) *pup = up;
6203 if (pbutton) *pbutton = button;
6205 return (TRUE);
6209 /* Prepare a mouse-event in *RESULT for placement in the input queue.
6211 If the event is a button press, then note that we have grabbed
6212 the mouse. */
6214 static Lisp_Object
6215 construct_mouse_click (result, msg, f)
6216 struct input_event *result;
6217 W32Msg *msg;
6218 struct frame *f;
6220 int button;
6221 int up;
6223 parse_button (msg->msg.message, HIWORD (msg->msg.wParam),
6224 &button, &up);
6226 /* Make the event type NO_EVENT; we'll change that when we decide
6227 otherwise. */
6228 result->kind = MOUSE_CLICK_EVENT;
6229 result->code = button;
6230 result->timestamp = msg->msg.time;
6231 result->modifiers = (msg->dwModifiers
6232 | (up
6233 ? up_modifier
6234 : down_modifier));
6236 XSETINT (result->x, LOWORD (msg->msg.lParam));
6237 XSETINT (result->y, HIWORD (msg->msg.lParam));
6238 XSETFRAME (result->frame_or_window, f);
6239 result->arg = Qnil;
6240 return Qnil;
6243 static Lisp_Object
6244 construct_mouse_wheel (result, msg, f)
6245 struct input_event *result;
6246 W32Msg *msg;
6247 struct frame *f;
6249 POINT p;
6250 result->kind = MOUSE_WHEEL_EVENT;
6251 result->code = (short) HIWORD (msg->msg.wParam);
6252 result->timestamp = msg->msg.time;
6253 result->modifiers = msg->dwModifiers;
6254 p.x = LOWORD (msg->msg.lParam);
6255 p.y = HIWORD (msg->msg.lParam);
6256 ScreenToClient (msg->msg.hwnd, &p);
6257 XSETINT (result->x, p.x);
6258 XSETINT (result->y, p.y);
6259 XSETFRAME (result->frame_or_window, f);
6260 result->arg = Qnil;
6261 return Qnil;
6264 static Lisp_Object
6265 construct_drag_n_drop (result, msg, f)
6266 struct input_event *result;
6267 W32Msg *msg;
6268 struct frame *f;
6270 Lisp_Object files;
6271 Lisp_Object frame;
6272 HDROP hdrop;
6273 POINT p;
6274 WORD num_files;
6275 char *name;
6276 int i, len;
6278 result->kind = DRAG_N_DROP_EVENT;
6279 result->code = 0;
6280 result->timestamp = msg->msg.time;
6281 result->modifiers = msg->dwModifiers;
6283 hdrop = (HDROP) msg->msg.wParam;
6284 DragQueryPoint (hdrop, &p);
6286 #if 0
6287 p.x = LOWORD (msg->msg.lParam);
6288 p.y = HIWORD (msg->msg.lParam);
6289 ScreenToClient (msg->msg.hwnd, &p);
6290 #endif
6292 XSETINT (result->x, p.x);
6293 XSETINT (result->y, p.y);
6295 num_files = DragQueryFile (hdrop, 0xFFFFFFFF, NULL, 0);
6296 files = Qnil;
6298 for (i = 0; i < num_files; i++)
6300 len = DragQueryFile (hdrop, i, NULL, 0);
6301 if (len <= 0)
6302 continue;
6303 name = alloca (len + 1);
6304 DragQueryFile (hdrop, i, name, len + 1);
6305 files = Fcons (DECODE_FILE (build_string (name)), files);
6308 DragFinish (hdrop);
6310 XSETFRAME (frame, f);
6311 result->frame_or_window = Fcons (frame, files);
6312 result->arg = Qnil;
6313 return Qnil;
6317 /* Function to report a mouse movement to the mainstream Emacs code.
6318 The input handler calls this.
6320 We have received a mouse movement event, which is given in *event.
6321 If the mouse is over a different glyph than it was last time, tell
6322 the mainstream emacs code by setting mouse_moved. If not, ask for
6323 another motion event, so we can check again the next time it moves. */
6325 static MSG last_mouse_motion_event;
6326 static Lisp_Object last_mouse_motion_frame;
6328 static void remember_mouse_glyph P_ ((struct frame *, int, int));
6330 static void
6331 note_mouse_movement (frame, msg)
6332 FRAME_PTR frame;
6333 MSG *msg;
6335 int mouse_x = LOWORD (msg->lParam);
6336 int mouse_y = HIWORD (msg->lParam);
6338 last_mouse_movement_time = msg->time;
6339 memcpy (&last_mouse_motion_event, msg, sizeof (last_mouse_motion_event));
6340 XSETFRAME (last_mouse_motion_frame, frame);
6342 #if 0 /* Calling Lisp asynchronously is not safe. */
6343 if (mouse_autoselect_window)
6345 int area;
6346 Lisp_Object window;
6347 static Lisp_Object last_window;
6349 window = window_from_coordinates (frame, mouse_x, mouse_y, &area, 0);
6351 /* Window will be selected only when it is not selected now and
6352 last mouse movement event was not in it. Minibuffer window
6353 will be selected iff it is active. */
6354 if (!EQ (window, last_window)
6355 && !EQ (window, selected_window)
6356 && (!MINI_WINDOW_P (XWINDOW (window))
6357 || (EQ (window, minibuf_window) && minibuf_level > 0)))
6358 Fselect_window (window);
6360 last_window=window;
6362 #endif
6364 if (msg->hwnd != FRAME_W32_WINDOW (frame))
6366 frame->mouse_moved = 1;
6367 last_mouse_scroll_bar = Qnil;
6368 note_mouse_highlight (frame, -1, -1);
6371 /* Has the mouse moved off the glyph it was on at the last sighting? */
6372 else if (mouse_x < last_mouse_glyph.left
6373 || mouse_x > last_mouse_glyph.right
6374 || mouse_y < last_mouse_glyph.top
6375 || mouse_y > last_mouse_glyph.bottom)
6377 frame->mouse_moved = 1;
6378 last_mouse_scroll_bar = Qnil;
6379 note_mouse_highlight (frame, mouse_x, mouse_y);
6380 /* Remember the mouse position here, as w32_mouse_position only
6381 gets called when mouse tracking is enabled but we also need
6382 to keep track of the mouse for help_echo and highlighting at
6383 other times. */
6384 remember_mouse_glyph (frame, mouse_x, mouse_y);
6389 /************************************************************************
6390 Mouse Face
6391 ************************************************************************/
6393 /* Find the glyph under window-relative coordinates X/Y in window W.
6394 Consider only glyphs from buffer text, i.e. no glyphs from overlay
6395 strings. Return in *HPOS and *VPOS the row and column number of
6396 the glyph found. Return in *AREA the glyph area containing X.
6397 Value is a pointer to the glyph found or null if X/Y is not on
6398 text, or we can't tell because W's current matrix is not up to
6399 date. */
6401 static struct glyph *
6402 x_y_to_hpos_vpos (w, x, y, hpos, vpos, area, buffer_only_p)
6403 struct window *w;
6404 int x, y;
6405 int *hpos, *vpos, *area;
6406 int buffer_only_p;
6408 struct glyph *glyph, *end;
6409 struct glyph_row *row = NULL;
6410 int x0, i, left_area_width;
6412 /* Find row containing Y. Give up if some row is not enabled. */
6413 for (i = 0; i < w->current_matrix->nrows; ++i)
6415 row = MATRIX_ROW (w->current_matrix, i);
6416 if (!row->enabled_p)
6417 return NULL;
6418 if (y >= row->y && y < MATRIX_ROW_BOTTOM_Y (row))
6419 break;
6422 *vpos = i;
6423 *hpos = 0;
6425 /* Give up if Y is not in the window. */
6426 if (i == w->current_matrix->nrows)
6427 return NULL;
6429 /* Get the glyph area containing X. */
6430 if (w->pseudo_window_p)
6432 *area = TEXT_AREA;
6433 x0 = 0;
6435 else
6437 left_area_width = window_box_width (w, LEFT_MARGIN_AREA);
6438 if (x < left_area_width)
6440 *area = LEFT_MARGIN_AREA;
6441 x0 = 0;
6443 else if (x < left_area_width + window_box_width (w, TEXT_AREA))
6445 *area = TEXT_AREA;
6446 x0 = row->x + left_area_width;
6448 else
6450 *area = RIGHT_MARGIN_AREA;
6451 x0 = left_area_width + window_box_width (w, TEXT_AREA);
6455 /* Find glyph containing X. */
6456 glyph = row->glyphs[*area];
6457 end = glyph + row->used[*area];
6458 while (glyph < end)
6460 if (x < x0 + glyph->pixel_width)
6462 if (w->pseudo_window_p)
6463 break;
6464 else if (!buffer_only_p || BUFFERP (glyph->object))
6465 break;
6468 x0 += glyph->pixel_width;
6469 ++glyph;
6472 if (glyph == end)
6473 return NULL;
6475 *hpos = glyph - row->glyphs[*area];
6476 return glyph;
6480 /* Convert frame-relative x/y to coordinates relative to window W.
6481 Takes pseudo-windows into account. */
6483 static void
6484 frame_to_window_pixel_xy (w, x, y)
6485 struct window *w;
6486 int *x, *y;
6488 if (w->pseudo_window_p)
6490 /* A pseudo-window is always full-width, and starts at the
6491 left edge of the frame, plus a frame border. */
6492 struct frame *f = XFRAME (w->frame);
6493 *x -= FRAME_INTERNAL_BORDER_WIDTH_SAFE (f);
6494 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
6496 else
6498 *x = FRAME_TO_WINDOW_PIXEL_X (w, *x);
6499 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
6504 /* Take proper action when mouse has moved to the mode or header line of
6505 window W, x-position X. MODE_LINE_P non-zero means mouse is on the
6506 mode line. X is relative to the start of the text display area of
6507 W, so the width of fringes and scroll bars must be subtracted
6508 to get a position relative to the start of the mode line. */
6510 static void
6511 note_mode_line_highlight (w, x, mode_line_p)
6512 struct window *w;
6513 int x, mode_line_p;
6515 struct frame *f = XFRAME (w->frame);
6516 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
6517 Cursor cursor = dpyinfo->vertical_scroll_bar_cursor;
6518 struct glyph_row *row;
6520 if (mode_line_p)
6521 row = MATRIX_MODE_LINE_ROW (w->current_matrix);
6522 else
6523 row = MATRIX_HEADER_LINE_ROW (w->current_matrix);
6525 if (row->enabled_p)
6527 struct glyph *glyph, *end;
6528 Lisp_Object help, map;
6529 int x0;
6531 /* Find the glyph under X. */
6532 glyph = row->glyphs[TEXT_AREA];
6533 end = glyph + row->used[TEXT_AREA];
6534 x0 = - (FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f)
6535 + FRAME_X_LEFT_FRINGE_WIDTH (f));
6537 while (glyph < end
6538 && x >= x0 + glyph->pixel_width)
6540 x0 += glyph->pixel_width;
6541 ++glyph;
6544 if (glyph < end
6545 && STRINGP (glyph->object)
6546 && STRING_INTERVALS (glyph->object)
6547 && glyph->charpos >= 0
6548 && glyph->charpos < SCHARS (glyph->object))
6550 /* If we're on a string with `help-echo' text property,
6551 arrange for the help to be displayed. This is done by
6552 setting the global variable help_echo to the help string. */
6553 help = Fget_text_property (make_number (glyph->charpos),
6554 Qhelp_echo, glyph->object);
6555 if (!NILP (help))
6557 help_echo = help;
6558 XSETWINDOW (help_echo_window, w);
6559 help_echo_object = glyph->object;
6560 help_echo_pos = glyph->charpos;
6563 /* Change the mouse pointer according to what is under X/Y. */
6564 map = Fget_text_property (make_number (glyph->charpos),
6565 Qlocal_map, glyph->object);
6566 if (KEYMAPP (map))
6567 cursor = f->output_data.w32->nontext_cursor;
6568 else
6570 map = Fget_text_property (make_number (glyph->charpos),
6571 Qkeymap, glyph->object);
6572 if (KEYMAPP (map))
6573 cursor = f->output_data.w32->nontext_cursor;
6577 w32_define_cursor (FRAME_W32_WINDOW (f), cursor);
6581 /* Take proper action when the mouse has moved to position X, Y on
6582 frame F as regards highlighting characters that have mouse-face
6583 properties. Also de-highlighting chars where the mouse was before.
6584 X and Y can be negative or out of range. */
6586 static void
6587 note_mouse_highlight (f, x, y)
6588 struct frame *f;
6589 int x, y;
6591 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
6592 int portion;
6593 Lisp_Object window;
6594 struct window *w;
6595 Cursor cursor = 0;
6596 struct buffer *b;
6598 /* When a menu is active, don't highlight because this looks odd. */
6599 if (popup_activated ())
6600 return;
6602 if (NILP (Vmouse_highlight)
6603 || !f->glyphs_initialized_p)
6604 return;
6606 dpyinfo->mouse_face_mouse_x = x;
6607 dpyinfo->mouse_face_mouse_y = y;
6608 dpyinfo->mouse_face_mouse_frame = f;
6610 if (dpyinfo->mouse_face_defer)
6611 return;
6613 if (gc_in_progress)
6615 dpyinfo->mouse_face_deferred_gc = 1;
6616 return;
6619 /* Which window is that in? */
6620 window = window_from_coordinates (f, x, y, &portion, 1);
6622 /* If we were displaying active text in another window, clear that. */
6623 if (! EQ (window, dpyinfo->mouse_face_window))
6624 clear_mouse_face (dpyinfo);
6626 /* Not on a window -> return. */
6627 if (!WINDOWP (window))
6628 return;
6630 /* Reset help_echo. It will get recomputed below. */
6631 help_echo = Qnil;
6633 /* Convert to window-relative pixel coordinates. */
6634 w = XWINDOW (window);
6635 frame_to_window_pixel_xy (w, &x, &y);
6637 /* Handle tool-bar window differently since it doesn't display a
6638 buffer. */
6639 if (EQ (window, f->tool_bar_window))
6641 note_tool_bar_highlight (f, x, y);
6642 return;
6645 /* Mouse is on the mode or header line? */
6646 if (portion == 1 || portion == 3)
6648 note_mode_line_highlight (w, x, portion == 1);
6649 return;
6652 if (portion == 2)
6653 cursor = f->output_data.w32->horizontal_drag_cursor;
6654 else
6655 cursor = f->output_data.w32->text_cursor;
6657 /* Are we in a window whose display is up to date?
6658 And verify the buffer's text has not changed. */
6659 b = XBUFFER (w->buffer);
6660 if (/* Within text portion of the window. */
6661 portion == 0
6662 && EQ (w->window_end_valid, w->buffer)
6663 && XFASTINT (w->last_modified) == BUF_MODIFF (b)
6664 && XFASTINT (w->last_overlay_modified) == BUF_OVERLAY_MODIFF (b))
6666 int hpos, vpos, pos, i, area;
6667 struct glyph *glyph;
6668 Lisp_Object object;
6669 Lisp_Object mouse_face = Qnil, overlay = Qnil, position;
6670 Lisp_Object *overlay_vec = NULL;
6671 int len, noverlays;
6672 struct buffer *obuf;
6673 int obegv, ozv, same_region;
6675 /* Find the glyph under X/Y. */
6676 glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, &area, 0);
6678 /* Clear mouse face if X/Y not over text. */
6679 if (glyph == NULL
6680 || area != TEXT_AREA
6681 || !MATRIX_ROW (w->current_matrix, vpos)->displays_text_p)
6683 clear_mouse_face (dpyinfo);
6684 cursor = f->output_data.w32->nontext_cursor;
6685 goto set_cursor;
6688 pos = glyph->charpos;
6689 object = glyph->object;
6690 if (!STRINGP (object) && !BUFFERP (object))
6691 goto set_cursor;
6693 /* If we get an out-of-range value, return now; avoid an error. */
6694 if (BUFFERP (object) && pos > BUF_Z (b))
6695 goto set_cursor;
6697 /* Make the window's buffer temporarily current for
6698 overlays_at and compute_char_face. */
6699 obuf = current_buffer;
6700 current_buffer = b;
6701 obegv = BEGV;
6702 ozv = ZV;
6703 BEGV = BEG;
6704 ZV = Z;
6706 /* Is this char mouse-active or does it have help-echo? */
6707 position = make_number (pos);
6709 if (BUFFERP (object))
6711 /* Put all the overlays we want in a vector in overlay_vec.
6712 Store the length in len. If there are more than 10, make
6713 enough space for all, and try again. */
6714 len = 10;
6715 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
6716 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL, 0);
6717 if (noverlays > len)
6719 len = noverlays;
6720 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
6721 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL,0);
6724 /* Sort overlays into increasing priority order. */
6725 noverlays = sort_overlays (overlay_vec, noverlays, w);
6727 else
6728 noverlays = 0;
6730 same_region = (EQ (window, dpyinfo->mouse_face_window)
6731 && vpos >= dpyinfo->mouse_face_beg_row
6732 && vpos <= dpyinfo->mouse_face_end_row
6733 && (vpos > dpyinfo->mouse_face_beg_row
6734 || hpos >= dpyinfo->mouse_face_beg_col)
6735 && (vpos < dpyinfo->mouse_face_end_row
6736 || hpos < dpyinfo->mouse_face_end_col
6737 || dpyinfo->mouse_face_past_end));
6739 if (same_region)
6740 cursor = 0;
6742 /* Check mouse-face highlighting. */
6743 if (! same_region
6744 /* If there exists an overlay with mouse-face overlapping
6745 the one we are currently highlighting, we have to
6746 check if we enter the overlapping overlay, and then
6747 highlight that. */
6748 || (OVERLAYP (dpyinfo->mouse_face_overlay)
6749 && mouse_face_overlay_overlaps (dpyinfo->mouse_face_overlay)))
6751 /* Find the highest priority overlay that has a mouse-face
6752 property. */
6753 overlay = Qnil;
6754 for (i = noverlays - 1; i >= 0 && NILP (overlay); --i)
6756 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
6757 if (!NILP (mouse_face))
6758 overlay = overlay_vec[i];
6761 /* If we're actually highlighting the same overlay as
6762 before, there's no need to do that again. */
6763 if (!NILP (overlay)
6764 && EQ (overlay, dpyinfo->mouse_face_overlay))
6765 goto check_help_echo;
6767 dpyinfo->mouse_face_overlay = overlay;
6769 /* Clear the display of the old active region, if any. */
6770 if (clear_mouse_face (dpyinfo))
6771 cursor = 0;
6773 /* If no overlay applies, get a text property. */
6774 if (NILP (overlay))
6775 mouse_face = Fget_text_property (position, Qmouse_face, object);
6777 /* Handle the overlay case. */
6778 if (!NILP (overlay))
6780 /* Find the range of text around this char that
6781 should be active. */
6782 Lisp_Object before, after;
6783 int ignore;
6785 before = Foverlay_start (overlay);
6786 after = Foverlay_end (overlay);
6787 /* Record this as the current active region. */
6788 fast_find_position (w, XFASTINT (before),
6789 &dpyinfo->mouse_face_beg_col,
6790 &dpyinfo->mouse_face_beg_row,
6791 &dpyinfo->mouse_face_beg_x,
6792 &dpyinfo->mouse_face_beg_y, Qnil);
6794 dpyinfo->mouse_face_past_end
6795 = !fast_find_position (w, XFASTINT (after),
6796 &dpyinfo->mouse_face_end_col,
6797 &dpyinfo->mouse_face_end_row,
6798 &dpyinfo->mouse_face_end_x,
6799 &dpyinfo->mouse_face_end_y, Qnil);
6800 dpyinfo->mouse_face_window = window;
6802 dpyinfo->mouse_face_face_id
6803 = face_at_buffer_position (w, pos, 0, 0,
6804 &ignore, pos + 1,
6805 !dpyinfo->mouse_face_hidden);
6807 /* Display it as active. */
6808 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
6809 cursor = 0;
6811 /* Handle the text property case. */
6812 else if (! NILP (mouse_face) && BUFFERP (object))
6814 /* Find the range of text around this char that
6815 should be active. */
6816 Lisp_Object before, after, beginning, end;
6817 int ignore;
6819 beginning = Fmarker_position (w->start);
6820 end = make_number (BUF_Z (XBUFFER (object))
6821 - XFASTINT (w->window_end_pos));
6822 before
6823 = Fprevious_single_property_change (make_number (pos + 1),
6824 Qmouse_face,
6825 object, beginning);
6826 after
6827 = Fnext_single_property_change (position, Qmouse_face,
6828 object, end);
6830 /* Record this as the current active region. */
6831 fast_find_position (w, XFASTINT (before),
6832 &dpyinfo->mouse_face_beg_col,
6833 &dpyinfo->mouse_face_beg_row,
6834 &dpyinfo->mouse_face_beg_x,
6835 &dpyinfo->mouse_face_beg_y, Qnil);
6836 dpyinfo->mouse_face_past_end
6837 = !fast_find_position (w, XFASTINT (after),
6838 &dpyinfo->mouse_face_end_col,
6839 &dpyinfo->mouse_face_end_row,
6840 &dpyinfo->mouse_face_end_x,
6841 &dpyinfo->mouse_face_end_y, Qnil);
6842 dpyinfo->mouse_face_window = window;
6844 if (BUFFERP (object))
6845 dpyinfo->mouse_face_face_id
6846 = face_at_buffer_position (w, pos, 0, 0,
6847 &ignore, pos + 1,
6848 !dpyinfo->mouse_face_hidden);
6850 /* Display it as active. */
6851 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
6852 cursor = 0;
6854 else if (!NILP (mouse_face) && STRINGP (object))
6856 Lisp_Object b, e;
6857 int ignore;
6859 b = Fprevious_single_property_change (make_number (pos + 1),
6860 Qmouse_face,
6861 object, Qnil);
6862 e = Fnext_single_property_change (position, Qmouse_face,
6863 object, Qnil);
6864 if (NILP (b))
6865 b = make_number (0);
6866 if (NILP (e))
6867 e = make_number (SCHARS (object) - 1);
6868 fast_find_string_pos (w, XINT (b), object,
6869 &dpyinfo->mouse_face_beg_col,
6870 &dpyinfo->mouse_face_beg_row,
6871 &dpyinfo->mouse_face_beg_x,
6872 &dpyinfo->mouse_face_beg_y, 0);
6873 fast_find_string_pos (w, XINT (e), object,
6874 &dpyinfo->mouse_face_end_col,
6875 &dpyinfo->mouse_face_end_row,
6876 &dpyinfo->mouse_face_end_x,
6877 &dpyinfo->mouse_face_end_y, 1);
6878 dpyinfo->mouse_face_past_end = 0;
6879 dpyinfo->mouse_face_window = window;
6880 dpyinfo->mouse_face_face_id
6881 = face_at_string_position (w, object, pos, 0, 0, 0, &ignore,
6882 glyph->face_id, 1);
6883 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
6884 cursor = 0;
6886 else if (STRINGP (object) && NILP (mouse_face))
6888 /* A string which doesn't have mouse-face, but
6889 the text ``under'' it might have. */
6890 struct glyph_row *r = MATRIX_ROW (w->current_matrix, vpos);
6891 int start = MATRIX_ROW_START_CHARPOS (r);
6893 pos = string_buffer_position (w, object, start);
6894 if (pos > 0)
6895 mouse_face = get_char_property_and_overlay (make_number (pos),
6896 Qmouse_face,
6897 w->buffer,
6898 &overlay);
6899 if (!NILP (mouse_face) && !NILP (overlay))
6901 Lisp_Object before = Foverlay_start (overlay);
6902 Lisp_Object after = Foverlay_end (overlay);
6903 int ignore;
6905 /* Note that we might not be able to find position
6906 BEFORE in the glyph matrix if the overlay is
6907 entirely covered by a `display' property. In
6908 this case, we overshoot. So let's stop in
6909 the glyph matrix before glyphs for OBJECT. */
6910 fast_find_position (w, XFASTINT (before),
6911 &dpyinfo->mouse_face_beg_col,
6912 &dpyinfo->mouse_face_beg_row,
6913 &dpyinfo->mouse_face_beg_x,
6914 &dpyinfo->mouse_face_beg_y,
6915 object);
6917 dpyinfo->mouse_face_past_end
6918 = !fast_find_position (w, XFASTINT (after),
6919 &dpyinfo->mouse_face_end_col,
6920 &dpyinfo->mouse_face_end_row,
6921 &dpyinfo->mouse_face_end_x,
6922 &dpyinfo->mouse_face_end_y,
6923 Qnil);
6924 dpyinfo->mouse_face_window = window;
6925 dpyinfo->mouse_face_face_id
6926 = face_at_buffer_position (w, pos, 0, 0,
6927 &ignore, pos + 1,
6928 !dpyinfo->mouse_face_hidden);
6930 /* Display it as active. */
6931 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
6932 cursor = 0;
6937 check_help_echo:
6939 /* Look for a `help-echo' property. */
6941 Lisp_Object help, overlay;
6943 /* Check overlays first. */
6944 help = overlay = Qnil;
6945 for (i = noverlays - 1; i >= 0 && NILP (help); --i)
6947 overlay = overlay_vec[i];
6948 help = Foverlay_get (overlay, Qhelp_echo);
6951 if (!NILP (help))
6953 help_echo = help;
6954 help_echo_window = window;
6955 help_echo_object = overlay;
6956 help_echo_pos = pos;
6958 else
6960 Lisp_Object object = glyph->object;
6961 int charpos = glyph->charpos;
6963 /* Try text properties. */
6964 if (STRINGP (object)
6965 && charpos >= 0
6966 && charpos < SCHARS (object))
6968 help = Fget_text_property (make_number (charpos),
6969 Qhelp_echo, object);
6970 if (NILP (help))
6972 /* If the string itself doesn't specify a help-echo,
6973 see if the buffer text ``under'' it does. */
6974 struct glyph_row *r
6975 = MATRIX_ROW (w->current_matrix, vpos);
6976 int start = MATRIX_ROW_START_CHARPOS (r);
6977 int pos = string_buffer_position (w, object, start);
6978 if (pos > 0)
6980 help = Fget_char_property (make_number (pos),
6981 Qhelp_echo, w->buffer);
6982 if (!NILP (help))
6984 charpos = pos;
6985 object = w->buffer;
6990 else if (BUFFERP (object)
6991 && charpos >= BEGV
6992 && charpos < ZV)
6993 help = Fget_text_property (make_number (charpos), Qhelp_echo,
6994 object);
6996 if (!NILP (help))
6998 help_echo = help;
6999 help_echo_window = window;
7000 help_echo_object = object;
7001 help_echo_pos = charpos;
7006 BEGV = obegv;
7007 ZV = ozv;
7008 current_buffer = obuf;
7011 set_cursor:
7012 if (cursor)
7013 w32_define_cursor (FRAME_W32_WINDOW (f), cursor);
7016 static void
7017 redo_mouse_highlight ()
7019 if (!NILP (last_mouse_motion_frame)
7020 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame)))
7021 note_mouse_highlight (XFRAME (last_mouse_motion_frame),
7022 LOWORD (last_mouse_motion_event.lParam),
7023 HIWORD (last_mouse_motion_event.lParam));
7026 void
7027 w32_define_cursor (window, cursor)
7028 Window window;
7029 Cursor cursor;
7031 PostMessage (window, WM_EMACS_SETCURSOR, (WPARAM) cursor, 0);
7035 /***********************************************************************
7036 Tool-bars
7037 ***********************************************************************/
7039 static int x_tool_bar_item P_ ((struct frame *, int, int,
7040 struct glyph **, int *, int *, int *));
7042 /* Tool-bar item index of the item on which a mouse button was pressed
7043 or -1. */
7045 static int last_tool_bar_item;
7048 /* Get information about the tool-bar item at position X/Y on frame F.
7049 Return in *GLYPH a pointer to the glyph of the tool-bar item in
7050 the current matrix of the tool-bar window of F, or NULL if not
7051 on a tool-bar item. Return in *PROP_IDX the index of the tool-bar
7052 item in F->tool_bar_items. Value is
7054 -1 if X/Y is not on a tool-bar item
7055 0 if X/Y is on the same item that was highlighted before.
7056 1 otherwise. */
7058 static int
7059 x_tool_bar_item (f, x, y, glyph, hpos, vpos, prop_idx)
7060 struct frame *f;
7061 int x, y;
7062 struct glyph **glyph;
7063 int *hpos, *vpos, *prop_idx;
7065 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
7066 struct window *w = XWINDOW (f->tool_bar_window);
7067 int area;
7069 /* Find the glyph under X/Y. */
7070 *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, &area, 0);
7071 if (*glyph == NULL)
7072 return -1;
7074 /* Get the start of this tool-bar item's properties in
7075 f->tool_bar_items. */
7076 if (!tool_bar_item_info (f, *glyph, prop_idx))
7077 return -1;
7079 /* Is mouse on the highlighted item? */
7080 if (EQ (f->tool_bar_window, dpyinfo->mouse_face_window)
7081 && *vpos >= dpyinfo->mouse_face_beg_row
7082 && *vpos <= dpyinfo->mouse_face_end_row
7083 && (*vpos > dpyinfo->mouse_face_beg_row
7084 || *hpos >= dpyinfo->mouse_face_beg_col)
7085 && (*vpos < dpyinfo->mouse_face_end_row
7086 || *hpos < dpyinfo->mouse_face_end_col
7087 || dpyinfo->mouse_face_past_end))
7088 return 0;
7090 return 1;
7094 /* Handle mouse button event on the tool-bar of frame F, at
7095 frame-relative coordinates X/Y. EVENT_TYPE is either ButtionPress
7096 or ButtonRelase. */
7098 static void
7099 w32_handle_tool_bar_click (f, button_event)
7100 struct frame *f;
7101 struct input_event *button_event;
7103 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
7104 struct window *w = XWINDOW (f->tool_bar_window);
7105 int hpos, vpos, prop_idx;
7106 struct glyph *glyph;
7107 Lisp_Object enabled_p;
7108 int x = XFASTINT (button_event->x);
7109 int y = XFASTINT (button_event->y);
7111 /* If not on the highlighted tool-bar item, return. */
7112 frame_to_window_pixel_xy (w, &x, &y);
7113 if (x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx) != 0)
7114 return;
7116 /* If item is disabled, do nothing. */
7117 enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
7118 if (NILP (enabled_p))
7119 return;
7121 if (button_event->modifiers & down_modifier)
7123 /* Show item in pressed state. */
7124 show_mouse_face (dpyinfo, DRAW_IMAGE_SUNKEN);
7125 dpyinfo->mouse_face_image_state = DRAW_IMAGE_SUNKEN;
7126 last_tool_bar_item = prop_idx;
7128 else
7130 Lisp_Object key, frame;
7131 struct input_event event;
7133 /* Show item in released state. */
7134 show_mouse_face (dpyinfo, DRAW_IMAGE_RAISED);
7135 dpyinfo->mouse_face_image_state = DRAW_IMAGE_RAISED;
7137 key = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_KEY);
7139 XSETFRAME (frame, f);
7140 event.kind = TOOL_BAR_EVENT;
7141 event.frame_or_window = frame;
7142 event.arg = frame;
7143 kbd_buffer_store_event (&event);
7145 event.kind = TOOL_BAR_EVENT;
7146 event.frame_or_window = frame;
7147 event.arg = key;
7148 /* The keyboard buffer doesn't like the up modifier being set. */
7149 event.modifiers = button_event->modifiers & ~up_modifier;
7150 kbd_buffer_store_event (&event);
7151 last_tool_bar_item = -1;
7156 /* Possibly highlight a tool-bar item on frame F when mouse moves to
7157 tool-bar window-relative coordinates X/Y. Called from
7158 note_mouse_highlight. */
7160 static void
7161 note_tool_bar_highlight (f, x, y)
7162 struct frame *f;
7163 int x, y;
7165 Lisp_Object window = f->tool_bar_window;
7166 struct window *w = XWINDOW (window);
7167 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
7168 int hpos, vpos;
7169 struct glyph *glyph;
7170 struct glyph_row *row;
7171 int i;
7172 Lisp_Object enabled_p;
7173 int prop_idx;
7174 enum draw_glyphs_face draw = DRAW_IMAGE_RAISED;
7175 int mouse_down_p, rc;
7177 /* Function note_mouse_highlight is called with negative x(y
7178 values when mouse moves outside of the frame. */
7179 if (x <= 0 || y <= 0)
7181 clear_mouse_face (dpyinfo);
7182 return;
7185 rc = x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx);
7186 if (rc < 0)
7188 /* Not on tool-bar item. */
7189 clear_mouse_face (dpyinfo);
7190 return;
7192 else if (rc == 0)
7193 /* On same tool-bar item as before. */
7194 goto set_help_echo;
7196 clear_mouse_face (dpyinfo);
7198 /* Mouse is down, but on different tool-bar item? */
7199 mouse_down_p = (dpyinfo->grabbed
7200 && f == last_mouse_frame
7201 && FRAME_LIVE_P (f));
7202 if (mouse_down_p
7203 && last_tool_bar_item != prop_idx)
7204 return;
7206 dpyinfo->mouse_face_image_state = DRAW_NORMAL_TEXT;
7207 draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
7209 /* If tool-bar item is not enabled, don't highlight it. */
7210 enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
7211 if (!NILP (enabled_p))
7213 /* Compute the x-position of the glyph. In front and past the
7214 image is a space. We include this is the highlighted area. */
7215 row = MATRIX_ROW (w->current_matrix, vpos);
7216 for (i = x = 0; i < hpos; ++i)
7217 x += row->glyphs[TEXT_AREA][i].pixel_width;
7219 /* Record this as the current active region. */
7220 dpyinfo->mouse_face_beg_col = hpos;
7221 dpyinfo->mouse_face_beg_row = vpos;
7222 dpyinfo->mouse_face_beg_x = x;
7223 dpyinfo->mouse_face_beg_y = row->y;
7224 dpyinfo->mouse_face_past_end = 0;
7226 dpyinfo->mouse_face_end_col = hpos + 1;
7227 dpyinfo->mouse_face_end_row = vpos;
7228 dpyinfo->mouse_face_end_x = x + glyph->pixel_width;
7229 dpyinfo->mouse_face_end_y = row->y;
7230 dpyinfo->mouse_face_window = window;
7231 dpyinfo->mouse_face_face_id = TOOL_BAR_FACE_ID;
7233 /* Display it as active. */
7234 show_mouse_face (dpyinfo, draw);
7235 dpyinfo->mouse_face_image_state = draw;
7238 set_help_echo:
7240 /* Set help_echo to a help string.to display for this tool-bar item.
7241 w32_read_socket does the rest. */
7242 help_echo_object = help_echo_window = Qnil;
7243 help_echo_pos = -1;
7244 help_echo = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_HELP);
7245 if (NILP (help_echo))
7246 help_echo = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_CAPTION);
7251 /* Find the glyph matrix position of buffer position CHARPOS in window
7252 *W. HPOS, *VPOS, *X, and *Y are set to the positions found. W's
7253 current glyphs must be up to date. If CHARPOS is above window
7254 start return (0, 0, 0, 0). If CHARPOS is after end of W, return end
7255 of last line in W. In the row containing CHARPOS, stop before glyphs
7256 having STOP as object. */
7258 #if 0 /* This is a version of fast_find_position that's more correct
7259 in the presence of hscrolling, for example. I didn't install
7260 it right away because the problem fixed is minor, it failed
7261 in 20.x as well, and I think it's too risky to install
7262 so near the release of 21.1. 2001-09-25 gerd. */
7264 static int
7265 fast_find_position (w, charpos, hpos, vpos, x, y, stop)
7266 struct window *w;
7267 int charpos;
7268 int *hpos, *vpos, *x, *y;
7269 Lisp_Object stop;
7271 struct glyph_row *row, *first;
7272 struct glyph *glyph, *end;
7273 int i, past_end = 0;
7275 first = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
7276 row = row_containing_pos (w, charpos, first, NULL, 0);
7277 if (row == NULL)
7279 if (charpos < MATRIX_ROW_START_CHARPOS (first))
7281 *x = *y = *hpos = *vpos = 0;
7282 return 0;
7284 else
7286 row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos));
7287 past_end = 1;
7291 *x = row->x;
7292 *y = row->y;
7293 *vpos = MATRIX_ROW_VPOS (row, w->current_matrix);
7295 glyph = row->glyphs[TEXT_AREA];
7296 end = glyph + row->used[TEXT_AREA];
7298 /* Skip over glyphs not having an object at the start of the row.
7299 These are special glyphs like truncation marks on terminal
7300 frames. */
7301 if (row->displays_text_p)
7302 while (glyph < end
7303 && INTEGERP (glyph->object)
7304 && !EQ (stop, glyph->object)
7305 && glyph->charpos < 0)
7307 *x += glyph->pixel_width;
7308 ++glyph;
7311 while (glyph < end
7312 && !INTEGERP (glyph->object)
7313 && !EQ (stop, glyph->object)
7314 && (!BUFFERP (glyph->object)
7315 || glyph->charpos < charpos))
7317 *x += glyph->pixel_width;
7318 ++glyph;
7321 *hpos = glyph - row->glyphs[TEXT_AREA];
7322 return past_end;
7325 #else /* not 0 */
7327 static int
7328 fast_find_position (w, pos, hpos, vpos, x, y, stop)
7329 struct window *w;
7330 int pos;
7331 int *hpos, *vpos, *x, *y;
7332 Lisp_Object stop;
7334 int i;
7335 int lastcol;
7336 int maybe_next_line_p = 0;
7337 int line_start_position;
7338 int yb = window_text_bottom_y (w);
7339 struct glyph_row *row, *best_row;
7340 int row_vpos, best_row_vpos;
7341 int current_x;
7343 row = best_row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
7344 row_vpos = best_row_vpos = MATRIX_ROW_VPOS (row, w->current_matrix);
7346 while (row->y < yb)
7348 if (row->used[TEXT_AREA])
7349 line_start_position = row->glyphs[TEXT_AREA]->charpos;
7350 else
7351 line_start_position = 0;
7353 if (line_start_position > pos)
7354 break;
7355 /* If the position sought is the end of the buffer,
7356 don't include the blank lines at the bottom of the window. */
7357 else if (line_start_position == pos
7358 && pos == BUF_ZV (XBUFFER (w->buffer)))
7360 maybe_next_line_p = 1;
7361 break;
7363 else if (line_start_position > 0)
7365 best_row = row;
7366 best_row_vpos = row_vpos;
7369 if (row->y + row->height >= yb)
7370 break;
7372 ++row;
7373 ++row_vpos;
7376 /* Find the right column within BEST_ROW. */
7377 lastcol = 0;
7378 current_x = best_row->x;
7379 for (i = 0; i < best_row->used[TEXT_AREA]; i++)
7381 struct glyph *glyph = best_row->glyphs[TEXT_AREA] + i;
7382 int charpos = glyph->charpos;
7384 if (BUFFERP (glyph->object))
7386 if (charpos == pos)
7388 *hpos = i;
7389 *vpos = best_row_vpos;
7390 *x = current_x;
7391 *y = best_row->y;
7392 return 1;
7394 else if (charpos > pos)
7395 break;
7397 else if (EQ (glyph->object, stop))
7398 break;
7400 if (charpos > 0)
7401 lastcol = i;
7402 current_x += glyph->pixel_width;
7405 /* If we're looking for the end of the buffer,
7406 and we didn't find it in the line we scanned,
7407 use the start of the following line. */
7408 if (maybe_next_line_p)
7410 ++best_row;
7411 ++best_row_vpos;
7412 lastcol = 0;
7413 current_x = best_row->x;
7416 *vpos = best_row_vpos;
7417 *hpos = lastcol + 1;
7418 *x = current_x;
7419 *y = best_row->y;
7420 return 0;
7423 #endif /* not 0 */
7426 /* Find the position of the glyph for position POS in OBJECT in
7427 window W's current matrix, and return in *X/*Y the pixel
7428 coordinates, and return in *HPOS/*VPOS the column/row of the glyph.
7430 RIGHT_P non-zero means return the position of the right edge of the
7431 glyph, RIGHT_P zero means return the left edge position.
7433 If no glyph for POS exists in the matrix, return the position of
7434 the glyph with the next smaller position that is in the matrix, if
7435 RIGHT_P is zero. If RIGHT_P is non-zero, and no glyph for POS
7436 exists in the matrix, return the position of the glyph with the
7437 next larger position in OBJECT.
7439 Value is non-zero if a glyph was found. */
7441 static int
7442 fast_find_string_pos (w, pos, object, hpos, vpos, x, y, right_p)
7443 struct window *w;
7444 int pos;
7445 Lisp_Object object;
7446 int *hpos, *vpos, *x, *y;
7447 int right_p;
7449 int yb = window_text_bottom_y (w);
7450 struct glyph_row *r;
7451 struct glyph *best_glyph = NULL;
7452 struct glyph_row *best_row = NULL;
7453 int best_x = 0;
7455 for (r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
7456 r->enabled_p && r->y < yb;
7457 ++r)
7459 struct glyph *g = r->glyphs[TEXT_AREA];
7460 struct glyph *e = g + r->used[TEXT_AREA];
7461 int gx;
7463 for (gx = r->x; g < e; gx += g->pixel_width, ++g)
7464 if (EQ (g->object, object))
7466 if (g->charpos == pos)
7468 best_glyph = g;
7469 best_x = gx;
7470 best_row = r;
7471 goto found;
7473 else if (best_glyph == NULL
7474 || ((abs (g->charpos - pos)
7475 < abs (best_glyph->charpos - pos))
7476 && (right_p
7477 ? g->charpos < pos
7478 : g->charpos > pos)))
7480 best_glyph = g;
7481 best_x = gx;
7482 best_row = r;
7487 found:
7489 if (best_glyph)
7491 *x = best_x;
7492 *hpos = best_glyph - best_row->glyphs[TEXT_AREA];
7494 if (right_p)
7496 *x += best_glyph->pixel_width;
7497 ++*hpos;
7500 *y = best_row->y;
7501 *vpos = best_row - w->current_matrix->rows;
7504 return best_glyph != NULL;
7508 /* Display the active region described by mouse_face_*
7509 in its mouse-face if HL > 0, in its normal face if HL = 0. */
7511 static void
7512 show_mouse_face (dpyinfo, draw)
7513 struct w32_display_info *dpyinfo;
7514 enum draw_glyphs_face draw;
7516 struct window *w = XWINDOW (dpyinfo->mouse_face_window);
7517 struct frame *f = XFRAME (WINDOW_FRAME (w));
7519 if (/* If window is in the process of being destroyed, don't bother
7520 to do anything. */
7521 w->current_matrix != NULL
7522 /* Don't update mouse highlight if hidden */
7523 && (draw != DRAW_MOUSE_FACE || !dpyinfo->mouse_face_hidden)
7524 /* Recognize when we are called to operate on rows that don't exist
7525 anymore. This can happen when a window is split. */
7526 && dpyinfo->mouse_face_end_row < w->current_matrix->nrows)
7528 int phys_cursor_on_p = w->phys_cursor_on_p;
7529 struct glyph_row *row, *first, *last;
7531 first = MATRIX_ROW (w->current_matrix, dpyinfo->mouse_face_beg_row);
7532 last = MATRIX_ROW (w->current_matrix, dpyinfo->mouse_face_end_row);
7534 for (row = first; row <= last && row->enabled_p; ++row)
7536 int start_hpos, end_hpos, start_x;
7538 /* For all but the first row, the highlight starts at column 0. */
7539 if (row == first)
7541 start_hpos = dpyinfo->mouse_face_beg_col;
7542 start_x = dpyinfo->mouse_face_beg_x;
7544 else
7546 start_hpos = 0;
7547 start_x = 0;
7550 if (row == last)
7551 end_hpos = dpyinfo->mouse_face_end_col;
7552 else
7553 end_hpos = row->used[TEXT_AREA];
7555 if (end_hpos > start_hpos)
7557 x_draw_glyphs (w, start_x, row, TEXT_AREA,
7558 start_hpos, end_hpos, draw, 0);
7560 row->mouse_face_p
7561 = draw == DRAW_MOUSE_FACE || draw == DRAW_IMAGE_RAISED;
7565 /* When we've written over the cursor, arrange for it to
7566 be displayed again. */
7567 if (phys_cursor_on_p && !w->phys_cursor_on_p)
7568 x_display_cursor (w, 1,
7569 w->phys_cursor.hpos, w->phys_cursor.vpos,
7570 w->phys_cursor.x, w->phys_cursor.y);
7573 /* Change the mouse cursor. */
7574 if (draw == DRAW_NORMAL_TEXT)
7575 w32_define_cursor (FRAME_W32_WINDOW (f),
7576 f->output_data.w32->text_cursor);
7577 else if (draw == DRAW_MOUSE_FACE)
7578 w32_define_cursor (FRAME_W32_WINDOW (f),
7579 f->output_data.w32->hand_cursor);
7580 else
7581 w32_define_cursor (FRAME_W32_WINDOW (f),
7582 f->output_data.w32->nontext_cursor);
7586 /* Clear out the mouse-highlighted active region.
7587 Redraw it un-highlighted first. */
7589 static int
7590 clear_mouse_face (dpyinfo)
7591 struct w32_display_info *dpyinfo;
7593 int cleared = 0;
7595 if (! NILP (dpyinfo->mouse_face_window))
7597 show_mouse_face (dpyinfo, DRAW_NORMAL_TEXT);
7598 cleared = 1;
7601 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
7602 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
7603 dpyinfo->mouse_face_window = Qnil;
7604 dpyinfo->mouse_face_overlay = Qnil;
7605 return cleared;
7609 /* Clear any mouse-face on window W. This function is part of the
7610 redisplay interface, and is called from try_window_id and similar
7611 functions to ensure the mouse-highlight is off. */
7613 static void
7614 x_clear_mouse_face (w)
7615 struct window *w;
7617 struct w32_display_info *dpyinfo
7618 = FRAME_W32_DISPLAY_INFO (XFRAME (w->frame));
7619 Lisp_Object window;
7621 BLOCK_INPUT;
7622 XSETWINDOW (window, w);
7623 if (EQ (window, dpyinfo->mouse_face_window))
7624 clear_mouse_face (dpyinfo);
7625 UNBLOCK_INPUT;
7629 /* Just discard the mouse face information for frame F, if any.
7630 This is used when the size of F is changed. */
7632 void
7633 cancel_mouse_face (f)
7634 FRAME_PTR f;
7636 Lisp_Object window;
7637 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
7639 window = dpyinfo->mouse_face_window;
7640 if (! NILP (window) && XFRAME (XWINDOW (window)->frame) == f)
7642 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
7643 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
7644 dpyinfo->mouse_face_window = Qnil;
7648 static struct scroll_bar *x_window_to_scroll_bar ();
7649 static void x_scroll_bar_report_motion ();
7650 static void x_check_fullscreen P_ ((struct frame *));
7651 static void x_check_fullscreen_move P_ ((struct frame *));
7652 static int glyph_rect P_ ((struct frame *f, int, int, RECT *));
7655 /* Try to determine frame pixel position and size of the glyph under
7656 frame pixel coordinates X/Y on frame F . Return the position and
7657 size in *RECT. Value is non-zero if we could compute these
7658 values. */
7660 static int
7661 glyph_rect (f, x, y, rect)
7662 struct frame *f;
7663 int x, y;
7664 RECT *rect;
7666 Lisp_Object window;
7667 int part;
7669 window = window_from_coordinates (f, x, y, &part, 0);
7670 if (!NILP (window))
7672 struct window *w = XWINDOW (window);
7673 struct glyph_row *r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
7674 struct glyph_row *end = r + w->current_matrix->nrows - 1;
7676 frame_to_window_pixel_xy (w, &x, &y);
7678 for (; r < end && r->enabled_p; ++r)
7679 if (r->y <= y && r->y + r->height > y)
7681 /* Found the row at y. */
7682 struct glyph *g = r->glyphs[TEXT_AREA];
7683 struct glyph *end = g + r->used[TEXT_AREA];
7684 int gx;
7686 rect->top = WINDOW_TO_FRAME_PIXEL_Y (w, r->y);
7687 rect->bottom = rect->top + r->height;
7689 if (x < r->x)
7691 /* x is to the left of the first glyph in the row. */
7692 rect->left = XINT (w->left);
7693 rect->right = WINDOW_TO_FRAME_PIXEL_X (w, r->x);
7694 return 1;
7697 for (gx = r->x; g < end; gx += g->pixel_width, ++g)
7698 if (gx <= x && gx + g->pixel_width > x)
7700 /* x is on a glyph. */
7701 rect->left = WINDOW_TO_FRAME_PIXEL_X (w, gx);
7702 rect->right = rect->left + g->pixel_width;
7703 return 1;
7706 /* x is to the right of the last glyph in the row. */
7707 rect->left = WINDOW_TO_FRAME_PIXEL_X (w, gx);
7708 rect->right = XINT (w->left) + XINT (w->width);
7709 return 1;
7713 /* The y is not on any row. */
7714 return 0;
7717 /* Record the position of the mouse in last_mouse_glyph. */
7718 static void
7719 remember_mouse_glyph (f1, gx, gy)
7720 struct frame * f1;
7721 int gx, gy;
7723 if (!glyph_rect (f1, gx, gy, &last_mouse_glyph))
7725 int width = FRAME_SMALLEST_CHAR_WIDTH (f1);
7726 int height = FRAME_SMALLEST_FONT_HEIGHT (f1);
7728 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to
7729 round down even for negative values. */
7730 if (gx < 0)
7731 gx -= width - 1;
7732 if (gy < 0)
7733 gy -= height - 1;
7734 #if 0
7735 /* This was the original code from XTmouse_position, but it seems
7736 to give the position of the glyph diagonally next to the one
7737 the mouse is over. */
7738 gx = (gx + width - 1) / width * width;
7739 gy = (gy + height - 1) / height * height;
7740 #else
7741 gx = gx / width * width;
7742 gy = gy / height * height;
7743 #endif
7745 last_mouse_glyph.left = gx;
7746 last_mouse_glyph.top = gy;
7747 last_mouse_glyph.right = gx + width;
7748 last_mouse_glyph.bottom = gy + height;
7752 /* Return the current position of the mouse.
7753 *fp should be a frame which indicates which display to ask about.
7755 If the mouse movement started in a scroll bar, set *fp, *bar_window,
7756 and *part to the frame, window, and scroll bar part that the mouse
7757 is over. Set *x and *y to the portion and whole of the mouse's
7758 position on the scroll bar.
7760 If the mouse movement started elsewhere, set *fp to the frame the
7761 mouse is on, *bar_window to nil, and *x and *y to the character cell
7762 the mouse is over.
7764 Set *time to the server time-stamp for the time at which the mouse
7765 was at this position.
7767 Don't store anything if we don't have a valid set of values to report.
7769 This clears the mouse_moved flag, so we can wait for the next mouse
7770 movement. */
7772 static void
7773 w32_mouse_position (fp, insist, bar_window, part, x, y, time)
7774 FRAME_PTR *fp;
7775 int insist;
7776 Lisp_Object *bar_window;
7777 enum scroll_bar_part *part;
7778 Lisp_Object *x, *y;
7779 unsigned long *time;
7781 FRAME_PTR f1;
7783 BLOCK_INPUT;
7785 if (! NILP (last_mouse_scroll_bar) && insist == 0)
7786 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
7787 else
7789 POINT pt;
7791 Lisp_Object frame, tail;
7793 /* Clear the mouse-moved flag for every frame on this display. */
7794 FOR_EACH_FRAME (tail, frame)
7795 XFRAME (frame)->mouse_moved = 0;
7797 last_mouse_scroll_bar = Qnil;
7799 GetCursorPos (&pt);
7801 /* Now we have a position on the root; find the innermost window
7802 containing the pointer. */
7804 if (FRAME_W32_DISPLAY_INFO (*fp)->grabbed && last_mouse_frame
7805 && FRAME_LIVE_P (last_mouse_frame))
7807 /* If mouse was grabbed on a frame, give coords for that frame
7808 even if the mouse is now outside it. */
7809 f1 = last_mouse_frame;
7811 else
7813 /* Is window under mouse one of our frames? */
7814 f1 = x_any_window_to_frame (FRAME_W32_DISPLAY_INFO (*fp),
7815 WindowFromPoint (pt));
7818 /* If not, is it one of our scroll bars? */
7819 if (! f1)
7821 struct scroll_bar *bar
7822 = x_window_to_scroll_bar (WindowFromPoint (pt));
7824 if (bar)
7826 f1 = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
7830 if (f1 == 0 && insist > 0)
7831 f1 = SELECTED_FRAME ();
7833 if (f1)
7835 /* Ok, we found a frame. Store all the values.
7836 last_mouse_glyph is a rectangle used to reduce the
7837 generation of mouse events. To not miss any motion
7838 events, we must divide the frame into rectangles of the
7839 size of the smallest character that could be displayed
7840 on it, i.e. into the same rectangles that matrices on
7841 the frame are divided into. */
7843 #if OLD_REDISPLAY_CODE
7844 int ignore1, ignore2;
7846 ScreenToClient (FRAME_W32_WINDOW (f1), &pt);
7848 pixel_to_glyph_coords (f1, pt.x, pt.y, &ignore1, &ignore2,
7849 &last_mouse_glyph,
7850 FRAME_W32_DISPLAY_INFO (f1)->grabbed
7851 || insist);
7852 #else
7853 ScreenToClient (FRAME_W32_WINDOW (f1), &pt);
7854 remember_mouse_glyph (f1, pt.x, pt.y);
7855 #endif
7857 *bar_window = Qnil;
7858 *part = 0;
7859 *fp = f1;
7860 XSETINT (*x, pt.x);
7861 XSETINT (*y, pt.y);
7862 *time = last_mouse_movement_time;
7867 UNBLOCK_INPUT;
7871 /* Scroll bar support. */
7873 /* Given a window ID, find the struct scroll_bar which manages it.
7874 This can be called in GC, so we have to make sure to strip off mark
7875 bits. */
7877 static struct scroll_bar *
7878 x_window_to_scroll_bar (window_id)
7879 Window window_id;
7881 Lisp_Object tail;
7883 for (tail = Vframe_list;
7884 XGCTYPE (tail) == Lisp_Cons;
7885 tail = XCDR (tail))
7887 Lisp_Object frame, bar, condemned;
7889 frame = XCAR (tail);
7890 /* All elements of Vframe_list should be frames. */
7891 if (! GC_FRAMEP (frame))
7892 abort ();
7894 /* Scan this frame's scroll bar list for a scroll bar with the
7895 right window ID. */
7896 condemned = FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame));
7897 for (bar = FRAME_SCROLL_BARS (XFRAME (frame));
7898 /* This trick allows us to search both the ordinary and
7899 condemned scroll bar lists with one loop. */
7900 ! GC_NILP (bar) || (bar = condemned,
7901 condemned = Qnil,
7902 ! GC_NILP (bar));
7903 bar = XSCROLL_BAR (bar)->next)
7904 if (SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar)) == window_id)
7905 return XSCROLL_BAR (bar);
7908 return 0;
7913 /* Set the thumb size and position of scroll bar BAR. We are currently
7914 displaying PORTION out of a whole WHOLE, and our position POSITION. */
7916 static void
7917 w32_set_scroll_bar_thumb (bar, portion, position, whole)
7918 struct scroll_bar *bar;
7919 int portion, position, whole;
7921 Window w = SCROLL_BAR_W32_WINDOW (bar);
7922 double range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
7923 int sb_page, sb_pos;
7924 BOOL draggingp = !NILP (bar->dragging) ? TRUE : FALSE;
7926 if (whole)
7928 /* Position scroll bar at rock bottom if the bottom of the
7929 buffer is visible. This avoids shinking the thumb away
7930 to nothing if it is held at the bottom of the buffer. */
7931 if (position + portion >= whole)
7933 sb_page = range * (whole - position) / whole
7934 + VERTICAL_SCROLL_BAR_MIN_HANDLE;
7935 sb_pos = range;
7938 sb_page = portion * range / whole + VERTICAL_SCROLL_BAR_MIN_HANDLE;
7939 sb_pos = position * range / whole;
7941 else
7943 sb_page = range;
7944 sb_pos = 0;
7947 BLOCK_INPUT;
7949 if (pfnSetScrollInfo)
7951 SCROLLINFO si;
7953 si.cbSize = sizeof (si);
7954 /* Only update page size if currently dragging, to reduce
7955 flicker effects. */
7956 if (draggingp)
7957 si.fMask = SIF_PAGE;
7958 else
7959 si.fMask = SIF_PAGE | SIF_POS;
7960 si.nPage = sb_page;
7961 si.nPos = sb_pos;
7963 pfnSetScrollInfo (w, SB_CTL, &si, !draggingp);
7965 else
7966 SetScrollPos (w, SB_CTL, sb_pos, !draggingp);
7968 UNBLOCK_INPUT;
7972 /************************************************************************
7973 Scroll bars, general
7974 ************************************************************************/
7976 HWND
7977 my_create_scrollbar (f, bar)
7978 struct frame * f;
7979 struct scroll_bar * bar;
7981 return (HWND) SendMessage (FRAME_W32_WINDOW (f),
7982 WM_EMACS_CREATESCROLLBAR, (WPARAM) f,
7983 (LPARAM) bar);
7986 /*#define ATTACH_THREADS*/
7988 BOOL
7989 my_show_window (FRAME_PTR f, HWND hwnd, int how)
7991 #ifndef ATTACH_THREADS
7992 return SendMessage (FRAME_W32_WINDOW (f), WM_EMACS_SHOWWINDOW,
7993 (WPARAM) hwnd, (LPARAM) how);
7994 #else
7995 return ShowWindow (hwnd, how);
7996 #endif
7999 void
8000 my_set_window_pos (HWND hwnd, HWND hwndAfter,
8001 int x, int y, int cx, int cy, UINT flags)
8003 #ifndef ATTACH_THREADS
8004 WINDOWPOS pos;
8005 pos.hwndInsertAfter = hwndAfter;
8006 pos.x = x;
8007 pos.y = y;
8008 pos.cx = cx;
8009 pos.cy = cy;
8010 pos.flags = flags;
8011 SendMessage (hwnd, WM_EMACS_SETWINDOWPOS, (WPARAM) &pos, 0);
8012 #else
8013 SetWindowPos (hwnd, hwndAfter, x, y, cx, cy, flags);
8014 #endif
8017 void
8018 my_set_focus (f, hwnd)
8019 struct frame * f;
8020 HWND hwnd;
8022 SendMessage (FRAME_W32_WINDOW (f), WM_EMACS_SETFOCUS,
8023 (WPARAM) hwnd, 0);
8026 void
8027 my_set_foreground_window (hwnd)
8028 HWND hwnd;
8030 SendMessage (hwnd, WM_EMACS_SETFOREGROUND, (WPARAM) hwnd, 0);
8033 void
8034 my_destroy_window (f, hwnd)
8035 struct frame * f;
8036 HWND hwnd;
8038 SendMessage (FRAME_W32_WINDOW (f), WM_EMACS_DESTROYWINDOW,
8039 (WPARAM) hwnd, 0);
8042 /* Create a scroll bar and return the scroll bar vector for it. W is
8043 the Emacs window on which to create the scroll bar. TOP, LEFT,
8044 WIDTH and HEIGHT are.the pixel coordinates and dimensions of the
8045 scroll bar. */
8047 static struct scroll_bar *
8048 x_scroll_bar_create (w, top, left, width, height)
8049 struct window *w;
8050 int top, left, width, height;
8052 struct frame *f = XFRAME (WINDOW_FRAME (w));
8053 HWND hwnd;
8054 struct scroll_bar *bar
8055 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
8057 BLOCK_INPUT;
8059 XSETWINDOW (bar->window, w);
8060 XSETINT (bar->top, top);
8061 XSETINT (bar->left, left);
8062 XSETINT (bar->width, width);
8063 XSETINT (bar->height, height);
8064 XSETINT (bar->start, 0);
8065 XSETINT (bar->end, 0);
8066 bar->dragging = Qnil;
8068 /* Requires geometry to be set before call to create the real window */
8070 hwnd = my_create_scrollbar (f, bar);
8072 if (pfnSetScrollInfo)
8074 SCROLLINFO si;
8076 si.cbSize = sizeof (si);
8077 si.fMask = SIF_ALL;
8078 si.nMin = 0;
8079 si.nMax = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height)
8080 + VERTICAL_SCROLL_BAR_MIN_HANDLE;
8081 si.nPage = si.nMax;
8082 si.nPos = 0;
8084 pfnSetScrollInfo (hwnd, SB_CTL, &si, FALSE);
8086 else
8088 SetScrollRange (hwnd, SB_CTL, 0,
8089 VERTICAL_SCROLL_BAR_TOP_RANGE (f, height), FALSE);
8090 SetScrollPos (hwnd, SB_CTL, 0, FALSE);
8093 SET_SCROLL_BAR_W32_WINDOW (bar, hwnd);
8095 /* Add bar to its frame's list of scroll bars. */
8096 bar->next = FRAME_SCROLL_BARS (f);
8097 bar->prev = Qnil;
8098 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
8099 if (! NILP (bar->next))
8100 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
8102 UNBLOCK_INPUT;
8104 return bar;
8108 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
8109 nil. */
8111 static void
8112 x_scroll_bar_remove (bar)
8113 struct scroll_bar *bar;
8115 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
8117 BLOCK_INPUT;
8119 /* Destroy the window. */
8120 my_destroy_window (f, SCROLL_BAR_W32_WINDOW (bar));
8122 /* Disassociate this scroll bar from its window. */
8123 XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
8125 UNBLOCK_INPUT;
8128 /* Set the handle of the vertical scroll bar for WINDOW to indicate
8129 that we are displaying PORTION characters out of a total of WHOLE
8130 characters, starting at POSITION. If WINDOW has no scroll bar,
8131 create one. */
8132 static void
8133 w32_set_vertical_scroll_bar (w, portion, whole, position)
8134 struct window *w;
8135 int portion, whole, position;
8137 struct frame *f = XFRAME (w->frame);
8138 struct scroll_bar *bar;
8139 int top, height, left, sb_left, width, sb_width;
8140 int window_x, window_y, window_width, window_height;
8142 /* Get window dimensions. */
8143 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
8144 top = window_y;
8145 width = FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f);
8146 height = window_height;
8148 /* Compute the left edge of the scroll bar area. */
8149 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
8150 left = XINT (w->left) + XINT (w->width) - FRAME_SCROLL_BAR_COLS (f);
8151 else
8152 left = XFASTINT (w->left);
8153 left *= CANON_X_UNIT (f);
8154 left += FRAME_INTERNAL_BORDER_WIDTH (f);
8156 /* Compute the width of the scroll bar which might be less than
8157 the width of the area reserved for the scroll bar. */
8158 if (FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0)
8159 sb_width = FRAME_SCROLL_BAR_PIXEL_WIDTH (f);
8160 else
8161 sb_width = width;
8163 /* Compute the left edge of the scroll bar. */
8164 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
8165 sb_left = left + width - sb_width - (width - sb_width) / 2;
8166 else
8167 sb_left = left + (width - sb_width) / 2;
8169 /* Does the scroll bar exist yet? */
8170 if (NILP (w->vertical_scroll_bar))
8172 HDC hdc;
8173 BLOCK_INPUT;
8174 if (width > 0 && height > 0)
8176 hdc = get_frame_dc (f);
8177 w32_clear_area (f, hdc, left, top, width, height);
8178 release_frame_dc (f, hdc);
8180 UNBLOCK_INPUT;
8182 bar = x_scroll_bar_create (w, top, sb_left, sb_width, height);
8184 else
8186 /* It may just need to be moved and resized. */
8187 HWND hwnd;
8189 bar = XSCROLL_BAR (w->vertical_scroll_bar);
8190 hwnd = SCROLL_BAR_W32_WINDOW (bar);
8192 /* If already correctly positioned, do nothing. */
8193 if ( XINT (bar->left) == sb_left
8194 && XINT (bar->top) == top
8195 && XINT (bar->width) == sb_width
8196 && XINT (bar->height) == height )
8198 /* Redraw after clear_frame. */
8199 if (!my_show_window (f, hwnd, SW_NORMAL))
8200 InvalidateRect (hwnd, NULL, FALSE);
8202 else
8204 HDC hdc;
8205 BLOCK_INPUT;
8206 if (width && height)
8208 hdc = get_frame_dc (f);
8209 /* Since Windows scroll bars are smaller than the space reserved
8210 for them on the frame, we have to clear "under" them. */
8211 w32_clear_area (f, hdc,
8212 left,
8213 top,
8214 width,
8215 height);
8216 release_frame_dc (f, hdc);
8218 /* Make sure scroll bar is "visible" before moving, to ensure the
8219 area of the parent window now exposed will be refreshed. */
8220 my_show_window (f, hwnd, SW_HIDE);
8221 MoveWindow (hwnd, sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8222 top, sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
8223 max (height, 1), TRUE);
8224 if (pfnSetScrollInfo)
8226 SCROLLINFO si;
8228 si.cbSize = sizeof (si);
8229 si.fMask = SIF_RANGE;
8230 si.nMin = 0;
8231 si.nMax = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height)
8232 + VERTICAL_SCROLL_BAR_MIN_HANDLE;
8234 pfnSetScrollInfo (hwnd, SB_CTL, &si, FALSE);
8236 else
8237 SetScrollRange (hwnd, SB_CTL, 0,
8238 VERTICAL_SCROLL_BAR_TOP_RANGE (f, height), FALSE);
8239 my_show_window (f, hwnd, SW_NORMAL);
8240 /* InvalidateRect (w, NULL, FALSE); */
8242 /* Remember new settings. */
8243 XSETINT (bar->left, sb_left);
8244 XSETINT (bar->top, top);
8245 XSETINT (bar->width, sb_width);
8246 XSETINT (bar->height, height);
8248 UNBLOCK_INPUT;
8251 w32_set_scroll_bar_thumb (bar, portion, position, whole);
8253 XSETVECTOR (w->vertical_scroll_bar, bar);
8257 /* The following three hooks are used when we're doing a thorough
8258 redisplay of the frame. We don't explicitly know which scroll bars
8259 are going to be deleted, because keeping track of when windows go
8260 away is a real pain - "Can you say set-window-configuration, boys
8261 and girls?" Instead, we just assert at the beginning of redisplay
8262 that *all* scroll bars are to be removed, and then save a scroll bar
8263 from the fiery pit when we actually redisplay its window. */
8265 /* Arrange for all scroll bars on FRAME to be removed at the next call
8266 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
8267 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
8269 static void
8270 w32_condemn_scroll_bars (frame)
8271 FRAME_PTR frame;
8273 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
8274 while (! NILP (FRAME_SCROLL_BARS (frame)))
8276 Lisp_Object bar;
8277 bar = FRAME_SCROLL_BARS (frame);
8278 FRAME_SCROLL_BARS (frame) = XSCROLL_BAR (bar)->next;
8279 XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
8280 XSCROLL_BAR (bar)->prev = Qnil;
8281 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
8282 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
8283 FRAME_CONDEMNED_SCROLL_BARS (frame) = bar;
8288 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
8289 Note that WINDOW isn't necessarily condemned at all. */
8291 static void
8292 w32_redeem_scroll_bar (window)
8293 struct window *window;
8295 struct scroll_bar *bar;
8296 struct frame *f;
8298 /* We can't redeem this window's scroll bar if it doesn't have one. */
8299 if (NILP (window->vertical_scroll_bar))
8300 abort ();
8302 bar = XSCROLL_BAR (window->vertical_scroll_bar);
8304 /* Unlink it from the condemned list. */
8305 f = XFRAME (WINDOW_FRAME (window));
8306 if (NILP (bar->prev))
8308 /* If the prev pointer is nil, it must be the first in one of
8309 the lists. */
8310 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
8311 /* It's not condemned. Everything's fine. */
8312 return;
8313 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
8314 window->vertical_scroll_bar))
8315 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
8316 else
8317 /* If its prev pointer is nil, it must be at the front of
8318 one or the other! */
8319 abort ();
8321 else
8322 XSCROLL_BAR (bar->prev)->next = bar->next;
8324 if (! NILP (bar->next))
8325 XSCROLL_BAR (bar->next)->prev = bar->prev;
8327 bar->next = FRAME_SCROLL_BARS (f);
8328 bar->prev = Qnil;
8329 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
8330 if (! NILP (bar->next))
8331 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
8334 /* Remove all scroll bars on FRAME that haven't been saved since the
8335 last call to `*condemn_scroll_bars_hook'. */
8337 static void
8338 w32_judge_scroll_bars (f)
8339 FRAME_PTR f;
8341 Lisp_Object bar, next;
8343 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
8345 /* Clear out the condemned list now so we won't try to process any
8346 more events on the hapless scroll bars. */
8347 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
8349 for (; ! NILP (bar); bar = next)
8351 struct scroll_bar *b = XSCROLL_BAR (bar);
8353 x_scroll_bar_remove (b);
8355 next = b->next;
8356 b->next = b->prev = Qnil;
8359 /* Now there should be no references to the condemned scroll bars,
8360 and they should get garbage-collected. */
8363 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
8364 is set to something other than NO_EVENT, it is enqueued.
8366 This may be called from a signal handler, so we have to ignore GC
8367 mark bits. */
8369 static int
8370 w32_scroll_bar_handle_click (bar, msg, emacs_event)
8371 struct scroll_bar *bar;
8372 W32Msg *msg;
8373 struct input_event *emacs_event;
8375 if (! GC_WINDOWP (bar->window))
8376 abort ();
8378 emacs_event->kind = W32_SCROLL_BAR_CLICK_EVENT;
8379 emacs_event->code = 0;
8380 /* not really meaningful to distinguish up/down */
8381 emacs_event->modifiers = msg->dwModifiers;
8382 emacs_event->frame_or_window = bar->window;
8383 emacs_event->arg = Qnil;
8384 emacs_event->timestamp = msg->msg.time;
8387 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
8388 int y;
8389 int dragging = !NILP (bar->dragging);
8391 if (pfnGetScrollInfo)
8393 SCROLLINFO si;
8395 si.cbSize = sizeof (si);
8396 si.fMask = SIF_POS;
8398 pfnGetScrollInfo ((HWND) msg->msg.lParam, SB_CTL, &si);
8399 y = si.nPos;
8401 else
8402 y = GetScrollPos ((HWND) msg->msg.lParam, SB_CTL);
8404 bar->dragging = Qnil;
8407 last_mouse_scroll_bar_pos = msg->msg.wParam;
8409 switch (LOWORD (msg->msg.wParam))
8411 case SB_LINEDOWN:
8412 emacs_event->part = scroll_bar_down_arrow;
8413 break;
8414 case SB_LINEUP:
8415 emacs_event->part = scroll_bar_up_arrow;
8416 break;
8417 case SB_PAGEUP:
8418 emacs_event->part = scroll_bar_above_handle;
8419 break;
8420 case SB_PAGEDOWN:
8421 emacs_event->part = scroll_bar_below_handle;
8422 break;
8423 case SB_TOP:
8424 emacs_event->part = scroll_bar_handle;
8425 y = 0;
8426 break;
8427 case SB_BOTTOM:
8428 emacs_event->part = scroll_bar_handle;
8429 y = top_range;
8430 break;
8431 case SB_THUMBTRACK:
8432 case SB_THUMBPOSITION:
8433 if (VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height)) <= 0xffff)
8434 y = HIWORD (msg->msg.wParam);
8435 bar->dragging = Qt;
8436 emacs_event->part = scroll_bar_handle;
8438 /* "Silently" update current position. */
8439 if (pfnSetScrollInfo)
8441 SCROLLINFO si;
8443 si.cbSize = sizeof (si);
8444 si.fMask = SIF_POS;
8445 si.nPos = y;
8446 /* Remember apparent position (we actually lag behind the real
8447 position, so don't set that directly. */
8448 last_scroll_bar_drag_pos = y;
8450 pfnSetScrollInfo (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, &si, FALSE);
8452 else
8453 SetScrollPos (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, y, FALSE);
8454 break;
8455 case SB_ENDSCROLL:
8456 /* If this is the end of a drag sequence, then reset the scroll
8457 handle size to normal and do a final redraw. Otherwise do
8458 nothing. */
8459 if (dragging)
8461 if (pfnSetScrollInfo)
8463 SCROLLINFO si;
8464 int start = XINT (bar->start);
8465 int end = XINT (bar->end);
8467 si.cbSize = sizeof (si);
8468 si.fMask = SIF_PAGE | SIF_POS;
8469 si.nPage = end - start + VERTICAL_SCROLL_BAR_MIN_HANDLE;
8470 si.nPos = last_scroll_bar_drag_pos;
8471 pfnSetScrollInfo (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, &si, TRUE);
8473 else
8474 SetScrollPos (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, y, TRUE);
8476 /* fall through */
8477 default:
8478 emacs_event->kind = NO_EVENT;
8479 return FALSE;
8482 XSETINT (emacs_event->x, y);
8483 XSETINT (emacs_event->y, top_range);
8485 return TRUE;
8489 /* Return information to the user about the current position of the mouse
8490 on the scroll bar. */
8492 static void
8493 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
8494 FRAME_PTR *fp;
8495 Lisp_Object *bar_window;
8496 enum scroll_bar_part *part;
8497 Lisp_Object *x, *y;
8498 unsigned long *time;
8500 struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
8501 Window w = SCROLL_BAR_W32_WINDOW (bar);
8502 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
8503 int pos;
8504 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
8506 BLOCK_INPUT;
8508 *fp = f;
8509 *bar_window = bar->window;
8511 if (pfnGetScrollInfo)
8513 SCROLLINFO si;
8515 si.cbSize = sizeof (si);
8516 si.fMask = SIF_POS | SIF_PAGE | SIF_RANGE;
8518 pfnGetScrollInfo (w, SB_CTL, &si);
8519 pos = si.nPos;
8520 top_range = si.nMax - si.nPage + 1;
8522 else
8523 pos = GetScrollPos (w, SB_CTL);
8525 switch (LOWORD (last_mouse_scroll_bar_pos))
8527 case SB_THUMBPOSITION:
8528 case SB_THUMBTRACK:
8529 *part = scroll_bar_handle;
8530 if (VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height)) <= 0xffff)
8531 pos = HIWORD (last_mouse_scroll_bar_pos);
8532 break;
8533 case SB_LINEDOWN:
8534 *part = scroll_bar_handle;
8535 pos++;
8536 break;
8537 default:
8538 *part = scroll_bar_handle;
8539 break;
8542 XSETINT (*x, pos);
8543 XSETINT (*y, top_range);
8545 f->mouse_moved = 0;
8546 last_mouse_scroll_bar = Qnil;
8548 *time = last_mouse_movement_time;
8550 UNBLOCK_INPUT;
8554 /* The screen has been cleared so we may have changed foreground or
8555 background colors, and the scroll bars may need to be redrawn.
8556 Clear out the scroll bars, and ask for expose events, so we can
8557 redraw them. */
8559 void
8560 x_scroll_bar_clear (f)
8561 FRAME_PTR f;
8563 Lisp_Object bar;
8565 /* We can have scroll bars even if this is 0,
8566 if we just turned off scroll bar mode.
8567 But in that case we should not clear them. */
8568 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
8569 for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar);
8570 bar = XSCROLL_BAR (bar)->next)
8572 HWND window = SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar));
8573 HDC hdc = GetDC (window);
8574 RECT rect;
8576 /* Hide scroll bar until ready to repaint. x_scroll_bar_move
8577 arranges to refresh the scroll bar if hidden. */
8578 my_show_window (f, window, SW_HIDE);
8580 GetClientRect (window, &rect);
8581 select_palette (f, hdc);
8582 w32_clear_rect (f, hdc, &rect);
8583 deselect_palette (f, hdc);
8585 ReleaseDC (window, hdc);
8590 /* The main W32 event-reading loop - w32_read_socket. */
8592 /* Record the last 100 characters stored
8593 to help debug the loss-of-chars-during-GC problem. */
8595 static int temp_index;
8596 static short temp_buffer[100];
8599 /* Read events coming from the W32 shell.
8600 This routine is called by the SIGIO handler.
8601 We return as soon as there are no more events to be read.
8603 Events representing keys are stored in buffer BUFP,
8604 which can hold up to NUMCHARS characters.
8605 We return the number of characters stored into the buffer,
8606 thus pretending to be `read'.
8608 EXPECTED is nonzero if the caller knows input is available.
8610 Some of these messages are reposted back to the message queue since the
8611 system calls the windows proc directly in a context where we cannot return
8612 the data nor can we guarantee the state we are in. So if we dispatch them
8613 we will get into an infinite loop. To prevent this from ever happening we
8614 will set a variable to indicate we are in the read_socket call and indicate
8615 which message we are processing since the windows proc gets called
8616 recursively with different messages by the system.
8620 w32_read_socket (sd, bufp, numchars, expected)
8621 register int sd;
8622 /* register */ struct input_event *bufp;
8623 /* register */ int numchars;
8624 int expected;
8626 int count = 0;
8627 int check_visibility = 0;
8628 W32Msg msg;
8629 struct frame *f;
8630 struct w32_display_info *dpyinfo = &one_w32_display_info;
8632 if (interrupt_input_blocked)
8634 interrupt_input_pending = 1;
8635 return -1;
8638 interrupt_input_pending = 0;
8639 BLOCK_INPUT;
8641 /* So people can tell when we have read the available input. */
8642 input_signal_count++;
8644 if (numchars <= 0)
8645 abort (); /* Don't think this happens. */
8647 /* TODO: tool-bars, ghostscript integration, mouse
8648 cursors. */
8649 while (get_next_msg (&msg, FALSE))
8651 switch (msg.msg.message)
8653 case WM_PAINT:
8654 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
8656 if (f)
8658 if (msg.rect.right == msg.rect.left ||
8659 msg.rect.bottom == msg.rect.top)
8661 /* We may get paint messages even though the client
8662 area is clipped - these are not expose events. */
8663 DebPrint (("clipped frame %p (%s) got WM_PAINT - ignored\n", f,
8664 SDATA (f->name)));
8666 else if (f->async_visible != 1)
8668 /* Definitely not obscured, so mark as visible. */
8669 f->async_visible = 1;
8670 f->async_iconified = 0;
8671 SET_FRAME_GARBAGED (f);
8672 DebPrint (("frame %p (%s) reexposed by WM_PAINT\n", f,
8673 SDATA (f->name)));
8675 /* WM_PAINT serves as MapNotify as well, so report
8676 visibility changes properly. */
8677 if (f->iconified)
8679 bufp->kind = DEICONIFY_EVENT;
8680 XSETFRAME (bufp->frame_or_window, f);
8681 bufp->arg = Qnil;
8682 bufp++;
8683 count++;
8684 numchars--;
8686 else if (! NILP (Vframe_list)
8687 && ! NILP (XCDR (Vframe_list)))
8688 /* Force a redisplay sooner or later to update the
8689 frame titles in case this is the second frame. */
8690 record_asynch_buffer_change ();
8692 else
8694 HDC hdc = get_frame_dc (f);
8696 /* Erase background again for safety. */
8697 w32_clear_rect (f, hdc, &msg.rect);
8698 release_frame_dc (f, hdc);
8699 expose_frame (f,
8700 msg.rect.left,
8701 msg.rect.top,
8702 msg.rect.right - msg.rect.left,
8703 msg.rect.bottom - msg.rect.top);
8706 break;
8708 case WM_INPUTLANGCHANGE:
8709 /* Generate a language change event. */
8710 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
8712 if (f)
8714 if (numchars == 0)
8715 abort ();
8717 bufp->kind = LANGUAGE_CHANGE_EVENT;
8718 XSETFRAME (bufp->frame_or_window, f);
8719 bufp->arg = Qnil;
8720 bufp->code = msg.msg.wParam;
8721 bufp->modifiers = msg.msg.lParam & 0xffff;
8722 bufp++;
8723 count++;
8724 numchars--;
8726 break;
8728 case WM_KEYDOWN:
8729 case WM_SYSKEYDOWN:
8730 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
8732 if (f && !f->iconified)
8734 if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight))
8736 dpyinfo->mouse_face_hidden = 1;
8737 clear_mouse_face (dpyinfo);
8740 if (temp_index == sizeof temp_buffer / sizeof (short))
8741 temp_index = 0;
8742 temp_buffer[temp_index++] = msg.msg.wParam;
8743 bufp->kind = NON_ASCII_KEYSTROKE_EVENT;
8744 bufp->code = msg.msg.wParam;
8745 bufp->modifiers = msg.dwModifiers;
8746 XSETFRAME (bufp->frame_or_window, f);
8747 bufp->arg = Qnil;
8748 bufp->timestamp = msg.msg.time;
8749 bufp++;
8750 numchars--;
8751 count++;
8753 break;
8755 case WM_SYSCHAR:
8756 case WM_CHAR:
8757 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
8759 if (f && !f->iconified)
8761 if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight))
8763 dpyinfo->mouse_face_hidden = 1;
8764 clear_mouse_face (dpyinfo);
8767 if (temp_index == sizeof temp_buffer / sizeof (short))
8768 temp_index = 0;
8769 temp_buffer[temp_index++] = msg.msg.wParam;
8770 bufp->kind = ASCII_KEYSTROKE_EVENT;
8771 bufp->code = msg.msg.wParam;
8772 bufp->modifiers = msg.dwModifiers;
8773 XSETFRAME (bufp->frame_or_window, f);
8774 bufp->arg = Qnil;
8775 bufp->timestamp = msg.msg.time;
8776 bufp++;
8777 numchars--;
8778 count++;
8780 break;
8782 case WM_MOUSEMOVE:
8783 /* Ignore non-movement. */
8785 int x = LOWORD (msg.msg.lParam);
8786 int y = HIWORD (msg.msg.lParam);
8787 if (x == last_mousemove_x && y == last_mousemove_y)
8788 break;
8789 last_mousemove_x = x;
8790 last_mousemove_y = y;
8793 previous_help_echo = help_echo;
8795 if (dpyinfo->grabbed && last_mouse_frame
8796 && FRAME_LIVE_P (last_mouse_frame))
8797 f = last_mouse_frame;
8798 else
8799 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
8801 if (dpyinfo->mouse_face_hidden)
8803 dpyinfo->mouse_face_hidden = 0;
8804 clear_mouse_face (dpyinfo);
8807 if (f)
8808 note_mouse_movement (f, &msg.msg);
8809 else
8811 /* If we move outside the frame, then we're
8812 certainly no longer on any text in the frame. */
8813 clear_mouse_face (dpyinfo);
8816 /* If the contents of the global variable help_echo
8817 has changed, generate a HELP_EVENT. */
8818 if (help_echo != previous_help_echo ||
8819 (!NILP (help_echo) && !STRINGP (help_echo) && f->mouse_moved))
8821 Lisp_Object frame;
8822 int n;
8824 if (help_echo == Qnil)
8826 help_echo_object = help_echo_window = Qnil;
8827 help_echo_pos = -1;
8830 if (f)
8831 XSETFRAME (frame, f);
8832 else
8833 frame = Qnil;
8835 any_help_event_p = 1;
8836 n = gen_help_event (bufp, numchars, help_echo, frame,
8837 help_echo_window, help_echo_object,
8838 help_echo_pos);
8839 bufp += n, count += n, numchars -= n;
8841 break;
8843 case WM_LBUTTONDOWN:
8844 case WM_LBUTTONUP:
8845 case WM_MBUTTONDOWN:
8846 case WM_MBUTTONUP:
8847 case WM_RBUTTONDOWN:
8848 case WM_RBUTTONUP:
8849 case WM_XBUTTONDOWN:
8850 case WM_XBUTTONUP:
8852 /* If we decide we want to generate an event to be seen
8853 by the rest of Emacs, we put it here. */
8854 struct input_event emacs_event;
8855 int tool_bar_p = 0;
8856 int button;
8857 int up;
8859 emacs_event.kind = NO_EVENT;
8861 if (dpyinfo->grabbed && last_mouse_frame
8862 && FRAME_LIVE_P (last_mouse_frame))
8863 f = last_mouse_frame;
8864 else
8865 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
8867 if (f)
8869 construct_mouse_click (&emacs_event, &msg, f);
8871 /* Is this in the tool-bar? */
8872 if (WINDOWP (f->tool_bar_window)
8873 && XFASTINT (XWINDOW (f->tool_bar_window)->height))
8875 Lisp_Object window;
8876 int p, x, y;
8878 x = XFASTINT (emacs_event.x);
8879 y = XFASTINT (emacs_event.y);
8881 /* Set x and y. */
8882 window = window_from_coordinates (f, x, y, &p, 1);
8884 if (EQ (window, f->tool_bar_window))
8886 w32_handle_tool_bar_click (f, &emacs_event);
8887 tool_bar_p = 1;
8891 if (!tool_bar_p)
8892 if (!dpyinfo->w32_focus_frame
8893 || f == dpyinfo->w32_focus_frame
8894 && (numchars >= 1))
8896 construct_mouse_click (bufp, &msg, f);
8897 bufp++;
8898 count++;
8899 numchars--;
8903 parse_button (msg.msg.message, HIWORD (msg.msg.wParam),
8904 &button, &up);
8906 if (up)
8908 dpyinfo->grabbed &= ~ (1 << button);
8910 else
8912 dpyinfo->grabbed |= (1 << button);
8913 last_mouse_frame = f;
8914 /* Ignore any mouse motion that happened
8915 before this event; any subsequent mouse-movement
8916 Emacs events should reflect only motion after
8917 the ButtonPress. */
8918 if (f != 0)
8919 f->mouse_moved = 0;
8921 if (!tool_bar_p)
8922 last_tool_bar_item = -1;
8924 break;
8927 case WM_MOUSEWHEEL:
8928 if (dpyinfo->grabbed && last_mouse_frame
8929 && FRAME_LIVE_P (last_mouse_frame))
8930 f = last_mouse_frame;
8931 else
8932 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
8934 if (f)
8936 if ((!dpyinfo->w32_focus_frame
8937 || f == dpyinfo->w32_focus_frame)
8938 && (numchars >= 1))
8940 construct_mouse_wheel (bufp, &msg, f);
8941 bufp++;
8942 count++;
8943 numchars--;
8946 break;
8948 case WM_DROPFILES:
8949 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
8951 if (f)
8953 construct_drag_n_drop (bufp, &msg, f);
8954 bufp++;
8955 count++;
8956 numchars--;
8958 break;
8960 case WM_VSCROLL:
8962 struct scroll_bar *bar =
8963 x_window_to_scroll_bar ((HWND)msg.msg.lParam);
8965 if (bar && numchars >= 1)
8967 if (w32_scroll_bar_handle_click (bar, &msg, bufp))
8969 bufp++;
8970 count++;
8971 numchars--;
8974 break;
8977 case WM_WINDOWPOSCHANGED:
8978 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
8979 if (f)
8981 x_check_fullscreen_move(f);
8982 if (f->output_data.w32->want_fullscreen & FULLSCREEN_WAIT)
8983 f->output_data.w32->want_fullscreen &=
8984 ~(FULLSCREEN_WAIT|FULLSCREEN_BOTH);
8986 check_visibility = 1;
8987 break;
8989 case WM_ACTIVATE:
8990 case WM_ACTIVATEAPP:
8991 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
8992 if (f)
8993 x_check_fullscreen (f);
8994 check_visibility = 1;
8995 break;
8997 case WM_MOVE:
8998 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
9000 if (f && !f->async_iconified)
9002 int x, y;
9004 x_real_positions (f, &x, &y);
9005 f->output_data.w32->left_pos = x;
9006 f->output_data.w32->top_pos = y;
9009 check_visibility = 1;
9010 break;
9012 case WM_SHOWWINDOW:
9013 /* wParam non-zero means Window is about to be shown, 0 means
9014 about to be hidden. */
9015 /* Redo the mouse-highlight after the tooltip has gone. */
9016 if (!msg.msg.wParam && msg.msg.hwnd == tip_window)
9018 tip_window = NULL;
9019 redo_mouse_highlight ();
9022 /* If window has been obscured or exposed by another window
9023 being maximised or minimised/restored, then recheck
9024 visibility of all frames. Direct changes to our own
9025 windows get handled by WM_SIZE. */
9026 #if 0
9027 if (msg.msg.lParam != 0)
9028 check_visibility = 1;
9029 else
9031 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
9032 f->async_visible = msg.msg.wParam;
9034 #endif
9036 check_visibility = 1;
9037 break;
9039 case WM_SIZE:
9040 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
9042 /* Inform lisp of whether frame has been iconified etc. */
9043 if (f)
9045 switch (msg.msg.wParam)
9047 case SIZE_MINIMIZED:
9048 f->async_visible = 0;
9049 f->async_iconified = 1;
9051 bufp->kind = ICONIFY_EVENT;
9052 XSETFRAME (bufp->frame_or_window, f);
9053 bufp->arg = Qnil;
9054 bufp++;
9055 count++;
9056 numchars--;
9057 break;
9059 case SIZE_MAXIMIZED:
9060 case SIZE_RESTORED:
9061 f->async_visible = 1;
9062 f->async_iconified = 0;
9064 /* wait_reading_process_input will notice this and update
9065 the frame's display structures. */
9066 SET_FRAME_GARBAGED (f);
9068 if (f->iconified)
9070 int x, y;
9072 /* Reset top and left positions of the Window
9073 here since Windows sends a WM_MOVE message
9074 BEFORE telling us the Window is minimized
9075 when the Window is iconified, with 3000,3000
9076 as the co-ords. */
9077 x_real_positions (f, &x, &y);
9078 f->output_data.w32->left_pos = x;
9079 f->output_data.w32->top_pos = y;
9081 bufp->kind = DEICONIFY_EVENT;
9082 XSETFRAME (bufp->frame_or_window, f);
9083 bufp->arg = Qnil;
9084 bufp++;
9085 count++;
9086 numchars--;
9088 else if (! NILP (Vframe_list)
9089 && ! NILP (XCDR (Vframe_list)))
9090 /* Force a redisplay sooner or later
9091 to update the frame titles
9092 in case this is the second frame. */
9093 record_asynch_buffer_change ();
9094 break;
9098 if (f && !f->async_iconified && msg.msg.wParam != SIZE_MINIMIZED)
9100 RECT rect;
9101 int rows;
9102 int columns;
9103 int width;
9104 int height;
9106 GetClientRect (msg.msg.hwnd, &rect);
9108 height = rect.bottom - rect.top;
9109 width = rect.right - rect.left;
9111 rows = PIXEL_TO_CHAR_HEIGHT (f, height);
9112 columns = PIXEL_TO_CHAR_WIDTH (f, width);
9114 /* TODO: Clip size to the screen dimensions. */
9116 /* Even if the number of character rows and columns has
9117 not changed, the font size may have changed, so we need
9118 to check the pixel dimensions as well. */
9120 if (columns != f->width
9121 || rows != f->height
9122 || width != f->output_data.w32->pixel_width
9123 || height != f->output_data.w32->pixel_height)
9125 change_frame_size (f, rows, columns, 0, 1, 0);
9126 SET_FRAME_GARBAGED (f);
9127 cancel_mouse_face (f);
9128 f->output_data.w32->pixel_width = width;
9129 f->output_data.w32->pixel_height = height;
9130 f->output_data.w32->win_gravity = NorthWestGravity;
9134 check_visibility = 1;
9135 break;
9137 case WM_MOUSELEAVE:
9138 f = x_any_window_to_frame (dpyinfo, msg.msg.hwnd);
9139 if (f)
9141 if (f == dpyinfo->mouse_face_mouse_frame)
9143 /* If we move outside the frame, then we're
9144 certainly no longer on any text in the frame. */
9145 clear_mouse_face (dpyinfo);
9146 dpyinfo->mouse_face_mouse_frame = 0;
9149 /* Generate a nil HELP_EVENT to cancel a help-echo.
9150 Do it only if there's something to cancel.
9151 Otherwise, the startup message is cleared when
9152 the mouse leaves the frame. */
9153 if (any_help_event_p)
9155 Lisp_Object frame;
9156 int n;
9158 XSETFRAME (frame, f);
9159 help_echo = Qnil;
9160 n = gen_help_event (bufp, numchars,
9161 Qnil, frame, Qnil, Qnil, 0);
9162 bufp += n, count += n, numchars -= n;
9165 break;
9167 case WM_SETFOCUS:
9168 f = x_any_window_to_frame (dpyinfo, msg.msg.hwnd);
9170 dpyinfo->w32_focus_event_frame = f;
9172 if (f)
9173 x_new_focus_frame (dpyinfo, f);
9176 dpyinfo->grabbed = 0;
9177 check_visibility = 1;
9178 break;
9180 case WM_KILLFOCUS:
9181 /* TODO: some of this belongs in MOUSE_LEAVE */
9182 f = x_top_window_to_frame (dpyinfo, msg.msg.hwnd);
9184 if (f)
9186 if (f == dpyinfo->w32_focus_event_frame)
9187 dpyinfo->w32_focus_event_frame = 0;
9189 if (f == dpyinfo->w32_focus_frame)
9190 x_new_focus_frame (dpyinfo, 0);
9192 if (f == dpyinfo->mouse_face_mouse_frame)
9194 /* If we move outside the frame, then we're
9195 certainly no longer on any text in the frame. */
9196 clear_mouse_face (dpyinfo);
9197 dpyinfo->mouse_face_mouse_frame = 0;
9200 /* Generate a nil HELP_EVENT to cancel a help-echo.
9201 Do it only if there's something to cancel.
9202 Otherwise, the startup message is cleared when
9203 the mouse leaves the frame. */
9204 if (any_help_event_p)
9206 Lisp_Object frame;
9207 int n;
9209 XSETFRAME (frame, f);
9210 help_echo = Qnil;
9211 n = gen_help_event (bufp, numchars,
9212 Qnil, frame, Qnil, Qnil, 0);
9213 bufp += n, count += n, numchars -=n;
9217 dpyinfo->grabbed = 0;
9218 check_visibility = 1;
9219 break;
9221 case WM_CLOSE:
9222 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
9224 if (f)
9226 if (numchars == 0)
9227 abort ();
9229 bufp->kind = DELETE_WINDOW_EVENT;
9230 XSETFRAME (bufp->frame_or_window, f);
9231 bufp->arg = Qnil;
9232 bufp++;
9233 count++;
9234 numchars--;
9236 break;
9238 case WM_INITMENU:
9239 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
9241 if (f)
9243 if (numchars == 0)
9244 abort ();
9246 bufp->kind = MENU_BAR_ACTIVATE_EVENT;
9247 XSETFRAME (bufp->frame_or_window, f);
9248 bufp->arg = Qnil;
9249 bufp++;
9250 count++;
9251 numchars--;
9253 break;
9255 case WM_COMMAND:
9256 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
9258 if (f)
9260 extern void menubar_selection_callback
9261 (FRAME_PTR f, void * client_data);
9262 menubar_selection_callback (f, (void *)msg.msg.wParam);
9265 check_visibility = 1;
9266 break;
9268 case WM_DISPLAYCHANGE:
9269 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
9271 if (f)
9273 dpyinfo->width = (short) LOWORD (msg.msg.lParam);
9274 dpyinfo->height = (short) HIWORD (msg.msg.lParam);
9275 dpyinfo->n_cbits = msg.msg.wParam;
9276 DebPrint (("display change: %d %d\n", dpyinfo->width,
9277 dpyinfo->height));
9280 check_visibility = 1;
9281 break;
9283 default:
9284 /* Check for messages registered at runtime. */
9285 if (msg.msg.message == msh_mousewheel)
9287 if (dpyinfo->grabbed && last_mouse_frame
9288 && FRAME_LIVE_P (last_mouse_frame))
9289 f = last_mouse_frame;
9290 else
9291 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
9293 if (f)
9295 if ((!dpyinfo->w32_focus_frame
9296 || f == dpyinfo->w32_focus_frame)
9297 && (numchars >= 1))
9299 construct_mouse_wheel (bufp, &msg, f);
9300 bufp++;
9301 count++;
9302 numchars--;
9306 break;
9310 /* If the focus was just given to an autoraising frame,
9311 raise it now. */
9312 /* ??? This ought to be able to handle more than one such frame. */
9313 if (pending_autoraise_frame)
9315 x_raise_frame (pending_autoraise_frame);
9316 pending_autoraise_frame = 0;
9319 /* Check which frames are still visisble, if we have enqueued any user
9320 events or been notified of events that may affect visibility. We
9321 do this here because there doesn't seem to be any direct
9322 notification from Windows that the visibility of a window has
9323 changed (at least, not in all cases). */
9324 if (count > 0 || check_visibility)
9326 Lisp_Object tail, frame;
9328 FOR_EACH_FRAME (tail, frame)
9330 FRAME_PTR f = XFRAME (frame);
9331 /* The tooltip has been drawn already. Avoid the
9332 SET_FRAME_GARBAGED below. */
9333 if (EQ (frame, tip_frame))
9334 continue;
9336 /* Check "visible" frames and mark each as obscured or not.
9337 Note that async_visible is nonzero for unobscured and
9338 obscured frames, but zero for hidden and iconified frames. */
9339 if (FRAME_W32_P (f) && f->async_visible)
9341 RECT clipbox;
9342 HDC hdc;
9344 enter_crit ();
9345 /* Query clipping rectangle for the entire window area
9346 (GetWindowDC), not just the client portion (GetDC).
9347 Otherwise, the scrollbars and menubar aren't counted as
9348 part of the visible area of the frame, and we may think
9349 the frame is obscured when really a scrollbar is still
9350 visible and gets WM_PAINT messages above. */
9351 hdc = GetWindowDC (FRAME_W32_WINDOW (f));
9352 GetClipBox (hdc, &clipbox);
9353 ReleaseDC (FRAME_W32_WINDOW (f), hdc);
9354 leave_crit ();
9356 if (clipbox.right == clipbox.left
9357 || clipbox.bottom == clipbox.top)
9359 /* Frame has become completely obscured so mark as
9360 such (we do this by setting async_visible to 2 so
9361 that FRAME_VISIBLE_P is still true, but redisplay
9362 will skip it). */
9363 f->async_visible = 2;
9365 if (!FRAME_OBSCURED_P (f))
9367 DebPrint (("frame %p (%s) obscured\n", f,
9368 SDATA (f->name)));
9371 else
9373 /* Frame is not obscured, so mark it as such. */
9374 f->async_visible = 1;
9376 if (FRAME_OBSCURED_P (f))
9378 SET_FRAME_GARBAGED (f);
9379 DebPrint (("obscured frame %p (%s) found to be visible\n", f,
9380 SDATA (f->name)));
9382 /* Force a redisplay sooner or later. */
9383 record_asynch_buffer_change ();
9390 UNBLOCK_INPUT;
9391 return count;
9397 /***********************************************************************
9398 Text Cursor
9399 ***********************************************************************/
9401 /* Notice if the text cursor of window W has been overwritten by a
9402 drawing operation that outputs glyphs starting at START_X and
9403 ending at END_X in the line given by output_cursor.vpos.
9404 Coordinates are area-relative. END_X < 0 means all the rest
9405 of the line after START_X has been written. */
9407 static void
9408 notice_overwritten_cursor (w, area, x0, x1, y0, y1)
9409 struct window *w;
9410 enum glyph_row_area area;
9411 int x0, x1, y0, y1;
9413 if (area == TEXT_AREA
9414 && w->phys_cursor_on_p
9415 && y0 <= w->phys_cursor.y
9416 && y1 >= w->phys_cursor.y + w->phys_cursor_height
9417 && x0 <= w->phys_cursor.x
9418 && (x1 < 0 || x1 > w->phys_cursor.x))
9419 w->phys_cursor_on_p = 0;
9423 /* Set clipping for output in glyph row ROW. W is the window in which
9424 we operate. GC is the graphics context to set clipping in.
9425 WHOLE_LINE_P non-zero means include the areas used for truncation
9426 mark display and alike in the clipping rectangle.
9428 ROW may be a text row or, e.g., a mode line. Text rows must be
9429 clipped to the interior of the window dedicated to text display,
9430 mode lines must be clipped to the whole window. */
9432 static void
9433 w32_clip_to_row (w, row, hdc, whole_line_p)
9434 struct window *w;
9435 struct glyph_row *row;
9436 HDC hdc;
9437 int whole_line_p;
9439 struct frame *f = XFRAME (WINDOW_FRAME (w));
9440 RECT clip_rect;
9441 int window_x, window_y, window_width, window_height;
9443 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
9445 clip_rect.left = WINDOW_TO_FRAME_PIXEL_X (w, 0);
9446 clip_rect.top = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
9447 clip_rect.top = max (clip_rect.top, window_y);
9448 clip_rect.right = clip_rect.left + window_width;
9449 clip_rect.bottom = clip_rect.top + row->visible_height;
9451 /* If clipping to the whole line, including trunc marks, extend
9452 the rectangle to the left and increase its width. */
9453 if (whole_line_p)
9455 clip_rect.left -= FRAME_X_LEFT_FRINGE_WIDTH (f);
9456 clip_rect.right += FRAME_X_FRINGE_WIDTH (f);
9459 w32_set_clip_rectangle (hdc, &clip_rect);
9463 /* Draw a hollow box cursor on window W in glyph row ROW. */
9465 static void
9466 x_draw_hollow_cursor (w, row)
9467 struct window *w;
9468 struct glyph_row *row;
9470 struct frame *f = XFRAME (WINDOW_FRAME (w));
9471 HDC hdc;
9472 RECT rect;
9473 int wd;
9474 struct glyph *cursor_glyph;
9475 HBRUSH hb = CreateSolidBrush (f->output_data.w32->cursor_pixel);
9477 /* Compute frame-relative coordinates from window-relative
9478 coordinates. */
9479 rect.left = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
9480 rect.top = (WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y)
9481 + row->ascent - w->phys_cursor_ascent);
9482 rect.bottom = rect.top + row->height;
9484 /* Get the glyph the cursor is on. If we can't tell because
9485 the current matrix is invalid or such, give up. */
9486 cursor_glyph = get_phys_cursor_glyph (w);
9487 if (cursor_glyph == NULL)
9488 return;
9490 /* Compute the width of the rectangle to draw. If on a stretch
9491 glyph, and `x-stretch-block-cursor' is nil, don't draw a
9492 rectangle as wide as the glyph, but use a canonical character
9493 width instead. */
9494 wd = cursor_glyph->pixel_width;
9495 if (cursor_glyph->type == STRETCH_GLYPH
9496 && !x_stretch_cursor_p)
9497 wd = min (CANON_X_UNIT (f), wd);
9499 rect.right = rect.left + wd;
9500 hdc = get_frame_dc (f);
9501 FrameRect (hdc, &rect, hb);
9502 DeleteObject (hb);
9504 release_frame_dc (f, hdc);
9508 /* Draw a bar cursor on window W in glyph row ROW.
9510 Implementation note: One would like to draw a bar cursor with an
9511 angle equal to the one given by the font property XA_ITALIC_ANGLE.
9512 Unfortunately, I didn't find a font yet that has this property set.
9513 --gerd. */
9515 static void
9516 x_draw_bar_cursor (w, row, width, kind)
9517 struct window *w;
9518 struct glyph_row *row;
9519 int width;
9520 enum text_cursor_kinds kind;
9522 struct frame *f = XFRAME (w->frame);
9523 struct glyph *cursor_glyph;
9524 int x;
9525 HDC hdc;
9527 /* If cursor is out of bounds, don't draw garbage. This can happen
9528 in mini-buffer windows when switching between echo area glyphs
9529 and mini-buffer. */
9530 cursor_glyph = get_phys_cursor_glyph (w);
9531 if (cursor_glyph == NULL)
9532 return;
9534 /* If on an image, draw like a normal cursor. That's usually better
9535 visible than drawing a bar, esp. if the image is large so that
9536 the bar might not be in the window. */
9537 if (cursor_glyph->type == IMAGE_GLYPH)
9539 struct glyph_row *row;
9540 row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
9541 x_draw_phys_cursor_glyph (w, row, DRAW_CURSOR);
9543 else
9545 COLORREF cursor_color = f->output_data.w32->cursor_pixel;
9546 struct face *face = FACE_FROM_ID (f, cursor_glyph->face_id);
9548 if (width < 0)
9549 width = FRAME_CURSOR_WIDTH (f);
9550 width = min (cursor_glyph->pixel_width, width);
9552 /* If the glyph's background equals the color we normally draw
9553 the bar cursor in, the bar cursor in its normal color is
9554 invisible. Use the glyph's foreground color instead in this
9555 case, on the assumption that the glyph's colors are chosen so
9556 that the glyph is legible. */
9557 if (face->background == cursor_color)
9558 cursor_color = face->foreground;
9560 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
9561 hdc = get_frame_dc (f);
9562 w32_clip_to_row (w, row, hdc, 0);
9564 if (kind == BAR_CURSOR)
9566 w32_fill_area (f, hdc, cursor_color, x,
9567 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
9568 width, row->height);
9570 else
9572 w32_fill_area (f, hdc, cursor_color, x,
9573 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y +
9574 row->height - width),
9575 cursor_glyph->pixel_width, width);
9577 release_frame_dc (f, hdc);
9582 /* Clear the cursor of window W to background color, and mark the
9583 cursor as not shown. This is used when the text where the cursor
9584 is is about to be rewritten. */
9586 static void
9587 x_clear_cursor (w)
9588 struct window *w;
9590 if (FRAME_VISIBLE_P (XFRAME (w->frame)) && w->phys_cursor_on_p)
9591 x_update_window_cursor (w, 0);
9595 /* Draw the cursor glyph of window W in glyph row ROW. See the
9596 comment of x_draw_glyphs for the meaning of HL. */
9598 static void
9599 x_draw_phys_cursor_glyph (w, row, hl)
9600 struct window *w;
9601 struct glyph_row *row;
9602 enum draw_glyphs_face hl;
9604 /* If cursor hpos is out of bounds, don't draw garbage. This can
9605 happen in mini-buffer windows when switching between echo area
9606 glyphs and mini-buffer. */
9607 if (w->phys_cursor.hpos < row->used[TEXT_AREA])
9609 int on_p = w->phys_cursor_on_p;
9610 x_draw_glyphs (w, w->phys_cursor.x, row, TEXT_AREA,
9611 w->phys_cursor.hpos, w->phys_cursor.hpos + 1,
9612 hl, 0);
9613 w->phys_cursor_on_p = on_p;
9615 /* When we erase the cursor, and ROW is overlapped by other
9616 rows, make sure that these overlapping parts of other rows
9617 are redrawn. */
9618 if (hl == DRAW_NORMAL_TEXT && row->overlapped_p)
9620 if (row > w->current_matrix->rows
9621 && MATRIX_ROW_OVERLAPS_SUCC_P (row - 1))
9622 x_fix_overlapping_area (w, row - 1, TEXT_AREA);
9624 if (MATRIX_ROW_BOTTOM_Y (row) < window_text_bottom_y (w)
9625 && MATRIX_ROW_OVERLAPS_PRED_P (row + 1))
9626 x_fix_overlapping_area (w, row + 1, TEXT_AREA);
9632 /* Erase the image of a cursor of window W from the screen. */
9634 static void
9635 x_erase_phys_cursor (w)
9636 struct window *w;
9638 struct frame *f = XFRAME (w->frame);
9639 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
9640 int hpos = w->phys_cursor.hpos;
9641 int vpos = w->phys_cursor.vpos;
9642 int mouse_face_here_p = 0;
9643 struct glyph_matrix *active_glyphs = w->current_matrix;
9644 struct glyph_row *cursor_row;
9645 struct glyph *cursor_glyph;
9646 enum draw_glyphs_face hl;
9648 /* No cursor displayed or row invalidated => nothing to do on the
9649 screen. */
9650 if (w->phys_cursor_type == NO_CURSOR)
9651 goto mark_cursor_off;
9653 /* VPOS >= active_glyphs->nrows means that window has been resized.
9654 Don't bother to erase the cursor. */
9655 if (vpos >= active_glyphs->nrows)
9656 goto mark_cursor_off;
9658 /* If row containing cursor is marked invalid, there is nothing we
9659 can do. */
9660 cursor_row = MATRIX_ROW (active_glyphs, vpos);
9661 if (!cursor_row->enabled_p)
9662 goto mark_cursor_off;
9664 /* If row is completely invisible, don't attempt to delete a cursor which
9665 isn't there. This may happen if cursor is at top of window, and
9666 we switch to a buffer with a header line in that window. */
9667 if (cursor_row->visible_height <= 0)
9668 goto mark_cursor_off;
9670 /* This can happen when the new row is shorter than the old one.
9671 In this case, either x_draw_glyphs or clear_end_of_line
9672 should have cleared the cursor. Note that we wouldn't be
9673 able to erase the cursor in this case because we don't have a
9674 cursor glyph at hand. */
9675 if (w->phys_cursor.hpos >= cursor_row->used[TEXT_AREA])
9676 goto mark_cursor_off;
9678 /* If the cursor is in the mouse face area, redisplay that when
9679 we clear the cursor. */
9680 if (! NILP (dpyinfo->mouse_face_window)
9681 && w == XWINDOW (dpyinfo->mouse_face_window)
9682 && (vpos > dpyinfo->mouse_face_beg_row
9683 || (vpos == dpyinfo->mouse_face_beg_row
9684 && hpos >= dpyinfo->mouse_face_beg_col))
9685 && (vpos < dpyinfo->mouse_face_end_row
9686 || (vpos == dpyinfo->mouse_face_end_row
9687 && hpos < dpyinfo->mouse_face_end_col))
9688 /* Don't redraw the cursor's spot in mouse face if it is at the
9689 end of a line (on a newline). The cursor appears there, but
9690 mouse highlighting does not. */
9691 && cursor_row->used[TEXT_AREA] > hpos)
9692 mouse_face_here_p = 1;
9694 /* Maybe clear the display under the cursor. */
9695 if (w->phys_cursor_type == HOLLOW_BOX_CURSOR)
9697 int x;
9698 int header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
9699 HDC hdc;
9701 cursor_glyph = get_phys_cursor_glyph (w);
9702 if (cursor_glyph == NULL)
9703 goto mark_cursor_off;
9705 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
9707 hdc = get_frame_dc (f);
9708 w32_clear_area (f, hdc, x,
9709 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
9710 cursor_row->y)),
9711 cursor_glyph->pixel_width,
9712 cursor_row->visible_height);
9713 release_frame_dc (f, hdc);
9716 /* Erase the cursor by redrawing the character underneath it. */
9717 if (mouse_face_here_p)
9718 hl = DRAW_MOUSE_FACE;
9719 else
9720 hl = DRAW_NORMAL_TEXT;
9721 x_draw_phys_cursor_glyph (w, cursor_row, hl);
9723 mark_cursor_off:
9724 w->phys_cursor_on_p = 0;
9725 w->phys_cursor_type = NO_CURSOR;
9729 /* Non-zero if physical cursor of window W is within mouse face. */
9731 static int
9732 cursor_in_mouse_face_p (w)
9733 struct window *w;
9735 struct w32_display_info *dpyinfo
9736 = FRAME_W32_DISPLAY_INFO (XFRAME (w->frame));
9737 int in_mouse_face = 0;
9739 if (WINDOWP (dpyinfo->mouse_face_window)
9740 && XWINDOW (dpyinfo->mouse_face_window) == w)
9742 int hpos = w->phys_cursor.hpos;
9743 int vpos = w->phys_cursor.vpos;
9745 if (vpos >= dpyinfo->mouse_face_beg_row
9746 && vpos <= dpyinfo->mouse_face_end_row
9747 && (vpos > dpyinfo->mouse_face_beg_row
9748 || hpos >= dpyinfo->mouse_face_beg_col)
9749 && (vpos < dpyinfo->mouse_face_end_row
9750 || hpos < dpyinfo->mouse_face_end_col
9751 || dpyinfo->mouse_face_past_end))
9752 in_mouse_face = 1;
9755 return in_mouse_face;
9759 /* Display or clear cursor of window W. If ON is zero, clear the
9760 cursor. If it is non-zero, display the cursor. If ON is nonzero,
9761 where to put the cursor is specified by HPOS, VPOS, X and Y. */
9763 void
9764 x_display_and_set_cursor (w, on, hpos, vpos, x, y)
9765 struct window *w;
9766 int on, hpos, vpos, x, y;
9768 struct frame *f = XFRAME (w->frame);
9769 int new_cursor_type;
9770 int new_cursor_width;
9771 int active_cursor;
9772 struct glyph_matrix *current_glyphs;
9773 struct glyph_row *glyph_row;
9774 struct glyph *glyph;
9776 /* This is pointless on invisible frames, and dangerous on garbaged
9777 windows and frames; in the latter case, the frame or window may
9778 be in the midst of changing its size, and x and y may be off the
9779 window. */
9780 if (! FRAME_VISIBLE_P (f)
9781 || FRAME_GARBAGED_P (f)
9782 || vpos >= w->current_matrix->nrows
9783 || hpos >= w->current_matrix->matrix_w)
9784 return;
9786 /* If cursor is off and we want it off, return quickly. */
9787 if (!on && !w->phys_cursor_on_p)
9788 return;
9790 current_glyphs = w->current_matrix;
9791 glyph_row = MATRIX_ROW (current_glyphs, vpos);
9792 glyph = glyph_row->glyphs[TEXT_AREA] + hpos;
9794 /* If cursor row is not enabled, we don't really know where to
9795 display the cursor. */
9796 if (!glyph_row->enabled_p)
9798 w->phys_cursor_on_p = 0;
9799 return;
9802 xassert (interrupt_input_blocked);
9804 /* Set new_cursor_type to the cursor we want to be displayed. */
9805 new_cursor_type = get_window_cursor_type (w, &new_cursor_width, &active_cursor);
9807 /* If cursor is currently being shown and we don't want it to be or
9808 it is in the wrong place, or the cursor type is not what we want,
9809 erase it. */
9810 if (w->phys_cursor_on_p
9811 && (!on
9812 || w->phys_cursor.x != x
9813 || w->phys_cursor.y != y
9814 || new_cursor_type != w->phys_cursor_type
9815 || ((new_cursor_type == BAR_CURSOR || new_cursor_type == HBAR_CURSOR)
9816 && new_cursor_width != w->phys_cursor_width)))
9817 x_erase_phys_cursor (w);
9819 /* Don't check phys_cursor_on_p here because that flag is only set
9820 to zero in some cases where we know that the cursor has been
9821 completely erased, to avoid the extra work of erasing the cursor
9822 twice. In other words, phys_cursor_on_p can be 1 and the cursor
9823 still not be visible, or it has only been partly erased. */
9824 if (on)
9826 w->phys_cursor_ascent = glyph_row->ascent;
9827 w->phys_cursor_height = glyph_row->height;
9829 /* Set phys_cursor_.* before x_draw_.* is called because some
9830 of them may need the information. */
9831 w->phys_cursor.x = x;
9832 w->phys_cursor.y = glyph_row->y;
9833 w->phys_cursor.hpos = hpos;
9834 w->phys_cursor.vpos = vpos;
9836 /* If the user wants to use the system caret, make sure our own
9837 cursor remains invisible. */
9838 if (w32_use_visible_system_caret)
9840 if (w->phys_cursor_type != NO_CURSOR)
9841 x_erase_phys_cursor (w);
9843 new_cursor_type = w->phys_cursor_type = NO_CURSOR;
9844 w->phys_cursor_width = -1;
9846 else
9848 w->phys_cursor_type = new_cursor_type;
9849 w->phys_cursor_width = new_cursor_width;
9852 w->phys_cursor_on_p = 1;
9854 /* If this is the active cursor, we need to track it with the
9855 system caret, so third party software like screen magnifiers
9856 and speech synthesizers can follow the cursor. */
9857 if (active_cursor)
9859 HWND hwnd = FRAME_W32_WINDOW (f);
9861 w32_system_caret_x
9862 = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
9863 w32_system_caret_y
9864 = (WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y)
9865 + glyph_row->ascent - w->phys_cursor_ascent);
9867 /* If the size of the active cursor changed, destroy the old
9868 system caret. */
9869 if (w32_system_caret_hwnd
9870 && (w32_system_caret_height != w->phys_cursor_height))
9871 PostMessage (hwnd, WM_EMACS_DESTROY_CARET, 0, 0);
9873 w32_system_caret_height = w->phys_cursor_height;
9875 /* Move the system caret. */
9876 PostMessage (hwnd, WM_EMACS_TRACK_CARET, 0, 0);
9879 switch (new_cursor_type)
9881 case HOLLOW_BOX_CURSOR:
9882 x_draw_hollow_cursor (w, glyph_row);
9883 break;
9885 case FILLED_BOX_CURSOR:
9886 x_draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
9887 break;
9889 case BAR_CURSOR:
9890 x_draw_bar_cursor (w, glyph_row, new_cursor_width, BAR_CURSOR);
9891 break;
9893 case HBAR_CURSOR:
9894 x_draw_bar_cursor (w, glyph_row, new_cursor_width, HBAR_CURSOR);
9895 break;
9897 case NO_CURSOR:
9898 break;
9900 default:
9901 abort ();
9907 /* Display the cursor on window W, or clear it. X and Y are window
9908 relative pixel coordinates. HPOS and VPOS are glyph matrix
9909 positions. If W is not the selected window, display a hollow
9910 cursor. ON non-zero means display the cursor at X, Y which
9911 correspond to HPOS, VPOS, otherwise it is cleared. */
9913 void
9914 x_display_cursor (w, on, hpos, vpos, x, y)
9915 struct window *w;
9916 int on, hpos, vpos, x, y;
9918 BLOCK_INPUT;
9919 x_display_and_set_cursor (w, on, hpos, vpos, x, y);
9920 UNBLOCK_INPUT;
9924 /* Display the cursor on window W, or clear it, according to ON_P.
9925 Don't change the cursor's position. */
9927 void
9928 x_update_cursor (f, on_p)
9929 struct frame *f;
9930 int on_p;
9932 x_update_cursor_in_window_tree (XWINDOW (f->root_window), on_p);
9936 /* Call x_update_window_cursor with parameter ON_P on all leaf windows
9937 in the window tree rooted at W. */
9939 static void
9940 x_update_cursor_in_window_tree (w, on_p)
9941 struct window *w;
9942 int on_p;
9944 while (w)
9946 if (!NILP (w->hchild))
9947 x_update_cursor_in_window_tree (XWINDOW (w->hchild), on_p);
9948 else if (!NILP (w->vchild))
9949 x_update_cursor_in_window_tree (XWINDOW (w->vchild), on_p);
9950 else
9951 x_update_window_cursor (w, on_p);
9953 w = NILP (w->next) ? 0 : XWINDOW (w->next);
9958 /* Switch the display of W's cursor on or off, according to the value
9959 of ON. */
9961 static void
9962 x_update_window_cursor (w, on)
9963 struct window *w;
9964 int on;
9966 /* Don't update cursor in windows whose frame is in the process
9967 of being deleted. */
9968 if (w->current_matrix)
9970 BLOCK_INPUT;
9971 x_display_and_set_cursor (w, on, w->phys_cursor.hpos,
9972 w->phys_cursor.vpos, w->phys_cursor.x,
9973 w->phys_cursor.y);
9974 UNBLOCK_INPUT;
9981 /* Icons. */
9984 x_bitmap_icon (f, icon)
9985 struct frame *f;
9986 Lisp_Object icon;
9988 HANDLE hicon;
9990 if (FRAME_W32_WINDOW (f) == 0)
9991 return 1;
9993 if (NILP (icon))
9994 hicon = LoadIcon (hinst, EMACS_CLASS);
9995 else if (STRINGP (icon))
9996 hicon = LoadImage (NULL, (LPCTSTR) SDATA (icon), IMAGE_ICON, 0, 0,
9997 LR_DEFAULTSIZE | LR_LOADFROMFILE);
9998 else if (SYMBOLP (icon))
10000 LPCTSTR name;
10002 if (EQ (icon, intern ("application")))
10003 name = (LPCTSTR) IDI_APPLICATION;
10004 else if (EQ (icon, intern ("hand")))
10005 name = (LPCTSTR) IDI_HAND;
10006 else if (EQ (icon, intern ("question")))
10007 name = (LPCTSTR) IDI_QUESTION;
10008 else if (EQ (icon, intern ("exclamation")))
10009 name = (LPCTSTR) IDI_EXCLAMATION;
10010 else if (EQ (icon, intern ("asterisk")))
10011 name = (LPCTSTR) IDI_ASTERISK;
10012 else if (EQ (icon, intern ("winlogo")))
10013 name = (LPCTSTR) IDI_WINLOGO;
10014 else
10015 return 1;
10017 hicon = LoadIcon (NULL, name);
10019 else
10020 return 1;
10022 if (hicon == NULL)
10023 return 1;
10025 PostMessage (FRAME_W32_WINDOW (f), WM_SETICON, (WPARAM) ICON_BIG,
10026 (LPARAM) hicon);
10028 return 0;
10032 /************************************************************************
10033 Handling X errors
10034 ************************************************************************/
10036 /* Display Error Handling functions not used on W32. Listing them here
10037 helps diff stay in step when comparing w32term.c with xterm.c.
10039 x_error_catcher (display, error)
10040 x_catch_errors (dpy)
10041 x_catch_errors_unwind (old_val)
10042 x_check_errors (dpy, format)
10043 x_had_errors_p (dpy)
10044 x_clear_errors (dpy)
10045 x_uncatch_errors (dpy, count)
10046 x_trace_wire ()
10047 x_connection_signal (signalnum)
10048 x_connection_closed (dpy, error_message)
10049 x_error_quitter (display, error)
10050 x_error_handler (display, error)
10051 x_io_error_quitter (display)
10056 /* Changing the font of the frame. */
10058 /* Give frame F the font named FONTNAME as its default font, and
10059 return the full name of that font. FONTNAME may be a wildcard
10060 pattern; in that case, we choose some font that fits the pattern.
10061 The return value shows which font we chose. */
10063 Lisp_Object
10064 x_new_font (f, fontname)
10065 struct frame *f;
10066 register char *fontname;
10068 struct font_info *fontp
10069 = FS_LOAD_FONT (f, 0, fontname, -1);
10071 if (!fontp)
10072 return Qnil;
10074 FRAME_FONT (f) = (XFontStruct *) (fontp->font);
10075 FRAME_BASELINE_OFFSET (f) = fontp->baseline_offset;
10076 FRAME_FONTSET (f) = -1;
10078 /* Compute the scroll bar width in character columns. */
10079 if (f->scroll_bar_pixel_width > 0)
10081 int wid = FONT_WIDTH (FRAME_FONT (f));
10082 f->scroll_bar_cols = (f->scroll_bar_pixel_width + wid-1) / wid;
10084 else
10086 int wid = FONT_WIDTH (FRAME_FONT (f));
10087 f->scroll_bar_cols = (14 + wid - 1) / wid;
10090 /* Now make the frame display the given font. */
10091 if (FRAME_W32_WINDOW (f) != 0)
10093 frame_update_line_height (f);
10094 if (NILP (tip_frame) || XFRAME (tip_frame) != f)
10095 x_set_window_size (f, 0, f->width, f->height);
10097 else
10098 /* If we are setting a new frame's font for the first time,
10099 there are no faces yet, so this font's height is the line height. */
10100 f->output_data.w32->line_height = FONT_HEIGHT (FRAME_FONT (f));
10102 return build_string (fontp->full_name);
10105 /* Give frame F the fontset named FONTSETNAME as its default font, and
10106 return the full name of that fontset. FONTSETNAME may be a wildcard
10107 pattern; in that case, we choose some fontset that fits the pattern.
10108 The return value shows which fontset we chose. */
10110 Lisp_Object
10111 x_new_fontset (f, fontsetname)
10112 struct frame *f;
10113 char *fontsetname;
10115 int fontset = fs_query_fontset (build_string (fontsetname), 0);
10116 Lisp_Object result;
10118 if (fontset < 0)
10119 return Qnil;
10121 if (FRAME_FONTSET (f) == fontset)
10122 /* This fontset is already set in frame F. There's nothing more
10123 to do. */
10124 return fontset_name (fontset);
10126 result = x_new_font (f, (SDATA (fontset_ascii (fontset))));
10128 if (!STRINGP (result))
10129 /* Can't load ASCII font. */
10130 return Qnil;
10132 /* Since x_new_font doesn't update any fontset information, do it now. */
10133 FRAME_FONTSET(f) = fontset;
10135 return build_string (fontsetname);
10138 /* Compute actual fringe widths */
10140 void
10141 x_compute_fringe_widths (f, redraw)
10142 struct frame *f;
10143 int redraw;
10145 int o_left = f->output_data.w32->left_fringe_width;
10146 int o_right = f->output_data.w32->right_fringe_width;
10147 int o_cols = f->output_data.w32->fringe_cols;
10149 Lisp_Object left_fringe = Fassq (Qleft_fringe, f->param_alist);
10150 Lisp_Object right_fringe = Fassq (Qright_fringe, f->param_alist);
10151 int left_fringe_width, right_fringe_width;
10153 if (!NILP (left_fringe))
10154 left_fringe = Fcdr (left_fringe);
10155 if (!NILP (right_fringe))
10156 right_fringe = Fcdr (right_fringe);
10158 left_fringe_width = ((NILP (left_fringe) || !INTEGERP (left_fringe)) ? 8 :
10159 XINT (left_fringe));
10160 right_fringe_width = ((NILP (right_fringe) || !INTEGERP (right_fringe)) ? 8 :
10161 XINT (right_fringe));
10163 if (left_fringe_width || right_fringe_width)
10165 int left_wid = left_fringe_width >= 0 ? left_fringe_width : -left_fringe_width;
10166 int right_wid = right_fringe_width >= 0 ? right_fringe_width : -right_fringe_width;
10167 int conf_wid = left_wid + right_wid;
10168 int font_wid = FONT_WIDTH (f->output_data.w32->font);
10169 int cols = (left_wid + right_wid + font_wid-1) / font_wid;
10170 int real_wid = cols * font_wid;
10171 if (left_wid && right_wid)
10173 if (left_fringe_width < 0)
10175 /* Left fringe width is fixed, adjust right fringe if necessary */
10176 f->output_data.w32->left_fringe_width = left_wid;
10177 f->output_data.w32->right_fringe_width = real_wid - left_wid;
10179 else if (right_fringe_width < 0)
10181 /* Right fringe width is fixed, adjust left fringe if necessary */
10182 f->output_data.w32->left_fringe_width = real_wid - right_wid;
10183 f->output_data.w32->right_fringe_width = right_wid;
10185 else
10187 /* Adjust both fringes with an equal amount.
10188 Note that we are doing integer arithmetic here, so don't
10189 lose a pixel if the total width is an odd number. */
10190 int fill = real_wid - conf_wid;
10191 f->output_data.w32->left_fringe_width = left_wid + fill/2;
10192 f->output_data.w32->right_fringe_width = right_wid + fill - fill/2;
10195 else if (left_fringe_width)
10197 f->output_data.w32->left_fringe_width = real_wid;
10198 f->output_data.w32->right_fringe_width = 0;
10200 else
10202 f->output_data.w32->left_fringe_width = 0;
10203 f->output_data.w32->right_fringe_width = real_wid;
10205 f->output_data.w32->fringe_cols = cols;
10206 f->output_data.w32->fringes_extra = real_wid;
10208 else
10210 f->output_data.w32->left_fringe_width = 0;
10211 f->output_data.w32->right_fringe_width = 0;
10212 f->output_data.w32->fringe_cols = 0;
10213 f->output_data.w32->fringes_extra = 0;
10216 if (redraw && FRAME_VISIBLE_P (f))
10217 if (o_left != f->output_data.w32->left_fringe_width ||
10218 o_right != f->output_data.w32->right_fringe_width ||
10219 o_cols != f->output_data.w32->fringe_cols)
10220 redraw_frame (f);
10223 /***********************************************************************
10224 TODO: W32 Input Methods
10225 ***********************************************************************/
10226 /* Listing missing functions from xterm.c helps diff stay in step.
10228 xim_destroy_callback (xim, client_data, call_data)
10229 xim_open_dpy (dpyinfo, resource_name)
10230 struct xim_inst_t
10231 xim_instantiate_callback (display, client_data, call_data)
10232 xim_initialize (dpyinfo, resource_name)
10233 xim_close_dpy (dpyinfo)
10238 /* Calculate the absolute position in frame F
10239 from its current recorded position values and gravity. */
10241 void
10242 x_calc_absolute_position (f)
10243 struct frame *f;
10245 POINT pt;
10246 int flags = f->output_data.w32->size_hint_flags;
10248 pt.x = pt.y = 0;
10250 /* Find the position of the outside upper-left corner of
10251 the inner window, with respect to the outer window.
10252 But do this only if we will need the results. */
10253 if (f->output_data.w32->parent_desc != FRAME_W32_DISPLAY_INFO (f)->root_window)
10255 BLOCK_INPUT;
10256 MapWindowPoints (FRAME_W32_WINDOW (f),
10257 f->output_data.w32->parent_desc,
10258 &pt, 1);
10259 UNBLOCK_INPUT;
10263 RECT rt;
10264 rt.left = rt.right = rt.top = rt.bottom = 0;
10266 BLOCK_INPUT;
10267 AdjustWindowRect(&rt, f->output_data.w32->dwStyle,
10268 FRAME_EXTERNAL_MENU_BAR (f));
10269 UNBLOCK_INPUT;
10271 pt.x += (rt.right - rt.left);
10272 pt.y += (rt.bottom - rt.top);
10275 /* Treat negative positions as relative to the leftmost bottommost
10276 position that fits on the screen. */
10277 if (flags & XNegative)
10278 f->output_data.w32->left_pos = (FRAME_W32_DISPLAY_INFO (f)->width
10279 - 2 * f->output_data.w32->border_width - pt.x
10280 - PIXEL_WIDTH (f)
10281 + f->output_data.w32->left_pos);
10283 if (flags & YNegative)
10284 f->output_data.w32->top_pos = (FRAME_W32_DISPLAY_INFO (f)->height
10285 - 2 * f->output_data.w32->border_width - pt.y
10286 - PIXEL_HEIGHT (f)
10287 + f->output_data.w32->top_pos);
10288 /* The left_pos and top_pos
10289 are now relative to the top and left screen edges,
10290 so the flags should correspond. */
10291 f->output_data.w32->size_hint_flags &= ~ (XNegative | YNegative);
10294 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
10295 to really change the position, and 0 when calling from
10296 x_make_frame_visible (in that case, XOFF and YOFF are the current
10297 position values). It is -1 when calling from x_set_frame_parameters,
10298 which means, do adjust for borders but don't change the gravity. */
10300 void
10301 x_set_offset (f, xoff, yoff, change_gravity)
10302 struct frame *f;
10303 register int xoff, yoff;
10304 int change_gravity;
10306 int modified_top, modified_left;
10308 if (change_gravity > 0)
10310 f->output_data.w32->top_pos = yoff;
10311 f->output_data.w32->left_pos = xoff;
10312 f->output_data.w32->size_hint_flags &= ~ (XNegative | YNegative);
10313 if (xoff < 0)
10314 f->output_data.w32->size_hint_flags |= XNegative;
10315 if (yoff < 0)
10316 f->output_data.w32->size_hint_flags |= YNegative;
10317 f->output_data.w32->win_gravity = NorthWestGravity;
10319 x_calc_absolute_position (f);
10321 BLOCK_INPUT;
10322 x_wm_set_size_hint (f, (long) 0, 0);
10324 modified_left = f->output_data.w32->left_pos;
10325 modified_top = f->output_data.w32->top_pos;
10327 my_set_window_pos (FRAME_W32_WINDOW (f),
10328 NULL,
10329 modified_left, modified_top,
10330 0, 0,
10331 SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
10332 UNBLOCK_INPUT;
10336 /* Check if we need to resize the frame due to a fullscreen request.
10337 If so needed, resize the frame. */
10338 static void
10339 x_check_fullscreen (f)
10340 struct frame *f;
10342 if (f->output_data.w32->want_fullscreen & FULLSCREEN_BOTH)
10344 int width, height, ign;
10346 x_real_positions (f, &f->output_data.w32->left_pos,
10347 &f->output_data.w32->top_pos);
10349 x_fullscreen_adjust (f, &width, &height, &ign, &ign);
10351 /* We do not need to move the window, it shall be taken care of
10352 when setting WM manager hints.
10353 If the frame is visible already, the position is checked by
10354 x_check_fullscreen_move. */
10355 if (f->width != width || f->height != height)
10357 change_frame_size (f, height, width, 0, 1, 0);
10358 SET_FRAME_GARBAGED (f);
10359 cancel_mouse_face (f);
10361 /* Wait for the change of frame size to occur */
10362 f->output_data.w32->want_fullscreen |= FULLSCREEN_WAIT;
10367 /* If frame parameters are set after the frame is mapped, we need to move
10368 the window. This is done in xfns.c.
10369 Some window managers moves the window to the right position, some
10370 moves the outer window manager window to the specified position.
10371 Here we check that we are in the right spot. If not, make a second
10372 move, assuming we are dealing with the second kind of window manager. */
10373 static void
10374 x_check_fullscreen_move (f)
10375 struct frame *f;
10377 if (f->output_data.w32->want_fullscreen & FULLSCREEN_MOVE_WAIT)
10379 int expect_top = f->output_data.w32->top_pos;
10380 int expect_left = f->output_data.w32->left_pos;
10382 if (f->output_data.w32->want_fullscreen & FULLSCREEN_HEIGHT)
10383 expect_top = 0;
10384 if (f->output_data.w32->want_fullscreen & FULLSCREEN_WIDTH)
10385 expect_left = 0;
10387 if (expect_top != f->output_data.w32->top_pos
10388 || expect_left != f->output_data.w32->left_pos)
10389 x_set_offset (f, expect_left, expect_top, 1);
10391 /* Just do this once */
10392 f->output_data.w32->want_fullscreen &= ~FULLSCREEN_MOVE_WAIT;
10397 /* Calculate fullscreen size. Return in *TOP_POS and *LEFT_POS the
10398 wanted positions of the WM window (not emacs window).
10399 Return in *WIDTH and *HEIGHT the wanted width and height of Emacs
10400 window (FRAME_X_WINDOW).
10402 void
10403 x_fullscreen_adjust (f, width, height, top_pos, left_pos)
10404 struct frame *f;
10405 int *width;
10406 int *height;
10407 int *top_pos;
10408 int *left_pos;
10410 int newwidth = f->width, newheight = f->height;
10412 *top_pos = f->output_data.w32->top_pos;
10413 *left_pos = f->output_data.w32->left_pos;
10415 if (f->output_data.w32->want_fullscreen & FULLSCREEN_HEIGHT)
10417 int ph;
10419 ph = FRAME_X_DISPLAY_INFO (f)->height;
10420 newheight = PIXEL_TO_CHAR_HEIGHT (f, ph);
10421 ph = CHAR_TO_PIXEL_HEIGHT (f, newheight)
10422 - f->output_data.w32->y_pixels_diff;
10423 newheight = PIXEL_TO_CHAR_HEIGHT (f, ph);
10424 *top_pos = 0;
10427 if (f->output_data.w32->want_fullscreen & FULLSCREEN_WIDTH)
10429 int pw;
10431 pw = FRAME_X_DISPLAY_INFO (f)->width;
10432 newwidth = PIXEL_TO_CHAR_WIDTH (f, pw);
10433 pw = CHAR_TO_PIXEL_WIDTH (f, newwidth)
10434 - f->output_data.w32->x_pixels_diff;
10435 newwidth = PIXEL_TO_CHAR_WIDTH (f, pw);
10436 *left_pos = 0;
10439 *width = newwidth;
10440 *height = newheight;
10444 /* Call this to change the size of frame F's x-window.
10445 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
10446 for this size change and subsequent size changes.
10447 Otherwise we leave the window gravity unchanged. */
10449 void
10450 x_set_window_size (f, change_gravity, cols, rows)
10451 struct frame *f;
10452 int change_gravity;
10453 int cols, rows;
10455 int pixelwidth, pixelheight;
10457 BLOCK_INPUT;
10459 check_frame_size (f, &rows, &cols);
10460 f->output_data.w32->vertical_scroll_bar_extra
10461 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
10463 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.w32->font)));
10465 x_compute_fringe_widths (f, 0);
10467 pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols);
10468 pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows);
10470 f->output_data.w32->win_gravity = NorthWestGravity;
10471 x_wm_set_size_hint (f, (long) 0, 0);
10474 RECT rect;
10476 rect.left = rect.top = 0;
10477 rect.right = pixelwidth;
10478 rect.bottom = pixelheight;
10480 AdjustWindowRect(&rect, f->output_data.w32->dwStyle,
10481 FRAME_EXTERNAL_MENU_BAR (f));
10483 my_set_window_pos (FRAME_W32_WINDOW (f),
10484 NULL,
10485 0, 0,
10486 rect.right - rect.left,
10487 rect.bottom - rect.top,
10488 SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE);
10491 /* Now, strictly speaking, we can't be sure that this is accurate,
10492 but the window manager will get around to dealing with the size
10493 change request eventually, and we'll hear how it went when the
10494 ConfigureNotify event gets here.
10496 We could just not bother storing any of this information here,
10497 and let the ConfigureNotify event set everything up, but that
10498 might be kind of confusing to the Lisp code, since size changes
10499 wouldn't be reported in the frame parameters until some random
10500 point in the future when the ConfigureNotify event arrives.
10502 We pass 1 for DELAY since we can't run Lisp code inside of
10503 a BLOCK_INPUT. */
10504 change_frame_size (f, rows, cols, 0, 1, 0);
10505 PIXEL_WIDTH (f) = pixelwidth;
10506 PIXEL_HEIGHT (f) = pixelheight;
10508 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
10509 receive in the ConfigureNotify event; if we get what we asked
10510 for, then the event won't cause the screen to become garbaged, so
10511 we have to make sure to do it here. */
10512 SET_FRAME_GARBAGED (f);
10514 /* If cursor was outside the new size, mark it as off. */
10515 mark_window_cursors_off (XWINDOW (f->root_window));
10517 /* Clear out any recollection of where the mouse highlighting was,
10518 since it might be in a place that's outside the new frame size.
10519 Actually checking whether it is outside is a pain in the neck,
10520 so don't try--just let the highlighting be done afresh with new size. */
10521 cancel_mouse_face (f);
10523 UNBLOCK_INPUT;
10526 /* Mouse warping. */
10528 void x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y);
10530 void
10531 x_set_mouse_position (f, x, y)
10532 struct frame *f;
10533 int x, y;
10535 int pix_x, pix_y;
10537 pix_x = CHAR_TO_PIXEL_COL (f, x) + FONT_WIDTH (f->output_data.w32->font) / 2;
10538 pix_y = CHAR_TO_PIXEL_ROW (f, y) + f->output_data.w32->line_height / 2;
10540 if (pix_x < 0) pix_x = 0;
10541 if (pix_x > PIXEL_WIDTH (f)) pix_x = PIXEL_WIDTH (f);
10543 if (pix_y < 0) pix_y = 0;
10544 if (pix_y > PIXEL_HEIGHT (f)) pix_y = PIXEL_HEIGHT (f);
10546 x_set_mouse_pixel_position (f, pix_x, pix_y);
10549 void
10550 x_set_mouse_pixel_position (f, pix_x, pix_y)
10551 struct frame *f;
10552 int pix_x, pix_y;
10554 RECT rect;
10555 POINT pt;
10557 BLOCK_INPUT;
10559 GetClientRect (FRAME_W32_WINDOW (f), &rect);
10560 pt.x = rect.left + pix_x;
10561 pt.y = rect.top + pix_y;
10562 ClientToScreen (FRAME_W32_WINDOW (f), &pt);
10564 SetCursorPos (pt.x, pt.y);
10566 UNBLOCK_INPUT;
10570 /* focus shifting, raising and lowering. */
10572 void
10573 x_focus_on_frame (f)
10574 struct frame *f;
10576 struct w32_display_info *dpyinfo = &one_w32_display_info;
10578 /* Give input focus to frame. */
10579 BLOCK_INPUT;
10580 #if 0
10581 /* Try not to change its Z-order if possible. */
10582 if (x_window_to_frame (dpyinfo, GetForegroundWindow ()))
10583 my_set_focus (f, FRAME_W32_WINDOW (f));
10584 else
10585 #endif
10586 my_set_foreground_window (FRAME_W32_WINDOW (f));
10587 UNBLOCK_INPUT;
10590 void
10591 x_unfocus_frame (f)
10592 struct frame *f;
10596 /* Raise frame F. */
10597 void
10598 x_raise_frame (f)
10599 struct frame *f;
10601 BLOCK_INPUT;
10603 /* Strictly speaking, raise-frame should only change the frame's Z
10604 order, leaving input focus unchanged. This is reasonable behaviour
10605 on X where the usual policy is point-to-focus. However, this
10606 behaviour would be very odd on Windows where the usual policy is
10607 click-to-focus.
10609 On X, if the mouse happens to be over the raised frame, it gets
10610 input focus anyway (so the window with focus will never be
10611 completely obscured) - if not, then just moving the mouse over it
10612 is sufficient to give it focus. On Windows, the user must actually
10613 click on the frame (preferrably the title bar so as not to move
10614 point), which is more awkward. Also, no other Windows program
10615 raises a window to the top but leaves another window (possibly now
10616 completely obscured) with input focus.
10618 Because there is a system setting on Windows that allows the user
10619 to choose the point to focus policy, we make the strict semantics
10620 optional, but by default we grab focus when raising. */
10622 if (NILP (Vw32_grab_focus_on_raise))
10624 /* The obvious call to my_set_window_pos doesn't work if Emacs is
10625 not already the foreground application: the frame is raised
10626 above all other frames belonging to us, but not above the
10627 current top window. To achieve that, we have to resort to this
10628 more cumbersome method. */
10630 HDWP handle = BeginDeferWindowPos (2);
10631 if (handle)
10633 DeferWindowPos (handle,
10634 FRAME_W32_WINDOW (f),
10635 HWND_TOP,
10636 0, 0, 0, 0,
10637 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
10639 DeferWindowPos (handle,
10640 GetForegroundWindow (),
10641 FRAME_W32_WINDOW (f),
10642 0, 0, 0, 0,
10643 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
10645 EndDeferWindowPos (handle);
10648 else
10650 my_set_foreground_window (FRAME_W32_WINDOW (f));
10653 UNBLOCK_INPUT;
10656 /* Lower frame F. */
10657 void
10658 x_lower_frame (f)
10659 struct frame *f;
10661 BLOCK_INPUT;
10662 my_set_window_pos (FRAME_W32_WINDOW (f),
10663 HWND_BOTTOM,
10664 0, 0, 0, 0,
10665 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
10666 UNBLOCK_INPUT;
10669 static void
10670 w32_frame_raise_lower (f, raise_flag)
10671 FRAME_PTR f;
10672 int raise_flag;
10674 if (! FRAME_W32_P (f))
10675 return;
10677 if (raise_flag)
10678 x_raise_frame (f);
10679 else
10680 x_lower_frame (f);
10683 /* Change of visibility. */
10685 /* This tries to wait until the frame is really visible.
10686 However, if the window manager asks the user where to position
10687 the frame, this will return before the user finishes doing that.
10688 The frame will not actually be visible at that time,
10689 but it will become visible later when the window manager
10690 finishes with it. */
10692 void
10693 x_make_frame_visible (f)
10694 struct frame *f;
10696 Lisp_Object type;
10698 BLOCK_INPUT;
10700 type = x_icon_type (f);
10701 if (!NILP (type))
10702 x_bitmap_icon (f, type);
10704 if (! FRAME_VISIBLE_P (f))
10706 /* We test FRAME_GARBAGED_P here to make sure we don't
10707 call x_set_offset a second time
10708 if we get to x_make_frame_visible a second time
10709 before the window gets really visible. */
10710 if (! FRAME_ICONIFIED_P (f)
10711 && ! f->output_data.w32->asked_for_visible)
10712 x_set_offset (f, f->output_data.w32->left_pos, f->output_data.w32->top_pos, 0);
10714 f->output_data.w32->asked_for_visible = 1;
10716 /* my_show_window (f, FRAME_W32_WINDOW (f), f->async_iconified ? SW_RESTORE : SW_SHOW); */
10717 my_show_window (f, FRAME_W32_WINDOW (f), SW_SHOWNORMAL);
10720 /* Synchronize to ensure Emacs knows the frame is visible
10721 before we do anything else. We do this loop with input not blocked
10722 so that incoming events are handled. */
10724 Lisp_Object frame;
10725 int count;
10727 /* This must come after we set COUNT. */
10728 UNBLOCK_INPUT;
10730 XSETFRAME (frame, f);
10732 /* Wait until the frame is visible. Process X events until a
10733 MapNotify event has been seen, or until we think we won't get a
10734 MapNotify at all.. */
10735 for (count = input_signal_count + 10;
10736 input_signal_count < count && !FRAME_VISIBLE_P (f);)
10738 /* Force processing of queued events. */
10739 /* TODO: x_sync equivalent? */
10741 /* Machines that do polling rather than SIGIO have been observed
10742 to go into a busy-wait here. So we'll fake an alarm signal
10743 to let the handler know that there's something to be read.
10744 We used to raise a real alarm, but it seems that the handler
10745 isn't always enabled here. This is probably a bug. */
10746 if (input_polling_used ())
10748 /* It could be confusing if a real alarm arrives while processing
10749 the fake one. Turn it off and let the handler reset it. */
10750 int old_poll_suppress_count = poll_suppress_count;
10751 poll_suppress_count = 1;
10752 poll_for_input_1 ();
10753 poll_suppress_count = old_poll_suppress_count;
10756 FRAME_SAMPLE_VISIBILITY (f);
10760 /* Change from mapped state to withdrawn state. */
10762 /* Make the frame visible (mapped and not iconified). */
10764 x_make_frame_invisible (f)
10765 struct frame *f;
10767 /* Don't keep the highlight on an invisible frame. */
10768 if (FRAME_W32_DISPLAY_INFO (f)->x_highlight_frame == f)
10769 FRAME_W32_DISPLAY_INFO (f)->x_highlight_frame = 0;
10771 BLOCK_INPUT;
10773 my_show_window (f, FRAME_W32_WINDOW (f), SW_HIDE);
10775 /* We can't distinguish this from iconification
10776 just by the event that we get from the server.
10777 So we can't win using the usual strategy of letting
10778 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
10779 and synchronize with the server to make sure we agree. */
10780 f->visible = 0;
10781 FRAME_ICONIFIED_P (f) = 0;
10782 f->async_visible = 0;
10783 f->async_iconified = 0;
10785 UNBLOCK_INPUT;
10788 /* Change window state from mapped to iconified. */
10790 void
10791 x_iconify_frame (f)
10792 struct frame *f;
10794 Lisp_Object type;
10796 /* Don't keep the highlight on an invisible frame. */
10797 if (FRAME_W32_DISPLAY_INFO (f)->x_highlight_frame == f)
10798 FRAME_W32_DISPLAY_INFO (f)->x_highlight_frame = 0;
10800 if (f->async_iconified)
10801 return;
10803 BLOCK_INPUT;
10805 type = x_icon_type (f);
10806 if (!NILP (type))
10807 x_bitmap_icon (f, type);
10809 /* Simulate the user minimizing the frame. */
10810 SendMessage (FRAME_W32_WINDOW (f), WM_SYSCOMMAND, SC_MINIMIZE, 0);
10812 UNBLOCK_INPUT;
10816 /* Free X resources of frame F. */
10818 void
10819 x_free_frame_resources (f)
10820 struct frame *f;
10822 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
10824 BLOCK_INPUT;
10826 if (FRAME_W32_WINDOW (f))
10827 my_destroy_window (f, FRAME_W32_WINDOW (f));
10829 free_frame_menubar (f);
10831 unload_color (f, f->output_data.x->foreground_pixel);
10832 unload_color (f, f->output_data.x->background_pixel);
10833 unload_color (f, f->output_data.w32->cursor_pixel);
10834 unload_color (f, f->output_data.w32->cursor_foreground_pixel);
10835 unload_color (f, f->output_data.w32->border_pixel);
10836 unload_color (f, f->output_data.w32->mouse_pixel);
10837 if (f->output_data.w32->white_relief.allocated_p)
10838 unload_color (f, f->output_data.w32->white_relief.pixel);
10839 if (f->output_data.w32->black_relief.allocated_p)
10840 unload_color (f, f->output_data.w32->black_relief.pixel);
10842 if (FRAME_FACE_CACHE (f))
10843 free_frame_faces (f);
10845 xfree (f->output_data.w32);
10846 f->output_data.w32 = NULL;
10848 if (f == dpyinfo->w32_focus_frame)
10849 dpyinfo->w32_focus_frame = 0;
10850 if (f == dpyinfo->w32_focus_event_frame)
10851 dpyinfo->w32_focus_event_frame = 0;
10852 if (f == dpyinfo->x_highlight_frame)
10853 dpyinfo->x_highlight_frame = 0;
10855 if (f == dpyinfo->mouse_face_mouse_frame)
10857 dpyinfo->mouse_face_beg_row
10858 = dpyinfo->mouse_face_beg_col = -1;
10859 dpyinfo->mouse_face_end_row
10860 = dpyinfo->mouse_face_end_col = -1;
10861 dpyinfo->mouse_face_window = Qnil;
10862 dpyinfo->mouse_face_deferred_gc = 0;
10863 dpyinfo->mouse_face_mouse_frame = 0;
10866 UNBLOCK_INPUT;
10870 /* Destroy the window of frame F. */
10872 x_destroy_window (f)
10873 struct frame *f;
10875 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
10877 x_free_frame_resources (f);
10879 dpyinfo->reference_count--;
10883 /* Setting window manager hints. */
10885 /* Set the normal size hints for the window manager, for frame F.
10886 FLAGS is the flags word to use--or 0 meaning preserve the flags
10887 that the window now has.
10888 If USER_POSITION is nonzero, we set the USPosition
10889 flag (this is useful when FLAGS is 0). */
10890 void
10891 x_wm_set_size_hint (f, flags, user_position)
10892 struct frame *f;
10893 long flags;
10894 int user_position;
10896 Window window = FRAME_W32_WINDOW (f);
10898 enter_crit ();
10900 SetWindowLong (window, WND_FONTWIDTH_INDEX, FONT_WIDTH (f->output_data.w32->font));
10901 SetWindowLong (window, WND_LINEHEIGHT_INDEX, f->output_data.w32->line_height);
10902 SetWindowLong (window, WND_BORDER_INDEX, f->output_data.w32->internal_border_width);
10903 SetWindowLong (window, WND_SCROLLBAR_INDEX, f->output_data.w32->vertical_scroll_bar_extra);
10905 leave_crit ();
10908 /* Window manager things */
10909 x_wm_set_icon_position (f, icon_x, icon_y)
10910 struct frame *f;
10911 int icon_x, icon_y;
10913 #if 0
10914 Window window = FRAME_W32_WINDOW (f);
10916 f->display.x->wm_hints.flags |= IconPositionHint;
10917 f->display.x->wm_hints.icon_x = icon_x;
10918 f->display.x->wm_hints.icon_y = icon_y;
10920 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->display.x->wm_hints);
10921 #endif
10925 /***********************************************************************
10926 Fonts
10927 ***********************************************************************/
10929 /* The following functions are listed here to help diff stay in step
10930 with xterm.c. See w32fns.c for definitions.
10932 x_get_font_info (f, font_idx)
10933 x_list_fonts (f, pattern, size, maxnames)
10937 #if GLYPH_DEBUG
10939 /* Check that FONT is valid on frame F. It is if it can be found in F's
10940 font table. */
10942 static void
10943 x_check_font (f, font)
10944 struct frame *f;
10945 XFontStruct *font;
10947 int i;
10948 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
10950 xassert (font != NULL);
10952 for (i = 0; i < dpyinfo->n_fonts; i++)
10953 if (dpyinfo->font_table[i].name
10954 && font == dpyinfo->font_table[i].font)
10955 break;
10957 xassert (i < dpyinfo->n_fonts);
10960 #endif /* GLYPH_DEBUG != 0 */
10962 /* Set *W to the minimum width, *H to the minimum font height of FONT.
10963 Note: There are (broken) X fonts out there with invalid XFontStruct
10964 min_bounds contents. For example, handa@etl.go.jp reports that
10965 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
10966 have font->min_bounds.width == 0. */
10968 static INLINE void
10969 x_font_min_bounds (font, w, h)
10970 XFontStruct *font;
10971 int *w, *h;
10974 * TODO: Windows does not appear to offer min bound, only
10975 * average and maximum width, and maximum height.
10977 *h = FONT_HEIGHT (font);
10978 *w = FONT_WIDTH (font);
10982 /* Compute the smallest character width and smallest font height over
10983 all fonts available on frame F. Set the members smallest_char_width
10984 and smallest_font_height in F's x_display_info structure to
10985 the values computed. Value is non-zero if smallest_font_height or
10986 smallest_char_width become smaller than they were before. */
10989 x_compute_min_glyph_bounds (f)
10990 struct frame *f;
10992 int i;
10993 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
10994 XFontStruct *font;
10995 int old_width = dpyinfo->smallest_char_width;
10996 int old_height = dpyinfo->smallest_font_height;
10998 dpyinfo->smallest_font_height = 100000;
10999 dpyinfo->smallest_char_width = 100000;
11001 for (i = 0; i < dpyinfo->n_fonts; ++i)
11002 if (dpyinfo->font_table[i].name)
11004 struct font_info *fontp = dpyinfo->font_table + i;
11005 int w, h;
11007 font = (XFontStruct *) fontp->font;
11008 xassert (font != (XFontStruct *) ~0);
11009 x_font_min_bounds (font, &w, &h);
11011 dpyinfo->smallest_font_height = min (dpyinfo->smallest_font_height, h);
11012 dpyinfo->smallest_char_width = min (dpyinfo->smallest_char_width, w);
11015 xassert (dpyinfo->smallest_char_width > 0
11016 && dpyinfo->smallest_font_height > 0);
11018 return (dpyinfo->n_fonts == 1
11019 || dpyinfo->smallest_char_width < old_width
11020 || dpyinfo->smallest_font_height < old_height);
11023 /* The following functions are listed here to help diff stay in step
11024 with xterm.c. See w32fns.c for definitions.
11026 x_load_font (f, fontname, size)
11027 x_query_font (f, fontname)
11028 x_find_ccl_program (fontp)
11032 /***********************************************************************
11033 Initialization
11034 ***********************************************************************/
11036 static int w32_initialized = 0;
11038 void
11039 w32_initialize_display_info (display_name)
11040 Lisp_Object display_name;
11042 struct w32_display_info *dpyinfo = &one_w32_display_info;
11044 bzero (dpyinfo, sizeof (*dpyinfo));
11046 /* Put it on w32_display_name_list. */
11047 w32_display_name_list = Fcons (Fcons (display_name, Qnil),
11048 w32_display_name_list);
11049 dpyinfo->name_list_element = XCAR (w32_display_name_list);
11051 dpyinfo->w32_id_name
11052 = (char *) xmalloc (SCHARS (Vinvocation_name)
11053 + SCHARS (Vsystem_name)
11054 + 2);
11055 sprintf (dpyinfo->w32_id_name, "%s@%s",
11056 SDATA (Vinvocation_name), SDATA (Vsystem_name));
11058 /* Default Console mode values - overridden when running in GUI mode
11059 with values obtained from system metrics. */
11060 dpyinfo->resx = 1;
11061 dpyinfo->resy = 1;
11062 dpyinfo->height_in = 1;
11063 dpyinfo->width_in = 1;
11064 dpyinfo->n_planes = 1;
11065 dpyinfo->n_cbits = 4;
11066 dpyinfo->n_fonts = 0;
11067 dpyinfo->smallest_font_height = 1;
11068 dpyinfo->smallest_char_width = 1;
11070 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
11071 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
11072 dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
11073 dpyinfo->mouse_face_window = Qnil;
11074 dpyinfo->mouse_face_overlay = Qnil;
11075 dpyinfo->mouse_face_hidden = 0;
11077 dpyinfo->vertical_scroll_bar_cursor = w32_load_cursor (IDC_ARROW);
11078 /* TODO: dpyinfo->gray */
11082 struct w32_display_info *
11083 w32_term_init (display_name, xrm_option, resource_name)
11084 Lisp_Object display_name;
11085 char *xrm_option;
11086 char *resource_name;
11088 struct w32_display_info *dpyinfo;
11089 HDC hdc;
11091 BLOCK_INPUT;
11093 if (!w32_initialized)
11095 w32_initialize ();
11096 w32_initialized = 1;
11100 int argc = 0;
11101 char *argv[3];
11103 argv[0] = "";
11104 argc = 1;
11105 if (xrm_option)
11107 argv[argc++] = "-xrm";
11108 argv[argc++] = xrm_option;
11112 w32_initialize_display_info (display_name);
11114 dpyinfo = &one_w32_display_info;
11116 /* Put this display on the chain. */
11117 dpyinfo->next = x_display_list;
11118 x_display_list = dpyinfo;
11120 hdc = GetDC (GetDesktopWindow ());
11122 dpyinfo->height = GetDeviceCaps (hdc, VERTRES);
11123 dpyinfo->width = GetDeviceCaps (hdc, HORZRES);
11124 dpyinfo->root_window = GetDesktopWindow ();
11125 dpyinfo->n_planes = GetDeviceCaps (hdc, PLANES);
11126 dpyinfo->n_cbits = GetDeviceCaps (hdc, BITSPIXEL);
11127 dpyinfo->resx = GetDeviceCaps (hdc, LOGPIXELSX);
11128 dpyinfo->resy = GetDeviceCaps (hdc, LOGPIXELSY);
11129 dpyinfo->has_palette = GetDeviceCaps (hdc, RASTERCAPS) & RC_PALETTE;
11130 dpyinfo->image_cache = make_image_cache ();
11131 dpyinfo->height_in = dpyinfo->height / dpyinfo->resx;
11132 dpyinfo->width_in = dpyinfo->width / dpyinfo->resy;
11133 ReleaseDC (GetDesktopWindow (), hdc);
11135 /* initialise palette with white and black */
11137 XColor color;
11138 w32_defined_color (0, "white", &color, 1);
11139 w32_defined_color (0, "black", &color, 1);
11142 /* Create Row Bitmaps and store them for later use. */
11143 left_bmp = CreateBitmap (left_width, left_height, 1, 1, left_bits);
11144 ov_bmp = CreateBitmap (ov_width, ov_height, 1, 1, ov_bits);
11145 right_bmp = CreateBitmap (right_width, right_height, 1, 1, right_bits);
11146 continued_bmp = CreateBitmap (continued_width, continued_height, 1,
11147 1, continued_bits);
11148 continuation_bmp = CreateBitmap (continuation_width, continuation_height,
11149 1, 1, continuation_bits);
11150 zv_bmp = CreateBitmap (zv_width, zv_height, 1, 1, zv_bits);
11152 #ifndef F_SETOWN_BUG
11153 #ifdef F_SETOWN
11154 #ifdef F_SETOWN_SOCK_NEG
11155 /* stdin is a socket here */
11156 fcntl (connection, F_SETOWN, -getpid ());
11157 #else /* ! defined (F_SETOWN_SOCK_NEG) */
11158 fcntl (connection, F_SETOWN, getpid ());
11159 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
11160 #endif /* ! defined (F_SETOWN) */
11161 #endif /* F_SETOWN_BUG */
11163 #ifdef SIGIO
11164 if (interrupt_input)
11165 init_sigio (connection);
11166 #endif /* ! defined (SIGIO) */
11168 UNBLOCK_INPUT;
11170 return dpyinfo;
11173 /* Get rid of display DPYINFO, assuming all frames are already gone. */
11175 void
11176 x_delete_display (dpyinfo)
11177 struct w32_display_info *dpyinfo;
11179 /* Discard this display from w32_display_name_list and w32_display_list.
11180 We can't use Fdelq because that can quit. */
11181 if (! NILP (w32_display_name_list)
11182 && EQ (XCAR (w32_display_name_list), dpyinfo->name_list_element))
11183 w32_display_name_list = XCDR (w32_display_name_list);
11184 else
11186 Lisp_Object tail;
11188 tail = w32_display_name_list;
11189 while (CONSP (tail) && CONSP (XCDR (tail)))
11191 if (EQ (XCAR (XCDR (tail)), dpyinfo->name_list_element))
11193 XSETCDR (tail, XCDR (XCDR (tail)));
11194 break;
11196 tail = XCDR (tail);
11200 /* free palette table */
11202 struct w32_palette_entry * plist;
11204 plist = dpyinfo->color_list;
11205 while (plist)
11207 struct w32_palette_entry * pentry = plist;
11208 plist = plist->next;
11209 xfree (pentry);
11211 dpyinfo->color_list = NULL;
11212 if (dpyinfo->palette)
11213 DeleteObject(dpyinfo->palette);
11215 xfree (dpyinfo->font_table);
11216 xfree (dpyinfo->w32_id_name);
11218 /* Destroy row bitmaps. */
11219 DeleteObject (left_bmp);
11220 DeleteObject (ov_bmp);
11221 DeleteObject (right_bmp);
11222 DeleteObject (continued_bmp);
11223 DeleteObject (continuation_bmp);
11224 DeleteObject (zv_bmp);
11227 /* Set up use of W32. */
11229 DWORD w32_msg_worker ();
11231 void
11232 x_flush (struct frame * f)
11233 { /* Nothing to do */ }
11235 static struct redisplay_interface w32_redisplay_interface =
11237 x_produce_glyphs,
11238 x_write_glyphs,
11239 x_insert_glyphs,
11240 x_clear_end_of_line,
11241 x_scroll_run,
11242 x_after_update_window_line,
11243 x_update_window_begin,
11244 x_update_window_end,
11245 w32_cursor_to,
11246 x_flush,
11247 x_clear_mouse_face,
11248 x_get_glyph_overhangs,
11249 x_fix_overlapping_area
11252 void
11253 w32_initialize ()
11255 rif = &w32_redisplay_interface;
11257 /* MSVC does not type K&R functions with no arguments correctly, and
11258 so we must explicitly cast them. */
11259 clear_frame_hook = (void (*)(void)) x_clear_frame;
11260 ring_bell_hook = (void (*)(void)) w32_ring_bell;
11261 update_begin_hook = x_update_begin;
11262 update_end_hook = x_update_end;
11264 read_socket_hook = w32_read_socket;
11266 frame_up_to_date_hook = w32_frame_up_to_date;
11268 mouse_position_hook = w32_mouse_position;
11269 frame_rehighlight_hook = w32_frame_rehighlight;
11270 frame_raise_lower_hook = w32_frame_raise_lower;
11271 set_vertical_scroll_bar_hook = w32_set_vertical_scroll_bar;
11272 condemn_scroll_bars_hook = w32_condemn_scroll_bars;
11273 redeem_scroll_bar_hook = w32_redeem_scroll_bar;
11274 judge_scroll_bars_hook = w32_judge_scroll_bars;
11275 estimate_mode_line_height_hook = x_estimate_mode_line_height;
11277 scroll_region_ok = 1; /* we'll scroll partial frames */
11278 char_ins_del_ok = 1;
11279 line_ins_del_ok = 1; /* we'll just blt 'em */
11280 fast_clear_end_of_line = 1; /* X does this well */
11281 memory_below_frame = 0; /* we don't remember what scrolls
11282 off the bottom */
11283 baud_rate = 19200;
11285 w32_system_caret_hwnd = NULL;
11286 w32_system_caret_height = 0;
11287 w32_system_caret_x = 0;
11288 w32_system_caret_y = 0;
11290 last_tool_bar_item = -1;
11291 any_help_event_p = 0;
11293 /* Initialize input mode: interrupt_input off, no flow control, allow
11294 8 bit character input, standard quit char. */
11295 Fset_input_mode (Qnil, Qnil, make_number (2), Qnil);
11297 /* Create the window thread - it will terminate itself or when the app terminates */
11299 init_crit ();
11301 dwMainThreadId = GetCurrentThreadId ();
11302 DuplicateHandle (GetCurrentProcess (), GetCurrentThread (),
11303 GetCurrentProcess (), &hMainThread, 0, TRUE, DUPLICATE_SAME_ACCESS);
11305 /* Wait for thread to start */
11308 MSG msg;
11310 PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE);
11312 hWindowsThread = CreateThread (NULL, 0,
11313 (LPTHREAD_START_ROUTINE) w32_msg_worker,
11314 0, 0, &dwWindowsThreadId);
11316 GetMessage (&msg, NULL, WM_EMACS_DONE, WM_EMACS_DONE);
11319 /* It is desirable that mainThread should have the same notion of
11320 focus window and active window as windowsThread. Unfortunately, the
11321 following call to AttachThreadInput, which should do precisely what
11322 we need, causes major problems when Emacs is linked as a console
11323 program. Unfortunately, we have good reasons for doing that, so
11324 instead we need to send messages to windowsThread to make some API
11325 calls for us (ones that affect, or depend on, the active/focus
11326 window state. */
11327 #ifdef ATTACH_THREADS
11328 AttachThreadInput (dwMainThreadId, dwWindowsThreadId, TRUE);
11329 #endif
11331 /* Dynamically link to optional system components. */
11333 HANDLE user_lib = LoadLibrary ("user32.dll");
11335 #define LOAD_PROC(fn) pfn##fn = (void *) GetProcAddress (user_lib, #fn)
11337 /* New proportional scroll bar functions. */
11338 LOAD_PROC (SetScrollInfo);
11339 LOAD_PROC (GetScrollInfo);
11341 #undef LOAD_PROC
11343 FreeLibrary (user_lib);
11345 /* If using proportional scroll bars, ensure handle is at least 5 pixels;
11346 otherwise use the fixed height. */
11347 vertical_scroll_bar_min_handle = (pfnSetScrollInfo != NULL) ? 5 :
11348 GetSystemMetrics (SM_CYVTHUMB);
11350 /* For either kind of scroll bar, take account of the arrows; these
11351 effectively form the border of the main scroll bar range. */
11352 vertical_scroll_bar_top_border = vertical_scroll_bar_bottom_border
11353 = GetSystemMetrics (SM_CYVSCROLL);
11357 void
11358 syms_of_w32term ()
11360 staticpro (&w32_display_name_list);
11361 w32_display_name_list = Qnil;
11363 staticpro (&last_mouse_scroll_bar);
11364 last_mouse_scroll_bar = Qnil;
11366 staticpro (&Qvendor_specific_keysyms);
11367 Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
11369 DEFVAR_INT ("w32-num-mouse-buttons",
11370 &Vw32_num_mouse_buttons,
11371 doc: /* Number of physical mouse buttons. */);
11372 Vw32_num_mouse_buttons = Qnil;
11374 DEFVAR_LISP ("w32-swap-mouse-buttons",
11375 &Vw32_swap_mouse_buttons,
11376 doc: /* Swap the mapping of middle and right mouse buttons.
11377 When nil, middle button is mouse-2 and right button is mouse-3. */);
11378 Vw32_swap_mouse_buttons = Qnil;
11380 DEFVAR_LISP ("w32-grab-focus-on-raise",
11381 &Vw32_grab_focus_on_raise,
11382 doc: /* Raised frame grabs input focus.
11383 When t, `raise-frame' grabs input focus as well. This fits well
11384 with the normal Windows click-to-focus policy, but might not be
11385 desirable when using a point-to-focus policy. */);
11386 Vw32_grab_focus_on_raise = Qt;
11388 DEFVAR_LISP ("w32-capslock-is-shiftlock",
11389 &Vw32_capslock_is_shiftlock,
11390 doc: /* Apply CapsLock state to non character input keys.
11391 When nil, CapsLock only affects normal character input keys. */);
11392 Vw32_capslock_is_shiftlock = Qnil;
11394 DEFVAR_LISP ("w32-recognize-altgr",
11395 &Vw32_recognize_altgr,
11396 doc: /* Recognize right-alt and left-ctrl as AltGr.
11397 When nil, the right-alt and left-ctrl key combination is
11398 interpreted normally. */);
11399 Vw32_recognize_altgr = Qt;
11401 DEFVAR_BOOL ("w32-enable-unicode-output",
11402 &w32_enable_unicode_output,
11403 doc: /* Enable the use of Unicode for text output if non-nil.
11404 Unicode output may prevent some third party applications for displaying
11405 Far-East Languages on Windows 95/98 from working properly.
11406 NT uses Unicode internally anyway, so this flag will probably have no
11407 affect on NT machines. */);
11408 w32_enable_unicode_output = 1;
11410 help_echo = Qnil;
11411 staticpro (&help_echo);
11412 help_echo_object = Qnil;
11413 staticpro (&help_echo_object);
11414 help_echo_window = Qnil;
11415 staticpro (&help_echo_window);
11416 previous_help_echo = Qnil;
11417 staticpro (&previous_help_echo);
11418 help_echo_pos = -1;
11420 DEFVAR_BOOL ("mouse-autoselect-window", &mouse_autoselect_window,
11421 doc: /* *Non-nil means autoselect window with mouse pointer. */);
11422 mouse_autoselect_window = 0;
11424 DEFVAR_BOOL ("w32-use-visible-system-caret",
11425 &w32_use_visible_system_caret,
11426 doc: /* Flag to make the system caret visible.
11427 When this is non-nil, Emacs will indicate the position of point by
11428 using the system caret instead of drawing its own cursor. Some screen
11429 reader software does not track the system cursor properly when it is
11430 invisible, and gets confused by Emacs drawing its own cursor, so this
11431 variable is initialized to t when Emacs detects that screen reader
11432 software is running as it starts up.
11434 When this variable is set, other variables affecting the appearance of
11435 the cursor have no effect. */);
11437 /* Initialize w32_use_visible_system_caret based on whether a screen
11438 reader is in use. */
11439 if (!SystemParametersInfo (SPI_GETSCREENREADER, 0,
11440 &w32_use_visible_system_caret, 0))
11441 w32_use_visible_system_caret = 0;
11443 DEFVAR_BOOL ("x-stretch-cursor", &x_stretch_cursor_p,
11444 doc: /* *Non-nil means draw block cursor as wide as the glyph under it.
11445 For example, if a block cursor is over a tab, it will be drawn as
11446 wide as that tab on the display. */);
11447 x_stretch_cursor_p = 0;
11449 DEFVAR_BOOL ("x-use-underline-position-properties",
11450 &x_use_underline_position_properties,
11451 doc: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
11452 nil means ignore them. If you encounter fonts with bogus
11453 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
11454 to 4.1, set this to nil. */);
11455 x_use_underline_position_properties = 1;
11457 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,
11458 doc: /* If not nil, Emacs uses toolkit scroll bars. */);
11459 Vx_toolkit_scroll_bars = Qt;
11461 staticpro (&last_mouse_motion_frame);
11462 last_mouse_motion_frame = Qnil;