Docstring fixes.
[emacs.git] / src / w32term.c
blobb336fc9fbe517173557c5331ef56e5c935be4d3d
1 /* Implementation of GUI terminal on the Microsoft W32 API.
2 Copyright (C) 1989, 93, 94, 95, 96, 1997, 1998, 1999, 2000
3 Free Software Foundation, Inc.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
22 #include <config.h>
23 #include <signal.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include "lisp.h"
27 #include "charset.h"
28 #include "blockinput.h"
30 #include "w32heap.h"
31 #include "w32term.h"
32 #include "w32bdf.h"
33 #include <shellapi.h>
35 #include "systty.h"
36 #include "systime.h"
37 #include "atimer.h"
39 #include <ctype.h>
40 #include <errno.h>
41 #include <setjmp.h>
42 #include <sys/stat.h>
44 #include "keyboard.h"
45 #include "frame.h"
46 #include "dispextern.h"
47 #include "fontset.h"
48 #include "termhooks.h"
49 #include "termopts.h"
50 #include "termchar.h"
51 #include "gnu.h"
52 #include "disptab.h"
53 #include "buffer.h"
54 #include "window.h"
55 #include "intervals.h"
56 #include "composite.h"
57 #include "coding.h"
59 #undef min
60 #undef max
61 #define min(x, y) (((x) < (y)) ? (x) : (y))
62 #define max(x, y) (((x) > (y)) ? (x) : (y))
64 #define abs(x) ((x) < 0 ? -(x) : (x))
66 #define BETWEEN(X, LOWER, UPPER) ((X) >= (LOWER) && (X) < (UPPER))
69 /* Bitmaps for truncated lines. */
71 enum bitmap_type
73 NO_BITMAP,
74 LEFT_TRUNCATION_BITMAP,
75 RIGHT_TRUNCATION_BITMAP,
76 OVERLAY_ARROW_BITMAP,
77 CONTINUED_LINE_BITMAP,
78 CONTINUATION_LINE_BITMAP,
79 ZV_LINE_BITMAP
82 enum w32_char_font_type
84 UNKNOWN_FONT,
85 ANSI_FONT,
86 UNICODE_FONT,
87 BDF_1D_FONT,
88 BDF_2D_FONT
91 /* Bitmaps are all unsigned short, as Windows requires bitmap data to
92 be Word aligned. For some reason they are horizontally reflected
93 compared to how they appear on X, so changes in xterm.c should be
94 reflected here. */
96 /* Bitmap drawn to indicate lines not displaying text if
97 `indicate-empty-lines' is non-nil. */
99 #define zv_width 8
100 #define zv_height 8
101 static unsigned short zv_bits[] = {
102 0x00, 0x00, 0x78, 0x78, 0x78, 0x78, 0x00, 0x00};
103 static HBITMAP zv_bmp;
105 /* An arrow like this: `<-'. */
107 #define left_width 8
108 #define left_height 8
109 static unsigned short left_bits[] = {
110 0x18, 0x30, 0x60, 0xfc, 0xfc, 0x60, 0x30, 0x18};
111 static HBITMAP left_bmp;
113 /* Right truncation arrow bitmap `->'. */
115 #define right_width 8
116 #define right_height 8
117 static unsigned short right_bits[] = {
118 0x18, 0x0c, 0x06, 0x3f, 0x3f, 0x06, 0x0c, 0x18};
119 static HBITMAP right_bmp;
121 /* Marker for continued lines. */
123 #define continued_width 8
124 #define continued_height 8
125 static unsigned short continued_bits[] = {
126 0x3c, 0x3e, 0x03, 0x27, 0x3f, 0x3e, 0x3c, 0x3e};
127 static HBITMAP continued_bmp;
129 /* Marker for continuation lines. */
131 #define continuation_width 8
132 #define continuation_height 8
133 static unsigned short continuation_bits[] = {
134 0x3c, 0x7c, 0xc0, 0xe4, 0xfc, 0x7c, 0x3c, 0x7c};
135 static HBITMAP continuation_bmp;
137 /* Overlay arrow bitmap. */
139 #if 0
140 /* A bomb. */
141 #define ov_width 8
142 #define ov_height 8
143 static unsigned short ov_bits[] = {
144 0x0c, 0x10, 0x3c, 0x7e, 0x5e, 0x5e, 0x46, 0x3c};
145 #else
146 /* A triangular arrow. */
147 #define ov_width 8
148 #define ov_height 8
149 static unsigned short ov_bits[] = {
150 0xc0, 0xf0, 0xf8, 0xfc, 0xfc, 0xf8, 0xf0, 0xc0};
151 #endif
152 static HBITMAP ov_bmp;
154 extern Lisp_Object Qhelp_echo;
157 /* Non-zero means Emacs uses toolkit scroll bars. */
159 int x_toolkit_scroll_bars_p;
161 /* If a string, w32_read_socket generates an event to display that string.
162 (The display is done in read_char.) */
164 static Lisp_Object help_echo;
165 static Lisp_Object help_echo_window;
166 static Lisp_Object help_echo_object;
167 static int help_echo_pos;
169 /* Temporary variable for w32_read_socket. */
171 static Lisp_Object previous_help_echo;
173 /* Non-zero means that a HELP_EVENT has been generated since Emacs
174 start. */
176 static int any_help_event_p;
178 /* Non-zero means draw block and hollow cursor as wide as the glyph
179 under it. For example, if a block cursor is over a tab, it will be
180 drawn as wide as that tab on the display. */
182 int x_stretch_cursor_p;
184 extern unsigned int msh_mousewheel;
186 extern void free_frame_menubar ();
188 extern void w32_menu_display_help (HMENU menu, UINT menu_item, UINT flags);
190 extern int w32_codepage_for_font (char *fontname);
192 extern Lisp_Object Vwindow_system;
194 #define x_any_window_to_frame x_window_to_frame
195 #define x_top_window_to_frame x_window_to_frame
198 /* This is display since w32 does not support multiple ones. */
199 struct w32_display_info one_w32_display_info;
201 /* This is a list of cons cells, each of the form (NAME . FONT-LIST-CACHE),
202 one for each element of w32_display_list and in the same order.
203 NAME is the name of the frame.
204 FONT-LIST-CACHE records previous values returned by x-list-fonts. */
205 Lisp_Object w32_display_name_list;
207 /* Frame being updated by update_frame. This is declared in term.c.
208 This is set by update_begin and looked at by all the
209 w32 functions. It is zero while not inside an update.
210 In that case, the w32 functions assume that `SELECTED_FRAME ()'
211 is the frame to apply to. */
212 extern struct frame *updating_frame;
214 /* This is a frame waiting to be autoraised, within w32_read_socket. */
215 struct frame *pending_autoraise_frame;
217 /* Nominal cursor position -- where to draw output.
218 HPOS and VPOS are window relative glyph matrix coordinates.
219 X and Y are window relative pixel coordinates. */
221 struct cursor_pos output_cursor;
223 /* Flag to enable Unicode output in case users wish to use programs
224 like Twinbridge on '95 rather than installed system level support
225 for Far East languages. */
226 int w32_enable_unicode_output;
228 DWORD dwWindowsThreadId = 0;
229 HANDLE hWindowsThread = NULL;
230 DWORD dwMainThreadId = 0;
231 HANDLE hMainThread = NULL;
233 #ifndef SIF_ALL
234 /* These definitions are new with Windows 95. */
235 #define SIF_RANGE 0x0001
236 #define SIF_PAGE 0x0002
237 #define SIF_POS 0x0004
238 #define SIF_DISABLENOSCROLL 0x0008
239 #define SIF_TRACKPOS 0x0010
240 #define SIF_ALL (SIF_RANGE | SIF_PAGE | SIF_POS | SIF_TRACKPOS)
242 typedef struct tagSCROLLINFO
244 UINT cbSize;
245 UINT fMask;
246 int nMin;
247 int nMax;
248 UINT nPage;
249 int nPos;
250 int nTrackPos;
251 } SCROLLINFO, FAR *LPSCROLLINFO;
252 typedef SCROLLINFO CONST FAR *LPCSCROLLINFO;
253 #endif /* SIF_ALL */
255 /* Dynamic linking to new proportional scroll bar functions. */
256 int (PASCAL *pfnSetScrollInfo) (HWND hwnd, int fnBar, LPSCROLLINFO lpsi, BOOL fRedraw);
257 BOOL (PASCAL *pfnGetScrollInfo) (HWND hwnd, int fnBar, LPSCROLLINFO lpsi);
259 int vertical_scroll_bar_min_handle;
260 int vertical_scroll_bar_top_border;
261 int vertical_scroll_bar_bottom_border;
263 int last_scroll_bar_drag_pos;
265 /* Mouse movement. */
267 /* Where the mouse was last time we reported a mouse event. */
269 FRAME_PTR last_mouse_frame;
270 static RECT last_mouse_glyph;
271 static Lisp_Object last_mouse_press_frame;
273 Lisp_Object Vw32_num_mouse_buttons;
275 Lisp_Object Vw32_swap_mouse_buttons;
277 /* Control whether x_raise_frame also sets input focus. */
278 Lisp_Object Vw32_grab_focus_on_raise;
280 /* Control whether Caps Lock affects non-ascii characters. */
281 Lisp_Object Vw32_capslock_is_shiftlock;
283 /* Control whether right-alt and left-ctrl should be recognized as AltGr. */
284 Lisp_Object Vw32_recognize_altgr;
286 /* The scroll bar in which the last motion event occurred.
288 If the last motion event occurred in a scroll bar, we set this
289 so w32_mouse_position can know whether to report a scroll bar motion or
290 an ordinary motion.
292 If the last motion event didn't occur in a scroll bar, we set this
293 to Qnil, to tell w32_mouse_position to return an ordinary motion event. */
294 static Lisp_Object last_mouse_scroll_bar;
295 static int last_mouse_scroll_bar_pos;
297 /* This is a hack. We would really prefer that w32_mouse_position would
298 return the time associated with the position it returns, but there
299 doesn't seem to be any way to wrest the time-stamp from the server
300 along with the position query. So, we just keep track of the time
301 of the last movement we received, and return that in hopes that
302 it's somewhat accurate. */
304 static Time last_mouse_movement_time;
306 /* Incremented by w32_read_socket whenever it really tries to read
307 events. */
309 #ifdef __STDC__
310 static int volatile input_signal_count;
311 #else
312 static int input_signal_count;
313 #endif
315 extern Lisp_Object Vcommand_line_args, Vsystem_name;
317 extern Lisp_Object Qface, Qmouse_face;
319 #ifndef USE_CRT_DLL
320 extern int errno;
321 #endif
323 /* A mask of extra modifier bits to put into every keyboard char. */
325 extern int extra_keyboard_modifiers;
327 /* Enumeration for overriding/changing the face to use for drawing
328 glyphs in x_draw_glyphs. */
330 enum draw_glyphs_face
332 DRAW_NORMAL_TEXT,
333 DRAW_INVERSE_VIDEO,
334 DRAW_CURSOR,
335 DRAW_MOUSE_FACE,
336 DRAW_IMAGE_RAISED,
337 DRAW_IMAGE_SUNKEN
340 static void x_update_window_end P_ ((struct window *, int, int));
341 static void frame_to_window_pixel_xy P_ ((struct window *, int *, int *));
342 void w32_delete_display P_ ((struct w32_display_info *));
343 static int fast_find_position P_ ((struct window *, int, int *, int *,
344 int *, int *));
345 static void set_output_cursor P_ ((struct cursor_pos *));
346 static struct glyph *x_y_to_hpos_vpos P_ ((struct window *, int, int,
347 int *, int *, int *));
348 static void note_mode_line_highlight P_ ((struct window *, int, int));
349 static void x_check_font P_ ((struct frame *, XFontStruct *));
350 static void note_mouse_highlight P_ ((struct frame *, int, int));
351 static void note_tool_bar_highlight P_ ((struct frame *f, int, int));
352 static void w32_handle_tool_bar_click P_ ((struct frame *,
353 struct input_event *));
354 static void show_mouse_face P_ ((struct w32_display_info *,
355 enum draw_glyphs_face));
356 void clear_mouse_face P_ ((struct w32_display_info *));
358 void x_lower_frame P_ ((struct frame *));
359 void x_scroll_bar_clear P_ ((struct frame *));
360 void x_wm_set_size_hint P_ ((struct frame *, long, int));
361 void x_raise_frame P_ ((struct frame *));
362 void x_set_window_size P_ ((struct frame *, int, int, int));
363 void x_wm_set_window_state P_ ((struct frame *, int));
364 void x_wm_set_icon_pixmap P_ ((struct frame *, int));
365 void w32_initialize P_ ((void));
366 static void x_font_min_bounds P_ ((XFontStruct *, int *, int *));
367 int x_compute_min_glyph_bounds P_ ((struct frame *));
368 static void x_draw_phys_cursor_glyph P_ ((struct window *,
369 struct glyph_row *,
370 enum draw_glyphs_face));
371 static void x_update_end P_ ((struct frame *));
372 static void w32_frame_up_to_date P_ ((struct frame *));
373 static void w32_reassert_line_highlight P_ ((int, int));
374 static void x_change_line_highlight P_ ((int, int, int, int));
375 static void w32_set_terminal_modes P_ ((void));
376 static void w32_reset_terminal_modes P_ ((void));
377 static void w32_cursor_to P_ ((int, int, int, int));
378 static void x_write_glyphs P_ ((struct glyph *, int));
379 static void x_clear_end_of_line P_ ((int));
380 static void x_clear_frame P_ ((void));
381 static void x_clear_cursor P_ ((struct window *));
382 static void frame_highlight P_ ((struct frame *));
383 static void frame_unhighlight P_ ((struct frame *));
384 static void w32_new_focus_frame P_ ((struct w32_display_info *,
385 struct frame *));
386 static void w32_frame_rehighlight P_ ((struct frame *));
387 static void x_frame_rehighlight P_ ((struct w32_display_info *));
388 static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *));
389 static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int));
390 static void expose_frame P_ ((struct frame *, int, int, int, int));
391 static void expose_window_tree P_ ((struct window *, RECT *));
392 static void expose_window P_ ((struct window *, RECT *));
393 static void expose_area P_ ((struct window *, struct glyph_row *,
394 RECT *, enum glyph_row_area));
395 static void expose_line P_ ((struct window *, struct glyph_row *,
396 RECT *));
397 void x_update_cursor P_ ((struct frame *, int));
398 static void x_update_cursor_in_window_tree P_ ((struct window *, int));
399 static void x_update_window_cursor P_ ((struct window *, int));
400 static void x_erase_phys_cursor P_ ((struct window *));
401 void x_display_cursor P_ ((struct window *w, int, int, int, int, int));
402 void x_display_and_set_cursor P_ ((struct window *, int, int, int, int, int));
403 static void w32_draw_bitmap P_ ((struct window *, HDC hdc, struct glyph_row *,
404 enum bitmap_type));
405 static int x_phys_cursor_in_rect_p P_ ((struct window *, RECT *));
406 static void x_draw_row_bitmaps P_ ((struct window *, struct glyph_row *));
407 static void note_overwritten_text_cursor P_ ((struct window *, int, int));
408 static void w32_clip_to_row P_ ((struct window *, struct glyph_row *,
409 HDC, int));
411 static Lisp_Object Qvendor_specific_keysyms;
414 /***********************************************************************
415 Debugging
416 ***********************************************************************/
418 #if 0
420 /* This is a function useful for recording debugging information about
421 the sequence of occurrences in this file. */
423 struct record
425 char *locus;
426 int type;
429 struct record event_record[100];
431 int event_record_index;
433 record_event (locus, type)
434 char *locus;
435 int type;
437 if (event_record_index == sizeof (event_record) / sizeof (struct record))
438 event_record_index = 0;
440 event_record[event_record_index].locus = locus;
441 event_record[event_record_index].type = type;
442 event_record_index++;
445 #endif /* 0 */
448 void XChangeGC (void * ignore, XGCValues* gc, unsigned long mask,
449 XGCValues *xgcv)
451 if (mask & GCForeground)
452 gc->foreground = xgcv->foreground;
453 if (mask & GCBackground)
454 gc->background = xgcv->background;
455 if (mask & GCFont)
456 gc->font = xgcv->font;
459 XGCValues *XCreateGC (void * ignore, Window window, unsigned long mask,
460 XGCValues *xgcv)
462 XGCValues *gc = (XGCValues *) xmalloc (sizeof (XGCValues));
463 bzero (gc, sizeof (XGCValues));
465 XChangeGC (ignore, gc, mask, xgcv);
467 return gc;
470 void XGetGCValues (void* ignore, XGCValues *gc,
471 unsigned long mask, XGCValues *xgcv)
473 XChangeGC (ignore, xgcv, mask, gc);
476 static void
477 w32_set_clip_rectangle (HDC hdc, RECT *rect)
479 if (rect)
481 HRGN clip_region = CreateRectRgnIndirect (rect);
482 SelectClipRgn (hdc, clip_region);
483 DeleteObject (clip_region);
485 else
486 SelectClipRgn (hdc, NULL);
490 /* Draw a hollow rectangle at the specified position. */
491 void
492 w32_draw_rectangle (HDC hdc, XGCValues *gc, int x, int y,
493 int width, int height)
495 HBRUSH hb, oldhb;
496 HPEN hp, oldhp;
498 hb = CreateSolidBrush (gc->background);
499 hp = CreatePen (PS_SOLID, 0, gc->foreground);
500 oldhb = SelectObject (hdc, hb);
501 oldhp = SelectObject (hdc, hp);
503 Rectangle (hdc, x, y, x + width, y + height);
505 SelectObject (hdc, oldhb);
506 SelectObject (hdc, oldhp);
507 DeleteObject (hb);
508 DeleteObject (hp);
511 /* Draw a filled rectangle at the specified position. */
512 void
513 w32_fill_rect (f, hdc, pix, lprect)
514 FRAME_PTR f;
515 HDC hdc;
516 COLORREF pix;
517 RECT * lprect;
519 HBRUSH hb;
520 RECT rect;
522 hb = CreateSolidBrush (pix);
523 FillRect (hdc, lprect, hb);
524 DeleteObject (hb);
527 void
528 w32_clear_window (f)
529 FRAME_PTR f;
531 RECT rect;
532 HDC hdc = get_frame_dc (f);
534 GetClientRect (FRAME_W32_WINDOW (f), &rect);
535 w32_clear_rect (f, hdc, &rect);
536 release_frame_dc (f, hdc);
540 /***********************************************************************
541 Starting and ending an update
542 ***********************************************************************/
544 /* Start an update of frame F. This function is installed as a hook
545 for update_begin, i.e. it is called when update_begin is called.
546 This function is called prior to calls to x_update_window_begin for
547 each window being updated. Currently, there is nothing to do here
548 because all interesting stuff is done on a window basis. */
550 static void
551 x_update_begin (f)
552 struct frame *f;
554 /* Nothing to do. We have to do something though, otherwise the
555 function gets optimized away and the hook is no longer valid. */
556 struct frame *cf = f;
560 /* Start update of window W. Set the global variable updated_window
561 to the window being updated and set output_cursor to the cursor
562 position of W. */
564 static void
565 x_update_window_begin (w)
566 struct window *w;
568 struct frame *f = XFRAME (WINDOW_FRAME (w));
569 struct w32_display_info *display_info = FRAME_W32_DISPLAY_INFO (f);
571 updated_window = w;
572 set_output_cursor (&w->cursor);
574 BLOCK_INPUT;
576 /* Regenerate display palette before drawing if list of requested
577 colors has changed. */
578 if (display_info->regen_palette)
580 w32_regenerate_palette (f);
581 display_info->regen_palette = FALSE;
584 if (f == display_info->mouse_face_mouse_frame)
586 /* Don't do highlighting for mouse motion during the update. */
587 display_info->mouse_face_defer = 1;
589 /* If F needs to be redrawn, simply forget about any prior mouse
590 highlighting. */
591 if (FRAME_GARBAGED_P (f))
592 display_info->mouse_face_window = Qnil;
594 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
595 their mouse_face_p flag set, which means that they are always
596 unequal to rows in a desired matrix which never have that
597 flag set. So, rows containing mouse-face glyphs are never
598 scrolled, and we don't have to switch the mouse highlight off
599 here to prevent it from being scrolled. */
601 /* Can we tell that this update does not affect the window
602 where the mouse highlight is? If so, no need to turn off.
603 Likewise, don't do anything if the frame is garbaged;
604 in that case, the frame's current matrix that we would use
605 is all wrong, and we will redisplay that line anyway. */
606 if (!NILP (display_info->mouse_face_window)
607 && w == XWINDOW (display_info->mouse_face_window))
609 int i;
611 for (i = 0; i < w->desired_matrix->nrows; ++i)
612 if (MATRIX_ROW_ENABLED_P (w->desired_matrix, i))
613 break;
615 if (i < w->desired_matrix->nrows)
616 clear_mouse_face (display_info);
618 #endif /* 0 */
621 UNBLOCK_INPUT;
625 /* Draw a vertical window border to the right of window W if W doesn't
626 have vertical scroll bars. */
628 static void
629 x_draw_vertical_border (w)
630 struct window *w;
632 struct frame *f = XFRAME (WINDOW_FRAME (w));
634 /* Redraw borders between horizontally adjacent windows. Don't
635 do it for frames with vertical scroll bars because either the
636 right scroll bar of a window, or the left scroll bar of its
637 neighbor will suffice as a border. */
638 if (!WINDOW_RIGHTMOST_P (w)
639 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
641 RECT r;
642 HDC hdc;
644 window_box_edges (w, -1, &r.left, &r.top, &r.right, &r.bottom);
645 r.left = r.right + FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f);
646 r.right = r.left + 1;
647 r.bottom -= 1;
649 hdc = get_frame_dc (f);
650 w32_fill_rect (f, hdc, FRAME_FOREGROUND_PIXEL (f), r);
651 release_frame_dc (f, hdc);
656 /* End update of window W (which is equal to updated_window).
658 Draw vertical borders between horizontally adjacent windows, and
659 display W's cursor if CURSOR_ON_P is non-zero.
661 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
662 glyphs in mouse-face were overwritten. In that case we have to
663 make sure that the mouse-highlight is properly redrawn.
665 W may be a menu bar pseudo-window in case we don't have X toolkit
666 support. Such windows don't have a cursor, so don't display it
667 here. */
669 static void
670 x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p)
671 struct window *w;
672 int cursor_on_p, mouse_face_overwritten_p;
674 if (!w->pseudo_window_p)
676 struct w32_display_info *dpyinfo
677 = FRAME_W32_DISPLAY_INFO (XFRAME (w->frame));
679 BLOCK_INPUT;
681 /* If a row with mouse-face was overwritten, arrange for
682 XTframe_up_to_date to redisplay the mouse highlight. */
683 if (mouse_face_overwritten_p)
685 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
686 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
687 dpyinfo->mouse_face_window = Qnil;
690 if (cursor_on_p)
691 x_display_and_set_cursor (w, 1, output_cursor.hpos,
692 output_cursor.vpos,
693 output_cursor.x, output_cursor.y);
694 x_draw_vertical_border (w);
695 UNBLOCK_INPUT;
698 updated_window = NULL;
702 /* End update of frame F. This function is installed as a hook in
703 update_end. */
705 static void
706 x_update_end (f)
707 struct frame *f;
709 /* Mouse highlight may be displayed again. */
710 FRAME_W32_DISPLAY_INFO (f)->mouse_face_defer = 0;
714 /* This function is called from various places in xdisp.c whenever a
715 complete update has been performed. The global variable
716 updated_window is not available here. */
718 static void
719 w32_frame_up_to_date (f)
720 struct frame *f;
722 if (FRAME_W32_P (f))
724 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
725 if (dpyinfo->mouse_face_deferred_gc
726 || f == dpyinfo->mouse_face_mouse_frame)
728 BLOCK_INPUT;
729 if (dpyinfo->mouse_face_mouse_frame)
730 note_mouse_highlight (dpyinfo->mouse_face_mouse_frame,
731 dpyinfo->mouse_face_mouse_x,
732 dpyinfo->mouse_face_mouse_y);
733 dpyinfo->mouse_face_deferred_gc = 0;
734 UNBLOCK_INPUT;
740 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
741 arrow bitmaps, or clear the areas where they would be displayed
742 before DESIRED_ROW is made current. The window being updated is
743 found in updated_window. This function It is called from
744 update_window_line only if it is known that there are differences
745 between bitmaps to be drawn between current row and DESIRED_ROW. */
747 static void
748 x_after_update_window_line (desired_row)
749 struct glyph_row *desired_row;
751 struct window *w = updated_window;
753 xassert (w);
755 if (!desired_row->mode_line_p && !w->pseudo_window_p)
757 BLOCK_INPUT;
758 x_draw_row_bitmaps (w, desired_row);
760 /* When a window has disappeared, make sure that no rest of
761 full-width rows stays visible in the internal border. */
762 if (windows_or_buffers_changed)
764 struct frame *f = XFRAME (w->frame);
765 int width = FRAME_INTERNAL_BORDER_WIDTH (f);
766 int height = desired_row->visible_height;
767 int x = (window_box_right (w, -1)
768 + FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f));
769 int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
770 HDC hdc = get_frame_dc (f);
772 w32_clear_area (f, hdc, x, y, width, height);
773 release_frame_dc (f, hdc);
776 UNBLOCK_INPUT;
781 /* Draw the bitmap WHICH in one of the areas to the left or right of
782 window W. ROW is the glyph row for which to display the bitmap; it
783 determines the vertical position at which the bitmap has to be
784 drawn. */
786 static void
787 w32_draw_bitmap (w, hdc, row, which)
788 struct window *w;
789 HDC hdc;
790 struct glyph_row *row;
791 enum bitmap_type which;
793 struct frame *f = XFRAME (WINDOW_FRAME (w));
794 Window window = FRAME_W32_WINDOW (f);
795 HDC compat_hdc;
796 int x, y, wd, h, dy;
797 HBITMAP pixmap;
798 HBRUSH fg_brush, orig_brush;
799 HANDLE horig_obj;
800 struct face *face;
802 /* Must clip because of partially visible lines. */
803 w32_clip_to_row (w, row, hdc, 1);
805 switch (which)
807 case LEFT_TRUNCATION_BITMAP:
808 wd = left_width;
809 h = left_height;
810 pixmap = left_bmp;
811 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
812 - wd
813 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
814 break;
816 case OVERLAY_ARROW_BITMAP:
817 wd = ov_width;
818 h = ov_height;
819 pixmap = ov_bmp;
820 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
821 - wd
822 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
823 break;
825 case RIGHT_TRUNCATION_BITMAP:
826 wd = right_width;
827 h = right_height;
828 pixmap = right_bmp;
829 x = window_box_right (w, -1);
830 x += (FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f) - wd) / 2;
831 break;
833 case CONTINUED_LINE_BITMAP:
834 wd = continued_width;
835 h = continued_height;
836 pixmap = continued_bmp;
837 x = window_box_right (w, -1);
838 x += (FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f) - wd) / 2;
839 break;
841 case CONTINUATION_LINE_BITMAP:
842 wd = continuation_width;
843 h = continuation_height;
844 pixmap = continuation_bmp;
845 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
846 - wd
847 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
848 break;
850 case ZV_LINE_BITMAP:
851 wd = zv_width;
852 h = zv_height;
853 pixmap = zv_bmp;
854 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
855 - wd
856 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
857 break;
859 default:
860 abort ();
863 /* Convert to frame coordinates. Set dy to the offset in the row to
864 start drawing the bitmap. */
865 y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
866 dy = (row->height - h) / 2;
868 /* Draw the bitmap. */
869 face = FACE_FROM_ID (f, BITMAP_AREA_FACE_ID);
871 compat_hdc = CreateCompatibleDC (hdc);
872 SaveDC (hdc);
873 fg_brush = CreateSolidBrush (FRAME_FOREGROUND_PIXEL (f));
874 orig_brush = SelectObject (hdc, fg_brush);
875 horig_obj = SelectObject (compat_hdc, pixmap);
876 SetTextColor (hdc, FRAME_BACKGROUND_PIXEL (f));
877 SetBkColor (hdc, FRAME_FOREGROUND_PIXEL (f));
878 #if 0 /* From w32bdf.c (which is from Meadow). */
879 BitBlt (hdc, x, y + dy, wd, h, compat_hdc, 0, 0, SRCCOPY);
880 #else
881 BitBlt (hdc, x, y + dy, wd, h, compat_hdc, 0, 0, 0xB8074A);
882 #endif
883 SelectObject (compat_hdc, horig_obj);
884 SelectObject (hdc, orig_brush);
885 DeleteObject (fg_brush);
886 DeleteDC (compat_hdc);
887 RestoreDC (hdc, -1);
891 /* Draw flags bitmaps for glyph row ROW on window W. Call this
892 function with input blocked. */
894 static void
895 x_draw_row_bitmaps (w, row)
896 struct window *w;
897 struct glyph_row *row;
899 struct frame *f = XFRAME (w->frame);
900 enum bitmap_type bitmap;
901 struct face *face;
902 int header_line_height = -1;
903 HDC hdc = get_frame_dc (f);
905 xassert (interrupt_input_blocked);
907 /* If row is completely invisible, because of vscrolling, we
908 don't have to draw anything. */
909 if (row->visible_height <= 0)
910 return;
912 face = FACE_FROM_ID (f, BITMAP_AREA_FACE_ID);
913 PREPARE_FACE_FOR_DISPLAY (f, face);
915 /* Decide which bitmap to draw at the left side. */
916 if (row->overlay_arrow_p)
917 bitmap = OVERLAY_ARROW_BITMAP;
918 else if (row->truncated_on_left_p)
919 bitmap = LEFT_TRUNCATION_BITMAP;
920 else if (MATRIX_ROW_CONTINUATION_LINE_P (row))
921 bitmap = CONTINUATION_LINE_BITMAP;
922 else if (row->indicate_empty_line_p)
923 bitmap = ZV_LINE_BITMAP;
924 else
925 bitmap = NO_BITMAP;
927 /* Clear flags area if no bitmap to draw or if bitmap doesn't fill
928 the flags area. */
929 if (bitmap == NO_BITMAP
930 || FRAME_FLAGS_BITMAP_WIDTH (f) < FRAME_X_LEFT_FLAGS_AREA_WIDTH (f)
931 || row->height > FRAME_FLAGS_BITMAP_HEIGHT (f))
933 /* If W has a vertical border to its left, don't draw over it. */
934 int border = ((XFASTINT (w->left) > 0
935 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
936 ? 1 : 0);
937 int left = window_box_left (w, -1);
939 if (header_line_height < 0)
940 header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
942 w32_fill_area (f, hdc, face->background,
943 left - FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) + border,
944 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
945 row->y)),
946 FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - border,
947 row->visible_height);
950 /* Draw the left bitmap. */
951 if (bitmap != NO_BITMAP)
952 w32_draw_bitmap (w, hdc, row, bitmap);
954 /* Decide which bitmap to draw at the right side. */
955 if (row->truncated_on_right_p)
956 bitmap = RIGHT_TRUNCATION_BITMAP;
957 else if (row->continued_p)
958 bitmap = CONTINUED_LINE_BITMAP;
959 else
960 bitmap = NO_BITMAP;
962 /* Clear flags area if no bitmap to draw of if bitmap doesn't fill
963 the flags area. */
964 if (bitmap == NO_BITMAP
965 || FRAME_FLAGS_BITMAP_WIDTH (f) < FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f)
966 || row->height > FRAME_FLAGS_BITMAP_HEIGHT (f))
968 int right = window_box_right (w, -1);
970 if (header_line_height < 0)
971 header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
973 w32_fill_area (f, hdc, face->background,
974 right,
975 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
976 row->y)),
977 FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f),
978 row->visible_height);
981 /* Draw the right bitmap. */
982 if (bitmap != NO_BITMAP)
983 w32_draw_bitmap (w, hdc, row, bitmap);
985 release_frame_dc (f, hdc);
989 /***********************************************************************
990 Line Highlighting
991 ***********************************************************************/
993 /* External interface to control of standout mode. Not used for W32
994 frames. Aborts when called. */
996 static void
997 w32_reassert_line_highlight (new, vpos)
998 int new, vpos;
1000 abort ();
1003 /* Call this when about to modify line at position VPOS and change
1004 whether it is highlighted. Not used for W32 frames. Aborts when
1005 called. */
1007 static void
1008 x_change_line_highlight (new_highlight, vpos, y, first_unused_hpos)
1009 int new_highlight, vpos, y, first_unused_hpos;
1011 abort ();
1014 /* This is called when starting Emacs and when restarting after
1015 suspend. When starting Emacs, no window is mapped. And nothing
1016 must be done to Emacs's own window if it is suspended (though that
1017 rarely happens). */
1019 static void
1020 w32_set_terminal_modes (void)
1024 /* This is called when exiting or suspending Emacs. Exiting will make
1025 the W32 windows go away, and suspending requires no action. */
1027 static void
1028 w32_reset_terminal_modes (void)
1034 /***********************************************************************
1035 Output Cursor
1036 ***********************************************************************/
1038 /* Set the global variable output_cursor to CURSOR. All cursor
1039 positions are relative to updated_window. */
1041 static void
1042 set_output_cursor (cursor)
1043 struct cursor_pos *cursor;
1045 output_cursor.hpos = cursor->hpos;
1046 output_cursor.vpos = cursor->vpos;
1047 output_cursor.x = cursor->x;
1048 output_cursor.y = cursor->y;
1052 /* Set a nominal cursor position.
1054 HPOS and VPOS are column/row positions in a window glyph matrix. X
1055 and Y are window text area relative pixel positions.
1057 If this is done during an update, updated_window will contain the
1058 window that is being updated and the position is the future output
1059 cursor position for that window. If updated_window is null, use
1060 selected_window and display the cursor at the given position. */
1062 static void
1063 w32_cursor_to (vpos, hpos, y, x)
1064 int vpos, hpos, y, x;
1066 struct window *w;
1068 /* If updated_window is not set, work on selected_window. */
1069 if (updated_window)
1070 w = updated_window;
1071 else
1072 w = XWINDOW (selected_window);
1074 /* Set the output cursor. */
1075 output_cursor.hpos = hpos;
1076 output_cursor.vpos = vpos;
1077 output_cursor.x = x;
1078 output_cursor.y = y;
1080 /* If not called as part of an update, really display the cursor.
1081 This will also set the cursor position of W. */
1082 if (updated_window == NULL)
1084 BLOCK_INPUT;
1085 x_display_cursor (w, 1, hpos, vpos, x, y);
1086 UNBLOCK_INPUT;
1092 /***********************************************************************
1093 Display Iterator
1094 ***********************************************************************/
1096 /* Function prototypes of this page. */
1098 static struct face *x_get_glyph_face_and_encoding P_ ((struct frame *,
1099 struct glyph *,
1100 wchar_t *,
1101 int *));
1102 static struct face *x_get_char_face_and_encoding P_ ((struct frame *, int,
1103 int, wchar_t *, int));
1104 static XCharStruct *w32_per_char_metric P_ ((HDC hdc, XFontStruct *,
1105 wchar_t *,
1106 enum w32_char_font_type));
1107 static enum w32_char_font_type
1108 w32_encode_char P_ ((int, wchar_t *, struct font_info *, int *));
1109 static void x_append_glyph P_ ((struct it *));
1110 static void x_append_composite_glyph P_ ((struct it *));
1111 static void x_append_stretch_glyph P_ ((struct it *it, Lisp_Object,
1112 int, int, double));
1113 static void x_produce_glyphs P_ ((struct it *));
1114 static void x_produce_image_glyph P_ ((struct it *it));
1117 /* Dealing with bits of wchar_t as if they were an XChar2B. */
1118 #define BUILD_WCHAR_T(byte1, byte2) \
1119 ((wchar_t)((((byte1) & 0x00ff) << 8) | ((byte2) & 0x00ff)))
1122 #define BYTE1(ch) \
1123 (((ch) & 0xff00) >> 8)
1125 #define BYTE2(ch) \
1126 ((ch) & 0x00ff)
1129 /* Get metrics of character CHAR2B in FONT. Value is always non-null.
1130 If CHAR2B is not contained in FONT, the font's default character
1131 metric is returned. */
1133 static XCharStruct *
1134 w32_bdf_per_char_metric (font, char2b, dim)
1135 XFontStruct *font;
1136 wchar_t *char2b;
1137 int dim;
1139 glyph_metric * bdf_metric;
1140 char buf[2];
1141 XCharStruct * pcm = (XCharStruct *) xmalloc (sizeof (XCharStruct));
1143 if (dim == 1)
1144 buf[0] = (char)char2b;
1145 else
1147 buf[0] = BYTE1 (*char2b);
1148 buf[1] = BYTE2 (*char2b);
1151 bdf_metric = w32_BDF_TextMetric (font->bdf, buf, dim);
1153 if (bdf_metric)
1155 pcm->width = bdf_metric->dwidth;
1156 pcm->lbearing = bdf_metric->bbox;
1157 pcm->rbearing = bdf_metric->dwidth
1158 - (bdf_metric->bbox + bdf_metric->bbw);
1159 pcm->ascent = bdf_metric->bboy + bdf_metric->bbh;
1160 pcm->descent = bdf_metric->bboy;
1162 else
1164 xfree (pcm);
1165 return NULL;
1167 return pcm;
1171 static XCharStruct *
1172 w32_per_char_metric (hdc, font, char2b, font_type)
1173 HDC hdc;
1174 XFontStruct *font;
1175 wchar_t *char2b;
1176 enum w32_char_font_type font_type;
1178 /* NTEMACS_TODO: Use GetGlyphOutline where possible (no Unicode
1179 version on W9x) */
1181 /* The result metric information. */
1182 XCharStruct *pcm;
1183 BOOL retval;
1185 xassert (font && char2b);
1186 xassert (font_type != UNKNOWN_FONT);
1188 if (font_type == BDF_1D_FONT)
1189 return w32_bdf_per_char_metric (font, char2b, 1);
1190 else if (font_type == BDF_2D_FONT)
1191 return w32_bdf_per_char_metric (font, char2b, 2);
1193 pcm = (XCharStruct *) xmalloc (sizeof (XCharStruct));
1195 if (font->hfont)
1196 SelectObject (hdc, font->hfont);
1198 if ((font->tm.tmPitchAndFamily & TMPF_TRUETYPE) != 0)
1200 ABC char_widths;
1202 if (font_type == UNICODE_FONT)
1203 retval = GetCharABCWidthsW (hdc, *char2b, *char2b, &char_widths);
1204 else if (font_type == ANSI_FONT)
1205 retval = GetCharABCWidthsA (hdc, *char2b, *char2b, &char_widths);
1207 if (retval)
1209 pcm->width = char_widths.abcA + char_widths.abcB + char_widths.abcC;
1210 pcm->lbearing = char_widths.abcA;
1211 pcm->rbearing = pcm->width - char_widths.abcC;
1213 else
1215 /* Windows 9x does not implement GetCharABCWidthsW, so if that
1216 failed, try GetTextExtentPoint32W, which is implemented and
1217 at least gives us some of the info we are after (total
1218 character width). */
1219 SIZE sz;
1221 if (font_type == UNICODE_FONT)
1222 retval = GetTextExtentPoint32W (hdc, char2b, 1, &sz);
1224 if (retval)
1226 pcm->width = sz.cx;
1227 pcm->rbearing = sz.cx;
1228 pcm->lbearing = 0;
1230 else
1232 xfree (pcm);
1233 return NULL;
1237 else
1239 /* Do our best to deduce the desired metrics data for non-Truetype
1240 fonts (generally, raster fonts). */
1241 INT char_width;
1243 retval = GetCharWidth (hdc, *char2b, *char2b, &char_width);
1244 if (retval)
1246 pcm->width = char_width;
1247 pcm->rbearing = char_width;
1248 pcm->lbearing = 0;
1250 else
1252 xfree (pcm);
1253 return NULL;
1257 pcm->ascent = FONT_BASE (font);
1258 pcm->descent = FONT_DESCENT (font);
1260 if (pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0)
1262 xfree (pcm);
1263 return NULL;
1266 return pcm;
1270 /* Determine if a font is double byte. */
1271 int w32_font_is_double_byte (XFontStruct *font)
1273 return font->double_byte_p;
1277 /* Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
1278 the two-byte form of C. Encoding is returned in *CHAR2B. */
1280 static INLINE enum w32_char_font_type
1281 w32_encode_char (c, char2b, font_info, two_byte_p)
1282 int c;
1283 wchar_t *char2b;
1284 struct font_info *font_info;
1285 int * two_byte_p;
1287 int charset = CHAR_CHARSET (c);
1288 int codepage;
1289 int unicode_p = 0;
1291 XFontStruct *font = font_info->font;
1293 xassert (two_byte_p);
1295 *two_byte_p = w32_font_is_double_byte (font);
1297 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
1298 This may be either a program in a special encoder language or a
1299 fixed encoding. */
1300 if (font_info->font_encoder)
1302 /* It's a program. */
1303 struct ccl_program *ccl = font_info->font_encoder;
1305 if (CHARSET_DIMENSION (charset) == 1)
1307 ccl->reg[0] = charset;
1308 ccl->reg[1] = BYTE2 (*char2b);
1310 else
1312 ccl->reg[0] = charset;
1313 ccl->reg[1] = BYTE1 (*char2b);
1314 ccl->reg[2] = BYTE2 (*char2b);
1317 ccl_driver (ccl, NULL, NULL, 0, 0, NULL);
1319 /* We assume that MSBs are appropriately set/reset by CCL
1320 program. */
1321 if (!*two_byte_p) /* 1-byte font */
1322 *char2b = BUILD_WCHAR_T (0, ccl->reg[1]);
1323 else
1324 *char2b = BUILD_WCHAR_T (ccl->reg[1], ccl->reg[2]);
1326 else if (font_info->encoding[charset])
1328 /* Fixed encoding scheme. See fontset.h for the meaning of the
1329 encoding numbers. */
1330 int enc = font_info->encoding[charset];
1332 if ((enc == 1 || enc == 2)
1333 && CHARSET_DIMENSION (charset) == 2)
1334 *char2b = BUILD_WCHAR_T (BYTE1 (*char2b) | 0x80, BYTE2 (*char2b));
1336 if (enc == 1 || enc == 3
1337 || (enc == 4 && CHARSET_DIMENSION (charset) == 1))
1338 *char2b = BUILD_WCHAR_T (BYTE1 (*char2b), BYTE2 (*char2b) | 0x80);
1339 else if (enc == 4)
1341 int sjis1, sjis2;
1343 ENCODE_SJIS (BYTE1 (*char2b), BYTE2 (*char2b),
1344 sjis1, sjis2);
1345 *char2b = BUILD_WCHAR_T (sjis1, sjis2);
1348 codepage = w32_codepage_for_font (font_info->name);
1350 /* If charset is not ASCII or Latin-1, may need to move it into
1351 Unicode space. */
1352 if ( font && !font->bdf && w32_use_unicode_for_codepage (codepage)
1353 && charset != CHARSET_ASCII && charset != charset_latin_iso8859_1)
1355 char temp[3];
1356 temp[0] = BYTE1 (*char2b);
1357 temp[1] = BYTE2 (*char2b);
1358 temp[2] = '\0';
1359 if (temp[0])
1360 MultiByteToWideChar (codepage, 0, temp, 2, char2b, 1);
1361 else
1362 MultiByteToWideChar (codepage, 0, temp+1, 1, char2b, 1);
1363 unicode_p = 1;
1364 *two_byte_p = 1;
1366 if (!font)
1367 return UNKNOWN_FONT;
1368 else if (font->bdf && CHARSET_DIMENSION (charset) == 1)
1369 return BDF_1D_FONT;
1370 else if (font->bdf)
1371 return BDF_2D_FONT;
1372 else if (unicode_p)
1373 return UNICODE_FONT;
1374 else
1375 return ANSI_FONT;
1379 /* Get face and two-byte form of character C in face FACE_ID on frame
1380 F. The encoding of C is returned in *CHAR2B. MULTIBYTE_P non-zero
1381 means we want to display multibyte text. Value is a pointer to a
1382 realized face that is ready for display. */
1384 static INLINE struct face *
1385 x_get_char_face_and_encoding (f, c, face_id, char2b, multibyte_p)
1386 struct frame *f;
1387 int c, face_id;
1388 wchar_t *char2b;
1389 int multibyte_p;
1391 struct face *face = FACE_FROM_ID (f, face_id);
1393 if (!multibyte_p)
1395 /* Unibyte case. We don't have to encode, but we have to make
1396 sure to use a face suitable for unibyte. */
1397 *char2b = BUILD_WCHAR_T (0, c);
1398 face_id = FACE_FOR_CHAR (f, face, c);
1399 face = FACE_FROM_ID (f, face_id);
1401 else if (c < 128 && face_id < BASIC_FACE_ID_SENTINEL)
1403 /* Case of ASCII in a face known to fit ASCII. */
1404 *char2b = BUILD_WCHAR_T (0, c);
1406 else
1408 int c1, c2, charset;
1410 /* Split characters into bytes. If c2 is -1 afterwards, C is
1411 really a one-byte character so that byte1 is zero. */
1412 SPLIT_CHAR (c, charset, c1, c2);
1413 if (c2 > 0)
1414 *char2b = BUILD_WCHAR_T (c1, c2);
1415 else
1416 *char2b = BUILD_WCHAR_T (0, c1);
1418 /* Maybe encode the character in *CHAR2B. */
1419 if (face->font != NULL)
1421 struct font_info *font_info
1422 = FONT_INFO_FROM_ID (f, face->font_info_id);
1423 if (font_info)
1424 w32_encode_char (c, char2b, font_info, &multibyte_p);
1428 /* Make sure X resources of the face are allocated. */
1429 xassert (face != NULL);
1430 PREPARE_FACE_FOR_DISPLAY (f, face);
1432 return face;
1436 /* Get face and two-byte form of character glyph GLYPH on frame F.
1437 The encoding of GLYPH->u.ch is returned in *CHAR2B. Value is
1438 a pointer to a realized face that is ready for display. */
1440 static INLINE struct face *
1441 x_get_glyph_face_and_encoding (f, glyph, char2b, two_byte_p)
1442 struct frame *f;
1443 struct glyph *glyph;
1444 wchar_t *char2b;
1445 int *two_byte_p;
1447 struct face *face;
1448 int dummy = 0;
1450 xassert (glyph->type == CHAR_GLYPH);
1451 face = FACE_FROM_ID (f, glyph->face_id);
1453 if (two_byte_p)
1454 *two_byte_p = 0;
1455 else
1456 two_byte_p = &dummy;
1458 if (!glyph->multibyte_p)
1460 /* Unibyte case. We don't have to encode, but we have to make
1461 sure to use a face suitable for unibyte. */
1462 *char2b = BUILD_WCHAR_T (0, glyph->u.ch);
1464 else if (glyph->u.ch < 128
1465 && glyph->face_id < BASIC_FACE_ID_SENTINEL)
1467 /* Case of ASCII in a face known to fit ASCII. */
1468 *char2b = BUILD_WCHAR_T (0, glyph->u.ch);
1470 else
1472 int c1, c2, charset;
1474 /* Split characters into bytes. If c2 is -1 afterwards, C is
1475 really a one-byte character so that byte1 is zero. */
1476 SPLIT_CHAR (glyph->u.ch, charset, c1, c2);
1477 if (c2 > 0)
1478 *char2b = BUILD_WCHAR_T (c1, c2);
1479 else
1480 *char2b = BUILD_WCHAR_T (0, c1);
1482 /* Maybe encode the character in *CHAR2B. */
1483 if (charset != CHARSET_ASCII)
1485 struct font_info *font_info
1486 = FONT_INFO_FROM_ID (f, face->font_info_id);
1487 if (font_info)
1489 glyph->w32_font_type
1490 = w32_encode_char (glyph->u.ch, char2b, font_info, two_byte_p);
1495 /* Make sure X resources of the face are allocated. */
1496 xassert (face != NULL);
1497 PREPARE_FACE_FOR_DISPLAY (f, face);
1498 return face;
1502 /* Store one glyph for IT->char_to_display in IT->glyph_row.
1503 Called from x_produce_glyphs when IT->glyph_row is non-null. */
1505 static INLINE void
1506 x_append_glyph (it)
1507 struct it *it;
1509 struct glyph *glyph;
1510 enum glyph_row_area area = it->area;
1512 xassert (it->glyph_row);
1513 xassert (it->char_to_display != '\n' && it->char_to_display != '\t');
1515 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1516 if (glyph < it->glyph_row->glyphs[area + 1])
1518 glyph->charpos = CHARPOS (it->position);
1519 glyph->object = it->object;
1520 glyph->pixel_width = it->pixel_width;
1521 glyph->voffset = it->voffset;
1522 glyph->type = CHAR_GLYPH;
1523 glyph->multibyte_p = it->multibyte_p;
1524 glyph->left_box_line_p = it->start_of_box_run_p;
1525 glyph->right_box_line_p = it->end_of_box_run_p;
1526 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
1527 || it->phys_descent > it->descent);
1528 glyph->padding_p = 0;
1529 glyph->glyph_not_available_p = it->glyph_not_available_p;
1530 glyph->face_id = it->face_id;
1531 glyph->u.ch = it->char_to_display;
1532 glyph->w32_font_type = UNKNOWN_FONT;
1533 ++it->glyph_row->used[area];
1537 /* Store one glyph for the composition IT->cmp_id in IT->glyph_row.
1538 Called from x_produce_glyphs when IT->glyph_row is non-null. */
1540 static INLINE void
1541 x_append_composite_glyph (it)
1542 struct it *it;
1544 struct glyph *glyph;
1545 enum glyph_row_area area = it->area;
1547 xassert (it->glyph_row);
1549 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1550 if (glyph < it->glyph_row->glyphs[area + 1])
1552 glyph->charpos = CHARPOS (it->position);
1553 glyph->object = it->object;
1554 glyph->pixel_width = it->pixel_width;
1555 glyph->voffset = it->voffset;
1556 glyph->type = COMPOSITE_GLYPH;
1557 glyph->multibyte_p = it->multibyte_p;
1558 glyph->left_box_line_p = it->start_of_box_run_p;
1559 glyph->right_box_line_p = it->end_of_box_run_p;
1560 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
1561 || it->phys_descent > it->descent);
1562 glyph->padding_p = 0;
1563 glyph->glyph_not_available_p = 0;
1564 glyph->face_id = it->face_id;
1565 glyph->u.cmp_id = it->cmp_id;
1566 glyph->w32_font_type = UNKNOWN_FONT;
1567 ++it->glyph_row->used[area];
1572 /* Change IT->ascent and IT->height according to the setting of
1573 IT->voffset. */
1575 static INLINE void
1576 take_vertical_position_into_account (it)
1577 struct it *it;
1579 if (it->voffset)
1581 if (it->voffset < 0)
1582 /* Increase the ascent so that we can display the text higher
1583 in the line. */
1584 it->ascent += abs (it->voffset);
1585 else
1586 /* Increase the descent so that we can display the text lower
1587 in the line. */
1588 it->descent += it->voffset;
1593 /* Produce glyphs/get display metrics for the image IT is loaded with.
1594 See the description of struct display_iterator in dispextern.h for
1595 an overview of struct display_iterator. */
1597 static void
1598 x_produce_image_glyph (it)
1599 struct it *it;
1601 struct image *img;
1602 struct face *face;
1604 xassert (it->what == IT_IMAGE);
1606 face = FACE_FROM_ID (it->f, it->face_id);
1607 img = IMAGE_FROM_ID (it->f, it->image_id);
1608 xassert (img);
1610 /* Make sure X resources of the face and image are loaded. */
1611 PREPARE_FACE_FOR_DISPLAY (it->f, face);
1612 prepare_image_for_display (it->f, img);
1614 it->ascent = it->phys_ascent = image_ascent (img, face);
1615 it->descent = it->phys_descent = img->height + 2 * img->margin - it->ascent;
1616 it->pixel_width = img->width + 2 * img->margin;
1618 it->nglyphs = 1;
1620 if (face->box != FACE_NO_BOX)
1622 it->ascent += face->box_line_width;
1623 it->descent += face->box_line_width;
1625 if (it->start_of_box_run_p)
1626 it->pixel_width += face->box_line_width;
1627 if (it->end_of_box_run_p)
1628 it->pixel_width += face->box_line_width;
1631 take_vertical_position_into_account (it);
1633 if (it->glyph_row)
1635 struct glyph *glyph;
1636 enum glyph_row_area area = it->area;
1638 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1639 if (glyph < it->glyph_row->glyphs[area + 1])
1641 glyph->charpos = CHARPOS (it->position);
1642 glyph->object = it->object;
1643 glyph->pixel_width = it->pixel_width;
1644 glyph->voffset = it->voffset;
1645 glyph->type = IMAGE_GLYPH;
1646 glyph->multibyte_p = it->multibyte_p;
1647 glyph->left_box_line_p = it->start_of_box_run_p;
1648 glyph->right_box_line_p = it->end_of_box_run_p;
1649 glyph->overlaps_vertically_p = 0;
1650 glyph->padding_p = 0;
1651 glyph->glyph_not_available_p = 0;
1652 glyph->face_id = it->face_id;
1653 glyph->u.img_id = img->id;
1654 glyph->w32_font_type = UNKNOWN_FONT;
1655 ++it->glyph_row->used[area];
1661 /* Append a stretch glyph to IT->glyph_row. OBJECT is the source
1662 of the glyph, WIDTH and HEIGHT are the width and height of the
1663 stretch. ASCENT is the percentage/100 of HEIGHT to use for the
1664 ascent of the glyph (0 <= ASCENT <= 1). */
1666 static void
1667 x_append_stretch_glyph (it, object, width, height, ascent)
1668 struct it *it;
1669 Lisp_Object object;
1670 int width, height;
1671 double ascent;
1673 struct glyph *glyph;
1674 enum glyph_row_area area = it->area;
1676 xassert (ascent >= 0 && ascent <= 1);
1678 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1679 if (glyph < it->glyph_row->glyphs[area + 1])
1681 glyph->charpos = CHARPOS (it->position);
1682 glyph->object = object;
1683 glyph->pixel_width = width;
1684 glyph->voffset = it->voffset;
1685 glyph->type = STRETCH_GLYPH;
1686 glyph->multibyte_p = it->multibyte_p;
1687 glyph->left_box_line_p = it->start_of_box_run_p;
1688 glyph->right_box_line_p = it->end_of_box_run_p;
1689 glyph->overlaps_vertically_p = 0;
1690 glyph->padding_p = 0;
1691 glyph->glyph_not_available_p = 0;
1692 glyph->face_id = it->face_id;
1693 glyph->u.stretch.ascent = height * ascent;
1694 glyph->u.stretch.height = height;
1695 glyph->w32_font_type = UNKNOWN_FONT;
1696 ++it->glyph_row->used[area];
1701 /* Produce a stretch glyph for iterator IT. IT->object is the value
1702 of the glyph property displayed. The value must be a list
1703 `(space KEYWORD VALUE ...)' with the following KEYWORD/VALUE pairs
1704 being recognized:
1706 1. `:width WIDTH' specifies that the space should be WIDTH *
1707 canonical char width wide. WIDTH may be an integer or floating
1708 point number.
1710 2. `:relative-width FACTOR' specifies that the width of the stretch
1711 should be computed from the width of the first character having the
1712 `glyph' property, and should be FACTOR times that width.
1714 3. `:align-to HPOS' specifies that the space should be wide enough
1715 to reach HPOS, a value in canonical character units.
1717 Exactly one of the above pairs must be present.
1719 4. `:height HEIGHT' specifies that the height of the stretch produced
1720 should be HEIGHT, measured in canonical character units.
1722 5. `:relative-height FACTOR' specifies that the height of the the
1723 stretch should be FACTOR times the height of the characters having
1724 the glyph property.
1726 Either none or exactly one of 4 or 5 must be present.
1728 6. `:ascent ASCENT' specifies that ASCENT percent of the height
1729 of the stretch should be used for the ascent of the stretch.
1730 ASCENT must be in the range 0 <= ASCENT <= 100. */
1732 #define NUMVAL(X) \
1733 ((INTEGERP (X) || FLOATP (X)) \
1734 ? XFLOATINT (X) \
1735 : - 1)
1738 static void
1739 x_produce_stretch_glyph (it)
1740 struct it *it;
1742 /* (space :width WIDTH :height HEIGHT. */
1743 extern Lisp_Object QCwidth, QCheight, QCascent, Qspace;
1744 extern Lisp_Object QCrelative_width, QCrelative_height;
1745 extern Lisp_Object QCalign_to;
1746 Lisp_Object prop, plist;
1747 double width = 0, height = 0, ascent = 0;
1748 struct face *face = FACE_FROM_ID (it->f, it->face_id);
1749 XFontStruct *font = face->font ? face->font : FRAME_FONT (it->f);
1751 PREPARE_FACE_FOR_DISPLAY (it->f, face);
1753 /* List should start with `space'. */
1754 xassert (CONSP (it->object) && EQ (XCAR (it->object), Qspace));
1755 plist = XCDR (it->object);
1757 /* Compute the width of the stretch. */
1758 if (prop = Fplist_get (plist, QCwidth),
1759 NUMVAL (prop) > 0)
1760 /* Absolute width `:width WIDTH' specified and valid. */
1761 width = NUMVAL (prop) * CANON_X_UNIT (it->f);
1762 else if (prop = Fplist_get (plist, QCrelative_width),
1763 NUMVAL (prop) > 0)
1765 /* Relative width `:relative-width FACTOR' specified and valid.
1766 Compute the width of the characters having the `glyph'
1767 property. */
1768 struct it it2;
1769 unsigned char *p = BYTE_POS_ADDR (IT_BYTEPOS (*it));
1771 it2 = *it;
1772 if (it->multibyte_p)
1774 int maxlen = ((IT_BYTEPOS (*it) >= GPT ? ZV : GPT)
1775 - IT_BYTEPOS (*it));
1776 it2.c = STRING_CHAR_AND_LENGTH (p, maxlen, it2.len);
1778 else
1779 it2.c = *p, it2.len = 1;
1781 it2.glyph_row = NULL;
1782 it2.what = IT_CHARACTER;
1783 x_produce_glyphs (&it2);
1784 width = NUMVAL (prop) * it2.pixel_width;
1786 else if (prop = Fplist_get (plist, QCalign_to),
1787 NUMVAL (prop) > 0)
1788 width = NUMVAL (prop) * CANON_X_UNIT (it->f) - it->current_x;
1789 else
1790 /* Nothing specified -> width defaults to canonical char width. */
1791 width = CANON_X_UNIT (it->f);
1793 /* Compute height. */
1794 if (prop = Fplist_get (plist, QCheight),
1795 NUMVAL (prop) > 0)
1796 height = NUMVAL (prop) * CANON_Y_UNIT (it->f);
1797 else if (prop = Fplist_get (plist, QCrelative_height),
1798 NUMVAL (prop) > 0)
1799 height = FONT_HEIGHT (font) * NUMVAL (prop);
1800 else
1801 height = FONT_HEIGHT (font);
1803 /* Compute percentage of height used for ascent. If
1804 `:ascent ASCENT' is present and valid, use that. Otherwise,
1805 derive the ascent from the font in use. */
1806 if (prop = Fplist_get (plist, QCascent),
1807 NUMVAL (prop) > 0 && NUMVAL (prop) <= 100)
1808 ascent = NUMVAL (prop) / 100.0;
1809 else
1810 ascent = (double) FONT_BASE (font) / FONT_HEIGHT (font);
1812 if (width <= 0)
1813 width = 1;
1814 if (height <= 0)
1815 height = 1;
1817 if (it->glyph_row)
1819 Lisp_Object object = it->stack[it->sp - 1].string;
1820 if (!STRINGP (object))
1821 object = it->w->buffer;
1822 x_append_stretch_glyph (it, object, width, height, ascent);
1825 it->pixel_width = width;
1826 it->ascent = it->phys_ascent = height * ascent;
1827 it->descent = it->phys_descent = height - it->ascent;
1828 it->nglyphs = 1;
1830 if (face->box != FACE_NO_BOX)
1832 it->ascent += face->box_line_width;
1833 it->descent += face->box_line_width;
1835 if (it->start_of_box_run_p)
1836 it->pixel_width += face->box_line_width;
1837 if (it->end_of_box_run_p)
1838 it->pixel_width += face->box_line_width;
1841 take_vertical_position_into_account (it);
1844 /* Return proper value to be used as baseline offset of font that has
1845 ASCENT and DESCENT to draw characters by the font at the vertical
1846 center of the line of frame F.
1848 Here, out task is to find the value of BOFF in the following figure;
1850 -------------------------+-----------+-
1851 -+-+---------+-+ | |
1852 | | | | | |
1853 | | | | F_ASCENT F_HEIGHT
1854 | | | ASCENT | |
1855 HEIGHT | | | | |
1856 | | |-|-+------+-----------|------- baseline
1857 | | | | BOFF | |
1858 | |---------|-+-+ | |
1859 | | | DESCENT | |
1860 -+-+---------+-+ F_DESCENT |
1861 -------------------------+-----------+-
1863 -BOFF + DESCENT + (F_HEIGHT - HEIGHT) / 2 = F_DESCENT
1864 BOFF = DESCENT + (F_HEIGHT - HEIGHT) / 2 - F_DESCENT
1865 DESCENT = FONT->descent
1866 HEIGHT = FONT_HEIGHT (FONT)
1867 F_DESCENT = (F->output_data.x->font->descent
1868 - F->output_data.x->baseline_offset)
1869 F_HEIGHT = FRAME_LINE_HEIGHT (F)
1872 #define VCENTER_BASELINE_OFFSET(FONT, F) \
1873 (FONT_DESCENT (FONT) \
1874 + (FRAME_LINE_HEIGHT ((F)) - FONT_HEIGHT ((FONT))) / 2 \
1875 - (FONT_DESCENT (FRAME_FONT (F)) - FRAME_BASELINE_OFFSET (F)))
1877 /* Produce glyphs/get display metrics for the display element IT is
1878 loaded with. See the description of struct display_iterator in
1879 dispextern.h for an overview of struct display_iterator. */
1881 static void
1882 x_produce_glyphs (it)
1883 struct it *it;
1885 it->glyph_not_available_p = 0;
1887 if (it->what == IT_CHARACTER)
1889 wchar_t char2b;
1890 XFontStruct *font;
1891 struct face *face = FACE_FROM_ID (it->f, it->face_id);
1892 XCharStruct *pcm;
1893 int font_not_found_p;
1894 struct font_info *font_info;
1895 int boff; /* baseline offset */
1896 HDC hdc;
1898 hdc = get_frame_dc (it->f);
1900 /* Maybe translate single-byte characters to multibyte, or the
1901 other way. */
1902 it->char_to_display = it->c;
1903 if (!ASCII_BYTE_P (it->c))
1905 if (unibyte_display_via_language_environment
1906 && SINGLE_BYTE_CHAR_P (it->c)
1907 && (it->c >= 0240
1908 || !NILP (Vnonascii_translation_table)))
1910 it->char_to_display = unibyte_char_to_multibyte (it->c);
1911 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
1912 face = FACE_FROM_ID (it->f, it->face_id);
1914 else if (!SINGLE_BYTE_CHAR_P (it->c)
1915 && !it->multibyte_p)
1917 it->char_to_display = multibyte_char_to_unibyte (it->c, Qnil);
1918 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
1919 face = FACE_FROM_ID (it->f, it->face_id);
1923 /* Get font to use. Encode IT->char_to_display. */
1924 x_get_char_face_and_encoding (it->f, it->char_to_display,
1925 it->face_id, &char2b,
1926 it->multibyte_p);
1927 font = face->font;
1929 /* When no suitable font found, use the default font. */
1930 font_not_found_p = font == NULL;
1931 if (font_not_found_p)
1933 font = FRAME_FONT (it->f);
1934 boff = it->f->output_data.w32->baseline_offset;
1935 font_info = NULL;
1937 else
1939 font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
1940 boff = font_info->baseline_offset;
1941 if (font_info->vertical_centering)
1942 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
1945 if (font->hfont)
1946 SelectObject (hdc, font->hfont);
1948 if (it->char_to_display >= ' '
1949 && (!it->multibyte_p || it->char_to_display < 128))
1951 /* Either unibyte or ASCII. */
1952 int stretched_p;
1954 it->nglyphs = 1;
1956 pcm = w32_per_char_metric (hdc, font, &char2b,
1957 font->bdf ? BDF_1D_FONT : ANSI_FONT);
1958 it->ascent = FONT_BASE (font) + boff;
1959 it->descent = FONT_DESCENT (font) - boff;
1961 if (pcm)
1963 it->phys_ascent = pcm->ascent + boff;
1964 it->phys_descent = pcm->descent - boff;
1965 it->pixel_width = pcm->width;
1967 else
1969 it->glyph_not_available_p = 1;
1970 it->phys_ascent = FONT_BASE (font) + boff;
1971 it->phys_descent = FONT_DESCENT (font) - boff;
1972 it->pixel_width = FONT_WIDTH (font);
1975 /* If this is a space inside a region of text with
1976 `space-width' property, change its width. */
1977 stretched_p = it->char_to_display == ' ' && !NILP (it->space_width);
1978 if (stretched_p)
1979 it->pixel_width *= XFLOATINT (it->space_width);
1981 /* If face has a box, add the box thickness to the character
1982 height. If character has a box line to the left and/or
1983 right, add the box line width to the character's width. */
1984 if (face->box != FACE_NO_BOX)
1986 int thick = face->box_line_width;
1988 it->ascent += thick;
1989 it->descent += thick;
1991 if (it->start_of_box_run_p)
1992 it->pixel_width += thick;
1993 if (it->end_of_box_run_p)
1994 it->pixel_width += thick;
1997 /* If face has an overline, add the height of the overline
1998 (1 pixel) and a 1 pixel margin to the character height. */
1999 if (face->overline_p)
2000 it->ascent += 2;
2002 take_vertical_position_into_account (it);
2004 /* If we have to actually produce glyphs, do it. */
2005 if (it->glyph_row)
2007 if (stretched_p)
2009 /* Translate a space with a `space-width' property
2010 into a stretch glyph. */
2011 double ascent = (double) FONT_BASE (font)
2012 / FONT_HEIGHT (font);
2013 x_append_stretch_glyph (it, it->object, it->pixel_width,
2014 it->ascent + it->descent, ascent);
2016 else
2017 x_append_glyph (it);
2019 /* If characters with lbearing or rbearing are displayed
2020 in this line, record that fact in a flag of the
2021 glyph row. This is used to optimize X output code. */
2022 if (pcm && (pcm->lbearing < 0 || pcm->rbearing > pcm->width))
2023 it->glyph_row->contains_overlapping_glyphs_p = 1;
2024 if (pcm)
2025 xfree (pcm);
2028 else if (it->char_to_display == '\n')
2030 /* A newline has no width but we need the height of the line. */
2031 it->pixel_width = 0;
2032 it->nglyphs = 0;
2033 it->ascent = it->phys_ascent = FONT_BASE (font) + boff;
2034 it->descent = it->phys_descent = FONT_DESCENT (font) - boff;
2036 if (face->box != FACE_NO_BOX)
2038 int thick = face->box_line_width;
2039 it->ascent += thick;
2040 it->descent += thick;
2043 else if (it->char_to_display == '\t')
2045 int tab_width = it->tab_width * CANON_X_UNIT (it->f);
2046 int x = it->current_x + it->continuation_lines_width;
2047 int next_tab_x = ((1 + x + tab_width - 1) / tab_width) * tab_width;
2049 /* If the distance from the current position to the next tab
2050 stop is less than a canonical character width, use the
2051 tab stop after that. */
2052 if (next_tab_x - x < CANON_X_UNIT (it->f))
2053 next_tab_x += tab_width;
2055 it->pixel_width = next_tab_x - x;
2056 it->nglyphs = 1;
2057 it->ascent = it->phys_ascent = FONT_BASE (font) + boff;
2058 it->descent = it->phys_descent = FONT_DESCENT (font) - boff;
2060 if (it->glyph_row)
2062 double ascent = (double) it->ascent / (it->ascent + it->descent);
2063 x_append_stretch_glyph (it, it->object, it->pixel_width,
2064 it->ascent + it->descent, ascent);
2067 else
2069 /* A multi-byte character.
2070 If we found a font, this font should give us the right
2071 metrics. If we didn't find a font, use the frame's
2072 default font and calculate the width of the character
2073 from the charset width; this is what old redisplay code
2074 did. */
2075 enum w32_char_font_type type;
2077 if (font->bdf && CHARSET_DIMENSION (CHAR_CHARSET (it->c)) == 1)
2078 type = BDF_1D_FONT;
2079 else if (font->bdf)
2080 type = BDF_2D_FONT;
2081 else
2082 type = UNICODE_FONT;
2084 pcm = w32_per_char_metric (hdc, font, &char2b, type);
2086 if (font_not_found_p || !pcm)
2088 int charset = CHAR_CHARSET (it->char_to_display);
2090 it->glyph_not_available_p = 1;
2091 it->pixel_width = (FONT_WIDTH (FRAME_FONT (it->f))
2092 * CHARSET_WIDTH (charset));
2093 it->phys_ascent = FONT_BASE (font) + boff;
2094 it->phys_descent = FONT_DESCENT (font) - boff;
2096 else
2098 it->pixel_width = pcm->width;
2099 it->phys_ascent = pcm->ascent + boff;
2100 it->phys_descent = pcm->descent - boff;
2101 if (it->glyph_row
2102 && (pcm->lbearing < 0
2103 || pcm->rbearing > pcm->width))
2104 it->glyph_row->contains_overlapping_glyphs_p = 1;
2106 it->nglyphs = 1;
2107 it->ascent = FONT_BASE (font) + boff;
2108 it->descent = FONT_DESCENT (font) - boff;
2110 if (face->box != FACE_NO_BOX)
2112 int thick = face->box_line_width;
2113 it->ascent += thick;
2114 it->descent += thick;
2116 if (it->start_of_box_run_p)
2117 it->pixel_width += thick;
2118 if (it->end_of_box_run_p)
2119 it->pixel_width += thick;
2122 /* If face has an overline, add the height of the overline
2123 (1 pixel) and a 1 pixel margin to the character height. */
2124 if (face->overline_p)
2125 it->ascent += 2;
2127 take_vertical_position_into_account (it);
2129 if (it->glyph_row)
2130 x_append_glyph (it);
2132 if (pcm)
2133 xfree (pcm);
2135 release_frame_dc (it->f, hdc);
2137 else if (it->what == IT_COMPOSITION)
2139 /* NTEMACS_TODO: Composite glyphs. */
2141 else if (it->what == IT_IMAGE)
2142 x_produce_image_glyph (it);
2143 else if (it->what == IT_STRETCH)
2144 x_produce_stretch_glyph (it);
2146 /* Accumulate dimensions. */
2147 xassert (it->ascent >= 0 && it->descent > 0);
2148 if (it->area == TEXT_AREA)
2149 it->current_x += it->pixel_width;
2151 it->descent += it->extra_line_spacing;
2153 it->max_ascent = max (it->max_ascent, it->ascent);
2154 it->max_descent = max (it->max_descent, it->descent);
2155 it->max_phys_ascent = max (it->max_phys_ascent, it->phys_ascent);
2156 it->max_phys_descent = max (it->max_phys_descent, it->phys_descent);
2160 /* Estimate the pixel height of the mode or top line on frame F.
2161 FACE_ID specifies what line's height to estimate. */
2164 x_estimate_mode_line_height (f, face_id)
2165 struct frame *f;
2166 enum face_id face_id;
2168 int height = 1;
2170 /* This function is called so early when Emacs starts that the face
2171 cache and mode line face are not yet initialized. */
2172 if (FRAME_FACE_CACHE (f))
2174 struct face *face = FACE_FROM_ID (f, face_id);
2175 if (face)
2176 height = FONT_HEIGHT (face->font) + 2 * face->box_line_width;
2179 return height;
2184 BOOL
2185 w32_use_unicode_for_codepage (codepage)
2186 int codepage;
2188 /* If the current codepage is supported, use Unicode for output. */
2189 return (w32_enable_unicode_output
2190 && codepage != CP_DEFAULT && IsValidCodePage (codepage));
2194 /***********************************************************************
2195 Glyph display
2196 ***********************************************************************/
2198 /* A sequence of glyphs to be drawn in the same face.
2200 This data structure is not really completely X specific, so it
2201 could possibly, at least partially, be useful for other systems. It
2202 is currently not part of the external redisplay interface because
2203 it's not clear what other systems will need. */
2205 struct glyph_string
2207 /* X-origin of the string. */
2208 int x;
2210 /* Y-origin and y-position of the base line of this string. */
2211 int y, ybase;
2213 /* The width of the string, not including a face extension. */
2214 int width;
2216 /* The width of the string, including a face extension. */
2217 int background_width;
2219 /* The height of this string. This is the height of the line this
2220 string is drawn in, and can be different from the height of the
2221 font the string is drawn in. */
2222 int height;
2224 /* Number of pixels this string overwrites in front of its x-origin.
2225 This number is zero if the string has an lbearing >= 0; it is
2226 -lbearing, if the string has an lbearing < 0. */
2227 int left_overhang;
2229 /* Number of pixels this string overwrites past its right-most
2230 nominal x-position, i.e. x + width. Zero if the string's
2231 rbearing is <= its nominal width, rbearing - width otherwise. */
2232 int right_overhang;
2234 /* The frame on which the glyph string is drawn. */
2235 struct frame *f;
2237 /* The window on which the glyph string is drawn. */
2238 struct window *w;
2240 /* X display and window for convenience. */
2241 Window window;
2243 /* The glyph row for which this string was built. It determines the
2244 y-origin and height of the string. */
2245 struct glyph_row *row;
2247 /* The area within row. */
2248 enum glyph_row_area area;
2250 /* Characters to be drawn, and number of characters. */
2251 wchar_t *char2b;
2252 int nchars;
2254 /* A face-override for drawing cursors, mouse face and similar. */
2255 enum draw_glyphs_face hl;
2257 /* Face in which this string is to be drawn. */
2258 struct face *face;
2260 /* Font in which this string is to be drawn. */
2261 XFontStruct *font;
2263 /* Font info for this string. */
2264 struct font_info *font_info;
2266 /* Non-null means this string describes (part of) a composition.
2267 All characters from char2b are drawn composed. */
2268 struct composition *cmp;
2270 /* Index of this glyph string's first character in the glyph
2271 definition of CMP. If this is zero, this glyph string describes
2272 the first character of a composition. */
2273 int gidx;
2275 /* 1 means this glyph strings face has to be drawn to the right end
2276 of the window's drawing area. */
2277 unsigned extends_to_end_of_line_p : 1;
2279 /* 1 means the background of this string has been drawn. */
2280 unsigned background_filled_p : 1;
2282 /* 1 means glyph string must be drawn with 16-bit functions. */
2283 unsigned two_byte_p : 1;
2285 /* 1 means that the original font determined for drawing this glyph
2286 string could not be loaded. The member `font' has been set to
2287 the frame's default font in this case. */
2288 unsigned font_not_found_p : 1;
2290 /* 1 means that the face in which this glyph string is drawn has a
2291 stipple pattern. */
2292 unsigned stippled_p : 1;
2294 /* 1 means only the foreground of this glyph string must be drawn,
2295 and we should use the physical height of the line this glyph
2296 string appears in as clip rect. */
2297 unsigned for_overlaps_p : 1;
2299 /* The GC to use for drawing this glyph string. */
2300 XGCValues *gc;
2302 HDC hdc;
2304 /* A pointer to the first glyph in the string. This glyph
2305 corresponds to char2b[0]. Needed to draw rectangles if
2306 font_not_found_p is 1. */
2307 struct glyph *first_glyph;
2309 /* Image, if any. */
2310 struct image *img;
2312 struct glyph_string *next, *prev;
2316 /* Encapsulate the different ways of displaying text under W32. */
2318 void W32_TEXTOUT (s, x, y,chars,nchars)
2319 struct glyph_string * s;
2320 int x, y;
2321 wchar_t * chars;
2322 int nchars;
2324 int charset_dim = w32_font_is_double_byte (s->gc->font) ? 2 : 1;
2325 if (s->gc->font->bdf)
2326 w32_BDF_TextOut (s->gc->font->bdf, s->hdc,
2327 x, y, (char *) chars, charset_dim, nchars, 0);
2328 else if (s->first_glyph->w32_font_type == UNICODE_FONT)
2329 ExtTextOutW (s->hdc, x, y, 0, NULL, chars, nchars, NULL);
2330 else
2331 ExtTextOut (s->hdc, x, y, 0, NULL, (char *) chars,
2332 nchars * charset_dim, NULL);
2335 #if 0
2337 static void
2338 x_dump_glyph_string (s)
2339 struct glyph_string *s;
2341 fprintf (stderr, "glyph string\n");
2342 fprintf (stderr, " x, y, w, h = %d, %d, %d, %d\n",
2343 s->x, s->y, s->width, s->height);
2344 fprintf (stderr, " ybase = %d\n", s->ybase);
2345 fprintf (stderr, " hl = %d\n", s->hl);
2346 fprintf (stderr, " left overhang = %d, right = %d\n",
2347 s->left_overhang, s->right_overhang);
2348 fprintf (stderr, " nchars = %d\n", s->nchars);
2349 fprintf (stderr, " extends to end of line = %d\n",
2350 s->extends_to_end_of_line_p);
2351 fprintf (stderr, " font height = %d\n", FONT_HEIGHT (s->font));
2352 fprintf (stderr, " bg width = %d\n", s->background_width);
2355 #endif /* GLYPH_DEBUG */
2359 static void x_append_glyph_string_lists P_ ((struct glyph_string **,
2360 struct glyph_string **,
2361 struct glyph_string *,
2362 struct glyph_string *));
2363 static void x_prepend_glyph_string_lists P_ ((struct glyph_string **,
2364 struct glyph_string **,
2365 struct glyph_string *,
2366 struct glyph_string *));
2367 static void x_append_glyph_string P_ ((struct glyph_string **,
2368 struct glyph_string **,
2369 struct glyph_string *));
2370 static int x_left_overwritten P_ ((struct glyph_string *));
2371 static int x_left_overwriting P_ ((struct glyph_string *));
2372 static int x_right_overwritten P_ ((struct glyph_string *));
2373 static int x_right_overwriting P_ ((struct glyph_string *));
2374 static int x_fill_glyph_string P_ ((struct glyph_string *, int, int,
2375 int, int));
2376 static void w32_init_glyph_string P_ ((struct glyph_string *, HDC hdc,
2377 wchar_t *, struct window *,
2378 struct glyph_row *,
2379 enum glyph_row_area, int,
2380 enum draw_glyphs_face));
2381 static int x_draw_glyphs P_ ((struct window *, int , struct glyph_row *,
2382 enum glyph_row_area, int, int,
2383 enum draw_glyphs_face, int *, int *, int));
2384 static void x_set_glyph_string_clipping P_ ((struct glyph_string *));
2385 static void x_set_glyph_string_gc P_ ((struct glyph_string *));
2386 static void x_draw_glyph_string_background P_ ((struct glyph_string *,
2387 int));
2388 static void x_draw_glyph_string_foreground P_ ((struct glyph_string *));
2389 static void x_draw_composite_glyph_string_foreground P_ ((struct glyph_string *));
2390 static void x_draw_glyph_string_box P_ ((struct glyph_string *));
2391 static void x_draw_glyph_string P_ ((struct glyph_string *));
2392 static void x_compute_glyph_string_overhangs P_ ((struct glyph_string *));
2393 static void x_set_cursor_gc P_ ((struct glyph_string *));
2394 static void x_set_mode_line_face_gc P_ ((struct glyph_string *));
2395 static void x_set_mouse_face_gc P_ ((struct glyph_string *));
2396 static void w32_get_glyph_overhangs P_ ((HDC hdc, struct glyph *,
2397 struct frame *,
2398 int *, int *));
2399 static void x_compute_overhangs_and_x P_ ((struct glyph_string *, int, int));
2400 static int w32_alloc_lighter_color (struct frame *, COLORREF *, double, int);
2401 static void w32_setup_relief_color P_ ((struct frame *, struct relief *,
2402 double, int, COLORREF));
2403 static void x_setup_relief_colors P_ ((struct glyph_string *));
2404 static void x_draw_image_glyph_string P_ ((struct glyph_string *));
2405 static void x_draw_image_relief P_ ((struct glyph_string *));
2406 static void x_draw_image_foreground P_ ((struct glyph_string *));
2407 static void w32_draw_image_foreground_1 P_ ((struct glyph_string *, HBITMAP));
2408 static void x_fill_image_glyph_string P_ ((struct glyph_string *));
2409 static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int,
2410 int, int, int));
2411 static void w32_draw_relief_rect P_ ((struct frame *, int, int, int, int,
2412 int, int, int, int, RECT *));
2413 static void w32_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,
2414 int, int, int, RECT *));
2415 static void x_fix_overlapping_area P_ ((struct window *, struct glyph_row *,
2416 enum glyph_row_area));
2419 /* Append the list of glyph strings with head H and tail T to the list
2420 with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the result. */
2422 static INLINE void
2423 x_append_glyph_string_lists (head, tail, h, t)
2424 struct glyph_string **head, **tail;
2425 struct glyph_string *h, *t;
2427 if (h)
2429 if (*head)
2430 (*tail)->next = h;
2431 else
2432 *head = h;
2433 h->prev = *tail;
2434 *tail = t;
2439 /* Prepend the list of glyph strings with head H and tail T to the
2440 list with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the
2441 result. */
2443 static INLINE void
2444 x_prepend_glyph_string_lists (head, tail, h, t)
2445 struct glyph_string **head, **tail;
2446 struct glyph_string *h, *t;
2448 if (h)
2450 if (*head)
2451 (*head)->prev = t;
2452 else
2453 *tail = t;
2454 t->next = *head;
2455 *head = h;
2460 /* Append glyph string S to the list with head *HEAD and tail *TAIL.
2461 Set *HEAD and *TAIL to the resulting list. */
2463 static INLINE void
2464 x_append_glyph_string (head, tail, s)
2465 struct glyph_string **head, **tail;
2466 struct glyph_string *s;
2468 s->next = s->prev = NULL;
2469 x_append_glyph_string_lists (head, tail, s, s);
2473 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
2474 face. */
2476 static void
2477 x_set_cursor_gc (s)
2478 struct glyph_string *s;
2480 if (s->font == FRAME_FONT (s->f)
2481 && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
2482 && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
2483 && !s->cmp)
2484 s->gc = s->f->output_data.w32->cursor_gc;
2485 else
2487 /* Cursor on non-default face: must merge. */
2488 XGCValues xgcv;
2489 unsigned long mask;
2491 xgcv.background = s->f->output_data.w32->cursor_pixel;
2492 xgcv.foreground = s->face->background;
2494 /* If the glyph would be invisible, try a different foreground. */
2495 if (xgcv.foreground == xgcv.background)
2496 xgcv.foreground = s->face->foreground;
2497 if (xgcv.foreground == xgcv.background)
2498 xgcv.foreground = s->f->output_data.w32->cursor_foreground_pixel;
2499 if (xgcv.foreground == xgcv.background)
2500 xgcv.foreground = s->face->foreground;
2502 /* Make sure the cursor is distinct from text in this face. */
2503 if (xgcv.background == s->face->background
2504 && xgcv.foreground == s->face->foreground)
2506 xgcv.background = s->face->foreground;
2507 xgcv.foreground = s->face->background;
2510 IF_DEBUG (x_check_font (s->f, s->font));
2511 xgcv.font = s->font;
2512 mask = GCForeground | GCBackground | GCFont;
2514 if (FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc)
2515 XChangeGC (NULL, FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc,
2516 mask, &xgcv);
2517 else
2518 FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc
2519 = XCreateGC (NULL, s->window, mask, &xgcv);
2521 s->gc = FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc;
2526 /* Set up S->gc of glyph string S for drawing text in mouse face. */
2528 static void
2529 x_set_mouse_face_gc (s)
2530 struct glyph_string *s;
2532 int face_id;
2533 struct face *face;
2535 /* What face has to be used for the mouse face? */
2536 face_id = FRAME_W32_DISPLAY_INFO (s->f)->mouse_face_face_id;
2537 face = FACE_FROM_ID (s->f, face_id);
2538 face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch);
2539 s->face = FACE_FROM_ID (s->f, face_id);
2540 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
2542 /* If font in this face is same as S->font, use it. */
2543 if (s->font == s->face->font)
2544 s->gc = s->face->gc;
2545 else
2547 /* Otherwise construct scratch_cursor_gc with values from FACE
2548 but font FONT. */
2549 XGCValues xgcv;
2550 unsigned long mask;
2552 xgcv.background = s->face->background;
2553 xgcv.foreground = s->face->foreground;
2554 IF_DEBUG (x_check_font (s->f, s->font));
2555 xgcv.font = s->font;
2556 mask = GCForeground | GCBackground | GCFont;
2558 if (FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc)
2559 XChangeGC (NULL, FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc,
2560 mask, &xgcv);
2561 else
2562 FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc
2563 = XCreateGC (NULL, s->window, mask, &xgcv);
2565 s->gc = FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc;
2568 xassert (s->gc != 0);
2572 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
2573 Faces to use in the mode line have already been computed when the
2574 matrix was built, so there isn't much to do, here. */
2576 static INLINE void
2577 x_set_mode_line_face_gc (s)
2578 struct glyph_string *s;
2580 s->gc = s->face->gc;
2584 /* Set S->gc of glyph string S for drawing that glyph string. Set
2585 S->stippled_p to a non-zero value if the face of S has a stipple
2586 pattern. */
2588 static INLINE void
2589 x_set_glyph_string_gc (s)
2590 struct glyph_string *s;
2592 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
2594 if (s->hl == DRAW_NORMAL_TEXT)
2596 s->gc = s->face->gc;
2597 s->stippled_p = s->face->stipple != 0;
2599 else if (s->hl == DRAW_INVERSE_VIDEO)
2601 x_set_mode_line_face_gc (s);
2602 s->stippled_p = s->face->stipple != 0;
2604 else if (s->hl == DRAW_CURSOR)
2606 x_set_cursor_gc (s);
2607 s->stippled_p = 0;
2609 else if (s->hl == DRAW_MOUSE_FACE)
2611 x_set_mouse_face_gc (s);
2612 s->stippled_p = s->face->stipple != 0;
2614 else if (s->hl == DRAW_IMAGE_RAISED
2615 || s->hl == DRAW_IMAGE_SUNKEN)
2617 s->gc = s->face->gc;
2618 s->stippled_p = s->face->stipple != 0;
2620 else
2622 s->gc = s->face->gc;
2623 s->stippled_p = s->face->stipple != 0;
2626 /* GC must have been set. */
2627 xassert (s->gc != 0);
2631 /* Return in *R the clipping rectangle for glyph string S. */
2633 static void
2634 w32_get_glyph_string_clip_rect (s, r)
2635 struct glyph_string *s;
2636 RECT *r;
2638 int r_height, r_width;
2640 if (s->row->full_width_p)
2642 /* Draw full-width. X coordinates are relative to S->w->left. */
2643 int canon_x = CANON_X_UNIT (s->f);
2645 r->left = WINDOW_LEFT_MARGIN (s->w) * canon_x;
2646 r_width = XFASTINT (s->w->width) * canon_x;
2648 if (FRAME_HAS_VERTICAL_SCROLL_BARS (s->f))
2650 int width = FRAME_SCROLL_BAR_WIDTH (s->f) * canon_x;
2651 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (s->f))
2652 r->left -= width;
2655 r->left += FRAME_INTERNAL_BORDER_WIDTH (s->f);
2657 /* Unless displaying a mode or menu bar line, which are always
2658 fully visible, clip to the visible part of the row. */
2659 if (s->w->pseudo_window_p)
2660 r_height = s->row->visible_height;
2661 else
2662 r_height = s->height;
2664 else
2666 /* This is a text line that may be partially visible. */
2667 r->left = WINDOW_AREA_TO_FRAME_PIXEL_X (s->w, s->area, 0);
2668 r_width = window_box_width (s->w, s->area);
2669 r_height = s->row->visible_height;
2672 /* Don't use S->y for clipping because it doesn't take partially
2673 visible lines into account. For example, it can be negative for
2674 partially visible lines at the top of a window. */
2675 if (!s->row->full_width_p
2676 && MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (s->w, s->row))
2677 r->top = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
2678 else
2679 r->top = max (0, s->row->y);
2681 /* If drawing a tool-bar window, draw it over the internal border
2682 at the top of the window. */
2683 if (s->w == XWINDOW (s->f->tool_bar_window))
2684 r->top -= s->f->output_data.w32->internal_border_width;
2686 /* If S draws overlapping rows, it's sufficient to use the top and
2687 bottom of the window for clipping because this glyph string
2688 intentionally draws over other lines. */
2689 if (s->for_overlaps_p)
2691 r->top = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
2692 r_height = window_text_bottom_y (s->w) - r->top;
2695 r->top = WINDOW_TO_FRAME_PIXEL_Y (s->w, r->top);
2697 r->bottom = r->top + r_height;
2698 r->right = r->left + r_width;
2702 /* Set clipping for output of glyph string S. S may be part of a mode
2703 line or menu if we don't have X toolkit support. */
2705 static INLINE void
2706 x_set_glyph_string_clipping (s)
2707 struct glyph_string *s;
2709 RECT r;
2710 w32_get_glyph_string_clip_rect (s, &r);
2711 w32_set_clip_rectangle (s->hdc, &r);
2715 /* Compute left and right overhang of glyph string S. If S is a glyph
2716 string for a composition, assume overhangs don't exist. */
2718 static INLINE void
2719 x_compute_glyph_string_overhangs (s)
2720 struct glyph_string *s;
2722 /* NTEMACS_TODO: Windows does not appear to have a method for
2723 getting this info without getting the ABC widths for each
2724 individual character and working it out manually. */
2728 /* Compute overhangs and x-positions for glyph string S and its
2729 predecessors, or successors. X is the starting x-position for S.
2730 BACKWARD_P non-zero means process predecessors. */
2732 static void
2733 x_compute_overhangs_and_x (s, x, backward_p)
2734 struct glyph_string *s;
2735 int x;
2736 int backward_p;
2738 if (backward_p)
2740 while (s)
2742 x_compute_glyph_string_overhangs (s);
2743 x -= s->width;
2744 s->x = x;
2745 s = s->prev;
2748 else
2750 while (s)
2752 x_compute_glyph_string_overhangs (s);
2753 s->x = x;
2754 x += s->width;
2755 s = s->next;
2761 /* Set *LEFT and *RIGHT to the left and right overhang of GLYPH on
2762 frame F. Overhangs of glyphs other than type CHAR_GLYPH are
2763 assumed to be zero. */
2765 static void
2766 w32_get_glyph_overhangs (hdc, glyph, f, left, right)
2767 HDC hdc;
2768 struct glyph *glyph;
2769 struct frame *f;
2770 int *left, *right;
2772 int c;
2774 *left = *right = 0;
2776 if (glyph->type == CHAR_GLYPH)
2778 XFontStruct *font;
2779 struct face *face;
2780 wchar_t char2b;
2781 XCharStruct *pcm;
2783 face = x_get_glyph_face_and_encoding (f, glyph, &char2b, NULL);
2784 font = face->font;
2786 if (font
2787 && (pcm = w32_per_char_metric (hdc, font, &char2b,
2788 glyph->w32_font_type)))
2790 if (pcm->rbearing > pcm->width)
2791 *right = pcm->rbearing - pcm->width;
2792 if (pcm->lbearing < 0)
2793 *left = -pcm->lbearing;
2794 xfree (pcm);
2800 static void
2801 x_get_glyph_overhangs (glyph, f, left, right)
2802 struct glyph *glyph;
2803 struct frame *f;
2804 int *left, *right;
2806 HDC hdc = get_frame_dc (f);
2807 /* Convert to unicode! */
2808 w32_get_glyph_overhangs (hdc, glyph, f, left, right);
2809 release_frame_dc (f, hdc);
2813 /* Return the index of the first glyph preceding glyph string S that
2814 is overwritten by S because of S's left overhang. Value is -1
2815 if no glyphs are overwritten. */
2817 static int
2818 x_left_overwritten (s)
2819 struct glyph_string *s;
2821 int k;
2823 if (s->left_overhang)
2825 int x = 0, i;
2826 struct glyph *glyphs = s->row->glyphs[s->area];
2827 int first = s->first_glyph - glyphs;
2829 for (i = first - 1; i >= 0 && x > -s->left_overhang; --i)
2830 x -= glyphs[i].pixel_width;
2832 k = i + 1;
2834 else
2835 k = -1;
2837 return k;
2841 /* Return the index of the first glyph preceding glyph string S that
2842 is overwriting S because of its right overhang. Value is -1 if no
2843 glyph in front of S overwrites S. */
2845 static int
2846 x_left_overwriting (s)
2847 struct glyph_string *s;
2849 int i, k, x;
2850 struct glyph *glyphs = s->row->glyphs[s->area];
2851 int first = s->first_glyph - glyphs;
2853 k = -1;
2854 x = 0;
2855 for (i = first - 1; i >= 0; --i)
2857 int left, right;
2858 w32_get_glyph_overhangs (s->hdc, glyphs + i, s->f, &left, &right);
2859 if (x + right > 0)
2860 k = i;
2861 x -= glyphs[i].pixel_width;
2864 return k;
2868 /* Return the index of the last glyph following glyph string S that is
2869 not overwritten by S because of S's right overhang. Value is -1 if
2870 no such glyph is found. */
2872 static int
2873 x_right_overwritten (s)
2874 struct glyph_string *s;
2876 int k = -1;
2878 if (s->right_overhang)
2880 int x = 0, i;
2881 struct glyph *glyphs = s->row->glyphs[s->area];
2882 int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
2883 int end = s->row->used[s->area];
2885 for (i = first; i < end && s->right_overhang > x; ++i)
2886 x += glyphs[i].pixel_width;
2888 k = i;
2891 return k;
2895 /* Return the index of the last glyph following glyph string S that
2896 overwrites S because of its left overhang. Value is negative
2897 if no such glyph is found. */
2899 static int
2900 x_right_overwriting (s)
2901 struct glyph_string *s;
2903 int i, k, x;
2904 int end = s->row->used[s->area];
2905 struct glyph *glyphs = s->row->glyphs[s->area];
2906 int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
2908 k = -1;
2909 x = 0;
2910 for (i = first; i < end; ++i)
2912 int left, right;
2913 w32_get_glyph_overhangs (s->hdc, glyphs + i, s->f, &left, &right);
2914 if (x - left < 0)
2915 k = i;
2916 x += glyphs[i].pixel_width;
2919 return k;
2923 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
2925 static INLINE void
2926 x_clear_glyph_string_rect (s, x, y, w, h)
2927 struct glyph_string *s;
2928 int x, y, w, h;
2930 int real_x = x;
2931 int real_y = y;
2932 int real_w = w;
2933 int real_h = h;
2934 #if 0
2935 /* Take clipping into account. */
2936 if (s->gc->clip_mask == Rect)
2938 real_x = max (real_x, s->gc->clip_rectangle.left);
2939 real_y = max (real_y, s->gc->clip_rectangle.top);
2940 real_w = min (real_w, s->gc->clip_rectangle.right
2941 - s->gc->clip_rectangle.left);
2942 real_h = min (real_h, s->gc->clip_rectangle.bottom
2943 - s->gc->clip_rectangle.top);
2945 #endif
2946 w32_fill_area (s->f, s->hdc, s->gc->background, real_x, real_y,
2947 real_w, real_h);
2951 /* Draw the background of glyph_string S. If S->background_filled_p
2952 is non-zero don't draw it. FORCE_P non-zero means draw the
2953 background even if it wouldn't be drawn normally. This is used
2954 when a string preceding S draws into the background of S, or S
2955 contains the first component of a composition. */
2957 static void
2958 x_draw_glyph_string_background (s, force_p)
2959 struct glyph_string *s;
2960 int force_p;
2962 /* Nothing to do if background has already been drawn or if it
2963 shouldn't be drawn in the first place. */
2964 if (!s->background_filled_p)
2966 #if 0 /* NTEMACS_TODO: stipple */
2967 if (s->stippled_p)
2969 /* Fill background with a stipple pattern. */
2970 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
2971 XFillRectangle (s->display, s->window, s->gc, s->x,
2972 s->y + s->face->box_line_width,
2973 s->background_width,
2974 s->height - 2 * s->face->box_line_width);
2975 XSetFillStyle (s->display, s->gc, FillSolid);
2976 s->background_filled_p = 1;
2978 else
2979 #endif
2980 if (FONT_HEIGHT (s->font) < s->height - 2 * s->face->box_line_width
2981 || s->font_not_found_p
2982 || s->extends_to_end_of_line_p
2983 || s->font->bdf
2984 || force_p)
2986 x_clear_glyph_string_rect (s, s->x, s->y + s->face->box_line_width,
2987 s->background_width,
2988 s->height - 2 * s->face->box_line_width);
2989 s->background_filled_p = 1;
2995 /* Draw the foreground of glyph string S. */
2997 static void
2998 x_draw_glyph_string_foreground (s)
2999 struct glyph_string *s;
3001 int i, x;
3003 /* If first glyph of S has a left box line, start drawing the text
3004 of S to the right of that box line. */
3005 if (s->face->box != FACE_NO_BOX
3006 && s->first_glyph->left_box_line_p)
3007 x = s->x + s->face->box_line_width;
3008 else
3009 x = s->x;
3011 if (s->for_overlaps_p || (s->background_filled_p && s->hl != DRAW_CURSOR))
3012 SetBkMode (s->hdc, TRANSPARENT);
3013 else
3014 SetBkMode (s->hdc, OPAQUE);
3016 SetTextColor (s->hdc, s->gc->foreground);
3017 SetBkColor (s->hdc, s->gc->background);
3018 SetTextAlign (s->hdc, TA_BASELINE | TA_LEFT);
3020 if (s->font && s->font->hfont)
3021 SelectObject (s->hdc, s->font->hfont);
3023 /* Draw characters of S as rectangles if S's font could not be
3024 loaded. */
3025 if (s->font_not_found_p)
3027 for (i = 0; i < s->nchars; ++i)
3029 struct glyph *g = s->first_glyph + i;
3031 w32_draw_rectangle (s->hdc, s->gc, x, s->y, g->pixel_width - 1,
3032 s->height - 1);
3033 x += g->pixel_width;
3036 else
3038 char *char1b = (char *) s->char2b;
3039 int boff = s->font_info->baseline_offset;
3041 if (s->font_info->vertical_centering)
3042 boff = VCENTER_BASELINE_OFFSET (s->font, s->f) - boff;
3044 /* If we can use 8-bit functions, condense S->char2b. */
3045 if (!s->two_byte_p)
3046 for (i = 0; i < s->nchars; ++i)
3047 char1b[i] = BYTE2 (s->char2b[i]);
3049 /* Draw text with TextOut and friends. */
3050 W32_TEXTOUT (s, x, s->ybase - boff, s->char2b, s->nchars);
3054 /* Draw the foreground of composite glyph string S. */
3056 static void
3057 x_draw_composite_glyph_string_foreground (s)
3058 struct glyph_string *s;
3060 int i, x;
3062 /* If first glyph of S has a left box line, start drawing the text
3063 of S to the right of that box line. */
3064 if (s->face->box != FACE_NO_BOX
3065 && s->first_glyph->left_box_line_p)
3066 x = s->x + s->face->box_line_width;
3067 else
3068 x = s->x;
3070 /* S is a glyph string for a composition. S->gidx is the index of
3071 the first character drawn for glyphs of this composition.
3072 S->gidx == 0 means we are drawing the very first character of
3073 this composition. */
3075 SetTextColor (s->hdc, s->gc->foreground);
3076 SetBkColor (s->hdc, s->gc->background);
3077 SetBkMode (s->hdc, TRANSPARENT);
3078 SetTextAlign (s->hdc, TA_BASELINE | TA_LEFT);
3080 /* Draw a rectangle for the composition if the font for the very
3081 first character of the composition could not be loaded. */
3082 if (s->font_not_found_p)
3084 if (s->gidx == 0)
3085 w32_draw_rectangle (s->hdc, s->gc, x, s->y, s->width - 1,
3086 s->height - 1);
3088 else
3090 for (i = 0; i < s->nchars; i++, ++s->gidx)
3091 W32_TEXTOUT (s, x + s->cmp->offsets[s->gidx * 2],
3092 s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
3093 s->char2b + i, 1);
3097 /* Allocate a color which is lighter or darker than *COLOR by FACTOR
3098 or DELTA. Try a color with RGB values multiplied by FACTOR first.
3099 If this produces the same color as COLOR, try a color where all RGB
3100 values have DELTA added. Return the allocated color in *COLOR.
3101 DISPLAY is the X display, CMAP is the colormap to operate on.
3102 Value is non-zero if successful. */
3104 static int
3105 w32_alloc_lighter_color (f, color, factor, delta)
3106 struct frame *f;
3107 COLORREF *color;
3108 double factor;
3109 int delta;
3111 COLORREF new;
3113 /* Change RGB values by specified FACTOR. Avoid overflow! */
3114 xassert (factor >= 0);
3115 new = PALETTERGB (min (0xff, factor * GetRValue (*color)),
3116 min (0xff, factor * GetGValue (*color)),
3117 min (0xff, factor * GetBValue (*color)));
3118 if (new == *color)
3119 new = PALETTERGB (max (0, min (0xff, delta + GetRValue (*color))),
3120 max (0, min (0xff, delta + GetGValue (*color))),
3121 max (0, min (0xff, delta + GetBValue (*color))));
3123 /* NTEMACS_TODO: Map to palette and retry with delta if same? */
3124 /* NTEMACS_TODO: Free colors (if using palette)? */
3126 if (new == *color)
3127 return 0;
3129 *color = new;
3131 return 1;
3135 /* Set up the foreground color for drawing relief lines of glyph
3136 string S. RELIEF is a pointer to a struct relief containing the GC
3137 with which lines will be drawn. Use a color that is FACTOR or
3138 DELTA lighter or darker than the relief's background which is found
3139 in S->f->output_data.x->relief_background. If such a color cannot
3140 be allocated, use DEFAULT_PIXEL, instead. */
3142 static void
3143 w32_setup_relief_color (f, relief, factor, delta, default_pixel)
3144 struct frame *f;
3145 struct relief *relief;
3146 double factor;
3147 int delta;
3148 COLORREF default_pixel;
3150 XGCValues xgcv;
3151 struct w32_output *di = f->output_data.w32;
3152 unsigned long mask = GCForeground;
3153 COLORREF pixel;
3154 COLORREF background = di->relief_background;
3155 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
3157 /* NTEMACS_TODO: Free colors (if using palette)? */
3159 /* Allocate new color. */
3160 xgcv.foreground = default_pixel;
3161 pixel = background;
3162 if (w32_alloc_lighter_color (f, &pixel, factor, delta))
3164 relief->allocated_p = 1;
3165 xgcv.foreground = relief->pixel = pixel;
3168 if (relief->gc == 0)
3170 #if 0 /* NTEMACS_TODO: stipple */
3171 xgcv.stipple = dpyinfo->gray;
3172 mask |= GCStipple;
3173 #endif
3174 relief->gc = XCreateGC (NULL, FRAME_W32_WINDOW (f), mask, &xgcv);
3176 else
3177 XChangeGC (NULL, relief->gc, mask, &xgcv);
3181 /* Set up colors for the relief lines around glyph string S. */
3183 static void
3184 x_setup_relief_colors (s)
3185 struct glyph_string *s;
3187 struct w32_output *di = s->f->output_data.w32;
3188 COLORREF color;
3190 if (s->face->use_box_color_for_shadows_p)
3191 color = s->face->box_color;
3192 else
3193 color = s->gc->background;
3195 if (di->white_relief.gc == 0
3196 || color != di->relief_background)
3198 di->relief_background = color;
3199 w32_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
3200 WHITE_PIX_DEFAULT (s->f));
3201 w32_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
3202 BLACK_PIX_DEFAULT (s->f));
3207 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
3208 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
3209 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
3210 relief. LEFT_P non-zero means draw a relief on the left side of
3211 the rectangle. RIGHT_P non-zero means draw a relief on the right
3212 side of the rectangle. CLIP_RECT is the clipping rectangle to use
3213 when drawing. */
3215 static void
3216 w32_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
3217 raised_p, left_p, right_p, clip_rect)
3218 struct frame *f;
3219 int left_x, top_y, right_x, bottom_y, left_p, right_p, raised_p;
3220 RECT *clip_rect;
3222 int i;
3223 XGCValues gc;
3224 HDC hdc = get_frame_dc (f);
3226 if (raised_p)
3227 gc.foreground = PALETTERGB (255, 255, 255);
3228 else
3229 gc.foreground = PALETTERGB (0, 0, 0);
3231 w32_set_clip_rectangle (hdc, clip_rect);
3233 /* Top. */
3234 for (i = 0; i < width; ++i)
3236 w32_fill_area (f, hdc, gc.foreground,
3237 left_x + i * left_p, top_y + i,
3238 (right_x + 1 - i * right_p) - (left_x + i * left_p), 1);
3241 /* Left. */
3242 if (left_p)
3243 for (i = 0; i < width; ++i)
3245 w32_fill_area (f, hdc, gc.foreground,
3246 left_x + i, top_y + i, 1,
3247 (bottom_y - i) - (top_y + i));
3250 w32_set_clip_rectangle (hdc, NULL);
3252 if (raised_p)
3253 gc.foreground = PALETTERGB (0, 0, 0);
3254 else
3255 gc.foreground = PALETTERGB (255, 255, 255);
3257 w32_set_clip_rectangle (hdc, clip_rect);
3259 /* Bottom. */
3260 for (i = 0; i < width; ++i)
3262 w32_fill_area (f, hdc, gc.foreground,
3263 left_x + i * left_p, bottom_y - i,
3264 (right_x + 1 - i * right_p) - left_x + i * left_p, 1);
3267 /* Right. */
3268 if (right_p)
3269 for (i = 0; i < width; ++i)
3271 w32_fill_area (f, hdc, gc.foreground,
3272 right_x - i, top_y + i + 1, 1,
3273 (bottom_y - i) - (top_y + i + 1));
3276 w32_set_clip_rectangle (hdc, NULL);
3278 release_frame_dc (f, hdc);
3282 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
3283 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
3284 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
3285 left side of the rectangle. RIGHT_P non-zero means draw a line
3286 on the right side of the rectangle. CLIP_RECT is the clipping
3287 rectangle to use when drawing. */
3289 static void
3290 w32_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
3291 left_p, right_p, clip_rect)
3292 struct glyph_string *s;
3293 int left_x, top_y, right_x, bottom_y, width, left_p, right_p;
3294 RECT *clip_rect;
3296 w32_set_clip_rectangle (s->hdc, clip_rect);
3298 /* Top. */
3299 w32_fill_area (s->f, s->hdc, s->face->box_color,
3300 left_x, top_y, right_x - left_x, width);
3302 /* Left. */
3303 if (left_p)
3305 w32_fill_area (s->f, s->hdc, s->face->box_color,
3306 left_x, top_y, width, bottom_y - top_y);
3309 /* Bottom. */
3310 w32_fill_area (s->f, s->hdc, s->face->box_color,
3311 left_x, bottom_y - width, right_x - left_x, width);
3313 /* Right. */
3314 if (right_p)
3316 w32_fill_area (s->f, s->hdc, s->face->box_color,
3317 right_x - width, top_y, width, bottom_y - top_y);
3320 w32_set_clip_rectangle (s->hdc, NULL);
3324 /* Draw a box around glyph string S. */
3326 static void
3327 x_draw_glyph_string_box (s)
3328 struct glyph_string *s;
3330 int width, left_x, right_x, top_y, bottom_y, last_x, raised_p;
3331 int left_p, right_p;
3332 struct glyph *last_glyph;
3333 RECT clip_rect;
3335 last_x = window_box_right (s->w, s->area);
3336 if (s->row->full_width_p
3337 && !s->w->pseudo_window_p)
3339 last_x += FRAME_X_RIGHT_FLAGS_AREA_WIDTH (s->f);
3340 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (s->f))
3341 last_x += FRAME_SCROLL_BAR_WIDTH (s->f) * CANON_X_UNIT (s->f);
3344 /* The glyph that may have a right box line. */
3345 last_glyph = (s->cmp || s->img
3346 ? s->first_glyph
3347 : s->first_glyph + s->nchars - 1);
3349 width = s->face->box_line_width;
3350 raised_p = s->face->box == FACE_RAISED_BOX;
3351 left_x = s->x;
3352 right_x = ((s->row->full_width_p
3353 ? last_x - 1
3354 : min (last_x, s->x + s->background_width) - 1));
3355 top_y = s->y;
3356 bottom_y = top_y + s->height - 1;
3358 left_p = (s->first_glyph->left_box_line_p
3359 || (s->hl == DRAW_MOUSE_FACE
3360 && (s->prev == NULL
3361 || s->prev->hl != s->hl)));
3362 right_p = (last_glyph->right_box_line_p
3363 || (s->hl == DRAW_MOUSE_FACE
3364 && (s->next == NULL
3365 || s->next->hl != s->hl)));
3367 w32_get_glyph_string_clip_rect (s, &clip_rect);
3369 if (s->face->box == FACE_SIMPLE_BOX)
3370 w32_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
3371 left_p, right_p, &clip_rect);
3372 else
3374 x_setup_relief_colors (s);
3375 w32_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
3376 width, raised_p, left_p, right_p, &clip_rect);
3381 /* Draw foreground of image glyph string S. */
3383 static void
3384 x_draw_image_foreground (s)
3385 struct glyph_string *s;
3387 int x;
3388 int y = s->ybase - image_ascent (s->img, s->face);
3390 /* If first glyph of S has a left box line, start drawing it to the
3391 right of that line. */
3392 if (s->face->box != FACE_NO_BOX
3393 && s->first_glyph->left_box_line_p)
3394 x = s->x + s->face->box_line_width;
3395 else
3396 x = s->x;
3398 /* If there is a margin around the image, adjust x- and y-position
3399 by that margin. */
3400 if (s->img->margin)
3402 x += s->img->margin;
3403 y += s->img->margin;
3406 SaveDC (s->hdc);
3408 if (s->img->pixmap)
3410 #if 0 /* NTEMACS_TODO: image mask */
3411 if (s->img->mask)
3413 /* We can't set both a clip mask and use XSetClipRectangles
3414 because the latter also sets a clip mask. We also can't
3415 trust on the shape extension to be available
3416 (XShapeCombineRegion). So, compute the rectangle to draw
3417 manually. */
3418 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
3419 | GCFunction);
3420 XGCValues xgcv;
3421 XRectangle clip_rect, image_rect, r;
3423 xgcv.clip_mask = s->img->mask;
3424 xgcv.clip_x_origin = x;
3425 xgcv.clip_y_origin = y;
3426 xgcv.function = GXcopy;
3427 XChangeGC (s->display, s->gc, mask, &xgcv);
3429 w32_get_glyph_string_clip_rect (s, &clip_rect);
3430 image_rect.x = x;
3431 image_rect.y = y;
3432 image_rect.width = s->img->width;
3433 image_rect.height = s->img->height;
3434 if (IntersectRect (&r, &clip_rect, &image_rect))
3435 XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
3436 r.x - x, r.y - y, r.width, r.height, r.x, r.y);
3438 else
3439 #endif
3441 HDC compat_hdc = CreateCompatibleDC (s->hdc);
3442 HBRUSH fg_brush = CreateSolidBrush (s->gc->foreground);
3443 HBRUSH orig_brush = SelectObject (s->hdc, fg_brush);
3444 HGDIOBJ orig_obj = SelectObject (compat_hdc, s->img->pixmap);
3445 x_set_glyph_string_clipping (s);
3447 SetTextColor (s->hdc, s->gc->foreground);
3448 SetBkColor (s->hdc, s->gc->background);
3449 #if 0 /* From w32bdf.c (which is from Meadow). */
3450 BitBlt (s->hdc, x, y, s->img->width, s->img->height,
3451 compat_hdc, 0, 0, SRCCOPY);
3452 #else
3453 BitBlt (s->hdc, x, y, s->img->width, s->img->height,
3454 compat_hdc, 0, 0, 0xB8074A);
3455 #endif
3456 SelectObject (s->hdc, orig_brush);
3457 DeleteObject (fg_brush);
3458 SelectObject (compat_hdc, orig_obj);
3459 DeleteDC (compat_hdc);
3461 /* When the image has a mask, we can expect that at
3462 least part of a mouse highlight or a block cursor will
3463 be visible. If the image doesn't have a mask, make
3464 a block cursor visible by drawing a rectangle around
3465 the image. I believe it's looking better if we do
3466 nothing here for mouse-face. */
3467 if (s->hl == DRAW_CURSOR)
3468 w32_draw_rectangle (s->hdc, s->gc, x, y, s->img->width - 1,
3469 s->img->height - 1);
3470 w32_set_clip_rectangle (s->hdc, NULL);
3473 else
3474 w32_draw_rectangle (s->hdc, s->gc, x, y, s->img->width -1,
3475 s->img->height - 1);
3477 RestoreDC (s->hdc ,-1);
3482 /* Draw a relief around the image glyph string S. */
3484 static void
3485 x_draw_image_relief (s)
3486 struct glyph_string *s;
3488 int x0, y0, x1, y1, thick, raised_p;
3489 RECT r;
3490 int x;
3491 int y = s->ybase - image_ascent (s->img, s->face);
3493 /* If first glyph of S has a left box line, start drawing it to the
3494 right of that line. */
3495 if (s->face->box != FACE_NO_BOX
3496 && s->first_glyph->left_box_line_p)
3497 x = s->x + s->face->box_line_width;
3498 else
3499 x = s->x;
3501 /* If there is a margin around the image, adjust x- and y-position
3502 by that margin. */
3503 if (s->img->margin)
3505 x += s->img->margin;
3506 y += s->img->margin;
3509 if (s->hl == DRAW_IMAGE_SUNKEN
3510 || s->hl == DRAW_IMAGE_RAISED)
3512 thick = tool_bar_button_relief > 0 ? tool_bar_button_relief : 3;
3513 raised_p = s->hl == DRAW_IMAGE_RAISED;
3515 else
3517 thick = abs (s->img->relief);
3518 raised_p = s->img->relief > 0;
3521 x0 = x - thick;
3522 y0 = y - thick;
3523 x1 = x + s->img->width + thick - 1;
3524 y1 = y + s->img->height + thick - 1;
3526 x_setup_relief_colors (s);
3527 w32_get_glyph_string_clip_rect (s, &r);
3528 w32_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p, 1, 1, &r);
3532 /* Draw the foreground of image glyph string S to PIXMAP. */
3534 static void
3535 w32_draw_image_foreground_1 (s, pixmap)
3536 struct glyph_string *s;
3537 HBITMAP pixmap;
3539 HDC hdc = CreateCompatibleDC (s->hdc);
3540 HGDIOBJ orig_hdc_obj = SelectObject (hdc, pixmap);
3541 int x;
3542 int y = s->ybase - s->y - image_ascent (s->img, s->face);
3544 /* If first glyph of S has a left box line, start drawing it to the
3545 right of that line. */
3546 if (s->face->box != FACE_NO_BOX
3547 && s->first_glyph->left_box_line_p)
3548 x = s->face->box_line_width;
3549 else
3550 x = 0;
3552 /* If there is a margin around the image, adjust x- and y-position
3553 by that margin. */
3554 if (s->img->margin)
3556 x += s->img->margin;
3557 y += s->img->margin;
3560 if (s->img->pixmap)
3562 #if 0 /* NTEMACS_TODO: image mask */
3563 if (s->img->mask)
3565 /* We can't set both a clip mask and use XSetClipRectangles
3566 because the latter also sets a clip mask. We also can't
3567 trust on the shape extension to be available
3568 (XShapeCombineRegion). So, compute the rectangle to draw
3569 manually. */
3570 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
3571 | GCFunction);
3572 XGCValues xgcv;
3574 xgcv.clip_mask = s->img->mask;
3575 xgcv.clip_x_origin = x;
3576 xgcv.clip_y_origin = y;
3577 xgcv.function = GXcopy;
3578 XChangeGC (s->display, s->gc, mask, &xgcv);
3580 XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
3581 0, 0, s->img->width, s->img->height, x, y);
3582 XSetClipMask (s->display, s->gc, None);
3584 else
3585 #endif
3587 HDC compat_hdc = CreateCompatibleDC (hdc);
3588 HBRUSH fg_brush = CreateSolidBrush (s->gc->foreground);
3589 HBRUSH orig_brush = SelectObject (hdc, fg_brush);
3590 HGDIOBJ orig_obj = SelectObject (compat_hdc, s->img->pixmap);
3592 SetTextColor (hdc, s->gc->foreground);
3593 SetBkColor (hdc, s->gc->background);
3594 #if 0 /* From w32bdf.c (which is from Meadow). */
3595 BitBlt (hdc, x, y, s->img->width, s->img->height,
3596 compat_hdc, 0, 0, SRCCOPY);
3597 #else
3598 BitBlt (hdc, x, y, s->img->width, s->img->height,
3599 compat_hdc, 0, 0, 0xB8074A);
3600 #endif
3601 SelectObject (hdc, orig_brush);
3602 DeleteObject (fg_brush);
3603 SelectObject (compat_hdc, orig_obj);
3604 DeleteDC (compat_hdc);
3606 /* When the image has a mask, we can expect that at
3607 least part of a mouse highlight or a block cursor will
3608 be visible. If the image doesn't have a mask, make
3609 a block cursor visible by drawing a rectangle around
3610 the image. I believe it's looking better if we do
3611 nothing here for mouse-face. */
3612 if (s->hl == DRAW_CURSOR)
3613 w32_draw_rectangle (hdc, s->gc, x, y, s->img->width - 1,
3614 s->img->height - 1);
3617 else
3618 w32_draw_rectangle (hdc, s->gc, x, y, s->img->width - 1,
3619 s->img->height - 1);
3621 SelectObject (hdc, orig_hdc_obj);
3622 DeleteDC (hdc);
3626 /* Draw part of the background of glyph string S. X, Y, W, and H
3627 give the rectangle to draw. */
3629 static void
3630 x_draw_glyph_string_bg_rect (s, x, y, w, h)
3631 struct glyph_string *s;
3632 int x, y, w, h;
3634 #if 0 /* NTEMACS_TODO: stipple */
3635 if (s->stippled_p)
3637 /* Fill background with a stipple pattern. */
3638 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
3639 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
3640 XSetFillStyle (s->display, s->gc, FillSolid);
3642 else
3643 #endif
3644 x_clear_glyph_string_rect (s, x, y, w, h);
3648 /* Draw image glyph string S.
3650 s->y
3651 s->x +-------------------------
3652 | s->face->box
3654 | +-------------------------
3655 | | s->img->margin
3657 | | +-------------------
3658 | | | the image
3662 static void
3663 x_draw_image_glyph_string (s)
3664 struct glyph_string *s;
3666 int x, y;
3667 int box_line_width = s->face->box_line_width;
3668 int margin = s->img->margin;
3669 int height;
3670 HBITMAP pixmap = 0;
3672 height = s->height - 2 * box_line_width;
3674 /* Fill background with face under the image. Do it only if row is
3675 taller than image or if image has a clip mask to reduce
3676 flickering. */
3677 s->stippled_p = s->face->stipple != 0;
3678 if (height > s->img->height
3679 || margin
3680 #if 0 /* NTEMACS_TODO: image mask */
3681 || s->img->mask
3682 #endif
3683 || s->img->pixmap == 0
3684 || s->width != s->background_width)
3686 if (box_line_width && s->first_glyph->left_box_line_p)
3687 x = s->x + box_line_width;
3688 else
3689 x = s->x;
3691 y = s->y + box_line_width;
3692 #if 0 /* NTEMACS_TODO: image mask */
3693 if (s->img->mask)
3695 /* Create a pixmap as large as the glyph string Fill it with
3696 the background color. Copy the image to it, using its
3697 mask. Copy the temporary pixmap to the display. */
3698 Screen *screen = FRAME_X_SCREEN (s->f);
3699 int depth = DefaultDepthOfScreen (screen);
3701 /* Create a pixmap as large as the glyph string. */
3702 pixmap = XCreatePixmap (s->display, s->window,
3703 s->background_width,
3704 s->height, depth);
3706 /* Don't clip in the following because we're working on the
3707 pixmap. */
3708 XSetClipMask (s->display, s->gc, None);
3710 /* Fill the pixmap with the background color/stipple. */
3711 if (s->stippled_p)
3713 /* Fill background with a stipple pattern. */
3714 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
3715 XFillRectangle (s->display, pixmap, s->gc,
3716 0, 0, s->background_width, s->height);
3717 XSetFillStyle (s->display, s->gc, FillSolid);
3719 else
3721 XGCValues xgcv;
3722 XGetGCValues (s->display, s->gc, GCForeground | GCBackground,
3723 &xgcv);
3724 XSetForeground (s->display, s->gc, xgcv.background);
3725 XFillRectangle (s->display, pixmap, s->gc,
3726 0, 0, s->background_width, s->height);
3727 XSetForeground (s->display, s->gc, xgcv.foreground);
3730 else
3731 #endif
3732 x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
3734 s->background_filled_p = 1;
3737 /* Draw the foreground. */
3738 if (pixmap != 0)
3740 w32_draw_image_foreground_1 (s, pixmap);
3741 x_set_glyph_string_clipping (s);
3743 HDC compat_hdc = CreateCompatibleDC (s->hdc);
3744 HBRUSH fg_brush = CreateSolidBrush (s->gc->foreground);
3745 HBRUSH orig_brush = SelectObject (s->hdc, fg_brush);
3746 HGDIOBJ orig_obj = SelectObject (compat_hdc, pixmap);
3748 SetTextColor (s->hdc, s->gc->foreground);
3749 SetBkColor (s->hdc, s->gc->background);
3750 #if 0 /* From w32bdf.c (which is from Meadow). */
3751 BitBlt (s->hdc, s->x, s->y, s->background_width, s->height,
3752 compat_hdc, 0, 0, SRCCOPY);
3753 #else
3754 BitBlt (s->hdc, s->x, s->y, s->background_width, s->height,
3755 compat_hdc, 0, 0, 0xB8074A);
3756 #endif
3757 SelectObject (s->hdc, orig_brush);
3758 DeleteObject (fg_brush);
3759 SelectObject (compat_hdc, orig_obj);
3760 DeleteDC (compat_hdc);
3762 DeleteObject (pixmap);
3763 pixmap = 0;
3765 else
3766 x_draw_image_foreground (s);
3768 /* If we must draw a relief around the image, do it. */
3769 if (s->img->relief
3770 || s->hl == DRAW_IMAGE_RAISED
3771 || s->hl == DRAW_IMAGE_SUNKEN)
3772 x_draw_image_relief (s);
3776 /* Draw stretch glyph string S. */
3778 static void
3779 x_draw_stretch_glyph_string (s)
3780 struct glyph_string *s;
3782 xassert (s->first_glyph->type == STRETCH_GLYPH);
3783 s->stippled_p = s->face->stipple != 0;
3785 if (s->hl == DRAW_CURSOR
3786 && !x_stretch_cursor_p)
3788 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
3789 as wide as the stretch glyph. */
3790 int width = min (CANON_X_UNIT (s->f), s->background_width);
3792 /* Draw cursor. */
3793 x_draw_glyph_string_bg_rect (s, s->x, s->y, width, s->height);
3795 /* Clear rest using the GC of the original non-cursor face. */
3796 if (width < s->background_width)
3798 XGCValues *gc = s->face->gc;
3799 int x = s->x + width, y = s->y;
3800 int w = s->background_width - width, h = s->height;
3801 RECT r;
3802 HDC hdc = s->hdc;
3803 w32_get_glyph_string_clip_rect (s, &r);
3804 w32_set_clip_rectangle (hdc, &r);
3806 #if 0 /* NTEMACS_TODO: stipple */
3807 if (s->face->stipple)
3809 /* Fill background with a stipple pattern. */
3810 XSetFillStyle (s->display, gc, FillOpaqueStippled);
3811 XFillRectangle (s->display, s->window, gc, x, y, w, h);
3812 XSetFillStyle (s->display, gc, FillSolid);
3814 else
3815 #endif
3817 w32_fill_area (s->f, s->hdc, gc->background, x, y, w, h);
3821 else
3822 x_draw_glyph_string_bg_rect (s, s->x, s->y, s->background_width,
3823 s->height);
3825 s->background_filled_p = 1;
3829 /* Draw glyph string S. */
3831 static void
3832 x_draw_glyph_string (s)
3833 struct glyph_string *s;
3835 /* If S draws into the background of its successor, draw the
3836 background of the successor first so that S can draw into it.
3837 This makes S->next use XDrawString instead of XDrawImageString. */
3838 if (s->next && s->right_overhang && !s->for_overlaps_p)
3840 xassert (s->next->img == NULL);
3841 x_set_glyph_string_gc (s->next);
3842 x_set_glyph_string_clipping (s->next);
3843 x_draw_glyph_string_background (s->next, 1);
3846 /* Set up S->gc, set clipping and draw S. */
3847 x_set_glyph_string_gc (s);
3848 x_set_glyph_string_clipping (s);
3850 switch (s->first_glyph->type)
3852 case IMAGE_GLYPH:
3853 x_draw_image_glyph_string (s);
3854 break;
3856 case STRETCH_GLYPH:
3857 x_draw_stretch_glyph_string (s);
3858 break;
3860 case CHAR_GLYPH:
3861 if (s->for_overlaps_p)
3862 s->background_filled_p = 1;
3863 else
3864 x_draw_glyph_string_background (s, 0);
3865 x_draw_glyph_string_foreground (s);
3866 break;
3868 case COMPOSITE_GLYPH:
3869 if (s->for_overlaps_p || s->gidx > 0)
3870 s->background_filled_p = 1;
3871 else
3872 x_draw_glyph_string_background (s, 1);
3873 x_draw_composite_glyph_string_foreground (s);
3874 break;
3876 default:
3877 abort ();
3880 if (!s->for_overlaps_p)
3882 /* Draw underline. */
3883 if (s->face->underline_p
3884 && (s->font->bdf || !s->font->tm.tmUnderlined))
3886 unsigned long h = 1;
3887 unsigned long dy = s->height - h;
3889 if (s->face->underline_defaulted_p)
3891 w32_fill_area (s->f, s->hdc, s->gc->foreground, s->x,
3892 s->y + dy, s->width, 1);
3894 else
3896 w32_fill_area (s->f, s->hdc, s->face->underline_color, s->x,
3897 s->y + dy, s->width, 1);
3901 /* Draw overline. */
3902 if (s->face->overline_p)
3904 unsigned long dy = 0, h = 1;
3906 if (s->face->overline_color_defaulted_p)
3908 w32_fill_area (s->f, s->hdc, s->gc->foreground, s->x,
3909 s->y + dy, s->width, h);
3911 else
3913 w32_fill_area (s->f, s->hdc, s->face->underline_color, s->x,
3914 s->y + dy, s->width, h);
3918 /* Draw strike-through. */
3919 if (s->face->strike_through_p
3920 && (s->font->bdf || !s->font->tm.tmStruckOut))
3922 unsigned long h = 1;
3923 unsigned long dy = (s->height - h) / 2;
3925 if (s->face->strike_through_color_defaulted_p)
3927 w32_fill_area (s->f, s->hdc, s->gc->foreground, s->x, s->y + dy,
3928 s->width, h);
3930 else
3932 w32_fill_area (s->f, s->hdc, s->face->underline_color, s->x,
3933 s->y + dy, s->width, h);
3937 /* Draw relief. */
3938 if (s->face->box != FACE_NO_BOX)
3939 x_draw_glyph_string_box (s);
3942 /* Reset clipping. */
3943 w32_set_clip_rectangle (s->hdc, NULL);
3947 static int x_fill_composite_glyph_string P_ ((struct glyph_string *,
3948 struct face **, int));
3951 /* Load glyph string S with a composition components specified by S->cmp.
3952 FACES is an array of faces for all components of this composition.
3953 S->gidx is the index of the first component for S.
3954 OVERLAPS_P non-zero means S should draw the foreground only, and
3955 use its lines physical height for clipping.
3957 Value is the index of a component not in S. */
3959 static int
3960 x_fill_composite_glyph_string (s, faces, overlaps_p)
3961 struct glyph_string *s;
3962 struct face **faces;
3963 int overlaps_p;
3965 int i;
3967 xassert (s);
3969 s->for_overlaps_p = overlaps_p;
3971 s->face = faces[s->gidx];
3972 s->font = s->face->font;
3973 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
3975 /* For all glyphs of this composition, starting at the offset
3976 S->gidx, until we reach the end of the definition or encounter a
3977 glyph that requires the different face, add it to S. */
3978 ++s->nchars;
3979 for (i = s->gidx + 1; i < s->cmp->glyph_len && faces[i] == s->face; ++i)
3980 ++s->nchars;
3982 /* All glyph strings for the same composition has the same width,
3983 i.e. the width set for the first component of the composition. */
3985 s->width = s->first_glyph->pixel_width;
3987 /* If the specified font could not be loaded, use the frame's
3988 default font, but record the fact that we couldn't load it in
3989 the glyph string so that we can draw rectangles for the
3990 characters of the glyph string. */
3991 if (s->font == NULL)
3993 s->font_not_found_p = 1;
3994 s->font = FRAME_FONT (s->f);
3997 /* Adjust base line for subscript/superscript text. */
3998 s->ybase += s->first_glyph->voffset;
4000 xassert (s->face && s->face->gc);
4002 /* This glyph string must always be drawn with 16-bit functions. */
4003 s->two_byte_p = 1;
4005 return s->gidx + s->nchars;
4009 /* Load glyph string S with a sequence of characters.
4010 FACE_ID is the face id of the string. START is the index of the
4011 first glyph to consider, END is the index of the last + 1.
4012 OVERLAPS_P non-zero means S should draw the foreground only, and
4013 use its lines physical height for clipping.
4015 Value is the index of the first glyph not in S. */
4017 static int
4018 x_fill_glyph_string (s, face_id, start, end, overlaps_p)
4019 struct glyph_string *s;
4020 int face_id;
4021 int start, end, overlaps_p;
4023 struct glyph *glyph, *last;
4024 int voffset;
4025 int glyph_not_available_p;
4027 xassert (s->f == XFRAME (s->w->frame));
4028 xassert (s->nchars == 0);
4029 xassert (start >= 0 && end > start);
4031 s->for_overlaps_p = overlaps_p;
4032 glyph = s->row->glyphs[s->area] + start;
4033 last = s->row->glyphs[s->area] + end;
4034 voffset = glyph->voffset;
4036 glyph_not_available_p = glyph->glyph_not_available_p;
4038 while (glyph < last
4039 && glyph->type == CHAR_GLYPH
4040 && glyph->voffset == voffset
4041 /* Same face id implies same font, nowadays. */
4042 && glyph->face_id == face_id
4043 && glyph->glyph_not_available_p == glyph_not_available_p)
4045 int two_byte_p;
4047 s->face = x_get_glyph_face_and_encoding (s->f, glyph,
4048 s->char2b + s->nchars,
4049 &two_byte_p);
4050 s->two_byte_p = two_byte_p;
4051 ++s->nchars;
4052 xassert (s->nchars <= end - start);
4053 s->width += glyph->pixel_width;
4054 ++glyph;
4057 s->font = s->face->font;
4058 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
4060 /* If the specified font could not be loaded, use the frame's font,
4061 but record the fact that we couldn't load it in
4062 S->font_not_found_p so that we can draw rectangles for the
4063 characters of the glyph string. */
4064 if (s->font == NULL || glyph_not_available_p)
4066 s->font_not_found_p = 1;
4067 s->font = FRAME_FONT (s->f);
4070 /* Adjust base line for subscript/superscript text. */
4071 s->ybase += voffset;
4073 xassert (s->face && s->face->gc);
4074 return glyph - s->row->glyphs[s->area];
4078 /* Fill glyph string S from image glyph S->first_glyph. */
4080 static void
4081 x_fill_image_glyph_string (s)
4082 struct glyph_string *s;
4084 xassert (s->first_glyph->type == IMAGE_GLYPH);
4085 s->img = IMAGE_FROM_ID (s->f, s->first_glyph->u.img_id);
4086 xassert (s->img);
4087 s->face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
4088 s->font = s->face->font;
4089 s->width = s->first_glyph->pixel_width;
4091 /* Adjust base line for subscript/superscript text. */
4092 s->ybase += s->first_glyph->voffset;
4096 /* Fill glyph string S from a sequence of stretch glyphs.
4098 ROW is the glyph row in which the glyphs are found, AREA is the
4099 area within the row. START is the index of the first glyph to
4100 consider, END is the index of the last + 1.
4102 Value is the index of the first glyph not in S. */
4104 static int
4105 x_fill_stretch_glyph_string (s, row, area, start, end)
4106 struct glyph_string *s;
4107 struct glyph_row *row;
4108 enum glyph_row_area area;
4109 int start, end;
4111 struct glyph *glyph, *last;
4112 int voffset, face_id;
4114 xassert (s->first_glyph->type == STRETCH_GLYPH);
4116 glyph = s->row->glyphs[s->area] + start;
4117 last = s->row->glyphs[s->area] + end;
4118 face_id = glyph->face_id;
4119 s->face = FACE_FROM_ID (s->f, face_id);
4120 s->font = s->face->font;
4121 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
4122 s->width = glyph->pixel_width;
4123 voffset = glyph->voffset;
4125 for (++glyph;
4126 (glyph < last
4127 && glyph->type == STRETCH_GLYPH
4128 && glyph->voffset == voffset
4129 && glyph->face_id == face_id);
4130 ++glyph)
4131 s->width += glyph->pixel_width;
4133 /* Adjust base line for subscript/superscript text. */
4134 s->ybase += voffset;
4136 xassert (s->face && s->face->gc);
4137 return glyph - s->row->glyphs[s->area];
4141 /* Initialize glyph string S. CHAR2B is a suitably allocated vector
4142 of XChar2b structures for S; it can't be allocated in
4143 x_init_glyph_string because it must be allocated via `alloca'. W
4144 is the window on which S is drawn. ROW and AREA are the glyph row
4145 and area within the row from which S is constructed. START is the
4146 index of the first glyph structure covered by S. HL is a
4147 face-override for drawing S. */
4149 static void
4150 w32_init_glyph_string (s, hdc, char2b, w, row, area, start, hl)
4151 struct glyph_string *s;
4152 HDC hdc;
4153 wchar_t *char2b;
4154 struct window *w;
4155 struct glyph_row *row;
4156 enum glyph_row_area area;
4157 int start;
4158 enum draw_glyphs_face hl;
4160 bzero (s, sizeof *s);
4161 s->w = w;
4162 s->f = XFRAME (w->frame);
4163 s->hdc = hdc;
4164 s->window = FRAME_W32_WINDOW (s->f);
4165 s->char2b = char2b;
4166 s->hl = hl;
4167 s->row = row;
4168 s->area = area;
4169 s->first_glyph = row->glyphs[area] + start;
4170 s->height = row->height;
4171 s->y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
4173 /* Display the internal border below the tool-bar window. */
4174 if (s->w == XWINDOW (s->f->tool_bar_window))
4175 s->y -= s->f->output_data.w32->internal_border_width;
4177 s->ybase = s->y + row->ascent;
4181 /* Set background width of glyph string S. START is the index of the
4182 first glyph following S. LAST_X is the right-most x-position + 1
4183 in the drawing area. */
4185 static INLINE void
4186 x_set_glyph_string_background_width (s, start, last_x)
4187 struct glyph_string *s;
4188 int start;
4189 int last_x;
4191 /* If the face of this glyph string has to be drawn to the end of
4192 the drawing area, set S->extends_to_end_of_line_p. */
4193 struct face *default_face = FACE_FROM_ID (s->f, DEFAULT_FACE_ID);
4195 if (start == s->row->used[s->area]
4196 && s->hl == DRAW_NORMAL_TEXT
4197 && ((s->area == TEXT_AREA && s->row->fill_line_p)
4198 || s->face->background != default_face->background
4199 || s->face->stipple != default_face->stipple))
4200 s->extends_to_end_of_line_p = 1;
4202 /* If S extends its face to the end of the line, set its
4203 background_width to the distance to the right edge of the drawing
4204 area. */
4205 if (s->extends_to_end_of_line_p)
4206 s->background_width = last_x - s->x + 1;
4207 else
4208 s->background_width = s->width;
4212 /* Add a glyph string for a stretch glyph to the list of strings
4213 between HEAD and TAIL. START is the index of the stretch glyph in
4214 row area AREA of glyph row ROW. END is the index of the last glyph
4215 in that glyph row area. X is the current output position assigned
4216 to the new glyph string constructed. HL overrides that face of the
4217 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
4218 is the right-most x-position of the drawing area. */
4220 #define BUILD_STRETCH_GLYPH_STRING(hdc, W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
4221 do \
4223 s = (struct glyph_string *) alloca (sizeof *s); \
4224 w32_init_glyph_string (s, hdc, NULL, W, ROW, AREA, START, HL); \
4225 START = x_fill_stretch_glyph_string (s, ROW, AREA, START, END); \
4226 x_append_glyph_string (&HEAD, &TAIL, s); \
4227 s->x = (X); \
4229 while (0)
4232 /* Add a glyph string for an image glyph to the list of strings
4233 between HEAD and TAIL. START is the index of the image glyph in
4234 row area AREA of glyph row ROW. END is the index of the last glyph
4235 in that glyph row area. X is the current output position assigned
4236 to the new glyph string constructed. HL overrides that face of the
4237 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
4238 is the right-most x-position of the drawing area. */
4240 #define BUILD_IMAGE_GLYPH_STRING(hdc, W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
4241 do \
4243 s = (struct glyph_string *) alloca (sizeof *s); \
4244 w32_init_glyph_string (s, hdc, NULL, W, ROW, AREA, START, HL); \
4245 x_fill_image_glyph_string (s); \
4246 x_append_glyph_string (&HEAD, &TAIL, s); \
4247 ++START; \
4248 s->x = (X); \
4250 while (0)
4253 /* Add a glyph string for a sequence of character glyphs to the list
4254 of strings between HEAD and TAIL. START is the index of the first
4255 glyph in row area AREA of glyph row ROW that is part of the new
4256 glyph string. END is the index of the last glyph in that glyph row
4257 area. X is the current output position assigned to the new glyph
4258 string constructed. HL overrides that face of the glyph; e.g. it
4259 is DRAW_CURSOR if a cursor has to be drawn. LAST_X is the
4260 right-most x-position of the drawing area. */
4262 #define BUILD_CHAR_GLYPH_STRINGS(hdc, W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
4263 do \
4265 int c, face_id; \
4266 wchar_t *char2b; \
4268 c = (ROW)->glyphs[AREA][START].u.ch; \
4269 face_id = (ROW)->glyphs[AREA][START].face_id; \
4271 s = (struct glyph_string *) alloca (sizeof *s); \
4272 char2b = (wchar_t *) alloca ((END - START) * sizeof *char2b); \
4273 w32_init_glyph_string (s, hdc, char2b, W, ROW, AREA, START, HL); \
4274 x_append_glyph_string (&HEAD, &TAIL, s); \
4275 s->x = (X); \
4276 START = x_fill_glyph_string (s, face_id, START, END, \
4277 OVERLAPS_P); \
4279 while (0)
4282 /* Add a glyph string for a composite sequence to the list of strings
4283 between HEAD and TAIL. START is the index of the first glyph in
4284 row area AREA of glyph row ROW that is part of the new glyph
4285 string. END is the index of the last glyph in that glyph row area.
4286 X is the current output position assigned to the new glyph string
4287 constructed. HL overrides that face of the glyph; e.g. it is
4288 DRAW_CURSOR if a cursor has to be drawn. LAST_X is the right-most
4289 x-position of the drawing area. */
4291 #define BUILD_COMPOSITE_GLYPH_STRING(hdc, W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
4292 do { \
4293 int cmp_id = (ROW)->glyphs[AREA][START].u.cmp_id; \
4294 int face_id = (ROW)->glyphs[AREA][START].face_id; \
4295 struct face *base_face = FACE_FROM_ID (XFRAME (w->frame), face_id); \
4296 struct composition *cmp = composition_table[cmp_id]; \
4297 int glyph_len = cmp->glyph_len; \
4298 wchar_t *char2b; \
4299 struct face **faces; \
4300 struct glyph_string *first_s = NULL; \
4301 int n; \
4303 base_face = base_face->ascii_face; \
4304 char2b = (wchar_t *) alloca ((sizeof *char2b) * glyph_len); \
4305 faces = (struct face **) alloca ((sizeof *faces) * glyph_len); \
4306 /* At first, fill in `char2b' and `faces'. */ \
4307 for (n = 0; n < glyph_len; n++) \
4309 int c = COMPOSITION_GLYPH (cmp, n); \
4310 int this_face_id = FACE_FOR_CHAR (XFRAME (w->frame), base_face, c); \
4311 faces[n] = FACE_FROM_ID (XFRAME (w->frame), this_face_id); \
4312 x_get_char_face_and_encoding (XFRAME (w->frame), c, \
4313 this_face_id, char2b + n, 1); \
4316 /* Make glyph_strings for each glyph sequence that is drawable by \
4317 the same face, and append them to HEAD/TAIL. */ \
4318 for (n = 0; n < cmp->glyph_len;) \
4320 s = (struct glyph_string *) alloca (sizeof *s); \
4321 w32_init_glyph_string (s, hdc, char2b + n, W, ROW, AREA, START, HL); \
4322 x_append_glyph_string (&(HEAD), &(TAIL), s); \
4323 s->cmp = cmp; \
4324 s->gidx = n; \
4325 s->x = (X); \
4327 if (n == 0) \
4328 first_s = s; \
4330 n = x_fill_composite_glyph_string (s, faces, OVERLAPS_P); \
4333 ++START; \
4334 s = first_s; \
4335 } while (0)
4338 /* Build a list of glyph strings between HEAD and TAIL for the glyphs
4339 of AREA of glyph row ROW on window W between indices START and END.
4340 HL overrides the face for drawing glyph strings, e.g. it is
4341 DRAW_CURSOR to draw a cursor. X and LAST_X are start and end
4342 x-positions of the drawing area.
4344 This is an ugly monster macro construct because we must use alloca
4345 to allocate glyph strings (because x_draw_glyphs can be called
4346 asynchronously). */
4348 #define BUILD_GLYPH_STRINGS(hdc, W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
4349 do \
4351 HEAD = TAIL = NULL; \
4352 while (START < END) \
4354 struct glyph *first_glyph = (ROW)->glyphs[AREA] + START; \
4355 switch (first_glyph->type) \
4357 case CHAR_GLYPH: \
4358 BUILD_CHAR_GLYPH_STRINGS (hdc, W, ROW, AREA, START, END, \
4359 HEAD, TAIL, HL, X, LAST_X, \
4360 OVERLAPS_P); \
4361 break; \
4363 case COMPOSITE_GLYPH: \
4364 BUILD_COMPOSITE_GLYPH_STRING (hdc, W, ROW, AREA, START, \
4365 END, HEAD, TAIL, HL, X, \
4366 LAST_X, OVERLAPS_P); \
4367 break; \
4369 case STRETCH_GLYPH: \
4370 BUILD_STRETCH_GLYPH_STRING (hdc, W, ROW, AREA, START, END,\
4371 HEAD, TAIL, HL, X, LAST_X); \
4372 break; \
4374 case IMAGE_GLYPH: \
4375 BUILD_IMAGE_GLYPH_STRING (hdc, W, ROW, AREA, START, END, \
4376 HEAD, TAIL, HL, X, LAST_X); \
4377 break; \
4379 default: \
4380 abort (); \
4383 x_set_glyph_string_background_width (s, START, LAST_X); \
4384 (X) += s->width; \
4387 while (0)
4390 /* Draw glyphs between START and END in AREA of ROW on window W,
4391 starting at x-position X. X is relative to AREA in W. HL is a
4392 face-override with the following meaning:
4394 DRAW_NORMAL_TEXT draw normally
4395 DRAW_CURSOR draw in cursor face
4396 DRAW_MOUSE_FACE draw in mouse face.
4397 DRAW_INVERSE_VIDEO draw in mode line face
4398 DRAW_IMAGE_SUNKEN draw an image with a sunken relief around it
4399 DRAW_IMAGE_RAISED draw an image with a raised relief around it
4401 If REAL_START is non-null, return in *REAL_START the real starting
4402 position for display. This can be different from START in case
4403 overlapping glyphs must be displayed. If REAL_END is non-null,
4404 return in *REAL_END the real end position for display. This can be
4405 different from END in case overlapping glyphs must be displayed.
4407 If OVERLAPS_P is non-zero, draw only the foreground of characters
4408 and clip to the physical height of ROW.
4410 Value is the x-position reached, relative to AREA of W. */
4412 static int
4413 x_draw_glyphs (w, x, row, area, start, end, hl, real_start, real_end,
4414 overlaps_p)
4415 struct window *w;
4416 int x;
4417 struct glyph_row *row;
4418 enum glyph_row_area area;
4419 int start, end;
4420 enum draw_glyphs_face hl;
4421 int *real_start, *real_end;
4422 int overlaps_p;
4424 struct glyph_string *head, *tail;
4425 struct glyph_string *s;
4426 int last_x, area_width;
4427 int x_reached;
4428 int i, j;
4429 HDC hdc = get_frame_dc (XFRAME (WINDOW_FRAME (w)));
4431 /* Let's rather be paranoid than getting a SEGV. */
4432 end = min (end, row->used[area]);
4433 start = max (0, start);
4434 start = min (end, start);
4436 if (real_start)
4437 *real_start = start;
4438 if (real_end)
4439 *real_end = end;
4441 /* Translate X to frame coordinates. Set last_x to the right
4442 end of the drawing area. */
4443 if (row->full_width_p)
4445 /* X is relative to the left edge of W, without scroll bars
4446 or flag areas. */
4447 struct frame *f = XFRAME (WINDOW_FRAME (w));
4448 /* int width = FRAME_FLAGS_AREA_WIDTH (f); */
4449 int window_left_x = WINDOW_LEFT_MARGIN (w) * CANON_X_UNIT (f);
4451 x += window_left_x;
4452 area_width = XFASTINT (w->width) * CANON_X_UNIT (f);
4453 last_x = window_left_x + area_width;
4455 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
4457 int width = FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
4458 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
4459 last_x += width;
4460 else
4461 x -= width;
4464 x += FRAME_INTERNAL_BORDER_WIDTH (f);
4465 last_x -= FRAME_INTERNAL_BORDER_WIDTH (f);
4467 else
4469 x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, x);
4470 area_width = window_box_width (w, area);
4471 last_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, area_width);
4474 /* Build a doubly-linked list of glyph_string structures between
4475 head and tail from what we have to draw. Note that the macro
4476 BUILD_GLYPH_STRINGS will modify its start parameter. That's
4477 the reason we use a separate variable `i'. */
4478 i = start;
4479 BUILD_GLYPH_STRINGS (hdc, w, row, area, i, end, head, tail, hl, x, last_x,
4480 overlaps_p);
4481 if (tail)
4482 x_reached = tail->x + tail->background_width;
4483 else
4484 x_reached = x;
4486 /* If there are any glyphs with lbearing < 0 or rbearing > width in
4487 the row, redraw some glyphs in front or following the glyph
4488 strings built above. */
4489 if (head && !overlaps_p && row->contains_overlapping_glyphs_p)
4491 int dummy_x = 0;
4492 struct glyph_string *h, *t;
4494 /* Compute overhangs for all glyph strings. */
4495 for (s = head; s; s = s->next)
4496 x_compute_glyph_string_overhangs (s);
4498 /* Prepend glyph strings for glyphs in front of the first glyph
4499 string that are overwritten because of the first glyph
4500 string's left overhang. The background of all strings
4501 prepended must be drawn because the first glyph string
4502 draws over it. */
4503 i = x_left_overwritten (head);
4504 if (i >= 0)
4506 j = i;
4507 BUILD_GLYPH_STRINGS (hdc, w, row, area, j, start, h, t,
4508 DRAW_NORMAL_TEXT, dummy_x, last_x,
4509 overlaps_p);
4510 start = i;
4511 if (real_start)
4512 *real_start = start;
4513 x_compute_overhangs_and_x (t, head->x, 1);
4514 x_prepend_glyph_string_lists (&head, &tail, h, t);
4517 /* Prepend glyph strings for glyphs in front of the first glyph
4518 string that overwrite that glyph string because of their
4519 right overhang. For these strings, only the foreground must
4520 be drawn, because it draws over the glyph string at `head'.
4521 The background must not be drawn because this would overwrite
4522 right overhangs of preceding glyphs for which no glyph
4523 strings exist. */
4524 i = x_left_overwriting (head);
4525 if (i >= 0)
4527 BUILD_GLYPH_STRINGS (hdc, w, row, area, i, start, h, t,
4528 DRAW_NORMAL_TEXT, dummy_x, last_x,
4529 overlaps_p);
4530 for (s = h; s; s = s->next)
4531 s->background_filled_p = 1;
4532 if (real_start)
4533 *real_start = i;
4534 x_compute_overhangs_and_x (t, head->x, 1);
4535 x_prepend_glyph_string_lists (&head, &tail, h, t);
4538 /* Append glyphs strings for glyphs following the last glyph
4539 string tail that are overwritten by tail. The background of
4540 these strings has to be drawn because tail's foreground draws
4541 over it. */
4542 i = x_right_overwritten (tail);
4543 if (i >= 0)
4545 BUILD_GLYPH_STRINGS (hdc, w, row, area, end, i, h, t,
4546 DRAW_NORMAL_TEXT, x, last_x,
4547 overlaps_p);
4548 x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
4549 x_append_glyph_string_lists (&head, &tail, h, t);
4550 if (real_end)
4551 *real_end = i;
4554 /* Append glyph strings for glyphs following the last glyph
4555 string tail that overwrite tail. The foreground of such
4556 glyphs has to be drawn because it writes into the background
4557 of tail. The background must not be drawn because it could
4558 paint over the foreground of following glyphs. */
4559 i = x_right_overwriting (tail);
4560 if (i >= 0)
4562 BUILD_GLYPH_STRINGS (hdc, w, row, area, end, i, h, t,
4563 DRAW_NORMAL_TEXT, x, last_x,
4564 overlaps_p);
4565 for (s = h; s; s = s->next)
4566 s->background_filled_p = 1;
4567 x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
4568 x_append_glyph_string_lists (&head, &tail, h, t);
4569 if (real_end)
4570 *real_end = i;
4574 /* Draw all strings. */
4575 for (s = head; s; s = s->next)
4576 x_draw_glyph_string (s);
4578 /* Value is the x-position up to which drawn, relative to AREA of W.
4579 This doesn't include parts drawn because of overhangs. */
4580 x_reached = FRAME_TO_WINDOW_PIXEL_X (w, x_reached);
4581 if (!row->full_width_p)
4583 if (area > LEFT_MARGIN_AREA)
4584 x_reached -= window_box_width (w, LEFT_MARGIN_AREA);
4585 if (area > TEXT_AREA)
4586 x_reached -= window_box_width (w, TEXT_AREA);
4589 release_frame_dc (XFRAME (WINDOW_FRAME (w)), hdc);
4591 return x_reached;
4595 /* Fix the display of area AREA of overlapping row ROW in window W. */
4597 static void
4598 x_fix_overlapping_area (w, row, area)
4599 struct window *w;
4600 struct glyph_row *row;
4601 enum glyph_row_area area;
4603 int i, x;
4605 BLOCK_INPUT;
4607 if (area == LEFT_MARGIN_AREA)
4608 x = 0;
4609 else if (area == TEXT_AREA)
4610 x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
4611 else
4612 x = (window_box_width (w, LEFT_MARGIN_AREA)
4613 + window_box_width (w, TEXT_AREA));
4615 for (i = 0; i < row->used[area];)
4617 if (row->glyphs[area][i].overlaps_vertically_p)
4619 int start = i, start_x = x;
4623 x += row->glyphs[area][i].pixel_width;
4624 ++i;
4626 while (i < row->used[area]
4627 && row->glyphs[area][i].overlaps_vertically_p);
4629 x_draw_glyphs (w, start_x, row, area, start, i,
4630 (row->inverse_p
4631 ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT),
4632 NULL, NULL, 1);
4634 else
4636 x += row->glyphs[area][i].pixel_width;
4637 ++i;
4641 UNBLOCK_INPUT;
4645 /* Output LEN glyphs starting at START at the nominal cursor position.
4646 Advance the nominal cursor over the text. The global variable
4647 updated_window contains the window being updated, updated_row is
4648 the glyph row being updated, and updated_area is the area of that
4649 row being updated. */
4651 static void
4652 x_write_glyphs (start, len)
4653 struct glyph *start;
4654 int len;
4656 int x, hpos, real_start, real_end;
4658 xassert (updated_window && updated_row);
4659 BLOCK_INPUT;
4661 /* Write glyphs. */
4663 hpos = start - updated_row->glyphs[updated_area];
4664 x = x_draw_glyphs (updated_window, output_cursor.x,
4665 updated_row, updated_area,
4666 hpos, hpos + len,
4667 (updated_row->inverse_p
4668 ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT),
4669 &real_start, &real_end, 0);
4671 /* If we drew over the cursor, note that it is not visible any more. */
4672 note_overwritten_text_cursor (updated_window, real_start,
4673 real_end - real_start);
4675 UNBLOCK_INPUT;
4677 /* Advance the output cursor. */
4678 output_cursor.hpos += len;
4679 output_cursor.x = x;
4683 /* Insert LEN glyphs from START at the nominal cursor position. */
4685 static void
4686 x_insert_glyphs (start, len)
4687 struct glyph *start;
4688 register int len;
4690 struct frame *f;
4691 struct window *w;
4692 int line_height, shift_by_width, shifted_region_width;
4693 struct glyph_row *row;
4694 struct glyph *glyph;
4695 int frame_x, frame_y, hpos, real_start, real_end;
4696 HDC hdc;
4698 xassert (updated_window && updated_row);
4699 BLOCK_INPUT;
4700 w = updated_window;
4701 f = XFRAME (WINDOW_FRAME (w));
4702 hdc = get_frame_dc (f);
4704 /* Get the height of the line we are in. */
4705 row = updated_row;
4706 line_height = row->height;
4708 /* Get the width of the glyphs to insert. */
4709 shift_by_width = 0;
4710 for (glyph = start; glyph < start + len; ++glyph)
4711 shift_by_width += glyph->pixel_width;
4713 /* Get the width of the region to shift right. */
4714 shifted_region_width = (window_box_width (w, updated_area)
4715 - output_cursor.x
4716 - shift_by_width);
4718 /* Shift right. */
4719 frame_x = WINDOW_TO_FRAME_PIXEL_X (w, output_cursor.x);
4720 frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, output_cursor.y);
4721 BitBlt (hdc, frame_x + shift_by_width, frame_y,
4722 shifted_region_width, line_height,
4723 hdc, frame_x, frame_y, SRCCOPY);
4725 /* Write the glyphs. */
4726 hpos = start - row->glyphs[updated_area];
4727 x_draw_glyphs (w, output_cursor.x, row, updated_area, hpos, hpos + len,
4728 DRAW_NORMAL_TEXT, &real_start, &real_end, 0);
4729 note_overwritten_text_cursor (w, real_start, real_end - real_start);
4731 /* Advance the output cursor. */
4732 output_cursor.hpos += len;
4733 output_cursor.x += shift_by_width;
4734 release_frame_dc (f, hdc);
4736 UNBLOCK_INPUT;
4740 /* Delete N glyphs at the nominal cursor position. Not implemented
4741 for X frames. */
4743 static void
4744 x_delete_glyphs (n)
4745 register int n;
4747 abort ();
4751 /* Erase the current text line from the nominal cursor position
4752 (inclusive) to pixel column TO_X (exclusive). The idea is that
4753 everything from TO_X onward is already erased.
4755 TO_X is a pixel position relative to updated_area of
4756 updated_window. TO_X == -1 means clear to the end of this area. */
4758 static void
4759 x_clear_end_of_line (to_x)
4760 int to_x;
4762 struct frame *f;
4763 struct window *w = updated_window;
4764 int max_x, min_y, max_y;
4765 int from_x, from_y, to_y;
4767 xassert (updated_window && updated_row);
4768 f = XFRAME (w->frame);
4770 if (updated_row->full_width_p)
4772 max_x = XFASTINT (w->width) * CANON_X_UNIT (f);
4773 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f)
4774 && !w->pseudo_window_p)
4775 max_x += FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
4777 else
4778 max_x = window_box_width (w, updated_area);
4779 max_y = window_text_bottom_y (w);
4781 /* TO_X == 0 means don't do anything. TO_X < 0 means clear to end
4782 of window. For TO_X > 0, truncate to end of drawing area. */
4783 if (to_x == 0)
4784 return;
4785 else if (to_x < 0)
4786 to_x = max_x;
4787 else
4788 to_x = min (to_x, max_x);
4790 to_y = min (max_y, output_cursor.y + updated_row->height);
4792 /* Notice if the cursor will be cleared by this operation. */
4793 if (!updated_row->full_width_p)
4794 note_overwritten_text_cursor (w, output_cursor.hpos, -1);
4796 from_x = output_cursor.x;
4798 /* Translate to frame coordinates. */
4799 if (updated_row->full_width_p)
4801 from_x = WINDOW_TO_FRAME_PIXEL_X (w, from_x);
4802 to_x = WINDOW_TO_FRAME_PIXEL_X (w, to_x);
4804 else
4806 from_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, from_x);
4807 to_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, to_x);
4810 min_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
4811 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, max (min_y, output_cursor.y));
4812 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, to_y);
4814 /* Prevent inadvertently clearing to end of the X window. */
4815 if (to_x > from_x && to_y > from_y)
4817 HDC hdc;
4818 BLOCK_INPUT;
4819 hdc = get_frame_dc (f);
4821 w32_clear_area (f, hdc, from_x, from_y, to_x - from_x, to_y - from_y);
4822 release_frame_dc (f, hdc);
4823 UNBLOCK_INPUT;
4828 /* Clear entire frame. If updating_frame is non-null, clear that
4829 frame. Otherwise clear the selected frame. */
4831 static void
4832 x_clear_frame ()
4834 struct frame *f;
4836 if (updating_frame)
4837 f = updating_frame;
4838 else
4839 f = SELECTED_FRAME ();
4841 /* Clearing the frame will erase any cursor, so mark them all as no
4842 longer visible. */
4843 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
4844 output_cursor.hpos = output_cursor.vpos = 0;
4845 output_cursor.x = -1;
4847 /* We don't set the output cursor here because there will always
4848 follow an explicit cursor_to. */
4849 BLOCK_INPUT;
4851 w32_clear_window (f);
4853 /* We have to clear the scroll bars, too. If we have changed
4854 colors or something like that, then they should be notified. */
4855 x_scroll_bar_clear (f);
4857 UNBLOCK_INPUT;
4861 /* Make audible bell. */
4863 static void
4864 w32_ring_bell (void)
4866 BLOCK_INPUT;
4868 if (visible_bell)
4870 int i;
4871 HWND hwnd = FRAME_W32_WINDOW (SELECTED_FRAME ());
4873 for (i = 0; i < 5; i++)
4875 FlashWindow (hwnd, TRUE);
4876 Sleep (10);
4878 FlashWindow (hwnd, FALSE);
4880 else
4881 w32_sys_ring_bell ();
4883 UNBLOCK_INPUT;
4887 /* Specify how many text lines, from the top of the window,
4888 should be affected by insert-lines and delete-lines operations.
4889 This, and those operations, are used only within an update
4890 that is bounded by calls to x_update_begin and x_update_end. */
4892 static void
4893 w32_set_terminal_window (n)
4894 register int n;
4896 /* This function intentionally left blank. */
4901 /***********************************************************************
4902 Line Dance
4903 ***********************************************************************/
4905 /* Perform an insert-lines or delete-lines operation, inserting N
4906 lines or deleting -N lines at vertical position VPOS. */
4908 static void
4909 x_ins_del_lines (vpos, n)
4910 int vpos, n;
4912 abort ();
4916 /* Scroll part of the display as described by RUN. */
4918 static void
4919 x_scroll_run (w, run)
4920 struct window *w;
4921 struct run *run;
4923 struct frame *f = XFRAME (w->frame);
4924 int x, y, width, height, from_y, to_y, bottom_y;
4925 HDC hdc = get_frame_dc (f);
4927 /* Get frame-relative bounding box of the text display area of W,
4928 without mode lines. Include in this box the flags areas to the
4929 left and right of W. */
4930 window_box (w, -1, &x, &y, &width, &height);
4931 width += FRAME_X_FLAGS_AREA_WIDTH (f);
4932 x -= FRAME_X_LEFT_FLAGS_AREA_WIDTH (f);
4934 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
4935 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
4936 bottom_y = y + height;
4938 if (to_y < from_y)
4940 /* Scrolling up. Make sure we don't copy part of the mode
4941 line at the bottom. */
4942 if (from_y + run->height > bottom_y)
4943 height = bottom_y - from_y;
4944 else
4945 height = run->height;
4947 else
4949 /* Scolling down. Make sure we don't copy over the mode line.
4950 at the bottom. */
4951 if (to_y + run->height > bottom_y)
4952 height = bottom_y - to_y;
4953 else
4954 height = run->height;
4957 BLOCK_INPUT;
4959 /* Cursor off. Will be switched on again in x_update_window_end. */
4960 updated_window = w;
4961 x_clear_cursor (w);
4963 BitBlt (hdc, x, to_y, width, height, hdc, x, from_y, SRCCOPY);
4965 UNBLOCK_INPUT;
4966 release_frame_dc (f, hdc);
4971 /***********************************************************************
4972 Exposure Events
4973 ***********************************************************************/
4975 /* Redisplay an exposed area of frame F. X and Y are the upper-left
4976 corner of the exposed rectangle. W and H are width and height of
4977 the exposed area. All are pixel values. W or H zero means redraw
4978 the entire frame. */
4980 static void
4981 expose_frame (f, x, y, w, h)
4982 struct frame *f;
4983 int x, y, w, h;
4985 RECT r;
4987 TRACE ((stderr, "expose_frame "));
4989 /* No need to redraw if frame will be redrawn soon. */
4990 if (FRAME_GARBAGED_P (f))
4992 TRACE ((stderr, " garbaged\n"));
4993 return;
4996 /* If basic faces haven't been realized yet, there is no point in
4997 trying to redraw anything. This can happen when we get an expose
4998 event while Emacs is starting, e.g. by moving another window. */
4999 if (FRAME_FACE_CACHE (f) == NULL
5000 || FRAME_FACE_CACHE (f)->used < BASIC_FACE_ID_SENTINEL)
5002 TRACE ((stderr, " no faces\n"));
5003 return;
5006 if (w == 0 || h == 0)
5008 r.left = r.top = 0;
5009 r.right = CANON_X_UNIT (f) * f->width;
5010 r.bottom = CANON_Y_UNIT (f) * f->height;
5012 else
5014 r.left = x;
5015 r.top = y;
5016 r.right = x + w;
5017 r.bottom = y + h;
5020 TRACE ((stderr, "(%d, %d, %d, %d)\n", r.left, r.top, r.right, r.bottom));
5021 expose_window_tree (XWINDOW (f->root_window), &r);
5023 if (WINDOWP (f->tool_bar_window))
5025 struct window *w = XWINDOW (f->tool_bar_window);
5026 RECT window_rect;
5027 RECT intersection_rect;
5028 int window_x, window_y, window_width, window_height;
5030 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
5031 window_rect.left = window_x;
5032 window_rect.top = window_y;
5033 window_rect.right = window_x + window_width;
5034 window_rect.bottom = window_y + window_height;
5036 if (IntersectRect (&intersection_rect, &r, &window_rect))
5037 expose_window (w, &intersection_rect);
5042 /* Redraw (parts) of all windows in the window tree rooted at W that
5043 intersect R. R contains frame pixel coordinates. */
5045 static void
5046 expose_window_tree (w, r)
5047 struct window *w;
5048 RECT *r;
5050 while (w)
5052 if (!NILP (w->hchild))
5053 expose_window_tree (XWINDOW (w->hchild), r);
5054 else if (!NILP (w->vchild))
5055 expose_window_tree (XWINDOW (w->vchild), r);
5056 else
5058 RECT window_rect;
5059 RECT intersection_rect;
5060 struct frame *f = XFRAME (w->frame);
5061 int window_x, window_y, window_width, window_height;
5063 /* Frame-relative pixel rectangle of W. */
5064 window_box (w, -1, &window_x, &window_y, &window_width,
5065 &window_height);
5066 window_rect.left
5067 = (window_x
5068 - FRAME_X_LEFT_FLAGS_AREA_WIDTH (f)
5069 - FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_Y_UNIT (f));
5070 window_rect.top = window_y;
5071 window_rect.right = window_rect.left
5072 + (window_width
5073 + FRAME_X_FLAGS_AREA_WIDTH (f)
5074 + FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f));
5075 window_rect.bottom = window_rect.top
5076 + window_height + CURRENT_MODE_LINE_HEIGHT (w);
5078 if (IntersectRect (&intersection_rect, r, &window_rect))
5079 expose_window (w, &intersection_rect);
5082 w = NILP (w->next) ? 0 : XWINDOW (w->next);
5087 /* Redraw the part of glyph row area AREA of glyph row ROW on window W
5088 which intersects rectangle R. R is in window-relative coordinates. */
5090 static void
5091 expose_area (w, row, r, area)
5092 struct window *w;
5093 struct glyph_row *row;
5094 RECT *r;
5095 enum glyph_row_area area;
5097 int x;
5098 struct glyph *first = row->glyphs[area];
5099 struct glyph *end = row->glyphs[area] + row->used[area];
5100 struct glyph *last;
5101 int first_x;
5103 /* Set x to the window-relative start position for drawing glyphs of
5104 AREA. The first glyph of the text area can be partially visible.
5105 The first glyphs of other areas cannot. */
5106 if (area == LEFT_MARGIN_AREA)
5107 x = 0;
5108 else if (area == TEXT_AREA)
5109 x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
5110 else
5111 x = (window_box_width (w, LEFT_MARGIN_AREA)
5112 + window_box_width (w, TEXT_AREA));
5114 if (area == TEXT_AREA && row->fill_line_p)
5115 /* If row extends face to end of line write the whole line. */
5116 x_draw_glyphs (w, x, row, area,
5117 0, row->used[area],
5118 row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT,
5119 NULL, NULL, 0);
5120 else
5122 /* Find the first glyph that must be redrawn. */
5123 while (first < end
5124 && x + first->pixel_width < r->left)
5126 x += first->pixel_width;
5127 ++first;
5130 /* Find the last one. */
5131 last = first;
5132 first_x = x;
5133 while (last < end
5134 && x < r->right)
5136 x += last->pixel_width;
5137 ++last;
5140 /* Repaint. */
5141 if (last > first)
5142 x_draw_glyphs (w, first_x, row, area,
5143 first - row->glyphs[area],
5144 last - row->glyphs[area],
5145 row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT,
5146 NULL, NULL, 0);
5151 /* Redraw the parts of the glyph row ROW on window W intersecting
5152 rectangle R. R is in window-relative coordinates. */
5154 static void
5155 expose_line (w, row, r)
5156 struct window *w;
5157 struct glyph_row *row;
5158 RECT *r;
5160 xassert (row->enabled_p);
5162 if (row->mode_line_p || w->pseudo_window_p)
5163 x_draw_glyphs (w, 0, row, TEXT_AREA, 0, row->used[TEXT_AREA],
5164 row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT,
5165 NULL, NULL, 0);
5166 else
5168 if (row->used[LEFT_MARGIN_AREA])
5169 expose_area (w, row, r, LEFT_MARGIN_AREA);
5170 if (row->used[TEXT_AREA])
5171 expose_area (w, row, r, TEXT_AREA);
5172 if (row->used[RIGHT_MARGIN_AREA])
5173 expose_area (w, row, r, RIGHT_MARGIN_AREA);
5174 x_draw_row_bitmaps (w, row);
5179 /* Return non-zero if W's cursor intersects rectangle R. */
5181 static int
5182 x_phys_cursor_in_rect_p (w, r)
5183 struct window *w;
5184 RECT *r;
5186 RECT cr, result;
5187 struct glyph *cursor_glyph;
5189 cursor_glyph = get_phys_cursor_glyph (w);
5190 if (cursor_glyph)
5192 cr.left = w->phys_cursor.x;
5193 cr.top = w->phys_cursor.y;
5194 cr.right = cr.left + cursor_glyph->pixel_width;
5195 cr.bottom = cr.top + w->phys_cursor_height;
5196 return IntersectRect (&result, &cr, r);
5198 else
5199 return 0;
5203 /* Redraw a rectangle of window W. R is a rectangle in window
5204 relative coordinates. Call this function with input blocked. */
5206 static void
5207 expose_window (w, r)
5208 struct window *w;
5209 RECT *r;
5211 struct glyph_row *row;
5212 int y;
5213 int yb = window_text_bottom_y (w);
5214 int cursor_cleared_p;
5216 /* If window is not yet fully initialized, do nothing. This can
5217 happen when toolkit scroll bars are used and a window is split.
5218 Reconfiguring the scroll bar will generate an expose for a newly
5219 created window. */
5220 if (w->current_matrix == NULL)
5221 return;
5223 TRACE ((stderr, "expose_window (%d, %d, %d, %d)\n",
5224 r->left, r->top, r->right, r->bottom));
5226 /* Convert to window coordinates. */
5227 r->left = FRAME_TO_WINDOW_PIXEL_X (w, r->left);
5228 r->top = FRAME_TO_WINDOW_PIXEL_Y (w, r->top);
5229 r->right = FRAME_TO_WINDOW_PIXEL_X (w, r->right);
5230 r->bottom = FRAME_TO_WINDOW_PIXEL_Y (w, r->bottom);
5232 /* Turn off the cursor. */
5233 if (!w->pseudo_window_p
5234 && x_phys_cursor_in_rect_p (w, r))
5236 x_clear_cursor (w);
5237 cursor_cleared_p = 1;
5239 else
5240 cursor_cleared_p = 0;
5242 /* Find the first row intersecting the rectangle R. */
5243 row = w->current_matrix->rows;
5244 y = 0;
5245 while (row->enabled_p
5246 && y < yb
5247 && y + row->height < r->top)
5249 y += row->height;
5250 ++row;
5253 /* Display the text in the rectangle, one text line at a time. */
5254 while (row->enabled_p
5255 && y < yb
5256 && y < r->bottom)
5258 expose_line (w, row, r);
5259 y += row->height;
5260 ++row;
5263 /* Display the mode line if there is one. */
5264 if (WINDOW_WANTS_MODELINE_P (w)
5265 && (row = MATRIX_MODE_LINE_ROW (w->current_matrix),
5266 row->enabled_p)
5267 && row->y < r->bottom)
5268 expose_line (w, row, r);
5270 if (!w->pseudo_window_p)
5272 /* Draw border between windows. */
5273 x_draw_vertical_border (w);
5275 /* Turn the cursor on again. */
5276 if (cursor_cleared_p)
5277 x_update_window_cursor (w, 1);
5282 static void
5283 frame_highlight (f)
5284 struct frame *f;
5286 x_update_cursor (f, 1);
5289 static void
5290 frame_unhighlight (f)
5291 struct frame *f;
5293 x_update_cursor (f, 1);
5296 /* The focus has changed. Update the frames as necessary to reflect
5297 the new situation. Note that we can't change the selected frame
5298 here, because the Lisp code we are interrupting might become confused.
5299 Each event gets marked with the frame in which it occurred, so the
5300 Lisp code can tell when the switch took place by examining the events. */
5302 static void
5303 x_new_focus_frame (dpyinfo, frame)
5304 struct w32_display_info *dpyinfo;
5305 struct frame *frame;
5307 struct frame *old_focus = dpyinfo->w32_focus_frame;
5309 if (frame != dpyinfo->w32_focus_frame)
5311 /* Set this before calling other routines, so that they see
5312 the correct value of w32_focus_frame. */
5313 dpyinfo->w32_focus_frame = frame;
5315 if (old_focus && old_focus->auto_lower)
5316 x_lower_frame (old_focus);
5318 if (dpyinfo->w32_focus_frame && dpyinfo->w32_focus_frame->auto_raise)
5319 pending_autoraise_frame = dpyinfo->w32_focus_frame;
5320 else
5321 pending_autoraise_frame = 0;
5324 x_frame_rehighlight (dpyinfo);
5327 /* Handle an event saying the mouse has moved out of an Emacs frame. */
5329 void
5330 x_mouse_leave (dpyinfo)
5331 struct w32_display_info *dpyinfo;
5333 x_new_focus_frame (dpyinfo, dpyinfo->w32_focus_event_frame);
5336 /* The focus has changed, or we have redirected a frame's focus to
5337 another frame (this happens when a frame uses a surrogate
5338 mini-buffer frame). Shift the highlight as appropriate.
5340 The FRAME argument doesn't necessarily have anything to do with which
5341 frame is being highlighted or un-highlighted; we only use it to find
5342 the appropriate X display info. */
5344 static void
5345 w32_frame_rehighlight (frame)
5346 struct frame *frame;
5348 x_frame_rehighlight (FRAME_W32_DISPLAY_INFO (frame));
5351 static void
5352 x_frame_rehighlight (dpyinfo)
5353 struct w32_display_info *dpyinfo;
5355 struct frame *old_highlight = dpyinfo->w32_highlight_frame;
5357 if (dpyinfo->w32_focus_frame)
5359 dpyinfo->w32_highlight_frame
5360 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->w32_focus_frame)))
5361 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->w32_focus_frame))
5362 : dpyinfo->w32_focus_frame);
5363 if (! FRAME_LIVE_P (dpyinfo->w32_highlight_frame))
5365 FRAME_FOCUS_FRAME (dpyinfo->w32_focus_frame) = Qnil;
5366 dpyinfo->w32_highlight_frame = dpyinfo->w32_focus_frame;
5369 else
5370 dpyinfo->w32_highlight_frame = 0;
5372 if (dpyinfo->w32_highlight_frame != old_highlight)
5374 if (old_highlight)
5375 frame_unhighlight (old_highlight);
5376 if (dpyinfo->w32_highlight_frame)
5377 frame_highlight (dpyinfo->w32_highlight_frame);
5381 /* Keyboard processing - modifier keys, etc. */
5383 /* Convert a keysym to its name. */
5385 char *
5386 x_get_keysym_name (keysym)
5387 int keysym;
5389 /* Make static so we can always return it */
5390 static char value[100];
5392 BLOCK_INPUT;
5393 GetKeyNameText (keysym, value, 100);
5394 UNBLOCK_INPUT;
5396 return value;
5401 /* Mouse clicks and mouse movement. Rah. */
5403 /* Given a pixel position (PIX_X, PIX_Y) on frame F, return glyph
5404 co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle that the
5405 glyph at X, Y occupies, if BOUNDS != 0. If NOCLIP is non-zero, do
5406 not force the value into range. */
5408 void
5409 pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds, noclip)
5410 FRAME_PTR f;
5411 register int pix_x, pix_y;
5412 register int *x, *y;
5413 RECT *bounds;
5414 int noclip;
5416 /* Support tty mode: if Vwindow_system is nil, behave correctly. */
5417 if (NILP (Vwindow_system))
5419 *x = pix_x;
5420 *y = pix_y;
5421 return;
5424 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
5425 even for negative values. */
5426 if (pix_x < 0)
5427 pix_x -= FONT_WIDTH (FRAME_FONT (f)) - 1;
5428 if (pix_y < 0)
5429 pix_y -= (f)->output_data.w32->line_height - 1;
5431 pix_x = PIXEL_TO_CHAR_COL (f, pix_x);
5432 pix_y = PIXEL_TO_CHAR_ROW (f, pix_y);
5434 if (bounds)
5436 bounds->left = CHAR_TO_PIXEL_COL (f, pix_x);
5437 bounds->top = CHAR_TO_PIXEL_ROW (f, pix_y);
5438 bounds->right = bounds->left + FONT_WIDTH (FRAME_FONT (f)) - 1;
5439 bounds->bottom = bounds->top + f->output_data.w32->line_height - 1;
5442 if (!noclip)
5444 if (pix_x < 0)
5445 pix_x = 0;
5446 else if (pix_x > FRAME_WINDOW_WIDTH (f))
5447 pix_x = FRAME_WINDOW_WIDTH (f);
5449 if (pix_y < 0)
5450 pix_y = 0;
5451 else if (pix_y > f->height)
5452 pix_y = f->height;
5455 *x = pix_x;
5456 *y = pix_y;
5460 /* Given HPOS/VPOS in the current matrix of W, return corresponding
5461 frame-relative pixel positions in *FRAME_X and *FRAME_Y. If we
5462 can't tell the positions because W's display is not up to date,
5463 return 0. */
5466 glyph_to_pixel_coords (w, hpos, vpos, frame_x, frame_y)
5467 struct window *w;
5468 int hpos, vpos;
5469 int *frame_x, *frame_y;
5471 int success_p;
5473 xassert (hpos >= 0 && hpos < w->current_matrix->matrix_w);
5474 xassert (vpos >= 0 && vpos < w->current_matrix->matrix_h);
5476 if (display_completed)
5478 struct glyph_row *row = MATRIX_ROW (w->current_matrix, vpos);
5479 struct glyph *glyph = row->glyphs[TEXT_AREA];
5480 struct glyph *end = glyph + min (hpos, row->used[TEXT_AREA]);
5482 *frame_y = row->y;
5483 *frame_x = row->x;
5484 while (glyph < end)
5486 *frame_x += glyph->pixel_width;
5487 ++glyph;
5490 success_p = 1;
5492 else
5494 *frame_y = *frame_x = 0;
5495 success_p = 0;
5498 *frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, *frame_y);
5499 *frame_x = WINDOW_TO_FRAME_PIXEL_X (w, *frame_x);
5500 return success_p;
5503 BOOL
5504 parse_button (message, pbutton, pup)
5505 int message;
5506 int * pbutton;
5507 int * pup;
5509 int button = 0;
5510 int up = 0;
5512 switch (message)
5514 case WM_LBUTTONDOWN:
5515 button = 0;
5516 up = 0;
5517 break;
5518 case WM_LBUTTONUP:
5519 button = 0;
5520 up = 1;
5521 break;
5522 case WM_MBUTTONDOWN:
5523 if (NILP (Vw32_swap_mouse_buttons))
5524 button = 1;
5525 else
5526 button = 2;
5527 up = 0;
5528 break;
5529 case WM_MBUTTONUP:
5530 if (NILP (Vw32_swap_mouse_buttons))
5531 button = 1;
5532 else
5533 button = 2;
5534 up = 1;
5535 break;
5536 case WM_RBUTTONDOWN:
5537 if (NILP (Vw32_swap_mouse_buttons))
5538 button = 2;
5539 else
5540 button = 1;
5541 up = 0;
5542 break;
5543 case WM_RBUTTONUP:
5544 if (NILP (Vw32_swap_mouse_buttons))
5545 button = 2;
5546 else
5547 button = 1;
5548 up = 1;
5549 break;
5550 default:
5551 return (FALSE);
5554 if (pup) *pup = up;
5555 if (pbutton) *pbutton = button;
5557 return (TRUE);
5561 /* Prepare a mouse-event in *RESULT for placement in the input queue.
5563 If the event is a button press, then note that we have grabbed
5564 the mouse. */
5566 static Lisp_Object
5567 construct_mouse_click (result, msg, f)
5568 struct input_event *result;
5569 W32Msg *msg;
5570 struct frame *f;
5572 int button;
5573 int up;
5575 parse_button (msg->msg.message, &button, &up);
5577 /* Make the event type no_event; we'll change that when we decide
5578 otherwise. */
5579 result->kind = mouse_click;
5580 result->code = button;
5581 result->timestamp = msg->msg.time;
5582 result->modifiers = (msg->dwModifiers
5583 | (up
5584 ? up_modifier
5585 : down_modifier));
5587 XSETINT (result->x, LOWORD (msg->msg.lParam));
5588 XSETINT (result->y, HIWORD (msg->msg.lParam));
5589 XSETFRAME (result->frame_or_window, f);
5590 result->arg = Qnil;
5591 return Qnil;
5594 static Lisp_Object
5595 construct_mouse_wheel (result, msg, f)
5596 struct input_event *result;
5597 W32Msg *msg;
5598 struct frame *f;
5600 POINT p;
5601 result->kind = mouse_wheel;
5602 result->code = (short) HIWORD (msg->msg.wParam);
5603 result->timestamp = msg->msg.time;
5604 result->modifiers = msg->dwModifiers;
5605 p.x = LOWORD (msg->msg.lParam);
5606 p.y = HIWORD (msg->msg.lParam);
5607 ScreenToClient (msg->msg.hwnd, &p);
5608 XSETINT (result->x, p.x);
5609 XSETINT (result->y, p.y);
5610 XSETFRAME (result->frame_or_window, f);
5611 result->arg = Qnil;
5612 return Qnil;
5615 static Lisp_Object
5616 construct_drag_n_drop (result, msg, f)
5617 struct input_event *result;
5618 W32Msg *msg;
5619 struct frame *f;
5621 Lisp_Object files;
5622 Lisp_Object frame;
5623 HDROP hdrop;
5624 POINT p;
5625 WORD num_files;
5626 char *name;
5627 int i, len;
5629 result->kind = drag_n_drop;
5630 result->code = 0;
5631 result->timestamp = msg->msg.time;
5632 result->modifiers = msg->dwModifiers;
5634 hdrop = (HDROP) msg->msg.wParam;
5635 DragQueryPoint (hdrop, &p);
5637 #if 0
5638 p.x = LOWORD (msg->msg.lParam);
5639 p.y = HIWORD (msg->msg.lParam);
5640 ScreenToClient (msg->msg.hwnd, &p);
5641 #endif
5643 XSETINT (result->x, p.x);
5644 XSETINT (result->y, p.y);
5646 num_files = DragQueryFile (hdrop, 0xFFFFFFFF, NULL, 0);
5647 files = Qnil;
5649 for (i = 0; i < num_files; i++)
5651 len = DragQueryFile (hdrop, i, NULL, 0);
5652 if (len <= 0)
5653 continue;
5654 name = alloca (len + 1);
5655 DragQueryFile (hdrop, i, name, len + 1);
5656 files = Fcons (build_string (name), files);
5659 DragFinish (hdrop);
5661 XSETFRAME (frame, f);
5662 result->frame_or_window = Fcons (frame, files);
5663 result->arg = Qnil;
5664 return Qnil;
5668 /* Function to report a mouse movement to the mainstream Emacs code.
5669 The input handler calls this.
5671 We have received a mouse movement event, which is given in *event.
5672 If the mouse is over a different glyph than it was last time, tell
5673 the mainstream emacs code by setting mouse_moved. If not, ask for
5674 another motion event, so we can check again the next time it moves. */
5676 static MSG last_mouse_motion_event;
5677 static Lisp_Object last_mouse_motion_frame;
5679 static void
5680 note_mouse_movement (frame, msg)
5681 FRAME_PTR frame;
5682 MSG *msg;
5684 last_mouse_movement_time = msg->time;
5685 memcpy (&last_mouse_motion_event, msg, sizeof (last_mouse_motion_event));
5686 XSETFRAME (last_mouse_motion_frame, frame);
5688 if (msg->hwnd != FRAME_W32_WINDOW (frame))
5690 frame->mouse_moved = 1;
5691 last_mouse_scroll_bar = Qnil;
5692 note_mouse_highlight (frame, -1, -1);
5695 /* Has the mouse moved off the glyph it was on at the last sighting? */
5696 else if (LOWORD (msg->lParam) < last_mouse_glyph.left
5697 || LOWORD (msg->lParam) > last_mouse_glyph.right
5698 || HIWORD (msg->lParam) < last_mouse_glyph.top
5699 || HIWORD (msg->lParam) > last_mouse_glyph.bottom)
5701 frame->mouse_moved = 1;
5702 last_mouse_scroll_bar = Qnil;
5704 note_mouse_highlight (frame, LOWORD (msg->lParam), HIWORD (msg->lParam));
5708 /* This is used for debugging, to turn off note_mouse_highlight. */
5710 int disable_mouse_highlight;
5714 /************************************************************************
5715 Mouse Face
5716 ************************************************************************/
5718 /* Find the glyph under window-relative coordinates X/Y in window W.
5719 Consider only glyphs from buffer text, i.e. no glyphs from overlay
5720 strings. Return in *HPOS and *VPOS the row and column number of
5721 the glyph found. Return in *AREA the glyph area containing X.
5722 Value is a pointer to the glyph found or null if X/Y is not on
5723 text, or we can't tell because W's current matrix is not up to
5724 date. */
5726 static struct glyph *
5727 x_y_to_hpos_vpos (w, x, y, hpos, vpos, area)
5728 struct window *w;
5729 int x, y;
5730 int *hpos, *vpos, *area;
5732 struct glyph *glyph, *end;
5733 struct glyph_row *row = NULL;
5734 int x0, i, left_area_width;
5736 /* Find row containing Y. Give up if some row is not enabled. */
5737 for (i = 0; i < w->current_matrix->nrows; ++i)
5739 row = MATRIX_ROW (w->current_matrix, i);
5740 if (!row->enabled_p)
5741 return NULL;
5742 if (y >= row->y && y < MATRIX_ROW_BOTTOM_Y (row))
5743 break;
5746 *vpos = i;
5747 *hpos = 0;
5749 /* Give up if Y is not in the window. */
5750 if (i == w->current_matrix->nrows)
5751 return NULL;
5753 /* Get the glyph area containing X. */
5754 if (w->pseudo_window_p)
5756 *area = TEXT_AREA;
5757 x0 = 0;
5759 else
5761 left_area_width = window_box_width (w, LEFT_MARGIN_AREA);
5762 if (x < left_area_width)
5764 *area = LEFT_MARGIN_AREA;
5765 x0 = 0;
5767 else if (x < left_area_width + window_box_width (w, TEXT_AREA))
5769 *area = TEXT_AREA;
5770 x0 = row->x + left_area_width;
5772 else
5774 *area = RIGHT_MARGIN_AREA;
5775 x0 = left_area_width + window_box_width (w, TEXT_AREA);
5779 /* Find glyph containing X. */
5780 glyph = row->glyphs[*area];
5781 end = glyph + row->used[*area];
5782 while (glyph < end)
5784 if (x < x0 + glyph->pixel_width)
5786 if (w->pseudo_window_p)
5787 break;
5788 else if (BUFFERP (glyph->object))
5789 break;
5792 x0 += glyph->pixel_width;
5793 ++glyph;
5796 if (glyph == end)
5797 return NULL;
5799 *hpos = glyph - row->glyphs[*area];
5800 return glyph;
5804 /* Convert frame-relative x/y to coordinates relative to window W.
5805 Takes pseudo-windows into account. */
5807 static void
5808 frame_to_window_pixel_xy (w, x, y)
5809 struct window *w;
5810 int *x, *y;
5812 if (w->pseudo_window_p)
5814 /* A pseudo-window is always full-width, and starts at the
5815 left edge of the frame, plus a frame border. */
5816 struct frame *f = XFRAME (w->frame);
5817 *x -= FRAME_INTERNAL_BORDER_WIDTH_SAFE (f);
5818 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
5820 else
5822 *x = FRAME_TO_WINDOW_PIXEL_X (w, *x);
5823 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
5828 /* Take proper action when mouse has moved to the mode or top line of
5829 window W, x-position X. MODE_LINE_P non-zero means mouse is on the
5830 mode line. X is relative to the start of the text display area of
5831 W, so the width of bitmap areas and scroll bars must be subtracted
5832 to get a position relative to the start of the mode line. */
5834 static void
5835 note_mode_line_highlight (w, x, mode_line_p)
5836 struct window *w;
5837 int x, mode_line_p;
5839 struct frame *f = XFRAME (w->frame);
5840 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
5841 Cursor cursor = dpyinfo->vertical_scroll_bar_cursor;
5842 struct glyph_row *row;
5844 if (mode_line_p)
5845 row = MATRIX_MODE_LINE_ROW (w->current_matrix);
5846 else
5847 row = MATRIX_HEADER_LINE_ROW (w->current_matrix);
5849 if (row->enabled_p)
5851 struct glyph *glyph, *end;
5852 Lisp_Object help, map;
5853 int x0;
5855 /* Find the glyph under X. */
5856 glyph = row->glyphs[TEXT_AREA];
5857 end = glyph + row->used[TEXT_AREA];
5858 x0 = - (FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f)
5859 + FRAME_X_LEFT_FLAGS_AREA_WIDTH (f));
5860 while (glyph < end
5861 && x >= x0 + glyph->pixel_width)
5863 x0 += glyph->pixel_width;
5864 ++glyph;
5867 if (glyph < end
5868 && STRINGP (glyph->object)
5869 && XSTRING (glyph->object)->intervals
5870 && glyph->charpos >= 0
5871 && glyph->charpos < XSTRING (glyph->object)->size)
5873 /* If we're on a string with `help-echo' text property,
5874 arrange for the help to be displayed. This is done by
5875 setting the global variable help_echo to the help string. */
5876 help = Fget_text_property (make_number (glyph->charpos),
5877 Qhelp_echo, glyph->object);
5878 if (!NILP (help))
5880 help_echo = help;
5881 XSETWINDOW (help_echo_window, w);
5882 help_echo_object = glyph->object;
5883 help_echo_pos = glyph->charpos;
5886 /* Change the mouse pointer according to what is under X/Y. */
5887 map = Fget_text_property (make_number (glyph->charpos),
5888 Qlocal_map, glyph->object);
5889 if (!NILP (Fkeymapp (map)))
5890 cursor = f->output_data.w32->nontext_cursor;
5894 #if 0 /* NTEMACS_TODO: mouse cursor */
5895 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);
5896 #endif
5900 /* Take proper action when the mouse has moved to position X, Y on
5901 frame F as regards highlighting characters that have mouse-face
5902 properties. Also de-highlighting chars where the mouse was before.
5903 X and Y can be negative or out of range. */
5905 static void
5906 note_mouse_highlight (f, x, y)
5907 struct frame *f;
5908 int x, y;
5910 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
5911 int portion;
5912 Lisp_Object window;
5913 struct window *w;
5915 /* When a menu is active, don't highlight because this looks odd. */
5916 if (popup_activated ())
5917 return;
5919 if (disable_mouse_highlight
5920 || !f->glyphs_initialized_p)
5921 return;
5923 dpyinfo->mouse_face_mouse_x = x;
5924 dpyinfo->mouse_face_mouse_y = y;
5925 dpyinfo->mouse_face_mouse_frame = f;
5927 if (dpyinfo->mouse_face_defer)
5928 return;
5930 if (gc_in_progress)
5932 dpyinfo->mouse_face_deferred_gc = 1;
5933 return;
5936 /* Which window is that in? */
5937 window = window_from_coordinates (f, x, y, &portion, 1);
5939 /* If we were displaying active text in another window, clear that. */
5940 if (! EQ (window, dpyinfo->mouse_face_window))
5941 clear_mouse_face (dpyinfo);
5943 /* Not on a window -> return. */
5944 if (!WINDOWP (window))
5945 return;
5947 /* Convert to window-relative pixel coordinates. */
5948 w = XWINDOW (window);
5949 frame_to_window_pixel_xy (w, &x, &y);
5951 /* Handle tool-bar window differently since it doesn't display a
5952 buffer. */
5953 if (EQ (window, f->tool_bar_window))
5955 note_tool_bar_highlight (f, x, y);
5956 return;
5959 if (portion == 1 || portion == 3)
5961 /* Mouse is on the mode or top line. */
5962 note_mode_line_highlight (w, x, portion == 1);
5963 return;
5965 #if 0 /* NTEMACS_TODO: mouse cursor */
5966 else
5967 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5968 f->output_data.x->text_cursor);
5969 #endif
5971 /* Are we in a window whose display is up to date?
5972 And verify the buffer's text has not changed. */
5973 if (/* Within text portion of the window. */
5974 portion == 0
5975 && EQ (w->window_end_valid, w->buffer)
5976 && XFASTINT (w->last_modified) == BUF_MODIFF (XBUFFER (w->buffer))
5977 && (XFASTINT (w->last_overlay_modified)
5978 == BUF_OVERLAY_MODIFF (XBUFFER (w->buffer))))
5980 int hpos, vpos, pos, i, area;
5981 struct glyph *glyph;
5983 /* Find the glyph under X/Y. */
5984 glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, &area);
5986 /* Clear mouse face if X/Y not over text. */
5987 if (glyph == NULL
5988 || area != TEXT_AREA
5989 || !MATRIX_ROW (w->current_matrix, vpos)->displays_text_p)
5991 clear_mouse_face (dpyinfo);
5992 return;
5995 pos = glyph->charpos;
5996 xassert (w->pseudo_window_p || BUFFERP (glyph->object));
5998 /* Check for mouse-face and help-echo. */
6000 Lisp_Object mouse_face, overlay, position;
6001 Lisp_Object *overlay_vec;
6002 int len, noverlays;
6003 struct buffer *obuf;
6004 int obegv, ozv;
6006 /* If we get an out-of-range value, return now; avoid an error. */
6007 if (pos > BUF_Z (XBUFFER (w->buffer)))
6008 return;
6010 /* Make the window's buffer temporarily current for
6011 overlays_at and compute_char_face. */
6012 obuf = current_buffer;
6013 current_buffer = XBUFFER (w->buffer);
6014 obegv = BEGV;
6015 ozv = ZV;
6016 BEGV = BEG;
6017 ZV = Z;
6019 /* Is this char mouse-active or does it have help-echo? */
6020 XSETINT (position, pos);
6022 /* Put all the overlays we want in a vector in overlay_vec.
6023 Store the length in len. If there are more than 10, make
6024 enough space for all, and try again. */
6025 len = 10;
6026 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
6027 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL, 0);
6028 if (noverlays > len)
6030 len = noverlays;
6031 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
6032 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL,0);
6035 /* Sort overlays into increasing priority order. */
6036 noverlays = sort_overlays (overlay_vec, noverlays, w);
6038 /* Check mouse-face highlighting. */
6039 if (! (EQ (window, dpyinfo->mouse_face_window)
6040 && vpos >= dpyinfo->mouse_face_beg_row
6041 && vpos <= dpyinfo->mouse_face_end_row
6042 && (vpos > dpyinfo->mouse_face_beg_row
6043 || hpos >= dpyinfo->mouse_face_beg_col)
6044 && (vpos < dpyinfo->mouse_face_end_row
6045 || hpos < dpyinfo->mouse_face_end_col
6046 || dpyinfo->mouse_face_past_end)))
6048 /* Clear the display of the old active region, if any. */
6049 clear_mouse_face (dpyinfo);
6051 /* Find the highest priority overlay that has a mouse-face prop. */
6052 overlay = Qnil;
6053 for (i = noverlays - 1; i >= 0; --i)
6055 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
6056 if (!NILP (mouse_face))
6058 overlay = overlay_vec[i];
6059 break;
6063 /* If no overlay applies, get a text property. */
6064 if (NILP (overlay))
6065 mouse_face = Fget_text_property (position, Qmouse_face, w->buffer);
6067 /* Handle the overlay case. */
6068 if (! NILP (overlay))
6070 /* Find the range of text around this char that
6071 should be active. */
6072 Lisp_Object before, after;
6073 int ignore;
6075 before = Foverlay_start (overlay);
6076 after = Foverlay_end (overlay);
6077 /* Record this as the current active region. */
6078 fast_find_position (w, XFASTINT (before),
6079 &dpyinfo->mouse_face_beg_col,
6080 &dpyinfo->mouse_face_beg_row,
6081 &dpyinfo->mouse_face_beg_x,
6082 &dpyinfo->mouse_face_beg_y);
6083 dpyinfo->mouse_face_past_end
6084 = !fast_find_position (w, XFASTINT (after),
6085 &dpyinfo->mouse_face_end_col,
6086 &dpyinfo->mouse_face_end_row,
6087 &dpyinfo->mouse_face_end_x,
6088 &dpyinfo->mouse_face_end_y);
6089 dpyinfo->mouse_face_window = window;
6090 dpyinfo->mouse_face_face_id
6091 = face_at_buffer_position (w, pos, 0, 0,
6092 &ignore, pos + 1, 1);
6094 /* Display it as active. */
6095 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
6097 /* Handle the text property case. */
6098 else if (! NILP (mouse_face))
6100 /* Find the range of text around this char that
6101 should be active. */
6102 Lisp_Object before, after, beginning, end;
6103 int ignore;
6105 beginning = Fmarker_position (w->start);
6106 XSETINT (end, (BUF_Z (XBUFFER (w->buffer))
6107 - XFASTINT (w->window_end_pos)));
6108 before
6109 = Fprevious_single_property_change (make_number (pos + 1),
6110 Qmouse_face,
6111 w->buffer, beginning);
6112 after
6113 = Fnext_single_property_change (position, Qmouse_face,
6114 w->buffer, end);
6115 /* Record this as the current active region. */
6116 fast_find_position (w, XFASTINT (before),
6117 &dpyinfo->mouse_face_beg_col,
6118 &dpyinfo->mouse_face_beg_row,
6119 &dpyinfo->mouse_face_beg_x,
6120 &dpyinfo->mouse_face_beg_y);
6121 dpyinfo->mouse_face_past_end
6122 = !fast_find_position (w, XFASTINT (after),
6123 &dpyinfo->mouse_face_end_col,
6124 &dpyinfo->mouse_face_end_row,
6125 &dpyinfo->mouse_face_end_x,
6126 &dpyinfo->mouse_face_end_y);
6127 dpyinfo->mouse_face_window = window;
6128 dpyinfo->mouse_face_face_id
6129 = face_at_buffer_position (w, pos, 0, 0,
6130 &ignore, pos + 1, 1);
6132 /* Display it as active. */
6133 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
6137 /* Look for a `help-echo' property. */
6139 Lisp_Object help, overlay;
6141 /* Check overlays first. */
6142 help = Qnil;
6143 for (i = noverlays - 1; i >= 0 && NILP (help); --i)
6145 overlay = overlay_vec[i];
6146 help = Foverlay_get (overlay, Qhelp_echo);
6149 if (!NILP (help))
6151 help_echo = help;
6152 help_echo_window = window;
6153 help_echo_object = overlay;
6154 help_echo_pos = pos;
6156 else
6158 /* Try text properties. */
6159 if ((STRINGP (glyph->object)
6160 && glyph->charpos >= 0
6161 && glyph->charpos < XSTRING (glyph->object)->size)
6162 || (BUFFERP (glyph->object)
6163 && glyph->charpos >= BEGV
6164 && glyph->charpos < ZV))
6165 help = Fget_text_property (make_number (glyph->charpos),
6166 Qhelp_echo, glyph->object);
6168 if (!NILP (help))
6170 help_echo = help;
6171 help_echo_window = window;
6172 help_echo_object = glyph->object;
6173 help_echo_pos = glyph->charpos;
6178 BEGV = obegv;
6179 ZV = ozv;
6180 current_buffer = obuf;
6185 static void
6186 redo_mouse_highlight ()
6188 if (!NILP (last_mouse_motion_frame)
6189 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame)))
6190 note_mouse_highlight (XFRAME (last_mouse_motion_frame),
6191 LOWORD (last_mouse_motion_event.lParam),
6192 HIWORD (last_mouse_motion_event.lParam));
6197 /***********************************************************************
6198 Tool-bars
6199 ***********************************************************************/
6201 static int x_tool_bar_item P_ ((struct frame *, int, int,
6202 struct glyph **, int *, int *, int *));
6204 /* Tool-bar item index of the item on which a mouse button was pressed
6205 or -1. */
6207 static int last_tool_bar_item;
6210 /* Get information about the tool-bar item at position X/Y on frame F.
6211 Return in *GLYPH a pointer to the glyph of the tool-bar item in
6212 the current matrix of the tool-bar window of F, or NULL if not
6213 on a tool-bar item. Return in *PROP_IDX the index of the tool-bar
6214 item in F->current_tool_bar_items. Value is
6216 -1 if X/Y is not on a tool-bar item
6217 0 if X/Y is on the same item that was highlighted before.
6218 1 otherwise. */
6220 static int
6221 x_tool_bar_item (f, x, y, glyph, hpos, vpos, prop_idx)
6222 struct frame *f;
6223 int x, y;
6224 struct glyph **glyph;
6225 int *hpos, *vpos, *prop_idx;
6227 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
6228 struct window *w = XWINDOW (f->tool_bar_window);
6229 int area;
6231 /* Find the glyph under X/Y. */
6232 *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, &area);
6233 if (*glyph == NULL)
6234 return -1;
6236 /* Get the start of this tool-bar item's properties in
6237 f->current_tool_bar_items. */
6238 if (!tool_bar_item_info (f, *glyph, prop_idx))
6239 return -1;
6241 /* Is mouse on the highlighted item? */
6242 if (EQ (f->tool_bar_window, dpyinfo->mouse_face_window)
6243 && *vpos >= dpyinfo->mouse_face_beg_row
6244 && *vpos <= dpyinfo->mouse_face_end_row
6245 && (*vpos > dpyinfo->mouse_face_beg_row
6246 || *hpos >= dpyinfo->mouse_face_beg_col)
6247 && (*vpos < dpyinfo->mouse_face_end_row
6248 || *hpos < dpyinfo->mouse_face_end_col
6249 || dpyinfo->mouse_face_past_end))
6250 return 0;
6252 return 1;
6256 /* Handle mouse button event on the tool-bar of frame F, at
6257 frame-relative coordinates X/Y. EVENT_TYPE is either ButtionPress
6258 or ButtonRelase. */
6260 static void
6261 w32_handle_tool_bar_click (f, button_event)
6262 struct frame *f;
6263 struct input_event *button_event;
6265 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
6266 struct window *w = XWINDOW (f->tool_bar_window);
6267 int hpos, vpos, prop_idx;
6268 struct glyph *glyph;
6269 Lisp_Object enabled_p;
6270 int x = XFASTINT (button_event->x);
6271 int y = XFASTINT (button_event->y);
6273 /* If not on the highlighted tool-bar item, return. */
6274 frame_to_window_pixel_xy (w, &x, &y);
6275 if (x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx) != 0)
6276 return;
6278 /* If item is disabled, do nothing. */
6279 enabled_p = (XVECTOR (f->current_tool_bar_items)
6280 ->contents[prop_idx + TOOL_BAR_ITEM_ENABLED_P]);
6281 if (NILP (enabled_p))
6282 return;
6284 if (button_event->kind == mouse_click)
6286 /* Show item in pressed state. */
6287 show_mouse_face (dpyinfo, DRAW_IMAGE_SUNKEN);
6288 dpyinfo->mouse_face_image_state = DRAW_IMAGE_SUNKEN;
6289 last_tool_bar_item = prop_idx;
6291 else
6293 Lisp_Object key, frame;
6294 struct input_event event;
6296 /* Show item in released state. */
6297 show_mouse_face (dpyinfo, DRAW_IMAGE_RAISED);
6298 dpyinfo->mouse_face_image_state = DRAW_IMAGE_RAISED;
6300 key = (XVECTOR (f->current_tool_bar_items)
6301 ->contents[prop_idx + TOOL_BAR_ITEM_KEY]);
6303 XSETFRAME (frame, f);
6304 event.kind = TOOL_BAR_EVENT;
6305 event.frame_or_window = frame;
6306 event.arg = frame;
6307 kbd_buffer_store_event (&event);
6309 event.kind = TOOL_BAR_EVENT;
6310 event.frame_or_window = frame;
6311 event.arg = key;
6312 event.modifiers = button_event->modifiers;
6313 kbd_buffer_store_event (&event);
6314 last_tool_bar_item = -1;
6319 /* Possibly highlight a tool-bar item on frame F when mouse moves to
6320 tool-bar window-relative coordinates X/Y. Called from
6321 note_mouse_highlight. */
6323 static void
6324 note_tool_bar_highlight (f, x, y)
6325 struct frame *f;
6326 int x, y;
6328 Lisp_Object window = f->tool_bar_window;
6329 struct window *w = XWINDOW (window);
6330 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
6331 int hpos, vpos;
6332 struct glyph *glyph;
6333 struct glyph_row *row;
6334 int i;
6335 Lisp_Object enabled_p;
6336 int prop_idx;
6337 enum draw_glyphs_face draw = DRAW_IMAGE_RAISED;
6338 int mouse_down_p, rc;
6340 /* Function note_mouse_highlight is called with negative x(y
6341 values when mouse moves outside of the frame. */
6342 if (x <= 0 || y <= 0)
6344 clear_mouse_face (dpyinfo);
6345 return;
6348 rc = x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx);
6349 if (rc < 0)
6351 /* Not on tool-bar item. */
6352 clear_mouse_face (dpyinfo);
6353 return;
6355 else if (rc == 0)
6356 /* On same tool-bar item as before. */
6357 goto set_help_echo;
6359 clear_mouse_face (dpyinfo);
6361 /* Mouse is down, but on different tool-bar item? */
6362 mouse_down_p = (dpyinfo->grabbed
6363 && f == last_mouse_frame
6364 && FRAME_LIVE_P (f));
6365 if (mouse_down_p
6366 && last_tool_bar_item != prop_idx)
6367 return;
6369 dpyinfo->mouse_face_image_state = DRAW_NORMAL_TEXT;
6370 draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
6372 /* If tool-bar item is not enabled, don't highlight it. */
6373 enabled_p = (XVECTOR (f->current_tool_bar_items)
6374 ->contents[prop_idx + TOOL_BAR_ITEM_ENABLED_P]);
6375 if (!NILP (enabled_p))
6377 /* Compute the x-position of the glyph. In front and past the
6378 image is a space. We include this is the highlighted area. */
6379 row = MATRIX_ROW (w->current_matrix, vpos);
6380 for (i = x = 0; i < hpos; ++i)
6381 x += row->glyphs[TEXT_AREA][i].pixel_width;
6383 /* Record this as the current active region. */
6384 dpyinfo->mouse_face_beg_col = hpos;
6385 dpyinfo->mouse_face_beg_row = vpos;
6386 dpyinfo->mouse_face_beg_x = x;
6387 dpyinfo->mouse_face_beg_y = row->y;
6388 dpyinfo->mouse_face_past_end = 0;
6390 dpyinfo->mouse_face_end_col = hpos + 1;
6391 dpyinfo->mouse_face_end_row = vpos;
6392 dpyinfo->mouse_face_end_x = x + glyph->pixel_width;
6393 dpyinfo->mouse_face_end_y = row->y;
6394 dpyinfo->mouse_face_window = window;
6395 dpyinfo->mouse_face_face_id = TOOL_BAR_FACE_ID;
6397 /* Display it as active. */
6398 show_mouse_face (dpyinfo, draw);
6399 dpyinfo->mouse_face_image_state = draw;
6402 set_help_echo:
6404 /* Set help_echo to a help string.to display for this tool-bar item.
6405 w32_read_socket does the rest. */
6406 help_echo_object = help_echo_window = Qnil;
6407 help_echo_pos = -1;
6408 help_echo = (XVECTOR (f->current_tool_bar_items)
6409 ->contents[prop_idx + TOOL_BAR_ITEM_HELP]);
6410 if (NILP (help_echo))
6411 help_echo = (XVECTOR (f->current_tool_bar_items)
6412 ->contents[prop_idx + TOOL_BAR_ITEM_CAPTION]);
6417 /* Find the glyph matrix position of buffer position POS in window W.
6418 *HPOS, *VPOS, *X, and *Y are set to the positions found. W's
6419 current glyphs must be up to date. If POS is above window start
6420 return (0, 0, 0, 0). If POS is after end of W, return end of
6421 last line in W. */
6423 static int
6424 fast_find_position (w, pos, hpos, vpos, x, y)
6425 struct window *w;
6426 int pos;
6427 int *hpos, *vpos, *x, *y;
6429 int i;
6430 int lastcol;
6431 int maybe_next_line_p = 0;
6432 int line_start_position;
6433 int yb = window_text_bottom_y (w);
6434 struct glyph_row *row = MATRIX_ROW (w->current_matrix, 0);
6435 struct glyph_row *best_row = row;
6436 int row_vpos = 0, best_row_vpos = 0;
6437 int current_x;
6439 while (row->y < yb)
6441 if (row->used[TEXT_AREA])
6442 line_start_position = row->glyphs[TEXT_AREA]->charpos;
6443 else
6444 line_start_position = 0;
6446 if (line_start_position > pos)
6447 break;
6448 /* If the position sought is the end of the buffer,
6449 don't include the blank lines at the bottom of the window. */
6450 else if (line_start_position == pos
6451 && pos == BUF_ZV (XBUFFER (w->buffer)))
6453 maybe_next_line_p = 1;
6454 break;
6456 else if (line_start_position > 0)
6458 best_row = row;
6459 best_row_vpos = row_vpos;
6462 if (row->y + row->height >= yb)
6463 break;
6465 ++row;
6466 ++row_vpos;
6469 /* Find the right column within BEST_ROW. */
6470 lastcol = 0;
6471 current_x = best_row->x;
6472 for (i = 0; i < best_row->used[TEXT_AREA]; i++)
6474 struct glyph *glyph = best_row->glyphs[TEXT_AREA] + i;
6475 int charpos;
6477 charpos = glyph->charpos;
6478 if (charpos == pos)
6480 *hpos = i;
6481 *vpos = best_row_vpos;
6482 *x = current_x;
6483 *y = best_row->y;
6484 return 1;
6486 else if (charpos > pos)
6487 break;
6488 else if (charpos > 0)
6489 lastcol = i;
6491 current_x += glyph->pixel_width;
6494 /* If we're looking for the end of the buffer,
6495 and we didn't find it in the line we scanned,
6496 use the start of the following line. */
6497 if (maybe_next_line_p)
6499 ++best_row;
6500 ++best_row_vpos;
6501 lastcol = 0;
6502 current_x = best_row->x;
6505 *vpos = best_row_vpos;
6506 *hpos = lastcol + 1;
6507 *x = current_x;
6508 *y = best_row->y;
6509 return 0;
6513 /* Display the active region described by mouse_face_*
6514 in its mouse-face if HL > 0, in its normal face if HL = 0. */
6516 static void
6517 show_mouse_face (dpyinfo, draw)
6518 struct w32_display_info *dpyinfo;
6519 enum draw_glyphs_face draw;
6521 struct window *w = XWINDOW (dpyinfo->mouse_face_window);
6522 struct frame *f = XFRAME (WINDOW_FRAME (w));
6523 int i;
6524 int cursor_off_p = 0;
6525 struct cursor_pos saved_cursor;
6527 saved_cursor = output_cursor;
6529 /* If window is in the process of being destroyed, don't bother
6530 to do anything. */
6531 if (w->current_matrix == NULL)
6532 goto set_x_cursor;
6534 /* Recognize when we are called to operate on rows that don't exist
6535 anymore. This can happen when a window is split. */
6536 if (dpyinfo->mouse_face_end_row >= w->current_matrix->nrows)
6537 goto set_x_cursor;
6539 set_output_cursor (&w->phys_cursor);
6541 /* Note that mouse_face_beg_row etc. are window relative. */
6542 for (i = dpyinfo->mouse_face_beg_row;
6543 i <= dpyinfo->mouse_face_end_row;
6544 i++)
6546 int start_hpos, end_hpos, start_x;
6547 struct glyph_row *row = MATRIX_ROW (w->current_matrix, i);
6549 /* Don't do anything if row doesn't have valid contents. */
6550 if (!row->enabled_p)
6551 continue;
6553 /* For all but the first row, the highlight starts at column 0. */
6554 if (i == dpyinfo->mouse_face_beg_row)
6556 start_hpos = dpyinfo->mouse_face_beg_col;
6557 start_x = dpyinfo->mouse_face_beg_x;
6559 else
6561 start_hpos = 0;
6562 start_x = 0;
6565 if (i == dpyinfo->mouse_face_end_row)
6566 end_hpos = dpyinfo->mouse_face_end_col;
6567 else
6568 end_hpos = row->used[TEXT_AREA];
6570 /* If the cursor's in the text we are about to rewrite, turn the
6571 cursor off. */
6572 if (!w->pseudo_window_p
6573 && i == output_cursor.vpos
6574 && output_cursor.hpos >= start_hpos - 1
6575 && output_cursor.hpos <= end_hpos)
6577 x_update_window_cursor (w, 0);
6578 cursor_off_p = 1;
6581 if (end_hpos > start_hpos)
6583 row->mouse_face_p = draw == DRAW_MOUSE_FACE;
6584 x_draw_glyphs (w, start_x, row, TEXT_AREA,
6585 start_hpos, end_hpos, draw, NULL, NULL, 0);
6589 /* If we turned the cursor off, turn it back on. */
6590 if (cursor_off_p)
6591 x_display_cursor (w, 1,
6592 output_cursor.hpos, output_cursor.vpos,
6593 output_cursor.x, output_cursor.y);
6595 output_cursor = saved_cursor;
6597 set_x_cursor:
6598 #if 0 /* NTEMACS_TODO: mouse cursor */
6599 /* Change the mouse cursor. */
6600 if (draw == DRAW_NORMAL_TEXT)
6601 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
6602 f->output_data.x->text_cursor);
6603 else if (draw == DRAW_MOUSE_FACE)
6604 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
6605 f->output_data.x->cross_cursor);
6606 else
6607 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
6608 f->output_data.x->nontext_cursor);
6609 #endif
6613 /* Clear out the mouse-highlighted active region.
6614 Redraw it un-highlighted first. */
6616 void
6617 clear_mouse_face (dpyinfo)
6618 struct w32_display_info *dpyinfo;
6620 if (tip_frame)
6621 return;
6623 if (! NILP (dpyinfo->mouse_face_window))
6624 show_mouse_face (dpyinfo, DRAW_NORMAL_TEXT);
6626 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
6627 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
6628 dpyinfo->mouse_face_window = Qnil;
6632 /* Clear any mouse-face on window W. This function is part of the
6633 redisplay interface, and is called from try_window_id and similar
6634 functions to ensure the mouse-highlight is off. */
6636 static void
6637 x_clear_mouse_face (w)
6638 struct window *w;
6640 struct w32_display_info *dpyinfo
6641 = FRAME_W32_DISPLAY_INFO (XFRAME (w->frame));
6642 Lisp_Object window;
6644 BLOCK_INPUT;
6645 XSETWINDOW (window, w);
6646 if (EQ (window, dpyinfo->mouse_face_window))
6647 clear_mouse_face (dpyinfo);
6648 UNBLOCK_INPUT;
6652 /* Just discard the mouse face information for frame F, if any.
6653 This is used when the size of F is changed. */
6655 void
6656 cancel_mouse_face (f)
6657 FRAME_PTR f;
6659 Lisp_Object window;
6660 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
6662 window = dpyinfo->mouse_face_window;
6663 if (! NILP (window) && XFRAME (XWINDOW (window)->frame) == f)
6665 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
6666 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
6667 dpyinfo->mouse_face_window = Qnil;
6671 static struct scroll_bar *x_window_to_scroll_bar ();
6672 static void x_scroll_bar_report_motion ();
6674 /* Return the current position of the mouse.
6675 *fp should be a frame which indicates which display to ask about.
6677 If the mouse movement started in a scroll bar, set *fp, *bar_window,
6678 and *part to the frame, window, and scroll bar part that the mouse
6679 is over. Set *x and *y to the portion and whole of the mouse's
6680 position on the scroll bar.
6682 If the mouse movement started elsewhere, set *fp to the frame the
6683 mouse is on, *bar_window to nil, and *x and *y to the character cell
6684 the mouse is over.
6686 Set *time to the server time-stamp for the time at which the mouse
6687 was at this position.
6689 Don't store anything if we don't have a valid set of values to report.
6691 This clears the mouse_moved flag, so we can wait for the next mouse
6692 movement. */
6694 static void
6695 w32_mouse_position (fp, insist, bar_window, part, x, y, time)
6696 FRAME_PTR *fp;
6697 int insist;
6698 Lisp_Object *bar_window;
6699 enum scroll_bar_part *part;
6700 Lisp_Object *x, *y;
6701 unsigned long *time;
6703 FRAME_PTR f1;
6705 BLOCK_INPUT;
6707 if (! NILP (last_mouse_scroll_bar) && insist == 0)
6708 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
6709 else
6711 POINT pt;
6713 Lisp_Object frame, tail;
6715 /* Clear the mouse-moved flag for every frame on this display. */
6716 FOR_EACH_FRAME (tail, frame)
6717 XFRAME (frame)->mouse_moved = 0;
6719 last_mouse_scroll_bar = Qnil;
6721 GetCursorPos (&pt);
6723 /* Now we have a position on the root; find the innermost window
6724 containing the pointer. */
6726 if (FRAME_W32_DISPLAY_INFO (*fp)->grabbed && last_mouse_frame
6727 && FRAME_LIVE_P (last_mouse_frame))
6729 /* If mouse was grabbed on a frame, give coords for that frame
6730 even if the mouse is now outside it. */
6731 f1 = last_mouse_frame;
6733 else
6735 /* Is window under mouse one of our frames? */
6736 f1 = x_window_to_frame (FRAME_W32_DISPLAY_INFO (*fp),
6737 WindowFromPoint (pt));
6740 /* If not, is it one of our scroll bars? */
6741 if (! f1)
6743 struct scroll_bar *bar
6744 = x_window_to_scroll_bar (WindowFromPoint (pt));
6746 if (bar)
6748 f1 = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
6752 if (f1 == 0 && insist > 0)
6753 f1 = SELECTED_FRAME ();
6755 if (f1)
6757 /* Ok, we found a frame. Store all the values.
6758 last_mouse_glyph is a rectangle used to reduce the
6759 generation of mouse events. To not miss any motion
6760 events, we must divide the frame into rectangles of the
6761 size of the smallest character that could be displayed
6762 on it, i.e. into the same rectangles that matrices on
6763 the frame are divided into. */
6765 #if OLD_REDISPLAY_CODE
6766 int ignore1, ignore2;
6768 ScreenToClient (FRAME_W32_WINDOW (f1), &pt);
6770 pixel_to_glyph_coords (f1, pt.x, pt.y, &ignore1, &ignore2,
6771 &last_mouse_glyph,
6772 FRAME_W32_DISPLAY_INFO (f1)->grabbed
6773 || insist);
6774 #else
6775 ScreenToClient (FRAME_W32_WINDOW (f1), &pt);
6777 int width = FRAME_SMALLEST_CHAR_WIDTH (f1);
6778 int height = FRAME_SMALLEST_FONT_HEIGHT (f1);
6779 int x = pt.x;
6780 int y = pt.y;
6782 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to
6783 round down even for negative values. */
6784 if (x < 0)
6785 x -= width - 1;
6786 if (y < 0)
6787 y -= height - 1;
6789 last_mouse_glyph.left = (x + width - 1) / width * width;
6790 last_mouse_glyph.top = (y + height - 1) / height * height;
6791 last_mouse_glyph.right = last_mouse_glyph.left + width;
6792 last_mouse_glyph.bottom = last_mouse_glyph.top + height;
6794 #endif
6796 *bar_window = Qnil;
6797 *part = 0;
6798 *fp = f1;
6799 XSETINT (*x, pt.x);
6800 XSETINT (*y, pt.y);
6801 *time = last_mouse_movement_time;
6806 UNBLOCK_INPUT;
6810 /* Scroll bar support. */
6812 /* Given a window ID, find the struct scroll_bar which manages it.
6813 This can be called in GC, so we have to make sure to strip off mark
6814 bits. */
6816 static struct scroll_bar *
6817 x_window_to_scroll_bar (window_id)
6818 Window window_id;
6820 Lisp_Object tail;
6822 for (tail = Vframe_list;
6823 XGCTYPE (tail) == Lisp_Cons;
6824 tail = XCDR (tail))
6826 Lisp_Object frame, bar, condemned;
6828 frame = XCAR (tail);
6829 /* All elements of Vframe_list should be frames. */
6830 if (! GC_FRAMEP (frame))
6831 abort ();
6833 /* Scan this frame's scroll bar list for a scroll bar with the
6834 right window ID. */
6835 condemned = FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame));
6836 for (bar = FRAME_SCROLL_BARS (XFRAME (frame));
6837 /* This trick allows us to search both the ordinary and
6838 condemned scroll bar lists with one loop. */
6839 ! GC_NILP (bar) || (bar = condemned,
6840 condemned = Qnil,
6841 ! GC_NILP (bar));
6842 bar = XSCROLL_BAR (bar)->next)
6843 if (SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar)) == window_id)
6844 return XSCROLL_BAR (bar);
6847 return 0;
6852 /* Set the thumb size and position of scroll bar BAR. We are currently
6853 displaying PORTION out of a whole WHOLE, and our position POSITION. */
6855 static void
6856 w32_set_scroll_bar_thumb (bar, portion, position, whole)
6857 struct scroll_bar *bar;
6858 int portion, position, whole;
6860 Window w = SCROLL_BAR_W32_WINDOW (bar);
6861 int range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
6862 int sb_page, sb_pos;
6863 BOOL draggingp = !NILP (bar->dragging) ? TRUE : FALSE;
6865 if (whole)
6867 /* Position scroll bar at rock bottom if the bottom of the
6868 buffer is visible. This avoids shinking the thumb away
6869 to nothing if it is held at the bottom of the buffer. */
6870 if (position + portion >= whole)
6872 sb_page = range * (whole - position) / whole
6873 + VERTICAL_SCROLL_BAR_MIN_HANDLE;
6874 sb_pos = range;
6877 sb_page = portion * range / whole + VERTICAL_SCROLL_BAR_MIN_HANDLE;
6878 sb_pos = position * range / whole;
6880 else
6882 sb_page = range;
6883 sb_pos = 0;
6886 BLOCK_INPUT;
6888 if (pfnSetScrollInfo)
6890 SCROLLINFO si;
6892 si.cbSize = sizeof (si);
6893 /* Only update page size if currently dragging, to reduce
6894 flicker effects. */
6895 if (draggingp)
6896 si.fMask = SIF_PAGE;
6897 else
6898 si.fMask = SIF_PAGE | SIF_POS;
6899 si.nPage = sb_page;
6900 si.nPos = sb_pos;
6902 pfnSetScrollInfo (w, SB_CTL, &si, !draggingp);
6904 else
6905 SetScrollPos (w, SB_CTL, sb_pos, !draggingp);
6907 UNBLOCK_INPUT;
6911 /************************************************************************
6912 Scroll bars, general
6913 ************************************************************************/
6915 HWND
6916 my_create_scrollbar (f, bar)
6917 struct frame * f;
6918 struct scroll_bar * bar;
6920 return (HWND) SendMessage (FRAME_W32_WINDOW (f),
6921 WM_EMACS_CREATESCROLLBAR, (WPARAM) f,
6922 (LPARAM) bar);
6925 //#define ATTACH_THREADS
6927 BOOL
6928 my_show_window (FRAME_PTR f, HWND hwnd, int how)
6930 #ifndef ATTACH_THREADS
6931 return SendMessage (FRAME_W32_WINDOW (f), WM_EMACS_SHOWWINDOW,
6932 (WPARAM) hwnd, (LPARAM) how);
6933 #else
6934 return ShowWindow (hwnd, how);
6935 #endif
6938 void
6939 my_set_window_pos (HWND hwnd, HWND hwndAfter,
6940 int x, int y, int cx, int cy, UINT flags)
6942 #ifndef ATTACH_THREADS
6943 WINDOWPOS pos;
6944 pos.hwndInsertAfter = hwndAfter;
6945 pos.x = x;
6946 pos.y = y;
6947 pos.cx = cx;
6948 pos.cy = cy;
6949 pos.flags = flags;
6950 SendMessage (hwnd, WM_EMACS_SETWINDOWPOS, (WPARAM) &pos, 0);
6951 #else
6952 SetWindowPos (hwnd, hwndAfter, x, y, cx, cy, flags);
6953 #endif
6956 void
6957 my_set_focus (f, hwnd)
6958 struct frame * f;
6959 HWND hwnd;
6961 SendMessage (FRAME_W32_WINDOW (f), WM_EMACS_SETFOCUS,
6962 (WPARAM) hwnd, 0);
6965 void
6966 my_set_foreground_window (hwnd)
6967 HWND hwnd;
6969 SendMessage (hwnd, WM_EMACS_SETFOREGROUND, (WPARAM) hwnd, 0);
6972 void
6973 my_destroy_window (f, hwnd)
6974 struct frame * f;
6975 HWND hwnd;
6977 SendMessage (FRAME_W32_WINDOW (f), WM_EMACS_DESTROYWINDOW,
6978 (WPARAM) hwnd, 0);
6981 /* Create a scroll bar and return the scroll bar vector for it. W is
6982 the Emacs window on which to create the scroll bar. TOP, LEFT,
6983 WIDTH and HEIGHT are.the pixel coordinates and dimensions of the
6984 scroll bar. */
6986 static struct scroll_bar *
6987 x_scroll_bar_create (w, top, left, width, height)
6988 struct window *w;
6989 int top, left, width, height;
6991 struct frame *f = XFRAME (WINDOW_FRAME (w));
6992 HWND hwnd;
6993 struct scroll_bar *bar
6994 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
6996 BLOCK_INPUT;
6998 XSETWINDOW (bar->window, w);
6999 XSETINT (bar->top, top);
7000 XSETINT (bar->left, left);
7001 XSETINT (bar->width, width);
7002 XSETINT (bar->height, height);
7003 XSETINT (bar->start, 0);
7004 XSETINT (bar->end, 0);
7005 bar->dragging = Qnil;
7007 /* Requires geometry to be set before call to create the real window */
7009 hwnd = my_create_scrollbar (f, bar);
7011 if (pfnSetScrollInfo)
7013 SCROLLINFO si;
7015 si.cbSize = sizeof (si);
7016 si.fMask = SIF_ALL;
7017 si.nMin = 0;
7018 si.nMax = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height)
7019 + VERTICAL_SCROLL_BAR_MIN_HANDLE;
7020 si.nPage = si.nMax;
7021 si.nPos = 0;
7023 pfnSetScrollInfo (hwnd, SB_CTL, &si, FALSE);
7025 else
7027 SetScrollRange (hwnd, SB_CTL, 0,
7028 VERTICAL_SCROLL_BAR_TOP_RANGE (f, height), FALSE);
7029 SetScrollPos (hwnd, SB_CTL, 0, FALSE);
7032 SET_SCROLL_BAR_W32_WINDOW (bar, hwnd);
7034 /* Add bar to its frame's list of scroll bars. */
7035 bar->next = FRAME_SCROLL_BARS (f);
7036 bar->prev = Qnil;
7037 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
7038 if (! NILP (bar->next))
7039 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
7041 UNBLOCK_INPUT;
7043 return bar;
7047 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
7048 nil. */
7050 static void
7051 x_scroll_bar_remove (bar)
7052 struct scroll_bar *bar;
7054 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
7056 BLOCK_INPUT;
7058 /* Destroy the window. */
7059 my_destroy_window (f, SCROLL_BAR_W32_WINDOW (bar));
7061 /* Disassociate this scroll bar from its window. */
7062 XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
7064 UNBLOCK_INPUT;
7067 /* Set the handle of the vertical scroll bar for WINDOW to indicate
7068 that we are displaying PORTION characters out of a total of WHOLE
7069 characters, starting at POSITION. If WINDOW has no scroll bar,
7070 create one. */
7071 static void
7072 w32_set_vertical_scroll_bar (w, portion, whole, position)
7073 struct window *w;
7074 int portion, whole, position;
7076 struct frame *f = XFRAME (w->frame);
7077 struct scroll_bar *bar;
7078 int top, height, left, sb_left, width, sb_width;
7079 int window_x, window_y, window_width, window_height;
7081 /* Get window dimensions. */
7082 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
7083 top = window_y;
7084 width = FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f);
7085 height = window_height;
7087 /* Compute the left edge of the scroll bar area. */
7088 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
7089 left = XINT (w->left) + XINT (w->width) - FRAME_SCROLL_BAR_COLS (f);
7090 else
7091 left = XFASTINT (w->left);
7092 left *= CANON_X_UNIT (f);
7093 left += FRAME_INTERNAL_BORDER_WIDTH (f);
7095 /* Compute the width of the scroll bar which might be less than
7096 the width of the area reserved for the scroll bar. */
7097 if (FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0)
7098 sb_width = FRAME_SCROLL_BAR_PIXEL_WIDTH (f);
7099 else
7100 sb_width = width;
7102 /* Compute the left edge of the scroll bar. */
7103 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
7104 sb_left = left + width - sb_width - (width - sb_width) / 2;
7105 else
7106 sb_left = left + (width - sb_width) / 2;
7108 /* Does the scroll bar exist yet? */
7109 if (NILP (w->vertical_scroll_bar))
7111 HDC hdc;
7112 BLOCK_INPUT;
7113 hdc = get_frame_dc (f);
7114 w32_clear_area (f, hdc, left, top, width, height);
7115 release_frame_dc (f, hdc);
7116 UNBLOCK_INPUT;
7118 bar = x_scroll_bar_create (w, top, sb_left, sb_width, height);
7120 else
7122 /* It may just need to be moved and resized. */
7123 HWND hwnd;
7125 bar = XSCROLL_BAR (w->vertical_scroll_bar);
7126 hwnd = SCROLL_BAR_W32_WINDOW (bar);
7128 /* If already correctly positioned, do nothing. */
7129 if ( XINT (bar->left) == sb_left
7130 && XINT (bar->top) == top
7131 && XINT (bar->width) == sb_width
7132 && XINT (bar->height) == height )
7134 /* Redraw after clear_frame. */
7135 if (!my_show_window (f, hwnd, SW_NORMAL))
7136 InvalidateRect (hwnd, NULL, FALSE);
7138 else
7140 HDC hdc;
7141 BLOCK_INPUT;
7143 hdc = get_frame_dc (f);
7144 /* Since Windows scroll bars are smaller than the space reserved
7145 for them on the frame, we have to clear "under" them. */
7146 w32_clear_area (f, hdc,
7147 left,
7148 top,
7149 width,
7150 height);
7151 release_frame_dc (f, hdc);
7153 /* Make sure scroll bar is "visible" before moving, to ensure the
7154 area of the parent window now exposed will be refreshed. */
7155 my_show_window (f, hwnd, SW_HIDE);
7156 MoveWindow (hwnd, sb_left, top,
7157 sb_width, height, TRUE);
7158 if (pfnSetScrollInfo)
7160 SCROLLINFO si;
7162 si.cbSize = sizeof (si);
7163 si.fMask = SIF_RANGE;
7164 si.nMin = 0;
7165 si.nMax = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height)
7166 + VERTICAL_SCROLL_BAR_MIN_HANDLE;
7168 pfnSetScrollInfo (hwnd, SB_CTL, &si, FALSE);
7170 else
7171 SetScrollRange (hwnd, SB_CTL, 0,
7172 VERTICAL_SCROLL_BAR_TOP_RANGE (f, height), FALSE);
7173 my_show_window (f, hwnd, SW_NORMAL);
7174 // InvalidateRect (w, NULL, FALSE);
7176 /* Remember new settings. */
7177 XSETINT (bar->left, sb_left);
7178 XSETINT (bar->top, top);
7179 XSETINT (bar->width, sb_width);
7180 XSETINT (bar->height, height);
7182 UNBLOCK_INPUT;
7185 w32_set_scroll_bar_thumb (bar, portion, position, whole);
7187 XSETVECTOR (w->vertical_scroll_bar, bar);
7191 /* The following three hooks are used when we're doing a thorough
7192 redisplay of the frame. We don't explicitly know which scroll bars
7193 are going to be deleted, because keeping track of when windows go
7194 away is a real pain - "Can you say set-window-configuration, boys
7195 and girls?" Instead, we just assert at the beginning of redisplay
7196 that *all* scroll bars are to be removed, and then save a scroll bar
7197 from the fiery pit when we actually redisplay its window. */
7199 /* Arrange for all scroll bars on FRAME to be removed at the next call
7200 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
7201 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
7203 static void
7204 w32_condemn_scroll_bars (frame)
7205 FRAME_PTR frame;
7207 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
7208 while (! NILP (FRAME_SCROLL_BARS (frame)))
7210 Lisp_Object bar;
7211 bar = FRAME_SCROLL_BARS (frame);
7212 FRAME_SCROLL_BARS (frame) = XSCROLL_BAR (bar)->next;
7213 XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
7214 XSCROLL_BAR (bar)->prev = Qnil;
7215 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
7216 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
7217 FRAME_CONDEMNED_SCROLL_BARS (frame) = bar;
7221 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
7222 Note that WINDOW isn't necessarily condemned at all. */
7223 static void
7224 w32_redeem_scroll_bar (window)
7225 struct window *window;
7227 struct scroll_bar *bar;
7229 /* We can't redeem this window's scroll bar if it doesn't have one. */
7230 if (NILP (window->vertical_scroll_bar))
7231 abort ();
7233 bar = XSCROLL_BAR (window->vertical_scroll_bar);
7235 /* Unlink it from the condemned list. */
7237 FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
7239 if (NILP (bar->prev))
7241 /* If the prev pointer is nil, it must be the first in one of
7242 the lists. */
7243 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
7244 /* It's not condemned. Everything's fine. */
7245 return;
7246 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
7247 window->vertical_scroll_bar))
7248 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
7249 else
7250 /* If its prev pointer is nil, it must be at the front of
7251 one or the other! */
7252 abort ();
7254 else
7255 XSCROLL_BAR (bar->prev)->next = bar->next;
7257 if (! NILP (bar->next))
7258 XSCROLL_BAR (bar->next)->prev = bar->prev;
7260 bar->next = FRAME_SCROLL_BARS (f);
7261 bar->prev = Qnil;
7262 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
7263 if (! NILP (bar->next))
7264 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
7268 /* Remove all scroll bars on FRAME that haven't been saved since the
7269 last call to `*condemn_scroll_bars_hook'. */
7271 static void
7272 w32_judge_scroll_bars (f)
7273 FRAME_PTR f;
7275 Lisp_Object bar, next;
7277 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
7279 /* Clear out the condemned list now so we won't try to process any
7280 more events on the hapless scroll bars. */
7281 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
7283 for (; ! NILP (bar); bar = next)
7285 struct scroll_bar *b = XSCROLL_BAR (bar);
7287 x_scroll_bar_remove (b);
7289 next = b->next;
7290 b->next = b->prev = Qnil;
7293 /* Now there should be no references to the condemned scroll bars,
7294 and they should get garbage-collected. */
7297 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
7298 is set to something other than no_event, it is enqueued.
7300 This may be called from a signal handler, so we have to ignore GC
7301 mark bits. */
7303 static int
7304 x_scroll_bar_handle_click (bar, msg, emacs_event)
7305 struct scroll_bar *bar;
7306 W32Msg *msg;
7307 struct input_event *emacs_event;
7309 if (! GC_WINDOWP (bar->window))
7310 abort ();
7312 emacs_event->kind = w32_scroll_bar_click;
7313 emacs_event->code = 0;
7314 /* not really meaningful to distinguish up/down */
7315 emacs_event->modifiers = msg->dwModifiers;
7316 emacs_event->frame_or_window = bar->window;
7317 emacs_event->arg = Qnil;
7318 emacs_event->timestamp = msg->msg.time;
7321 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
7322 int y;
7323 int dragging = !NILP (bar->dragging);
7325 if (pfnGetScrollInfo)
7327 SCROLLINFO si;
7329 si.cbSize = sizeof (si);
7330 si.fMask = SIF_POS;
7332 pfnGetScrollInfo ((HWND) msg->msg.lParam, SB_CTL, &si);
7333 y = si.nPos;
7335 else
7336 y = GetScrollPos ((HWND) msg->msg.lParam, SB_CTL);
7338 bar->dragging = Qnil;
7341 last_mouse_scroll_bar_pos = msg->msg.wParam;
7343 switch (LOWORD (msg->msg.wParam))
7345 case SB_LINEDOWN:
7346 emacs_event->part = scroll_bar_down_arrow;
7347 break;
7348 case SB_LINEUP:
7349 emacs_event->part = scroll_bar_up_arrow;
7350 break;
7351 case SB_PAGEUP:
7352 emacs_event->part = scroll_bar_above_handle;
7353 break;
7354 case SB_PAGEDOWN:
7355 emacs_event->part = scroll_bar_below_handle;
7356 break;
7357 case SB_TOP:
7358 emacs_event->part = scroll_bar_handle;
7359 y = 0;
7360 break;
7361 case SB_BOTTOM:
7362 emacs_event->part = scroll_bar_handle;
7363 y = top_range;
7364 break;
7365 case SB_THUMBTRACK:
7366 case SB_THUMBPOSITION:
7367 if (VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height)) <= 0xffff)
7368 y = HIWORD (msg->msg.wParam);
7369 bar->dragging = Qt;
7370 emacs_event->part = scroll_bar_handle;
7372 /* "Silently" update current position. */
7373 if (pfnSetScrollInfo)
7375 SCROLLINFO si;
7377 si.cbSize = sizeof (si);
7378 si.fMask = SIF_POS;
7379 si.nPos = y;
7380 /* Remember apparent position (we actually lag behind the real
7381 position, so don't set that directly. */
7382 last_scroll_bar_drag_pos = y;
7384 pfnSetScrollInfo (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, &si, FALSE);
7386 else
7387 SetScrollPos (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, y, FALSE);
7388 break;
7389 case SB_ENDSCROLL:
7390 /* If this is the end of a drag sequence, then reset the scroll
7391 handle size to normal and do a final redraw. Otherwise do
7392 nothing. */
7393 if (dragging)
7395 if (pfnSetScrollInfo)
7397 SCROLLINFO si;
7398 int start = XINT (bar->start);
7399 int end = XINT (bar->end);
7401 si.cbSize = sizeof (si);
7402 si.fMask = SIF_PAGE | SIF_POS;
7403 si.nPage = end - start + VERTICAL_SCROLL_BAR_MIN_HANDLE;
7404 si.nPos = last_scroll_bar_drag_pos;
7405 pfnSetScrollInfo (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, &si, TRUE);
7407 else
7408 SetScrollPos (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, y, TRUE);
7410 /* fall through */
7411 default:
7412 emacs_event->kind = no_event;
7413 return FALSE;
7416 XSETINT (emacs_event->x, y);
7417 XSETINT (emacs_event->y, top_range);
7419 return TRUE;
7423 /* Return information to the user about the current position of the mouse
7424 on the scroll bar. */
7426 static void
7427 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
7428 FRAME_PTR *fp;
7429 Lisp_Object *bar_window;
7430 enum scroll_bar_part *part;
7431 Lisp_Object *x, *y;
7432 unsigned long *time;
7434 struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
7435 Window w = SCROLL_BAR_W32_WINDOW (bar);
7436 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
7437 int pos;
7438 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
7440 BLOCK_INPUT;
7442 *fp = f;
7443 *bar_window = bar->window;
7445 if (pfnGetScrollInfo)
7447 SCROLLINFO si;
7449 si.cbSize = sizeof (si);
7450 si.fMask = SIF_POS | SIF_PAGE | SIF_RANGE;
7452 pfnGetScrollInfo (w, SB_CTL, &si);
7453 pos = si.nPos;
7454 top_range = si.nMax - si.nPage + 1;
7456 else
7457 pos = GetScrollPos (w, SB_CTL);
7459 switch (LOWORD (last_mouse_scroll_bar_pos))
7461 case SB_THUMBPOSITION:
7462 case SB_THUMBTRACK:
7463 *part = scroll_bar_handle;
7464 if (VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height)) <= 0xffff)
7465 pos = HIWORD (last_mouse_scroll_bar_pos);
7466 break;
7467 case SB_LINEDOWN:
7468 *part = scroll_bar_handle;
7469 pos++;
7470 break;
7471 default:
7472 *part = scroll_bar_handle;
7473 break;
7476 XSETINT (*x, pos);
7477 XSETINT (*y, top_range);
7479 f->mouse_moved = 0;
7480 last_mouse_scroll_bar = Qnil;
7482 *time = last_mouse_movement_time;
7484 UNBLOCK_INPUT;
7488 /* The screen has been cleared so we may have changed foreground or
7489 background colors, and the scroll bars may need to be redrawn.
7490 Clear out the scroll bars, and ask for expose events, so we can
7491 redraw them. */
7493 void
7494 x_scroll_bar_clear (f)
7495 FRAME_PTR f;
7497 Lisp_Object bar;
7499 /* We can have scroll bars even if this is 0,
7500 if we just turned off scroll bar mode.
7501 But in that case we should not clear them. */
7502 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
7503 for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar);
7504 bar = XSCROLL_BAR (bar)->next)
7506 HWND window = SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar));
7507 HDC hdc = GetDC (window);
7508 RECT rect;
7510 /* Hide scroll bar until ready to repaint. x_scroll_bar_move
7511 arranges to refresh the scroll bar if hidden. */
7512 my_show_window (f, window, SW_HIDE);
7514 GetClientRect (window, &rect);
7515 select_palette (f, hdc);
7516 w32_clear_rect (f, hdc, &rect);
7517 deselect_palette (f, hdc);
7519 ReleaseDC (window, hdc);
7523 show_scroll_bars (f, how)
7524 FRAME_PTR f;
7525 int how;
7527 Lisp_Object bar;
7529 for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar);
7530 bar = XSCROLL_BAR (bar)->next)
7532 HWND window = SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar));
7533 my_show_window (f, window, how);
7538 /* The main W32 event-reading loop - w32_read_socket. */
7540 /* Time stamp of enter window event. This is only used by w32_read_socket,
7541 but we have to put it out here, since static variables within functions
7542 sometimes don't work. */
7544 static Time enter_timestamp;
7546 /* Record the last 100 characters stored
7547 to help debug the loss-of-chars-during-GC problem. */
7549 static int temp_index;
7550 static short temp_buffer[100];
7553 /* Read events coming from the W32 shell.
7554 This routine is called by the SIGIO handler.
7555 We return as soon as there are no more events to be read.
7557 Events representing keys are stored in buffer BUFP,
7558 which can hold up to NUMCHARS characters.
7559 We return the number of characters stored into the buffer,
7560 thus pretending to be `read'.
7562 EXPECTED is nonzero if the caller knows input is available.
7564 Some of these messages are reposted back to the message queue since the
7565 system calls the windows proc directly in a context where we cannot return
7566 the data nor can we guarantee the state we are in. So if we dispatch them
7567 we will get into an infinite loop. To prevent this from ever happening we
7568 will set a variable to indicate we are in the read_socket call and indicate
7569 which message we are processing since the windows proc gets called
7570 recursively with different messages by the system.
7574 w32_read_socket (sd, bufp, numchars, expected)
7575 register int sd;
7576 /* register */ struct input_event *bufp;
7577 /* register */ int numchars;
7578 int expected;
7580 int count = 0;
7581 int check_visibility = 0;
7582 W32Msg msg;
7583 struct frame *f;
7584 struct w32_display_info *dpyinfo = &one_w32_display_info;
7586 if (interrupt_input_blocked)
7588 interrupt_input_pending = 1;
7589 return -1;
7592 interrupt_input_pending = 0;
7593 BLOCK_INPUT;
7595 /* So people can tell when we have read the available input. */
7596 input_signal_count++;
7598 if (numchars <= 0)
7599 abort (); /* Don't think this happens. */
7601 /* NTEMACS_TODO: tooltips, tool-bars, ghostscript integration, mouse
7602 cursors. */
7603 while (get_next_msg (&msg, FALSE))
7605 switch (msg.msg.message)
7607 case WM_PAINT:
7608 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
7610 if (f)
7612 if (msg.rect.right == msg.rect.left ||
7613 msg.rect.bottom == msg.rect.top)
7615 /* We may get paint messages even though the client
7616 area is clipped - these are not expose events. */
7617 DebPrint (("clipped frame %04x (%s) got WM_PAINT\n", f,
7618 XSTRING (f->name)->data));
7620 else if (f->async_visible != 1)
7622 /* Definitely not obscured, so mark as visible. */
7623 f->async_visible = 1;
7624 f->async_iconified = 0;
7625 SET_FRAME_GARBAGED (f);
7626 DebPrint (("frame %04x (%s) reexposed\n", f,
7627 XSTRING (f->name)->data));
7629 /* WM_PAINT serves as MapNotify as well, so report
7630 visibility changes properly. */
7631 if (f->iconified)
7633 bufp->kind = deiconify_event;
7634 XSETFRAME (bufp->frame_or_window, f);
7635 bufp->arg = Qnil;
7636 bufp++;
7637 count++;
7638 numchars--;
7640 else if (! NILP (Vframe_list)
7641 && ! NILP (XCDR (Vframe_list)))
7642 /* Force a redisplay sooner or later to update the
7643 frame titles in case this is the second frame. */
7644 record_asynch_buffer_change ();
7646 else
7648 HDC hdc = get_frame_dc (f);
7650 /* Erase background again for safety. */
7651 w32_clear_rect (f, hdc, &msg.rect);
7652 release_frame_dc (f, hdc);
7653 expose_frame (f,
7654 msg.rect.left,
7655 msg.rect.top,
7656 msg.rect.right - msg.rect.left,
7657 msg.rect.bottom - msg.rect.top);
7660 break;
7662 case WM_INPUTLANGCHANGE:
7663 /* Generate a language change event. */
7664 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
7666 if (f)
7668 if (numchars == 0)
7669 abort ();
7671 bufp->kind = language_change_event;
7672 XSETFRAME (bufp->frame_or_window, f);
7673 bufp->arg = Qnil;
7674 bufp->code = msg.msg.wParam;
7675 bufp->modifiers = msg.msg.lParam & 0xffff;
7676 bufp++;
7677 count++;
7678 numchars--;
7680 break;
7682 case WM_KEYDOWN:
7683 case WM_SYSKEYDOWN:
7684 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
7686 if (f && !f->iconified)
7688 if (temp_index == sizeof temp_buffer / sizeof (short))
7689 temp_index = 0;
7690 temp_buffer[temp_index++] = msg.msg.wParam;
7691 bufp->kind = non_ascii_keystroke;
7692 bufp->code = msg.msg.wParam;
7693 bufp->modifiers = msg.dwModifiers;
7694 XSETFRAME (bufp->frame_or_window, f);
7695 bufp->arg = Qnil;
7696 bufp->timestamp = msg.msg.time;
7697 bufp++;
7698 numchars--;
7699 count++;
7701 break;
7703 case WM_SYSCHAR:
7704 case WM_CHAR:
7705 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
7707 if (f && !f->iconified)
7709 if (temp_index == sizeof temp_buffer / sizeof (short))
7710 temp_index = 0;
7711 temp_buffer[temp_index++] = msg.msg.wParam;
7712 bufp->kind = ascii_keystroke;
7713 bufp->code = msg.msg.wParam;
7714 bufp->modifiers = msg.dwModifiers;
7715 XSETFRAME (bufp->frame_or_window, f);
7716 bufp->arg = Qnil;
7717 bufp->timestamp = msg.msg.time;
7718 bufp++;
7719 numchars--;
7720 count++;
7722 break;
7724 case WM_MOUSEMOVE:
7725 previous_help_echo = help_echo;
7726 help_echo = help_echo_object = help_echo_window = Qnil;
7727 help_echo_pos = -1;
7729 if (dpyinfo->grabbed && last_mouse_frame
7730 && FRAME_LIVE_P (last_mouse_frame))
7731 f = last_mouse_frame;
7732 else
7733 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
7735 if (f)
7736 note_mouse_movement (f, &msg.msg);
7737 else
7739 /* If we move outside the frame, then we're
7740 certainly no longer on any text in the frame. */
7741 clear_mouse_face (FRAME_W32_DISPLAY_INFO (f));
7744 /* If the contents of the global variable help_echo
7745 has changed, generate a HELP_EVENT. */
7746 if (!NILP (help_echo)
7747 || !NILP (previous_help_echo))
7749 Lisp_Object frame;
7750 int n;
7752 if (f)
7753 XSETFRAME (frame, f);
7754 else
7755 frame = Qnil;
7757 any_help_event_p = 1;
7758 n = gen_help_event (bufp, numchars, help_echo, frame,
7759 help_echo_window, help_echo_object,
7760 help_echo_pos);
7761 bufp += n, count += n, numchars -= n;
7763 break;
7765 case WM_LBUTTONDOWN:
7766 case WM_LBUTTONUP:
7767 case WM_MBUTTONDOWN:
7768 case WM_MBUTTONUP:
7769 case WM_RBUTTONDOWN:
7770 case WM_RBUTTONUP:
7772 /* If we decide we want to generate an event to be seen
7773 by the rest of Emacs, we put it here. */
7774 struct input_event emacs_event;
7775 int tool_bar_p = 0;
7776 int button;
7777 int up;
7779 emacs_event.kind = no_event;
7781 if (dpyinfo->grabbed && last_mouse_frame
7782 && FRAME_LIVE_P (last_mouse_frame))
7783 f = last_mouse_frame;
7784 else
7785 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
7787 if (f)
7789 construct_mouse_click (&emacs_event, &msg, f);
7791 /* Is this in the tool-bar? */
7792 if (WINDOWP (f->tool_bar_window)
7793 && XFASTINT (XWINDOW (f->tool_bar_window)->height))
7795 Lisp_Object window;
7796 int p, x, y;
7798 /* Set x and y. */
7799 window = window_from_coordinates (f,
7800 emacs_event.x,
7801 emacs_event.y,
7802 &p, 1);
7803 if (EQ (window, f->tool_bar_window))
7805 w32_handle_tool_bar_click (f, &emacs_event);
7806 tool_bar_p = 1;
7810 if (!tool_bar_p)
7811 if (!dpyinfo->w32_focus_frame
7812 || f == dpyinfo->w32_focus_frame
7813 && (numchars >= 1))
7815 construct_mouse_click (bufp, &msg, f);
7816 bufp++;
7817 count++;
7818 numchars--;
7822 parse_button (msg.msg.message, &button, &up);
7824 if (up)
7826 dpyinfo->grabbed &= ~ (1 << button);
7828 else
7830 dpyinfo->grabbed |= (1 << button);
7831 last_mouse_frame = f;
7832 /* Ignore any mouse motion that happened
7833 before this event; any subsequent mouse-movement
7834 Emacs events should reflect only motion after
7835 the ButtonPress. */
7836 if (f != 0)
7837 f->mouse_moved = 0;
7839 if (!tool_bar_p)
7840 last_tool_bar_item = -1;
7842 break;
7845 case WM_MOUSEWHEEL:
7846 if (dpyinfo->grabbed && last_mouse_frame
7847 && FRAME_LIVE_P (last_mouse_frame))
7848 f = last_mouse_frame;
7849 else
7850 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
7852 if (f)
7854 if ((!dpyinfo->w32_focus_frame
7855 || f == dpyinfo->w32_focus_frame)
7856 && (numchars >= 1))
7858 construct_mouse_wheel (bufp, &msg, f);
7859 bufp++;
7860 count++;
7861 numchars--;
7864 break;
7866 case WM_MENUSELECT:
7868 HMENU menu = (HMENU) msg.msg.lParam;
7869 UINT menu_item = (UINT) LOWORD (msg.msg.wParam);
7870 UINT flags = (UINT) HIWORD (msg.msg.wParam);
7872 w32_menu_display_help (menu, menu_item, flags);
7874 break;
7876 case WM_DROPFILES:
7877 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
7879 if (f)
7881 construct_drag_n_drop (bufp, &msg, f);
7882 bufp++;
7883 count++;
7884 numchars--;
7886 break;
7888 case WM_VSCROLL:
7890 struct scroll_bar *bar =
7891 x_window_to_scroll_bar ((HWND)msg.msg.lParam);
7893 if (bar && numchars >= 1)
7895 if (x_scroll_bar_handle_click (bar, &msg, bufp))
7897 bufp++;
7898 count++;
7899 numchars--;
7902 break;
7905 case WM_WINDOWPOSCHANGED:
7906 case WM_ACTIVATE:
7907 case WM_ACTIVATEAPP:
7908 check_visibility = 1;
7909 break;
7911 case WM_MOVE:
7912 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
7914 if (f && !f->async_iconified)
7916 int x, y;
7918 x_real_positions (f, &x, &y);
7919 f->output_data.w32->left_pos = x;
7920 f->output_data.w32->top_pos = y;
7923 check_visibility = 1;
7924 break;
7926 case WM_SHOWWINDOW:
7927 /* If window has been obscured or exposed by another window
7928 being maximised or minimised/restored, then recheck
7929 visibility of all frames. Direct changes to our own
7930 windows get handled by WM_SIZE. */
7931 #if 0
7932 if (msg.msg.lParam != 0)
7933 check_visibility = 1;
7934 else
7936 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
7937 f->async_visible = msg.msg.wParam;
7939 #endif
7941 check_visibility = 1;
7942 break;
7944 case WM_SIZE:
7945 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
7947 /* Inform lisp of whether frame has been iconified etc. */
7948 if (f)
7950 switch (msg.msg.wParam)
7952 case SIZE_MINIMIZED:
7953 f->async_visible = 0;
7954 f->async_iconified = 1;
7956 bufp->kind = iconify_event;
7957 XSETFRAME (bufp->frame_or_window, f);
7958 bufp->arg = Qnil;
7959 bufp++;
7960 count++;
7961 numchars--;
7962 break;
7964 case SIZE_MAXIMIZED:
7965 case SIZE_RESTORED:
7966 f->async_visible = 1;
7967 f->async_iconified = 0;
7969 /* wait_reading_process_input will notice this and update
7970 the frame's display structures. */
7971 SET_FRAME_GARBAGED (f);
7973 if (f->iconified)
7975 int x, y;
7977 /* Reset top and left positions of the Window
7978 here since Windows sends a WM_MOVE message
7979 BEFORE telling us the Window is minimized
7980 when the Window is iconified, with 3000,3000
7981 as the co-ords. */
7982 x_real_positions (f, &x, &y);
7983 f->output_data.w32->left_pos = x;
7984 f->output_data.w32->top_pos = y;
7986 bufp->kind = deiconify_event;
7987 XSETFRAME (bufp->frame_or_window, f);
7988 bufp->arg = Qnil;
7989 bufp++;
7990 count++;
7991 numchars--;
7993 else if (! NILP (Vframe_list)
7994 && ! NILP (XCDR (Vframe_list)))
7995 /* Force a redisplay sooner or later
7996 to update the frame titles
7997 in case this is the second frame. */
7998 record_asynch_buffer_change ();
7999 break;
8003 if (f && !f->async_iconified && msg.msg.wParam != SIZE_MINIMIZED)
8005 RECT rect;
8006 int rows;
8007 int columns;
8008 int width;
8009 int height;
8011 GetClientRect (msg.msg.hwnd, &rect);
8013 height = rect.bottom - rect.top;
8014 width = rect.right - rect.left;
8016 rows = PIXEL_TO_CHAR_HEIGHT (f, height);
8017 columns = PIXEL_TO_CHAR_WIDTH (f, width);
8019 /* TODO: Clip size to the screen dimensions. */
8021 /* Even if the number of character rows and columns has
8022 not changed, the font size may have changed, so we need
8023 to check the pixel dimensions as well. */
8025 if (columns != f->width
8026 || rows != f->height
8027 || width != f->output_data.w32->pixel_width
8028 || height != f->output_data.w32->pixel_height)
8030 change_frame_size (f, rows, columns, 0, 1, 0);
8031 SET_FRAME_GARBAGED (f);
8032 cancel_mouse_face (f);
8033 f->output_data.w32->pixel_width = width;
8034 f->output_data.w32->pixel_height = height;
8035 f->output_data.w32->win_gravity = NorthWestGravity;
8039 check_visibility = 1;
8040 break;
8042 case WM_SETFOCUS:
8043 f = x_any_window_to_frame (dpyinfo, msg.msg.hwnd);
8045 dpyinfo->w32_focus_event_frame = f;
8047 if (f)
8048 x_new_focus_frame (dpyinfo, f);
8051 dpyinfo->grabbed = 0;
8052 check_visibility = 1;
8053 break;
8055 case WM_KILLFOCUS:
8056 /* NTEMACS_TODO: some of this belongs in MOUSE_LEAVE */
8057 f = x_top_window_to_frame (dpyinfo, msg.msg.hwnd);
8059 if (f)
8061 Lisp_Object frame;
8063 if (f == dpyinfo->w32_focus_event_frame)
8064 dpyinfo->w32_focus_event_frame = 0;
8066 if (f == dpyinfo->w32_focus_frame)
8067 x_new_focus_frame (dpyinfo, 0);
8069 if (f == dpyinfo->mouse_face_mouse_frame)
8071 /* If we move outside the frame, then we're
8072 certainly no longer on any text in the frame. */
8073 clear_mouse_face (dpyinfo);
8074 dpyinfo->mouse_face_mouse_frame = 0;
8077 /* Generate a nil HELP_EVENT to cancel a help-echo.
8078 Do it only if there's something to cancel.
8079 Otherwise, the startup message is cleared when
8080 the mouse leaves the frame. */
8081 if (any_help_event_p)
8083 int n;
8085 XSETFRAME (frame, f);
8086 n = gen_help_event (bufp, numchars, Qnil, frame,
8087 Qnil, Qnil, 0);
8088 bufp += n, count += n, numchars -=n;
8092 dpyinfo->grabbed = 0;
8093 check_visibility = 1;
8094 break;
8096 case WM_CLOSE:
8097 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
8099 if (f)
8101 if (numchars == 0)
8102 abort ();
8104 bufp->kind = delete_window_event;
8105 XSETFRAME (bufp->frame_or_window, f);
8106 bufp->arg = Qnil;
8107 bufp++;
8108 count++;
8109 numchars--;
8111 break;
8113 case WM_INITMENU:
8114 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
8116 if (f)
8118 if (numchars == 0)
8119 abort ();
8121 bufp->kind = menu_bar_activate_event;
8122 XSETFRAME (bufp->frame_or_window, f);
8123 bufp->arg = Qnil;
8124 bufp++;
8125 count++;
8126 numchars--;
8128 break;
8130 case WM_COMMAND:
8131 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
8133 if (f)
8135 extern void menubar_selection_callback
8136 (FRAME_PTR f, void * client_data);
8137 menubar_selection_callback (f, (void *)msg.msg.wParam);
8140 check_visibility = 1;
8141 break;
8143 case WM_DISPLAYCHANGE:
8144 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
8146 if (f)
8148 dpyinfo->width = (short) LOWORD (msg.msg.lParam);
8149 dpyinfo->height = (short) HIWORD (msg.msg.lParam);
8150 dpyinfo->n_cbits = msg.msg.wParam;
8151 DebPrint (("display change: %d %d\n", dpyinfo->width,
8152 dpyinfo->height));
8155 check_visibility = 1;
8156 break;
8158 default:
8159 /* Check for messages registered at runtime. */
8160 if (msg.msg.message == msh_mousewheel)
8162 if (dpyinfo->grabbed && last_mouse_frame
8163 && FRAME_LIVE_P (last_mouse_frame))
8164 f = last_mouse_frame;
8165 else
8166 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
8168 if (f)
8170 if ((!dpyinfo->w32_focus_frame
8171 || f == dpyinfo->w32_focus_frame)
8172 && (numchars >= 1))
8174 construct_mouse_wheel (bufp, &msg, f);
8175 bufp++;
8176 count++;
8177 numchars--;
8181 break;
8185 /* If the focus was just given to an autoraising frame,
8186 raise it now. */
8187 /* ??? This ought to be able to handle more than one such frame. */
8188 if (pending_autoraise_frame)
8190 x_raise_frame (pending_autoraise_frame);
8191 pending_autoraise_frame = 0;
8194 /* Check which frames are still visisble, if we have enqueued any user
8195 events or been notified of events that may affect visibility. We
8196 do this here because there doesn't seem to be any direct
8197 notification from Windows that the visibility of a window has
8198 changed (at least, not in all cases). */
8199 if (count > 0 || check_visibility)
8201 Lisp_Object tail, frame;
8203 FOR_EACH_FRAME (tail, frame)
8205 FRAME_PTR f = XFRAME (frame);
8206 /* Check "visible" frames and mark each as obscured or not.
8207 Note that async_visible is nonzero for unobscured and
8208 obscured frames, but zero for hidden and iconified frames. */
8209 if (FRAME_W32_P (f) && f->async_visible)
8211 RECT clipbox;
8212 HDC hdc = get_frame_dc (f);
8213 GetClipBox (hdc, &clipbox);
8214 release_frame_dc (f, hdc);
8216 if (clipbox.right == clipbox.left
8217 || clipbox.bottom == clipbox.top)
8219 /* Frame has become completely obscured so mark as
8220 such (we do this by setting async_visible to 2 so
8221 that FRAME_VISIBLE_P is still true, but redisplay
8222 will skip it). */
8223 f->async_visible = 2;
8225 if (!FRAME_OBSCURED_P (f))
8227 DebPrint (("frame %04x (%s) obscured\n", f,
8228 XSTRING (f->name)->data));
8231 else
8233 /* Frame is not obscured, so mark it as such. */
8234 f->async_visible = 1;
8236 if (FRAME_OBSCURED_P (f))
8238 SET_FRAME_GARBAGED (f);
8239 DebPrint (("frame %04x (%s) reexposed\n", f,
8240 XSTRING (f->name)->data));
8242 /* Force a redisplay sooner or later. */
8243 record_asynch_buffer_change ();
8250 UNBLOCK_INPUT;
8251 return count;
8257 /***********************************************************************
8258 Text Cursor
8259 ***********************************************************************/
8261 /* Note if the text cursor of window W has been overwritten by a
8262 drawing operation that outputs N glyphs starting at HPOS in the
8263 line given by output_cursor.vpos. N < 0 means all the rest of the
8264 line after HPOS has been written. */
8266 static void
8267 note_overwritten_text_cursor (w, hpos, n)
8268 struct window *w;
8269 int hpos, n;
8271 if (updated_area == TEXT_AREA
8272 && output_cursor.vpos == w->phys_cursor.vpos
8273 && hpos <= w->phys_cursor.hpos
8274 && (n < 0
8275 || hpos + n > w->phys_cursor.hpos))
8276 w->phys_cursor_on_p = 0;
8280 /* Set clipping for output in glyph row ROW. W is the window in which
8281 we operate. GC is the graphics context to set clipping in.
8282 WHOLE_LINE_P non-zero means include the areas used for truncation
8283 mark display and alike in the clipping rectangle.
8285 ROW may be a text row or, e.g., a mode line. Text rows must be
8286 clipped to the interior of the window dedicated to text display,
8287 mode lines must be clipped to the whole window. */
8289 static void
8290 w32_clip_to_row (w, row, hdc, whole_line_p)
8291 struct window *w;
8292 struct glyph_row *row;
8293 HDC hdc;
8294 int whole_line_p;
8296 struct frame *f = XFRAME (WINDOW_FRAME (w));
8297 RECT clip_rect;
8298 int window_x, window_y, window_width, window_height;
8300 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
8302 clip_rect.left = WINDOW_TO_FRAME_PIXEL_X (w, 0);
8303 clip_rect.top = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
8304 clip_rect.top = max (clip_rect.top, window_y);
8305 clip_rect.right = clip_rect.left + window_width;
8306 clip_rect.bottom = clip_rect.top + row->visible_height;
8308 /* If clipping to the whole line, including trunc marks, extend
8309 the rectangle to the left and increase its width. */
8310 if (whole_line_p)
8312 clip_rect.left -= FRAME_X_LEFT_FLAGS_AREA_WIDTH (f);
8313 clip_rect.right += FRAME_X_FLAGS_AREA_WIDTH (f);
8316 w32_set_clip_rectangle (hdc, &clip_rect);
8320 /* Draw a hollow box cursor on window W in glyph row ROW. */
8322 static void
8323 x_draw_hollow_cursor (w, row)
8324 struct window *w;
8325 struct glyph_row *row;
8327 struct frame *f = XFRAME (WINDOW_FRAME (w));
8328 HDC hdc = get_frame_dc (f);
8329 RECT rect;
8330 int wd;
8331 struct glyph *cursor_glyph;
8332 HBRUSH hb = CreateSolidBrush (f->output_data.w32->cursor_pixel);
8334 /* Compute frame-relative coordinates from window-relative
8335 coordinates. */
8336 rect.left = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
8337 rect.top = (WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y)
8338 + row->ascent - w->phys_cursor_ascent);
8339 rect.bottom = rect.top + row->height - 1;
8341 /* Get the glyph the cursor is on. If we can't tell because
8342 the current matrix is invalid or such, give up. */
8343 cursor_glyph = get_phys_cursor_glyph (w);
8344 if (cursor_glyph == NULL)
8345 return;
8347 /* Compute the width of the rectangle to draw. If on a stretch
8348 glyph, and `x-stretch-block-cursor' is nil, don't draw a
8349 rectangle as wide as the glyph, but use a canonical character
8350 width instead. */
8351 wd = cursor_glyph->pixel_width - 1;
8352 if (cursor_glyph->type == STRETCH_GLYPH
8353 && !x_stretch_cursor_p)
8354 wd = min (CANON_X_UNIT (f), wd);
8356 rect.right = rect.left + wd;
8358 FrameRect (hdc, &rect, hb);
8359 DeleteObject (hb);
8361 release_frame_dc (f, hdc);
8365 /* Draw a bar cursor on window W in glyph row ROW.
8367 Implementation note: One would like to draw a bar cursor with an
8368 angle equal to the one given by the font property XA_ITALIC_ANGLE.
8369 Unfortunately, I didn't find a font yet that has this property set.
8370 --gerd. */
8372 static void
8373 x_draw_bar_cursor (w, row, width)
8374 struct window *w;
8375 struct glyph_row *row;
8376 int width;
8378 /* If cursor hpos is out of bounds, don't draw garbage. This can
8379 happen in mini-buffer windows when switching between echo area
8380 glyphs and mini-buffer. */
8381 if (w->phys_cursor.hpos < row->used[TEXT_AREA])
8383 struct frame *f = XFRAME (w->frame);
8384 struct glyph *cursor_glyph;
8385 int x;
8386 HDC hdc;
8388 cursor_glyph = get_phys_cursor_glyph (w);
8389 if (cursor_glyph == NULL)
8390 return;
8392 /* If on an image, draw like a normal cursor. That's usually better
8393 visible than drawing a bar, esp. if the image is large so that
8394 the bar might not be in the window. */
8395 if (cursor_glyph->type == IMAGE_GLYPH)
8397 struct glyph_row *row;
8398 row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
8399 x_draw_phys_cursor_glyph (w, row, DRAW_CURSOR);
8401 else
8404 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
8406 if (width < 0)
8407 width = f->output_data.w32->cursor_width;
8409 hdc = get_frame_dc (f);
8410 w32_fill_area (f, hdc, f->output_data.w32->cursor_pixel,
8412 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
8413 min (cursor_glyph->pixel_width, width),
8414 row->height);
8415 release_frame_dc (f, hdc);
8421 /* Clear the cursor of window W to background color, and mark the
8422 cursor as not shown. This is used when the text where the cursor
8423 is is about to be rewritten. */
8425 static void
8426 x_clear_cursor (w)
8427 struct window *w;
8429 if (FRAME_VISIBLE_P (XFRAME (w->frame)) && w->phys_cursor_on_p)
8430 x_update_window_cursor (w, 0);
8434 /* Draw the cursor glyph of window W in glyph row ROW. See the
8435 comment of x_draw_glyphs for the meaning of HL. */
8437 static void
8438 x_draw_phys_cursor_glyph (w, row, hl)
8439 struct window *w;
8440 struct glyph_row *row;
8441 enum draw_glyphs_face hl;
8443 /* If cursor hpos is out of bounds, don't draw garbage. This can
8444 happen in mini-buffer windows when switching between echo area
8445 glyphs and mini-buffer. */
8446 if (w->phys_cursor.hpos < row->used[TEXT_AREA])
8448 x_draw_glyphs (w, w->phys_cursor.x, row, TEXT_AREA,
8449 w->phys_cursor.hpos, w->phys_cursor.hpos + 1,
8450 hl, 0, 0, 0);
8452 /* When we erase the cursor, and ROW is overlapped by other
8453 rows, make sure that these overlapping parts of other rows
8454 are redrawn. */
8455 if (hl == DRAW_NORMAL_TEXT && row->overlapped_p)
8457 if (row > w->current_matrix->rows
8458 && MATRIX_ROW_OVERLAPS_SUCC_P (row - 1))
8459 x_fix_overlapping_area (w, row - 1, TEXT_AREA);
8461 if (MATRIX_ROW_BOTTOM_Y (row) < window_text_bottom_y (w)
8462 && MATRIX_ROW_OVERLAPS_PRED_P (row + 1))
8463 x_fix_overlapping_area (w, row + 1, TEXT_AREA);
8469 /* Erase the image of a cursor of window W from the screen. */
8471 static void
8472 x_erase_phys_cursor (w)
8473 struct window *w;
8475 struct frame *f = XFRAME (w->frame);
8476 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
8477 int hpos = w->phys_cursor.hpos;
8478 int vpos = w->phys_cursor.vpos;
8479 int mouse_face_here_p = 0;
8480 struct glyph_matrix *active_glyphs = w->current_matrix;
8481 struct glyph_row *cursor_row;
8482 struct glyph *cursor_glyph;
8483 enum draw_glyphs_face hl;
8485 /* No cursor displayed or row invalidated => nothing to do on the
8486 screen. */
8487 if (w->phys_cursor_type == NO_CURSOR)
8488 goto mark_cursor_off;
8490 /* VPOS >= active_glyphs->nrows means that window has been resized.
8491 Don't bother to erase the cursor. */
8492 if (vpos >= active_glyphs->nrows)
8493 goto mark_cursor_off;
8495 /* If row containing cursor is marked invalid, there is nothing we
8496 can do. */
8497 cursor_row = MATRIX_ROW (active_glyphs, vpos);
8498 if (!cursor_row->enabled_p)
8499 goto mark_cursor_off;
8501 /* This can happen when the new row is shorter than the old one.
8502 In this case, either x_draw_glyphs or clear_end_of_line
8503 should have cleared the cursor. Note that we wouldn't be
8504 able to erase the cursor in this case because we don't have a
8505 cursor glyph at hand. */
8506 if (w->phys_cursor.hpos >= cursor_row->used[TEXT_AREA])
8507 goto mark_cursor_off;
8509 /* If the cursor is in the mouse face area, redisplay that when
8510 we clear the cursor. */
8511 if (w == XWINDOW (dpyinfo->mouse_face_window)
8512 && (vpos > dpyinfo->mouse_face_beg_row
8513 || (vpos == dpyinfo->mouse_face_beg_row
8514 && hpos >= dpyinfo->mouse_face_beg_col))
8515 && (vpos < dpyinfo->mouse_face_end_row
8516 || (vpos == dpyinfo->mouse_face_end_row
8517 && hpos < dpyinfo->mouse_face_end_col))
8518 /* Don't redraw the cursor's spot in mouse face if it is at the
8519 end of a line (on a newline). The cursor appears there, but
8520 mouse highlighting does not. */
8521 && cursor_row->used[TEXT_AREA] > hpos)
8522 mouse_face_here_p = 1;
8524 /* Maybe clear the display under the cursor. */
8525 if (w->phys_cursor_type == HOLLOW_BOX_CURSOR)
8527 int x;
8528 int header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
8529 HDC hdc;
8531 cursor_glyph = get_phys_cursor_glyph (w);
8532 if (cursor_glyph == NULL)
8533 goto mark_cursor_off;
8535 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
8537 hdc = get_frame_dc (f);
8538 w32_clear_area (f, hdc, x,
8539 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
8540 cursor_row->y)),
8541 cursor_glyph->pixel_width,
8542 cursor_row->visible_height);
8543 release_frame_dc (f, hdc);
8546 /* Erase the cursor by redrawing the character underneath it. */
8547 if (mouse_face_here_p)
8548 hl = DRAW_MOUSE_FACE;
8549 else if (cursor_row->inverse_p)
8550 hl = DRAW_INVERSE_VIDEO;
8551 else
8552 hl = DRAW_NORMAL_TEXT;
8553 x_draw_phys_cursor_glyph (w, cursor_row, hl);
8555 mark_cursor_off:
8556 w->phys_cursor_on_p = 0;
8557 w->phys_cursor_type = NO_CURSOR;
8561 /* Display or clear cursor of window W. If ON is zero, clear the
8562 cursor. If it is non-zero, display the cursor. If ON is nonzero,
8563 where to put the cursor is specified by HPOS, VPOS, X and Y. */
8565 void
8566 x_display_and_set_cursor (w, on, hpos, vpos, x, y)
8567 struct window *w;
8568 int on, hpos, vpos, x, y;
8570 struct frame *f = XFRAME (w->frame);
8571 int new_cursor_type;
8572 int new_cursor_width;
8573 struct glyph_matrix *current_glyphs;
8574 struct glyph_row *glyph_row;
8575 struct glyph *glyph;
8577 /* This is pointless on invisible frames, and dangerous on garbaged
8578 windows and frames; in the latter case, the frame or window may
8579 be in the midst of changing its size, and x and y may be off the
8580 window. */
8581 if (! FRAME_VISIBLE_P (f)
8582 || FRAME_GARBAGED_P (f)
8583 || vpos >= w->current_matrix->nrows
8584 || hpos >= w->current_matrix->matrix_w)
8585 return;
8587 /* If cursor is off and we want it off, return quickly. */
8588 if (!on && !w->phys_cursor_on_p)
8589 return;
8591 current_glyphs = w->current_matrix;
8592 glyph_row = MATRIX_ROW (current_glyphs, vpos);
8593 glyph = glyph_row->glyphs[TEXT_AREA] + hpos;
8595 /* If cursor row is not enabled, we don't really know where to
8596 display the cursor. */
8597 if (!glyph_row->enabled_p)
8599 w->phys_cursor_on_p = 0;
8600 return;
8603 xassert (interrupt_input_blocked);
8605 /* Set new_cursor_type to the cursor we want to be displayed. In a
8606 mini-buffer window, we want the cursor only to appear if we are
8607 reading input from this window. For the selected window, we want
8608 the cursor type given by the frame parameter. If explicitly
8609 marked off, draw no cursor. In all other cases, we want a hollow
8610 box cursor. */
8611 new_cursor_width = -1;
8612 if (cursor_in_echo_area
8613 && FRAME_HAS_MINIBUF_P (f)
8614 && EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window))
8616 if (w == XWINDOW (echo_area_window))
8617 new_cursor_type = FRAME_DESIRED_CURSOR (f);
8618 else
8619 new_cursor_type = HOLLOW_BOX_CURSOR;
8621 else
8623 if (w != XWINDOW (selected_window)
8624 || f != FRAME_W32_DISPLAY_INFO (f)->w32_highlight_frame)
8626 extern int cursor_in_non_selected_windows;
8628 if (MINI_WINDOW_P (w)
8629 || !cursor_in_non_selected_windows
8630 || NILP (XBUFFER (w->buffer)->cursor_type))
8631 new_cursor_type = NO_CURSOR;
8632 else
8633 new_cursor_type = HOLLOW_BOX_CURSOR;
8635 else if (w->cursor_off_p)
8636 new_cursor_type = NO_CURSOR;
8637 else
8639 struct buffer *b = XBUFFER (w->buffer);
8641 if (EQ (b->cursor_type, Qt))
8642 new_cursor_type = FRAME_DESIRED_CURSOR (f);
8643 else
8644 new_cursor_type = x_specified_cursor_type (b->cursor_type,
8645 &new_cursor_width);
8649 /* If cursor is currently being shown and we don't want it to be or
8650 it is in the wrong place, or the cursor type is not what we want,
8651 erase it. */
8652 if (w->phys_cursor_on_p
8653 && (!on
8654 || w->phys_cursor.x != x
8655 || w->phys_cursor.y != y
8656 || new_cursor_type != w->phys_cursor_type))
8657 x_erase_phys_cursor (w);
8659 /* If the cursor is now invisible and we want it to be visible,
8660 display it. */
8661 if (on && !w->phys_cursor_on_p)
8663 w->phys_cursor_ascent = glyph_row->ascent;
8664 w->phys_cursor_height = glyph_row->height;
8666 /* Set phys_cursor_.* before x_draw_.* is called because some
8667 of them may need the information. */
8668 w->phys_cursor.x = x;
8669 w->phys_cursor.y = glyph_row->y;
8670 w->phys_cursor.hpos = hpos;
8671 w->phys_cursor.vpos = vpos;
8672 w->phys_cursor_type = new_cursor_type;
8673 w->phys_cursor_on_p = 1;
8675 switch (new_cursor_type)
8677 case HOLLOW_BOX_CURSOR:
8678 x_draw_hollow_cursor (w, glyph_row);
8679 break;
8681 case FILLED_BOX_CURSOR:
8682 x_draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
8683 break;
8685 case BAR_CURSOR:
8686 x_draw_bar_cursor (w, glyph_row, new_cursor_width);
8687 break;
8689 case NO_CURSOR:
8690 break;
8692 default:
8693 abort ();
8699 /* Display the cursor on window W, or clear it. X and Y are window
8700 relative pixel coordinates. HPOS and VPOS are glyph matrix
8701 positions. If W is not the selected window, display a hollow
8702 cursor. ON non-zero means display the cursor at X, Y which
8703 correspond to HPOS, VPOS, otherwise it is cleared. */
8705 void
8706 x_display_cursor (w, on, hpos, vpos, x, y)
8707 struct window *w;
8708 int on, hpos, vpos, x, y;
8710 BLOCK_INPUT;
8711 x_display_and_set_cursor (w, on, hpos, vpos, x, y);
8712 UNBLOCK_INPUT;
8716 /* Display the cursor on window W, or clear it, according to ON_P.
8717 Don't change the cursor's position. */
8719 void
8720 x_update_cursor (f, on_p)
8721 struct frame *f;
8722 int on_p;
8724 x_update_cursor_in_window_tree (XWINDOW (f->root_window), on_p);
8728 /* Call x_update_window_cursor with parameter ON_P on all leaf windows
8729 in the window tree rooted at W. */
8731 static void
8732 x_update_cursor_in_window_tree (w, on_p)
8733 struct window *w;
8734 int on_p;
8736 while (w)
8738 if (!NILP (w->hchild))
8739 x_update_cursor_in_window_tree (XWINDOW (w->hchild), on_p);
8740 else if (!NILP (w->vchild))
8741 x_update_cursor_in_window_tree (XWINDOW (w->vchild), on_p);
8742 else
8743 x_update_window_cursor (w, on_p);
8745 w = NILP (w->next) ? 0 : XWINDOW (w->next);
8750 /* Switch the display of W's cursor on or off, according to the value
8751 of ON. */
8753 static void
8754 x_update_window_cursor (w, on)
8755 struct window *w;
8756 int on;
8758 /* Don't update cursor in windows whose frame is in the process
8759 of being deleted. */
8760 if (w->current_matrix)
8762 BLOCK_INPUT;
8763 x_display_and_set_cursor (w, on, w->phys_cursor.hpos,
8764 w->phys_cursor.vpos, w->phys_cursor.x,
8765 w->phys_cursor.y);
8766 UNBLOCK_INPUT;
8773 /* Icons. */
8776 x_bitmap_icon (f, icon)
8777 struct frame *f;
8778 Lisp_Object icon;
8780 int mask, bitmap_id;
8781 Window icon_window;
8782 HANDLE hicon;
8784 if (FRAME_W32_WINDOW (f) == 0)
8785 return 1;
8787 if (NILP (icon))
8788 hicon = LoadIcon (hinst, EMACS_CLASS);
8789 else if (STRINGP (icon))
8790 hicon = LoadImage (NULL, (LPCTSTR) XSTRING (icon)->data, IMAGE_ICON, 0, 0,
8791 LR_DEFAULTSIZE | LR_LOADFROMFILE);
8792 else if (SYMBOLP (icon))
8794 LPCTSTR name;
8796 if (EQ (icon, intern ("application")))
8797 name = (LPCTSTR) IDI_APPLICATION;
8798 else if (EQ (icon, intern ("hand")))
8799 name = (LPCTSTR) IDI_HAND;
8800 else if (EQ (icon, intern ("question")))
8801 name = (LPCTSTR) IDI_QUESTION;
8802 else if (EQ (icon, intern ("exclamation")))
8803 name = (LPCTSTR) IDI_EXCLAMATION;
8804 else if (EQ (icon, intern ("asterisk")))
8805 name = (LPCTSTR) IDI_ASTERISK;
8806 else if (EQ (icon, intern ("winlogo")))
8807 name = (LPCTSTR) IDI_WINLOGO;
8808 else
8809 return 1;
8811 hicon = LoadIcon (NULL, name);
8813 else
8814 return 1;
8816 if (hicon == NULL)
8817 return 1;
8819 PostMessage (FRAME_W32_WINDOW (f), WM_SETICON, (WPARAM) ICON_BIG,
8820 (LPARAM) hicon);
8822 return 0;
8826 /* Changing the font of the frame. */
8828 /* Give frame F the font named FONTNAME as its default font, and
8829 return the full name of that font. FONTNAME may be a wildcard
8830 pattern; in that case, we choose some font that fits the pattern.
8831 The return value shows which font we chose. */
8833 Lisp_Object
8834 x_new_font (f, fontname)
8835 struct frame *f;
8836 register char *fontname;
8838 struct font_info *fontp
8839 = FS_LOAD_FONT (f, 0, fontname, -1);
8841 if (!fontp)
8842 return Qnil;
8844 FRAME_FONT (f) = (XFontStruct *) (fontp->font);
8845 FRAME_BASELINE_OFFSET (f) = fontp->baseline_offset;
8846 FRAME_FONTSET (f) = -1;
8848 /* Compute the scroll bar width in character columns. */
8849 if (f->scroll_bar_pixel_width > 0)
8851 int wid = FONT_WIDTH (FRAME_FONT (f));
8852 f->scroll_bar_cols = (f->scroll_bar_pixel_width + wid-1) / wid;
8854 else
8856 int wid = FONT_WIDTH (FRAME_FONT (f));
8857 f->scroll_bar_cols = (14 + wid - 1) / wid;
8860 /* Now make the frame display the given font. */
8861 if (FRAME_W32_WINDOW (f) != 0)
8863 frame_update_line_height (f);
8864 x_set_window_size (f, 0, f->width, f->height);
8866 else
8867 /* If we are setting a new frame's font for the first time,
8868 there are no faces yet, so this font's height is the line height. */
8869 f->output_data.w32->line_height = FONT_HEIGHT (FRAME_FONT (f));
8871 return build_string (fontp->full_name);
8874 /* Give frame F the fontset named FONTSETNAME as its default font, and
8875 return the full name of that fontset. FONTSETNAME may be a wildcard
8876 pattern; in that case, we choose some fontset that fits the pattern.
8877 The return value shows which fontset we chose. */
8879 Lisp_Object
8880 x_new_fontset (f, fontsetname)
8881 struct frame *f;
8882 char *fontsetname;
8884 int fontset = fs_query_fontset (build_string (fontsetname), 0);
8885 Lisp_Object result;
8886 char *fontname;
8888 if (fontset < 0)
8889 return Qnil;
8891 if (FRAME_FONTSET (f) == fontset)
8892 /* This fontset is already set in frame F. There's nothing more
8893 to do. */
8894 return fontset_name (fontset);
8896 result = x_new_font (f, (XSTRING (fontset_ascii (fontset))->data));
8898 if (!STRINGP (result))
8899 /* Can't load ASCII font. */
8900 return Qnil;
8902 /* Since x_new_font doesn't update any fontset information, do it now. */
8903 FRAME_FONTSET(f) = fontset;
8905 return build_string (fontsetname);
8909 #if GLYPH_DEBUG
8911 /* Check that FONT is valid on frame F. It is if it can be found in F's
8912 font table. */
8914 static void
8915 x_check_font (f, font)
8916 struct frame *f;
8917 XFontStruct *font;
8919 int i;
8920 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
8922 xassert (font != NULL);
8924 for (i = 0; i < dpyinfo->n_fonts; i++)
8925 if (dpyinfo->font_table[i].name
8926 && font == dpyinfo->font_table[i].font)
8927 break;
8929 xassert (i < dpyinfo->n_fonts);
8932 #endif /* GLYPH_DEBUG != 0 */
8934 /* Set *W to the minimum width, *H to the minimum font height of FONT.
8935 Note: There are (broken) X fonts out there with invalid XFontStruct
8936 min_bounds contents. For example, handa@etl.go.jp reports that
8937 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
8938 have font->min_bounds.width == 0. */
8940 static INLINE void
8941 x_font_min_bounds (font, w, h)
8942 XFontStruct *font;
8943 int *w, *h;
8946 * NTEMACS_TODO: Windows does not appear to offer min bound, only
8947 * average and maximum width, and maximum height.
8949 *h = FONT_HEIGHT (font);
8950 *w = FONT_WIDTH (font);
8954 /* Compute the smallest character width and smallest font height over
8955 all fonts available on frame F. Set the members smallest_char_width
8956 and smallest_font_height in F's x_display_info structure to
8957 the values computed. Value is non-zero if smallest_font_height or
8958 smallest_char_width become smaller than they were before. */
8961 x_compute_min_glyph_bounds (f)
8962 struct frame *f;
8964 int i;
8965 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
8966 XFontStruct *font;
8967 int old_width = dpyinfo->smallest_char_width;
8968 int old_height = dpyinfo->smallest_font_height;
8970 dpyinfo->smallest_font_height = 100000;
8971 dpyinfo->smallest_char_width = 100000;
8973 for (i = 0; i < dpyinfo->n_fonts; ++i)
8974 if (dpyinfo->font_table[i].name)
8976 struct font_info *fontp = dpyinfo->font_table + i;
8977 int w, h;
8979 font = (XFontStruct *) fontp->font;
8980 xassert (font != (XFontStruct *) ~0);
8981 x_font_min_bounds (font, &w, &h);
8983 dpyinfo->smallest_font_height = min (dpyinfo->smallest_font_height, h);
8984 dpyinfo->smallest_char_width = min (dpyinfo->smallest_char_width, w);
8987 xassert (dpyinfo->smallest_char_width > 0
8988 && dpyinfo->smallest_font_height > 0);
8990 return (dpyinfo->n_fonts == 1
8991 || dpyinfo->smallest_char_width < old_width
8992 || dpyinfo->smallest_font_height < old_height);
8996 /* Calculate the absolute position in frame F
8997 from its current recorded position values and gravity. */
8999 void
9000 x_calc_absolute_position (f)
9001 struct frame *f;
9003 Window child;
9004 POINT pt;
9005 int flags = f->output_data.w32->size_hint_flags;
9007 pt.x = pt.y = 0;
9009 /* Find the position of the outside upper-left corner of
9010 the inner window, with respect to the outer window. */
9011 if (f->output_data.w32->parent_desc != FRAME_W32_DISPLAY_INFO (f)->root_window)
9013 BLOCK_INPUT;
9014 MapWindowPoints (FRAME_W32_WINDOW (f),
9015 f->output_data.w32->parent_desc,
9016 &pt, 1);
9017 UNBLOCK_INPUT;
9021 RECT rt;
9022 rt.left = rt.right = rt.top = rt.bottom = 0;
9024 BLOCK_INPUT;
9025 AdjustWindowRect(&rt, f->output_data.w32->dwStyle,
9026 FRAME_EXTERNAL_MENU_BAR (f));
9027 UNBLOCK_INPUT;
9029 pt.x += (rt.right - rt.left);
9030 pt.y += (rt.bottom - rt.top);
9033 /* Treat negative positions as relative to the leftmost bottommost
9034 position that fits on the screen. */
9035 if (flags & XNegative)
9036 f->output_data.w32->left_pos = (FRAME_W32_DISPLAY_INFO (f)->width
9037 - 2 * f->output_data.w32->border_width - pt.x
9038 - PIXEL_WIDTH (f)
9039 + f->output_data.w32->left_pos);
9041 if (flags & YNegative)
9042 f->output_data.w32->top_pos = (FRAME_W32_DISPLAY_INFO (f)->height
9043 - 2 * f->output_data.w32->border_width - pt.y
9044 - PIXEL_HEIGHT (f)
9045 + f->output_data.w32->top_pos);
9046 /* The left_pos and top_pos
9047 are now relative to the top and left screen edges,
9048 so the flags should correspond. */
9049 f->output_data.w32->size_hint_flags &= ~ (XNegative | YNegative);
9052 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
9053 to really change the position, and 0 when calling from
9054 x_make_frame_visible (in that case, XOFF and YOFF are the current
9055 position values). It is -1 when calling from x_set_frame_parameters,
9056 which means, do adjust for borders but don't change the gravity. */
9058 void
9059 x_set_offset (f, xoff, yoff, change_gravity)
9060 struct frame *f;
9061 register int xoff, yoff;
9062 int change_gravity;
9064 int modified_top, modified_left;
9066 if (change_gravity > 0)
9068 f->output_data.w32->top_pos = yoff;
9069 f->output_data.w32->left_pos = xoff;
9070 f->output_data.w32->size_hint_flags &= ~ (XNegative | YNegative);
9071 if (xoff < 0)
9072 f->output_data.w32->size_hint_flags |= XNegative;
9073 if (yoff < 0)
9074 f->output_data.w32->size_hint_flags |= YNegative;
9075 f->output_data.w32->win_gravity = NorthWestGravity;
9077 x_calc_absolute_position (f);
9079 BLOCK_INPUT;
9080 x_wm_set_size_hint (f, (long) 0, 0);
9082 modified_left = f->output_data.w32->left_pos;
9083 modified_top = f->output_data.w32->top_pos;
9085 my_set_window_pos (FRAME_W32_WINDOW (f),
9086 NULL,
9087 modified_left, modified_top,
9088 0, 0,
9089 SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
9090 UNBLOCK_INPUT;
9093 /* Call this to change the size of frame F's x-window.
9094 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
9095 for this size change and subsequent size changes.
9096 Otherwise we leave the window gravity unchanged. */
9097 void
9098 x_set_window_size (f, change_gravity, cols, rows)
9099 struct frame *f;
9100 int change_gravity;
9101 int cols, rows;
9103 int pixelwidth, pixelheight;
9105 BLOCK_INPUT;
9107 check_frame_size (f, &rows, &cols);
9108 f->output_data.w32->vertical_scroll_bar_extra
9109 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
9111 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.w32->font)));
9112 f->output_data.w32->flags_areas_extra
9113 = FRAME_FLAGS_AREA_WIDTH (f);
9114 pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols);
9115 pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows);
9117 f->output_data.w32->win_gravity = NorthWestGravity;
9118 x_wm_set_size_hint (f, (long) 0, 0);
9121 RECT rect;
9123 rect.left = rect.top = 0;
9124 rect.right = pixelwidth;
9125 rect.bottom = pixelheight;
9127 AdjustWindowRect(&rect, f->output_data.w32->dwStyle,
9128 FRAME_EXTERNAL_MENU_BAR (f));
9130 my_set_window_pos (FRAME_W32_WINDOW (f),
9131 NULL,
9132 0, 0,
9133 rect.right - rect.left,
9134 rect.bottom - rect.top,
9135 SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE);
9138 /* Now, strictly speaking, we can't be sure that this is accurate,
9139 but the window manager will get around to dealing with the size
9140 change request eventually, and we'll hear how it went when the
9141 ConfigureNotify event gets here.
9143 We could just not bother storing any of this information here,
9144 and let the ConfigureNotify event set everything up, but that
9145 might be kind of confusing to the Lisp code, since size changes
9146 wouldn't be reported in the frame parameters until some random
9147 point in the future when the ConfigureNotify event arrives.
9149 We pass 1 for DELAY since we can't run Lisp code inside of
9150 a BLOCK_INPUT. */
9151 change_frame_size (f, rows, cols, 0, 1, 0);
9152 PIXEL_WIDTH (f) = pixelwidth;
9153 PIXEL_HEIGHT (f) = pixelheight;
9155 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
9156 receive in the ConfigureNotify event; if we get what we asked
9157 for, then the event won't cause the screen to become garbaged, so
9158 we have to make sure to do it here. */
9159 SET_FRAME_GARBAGED (f);
9161 /* If cursor was outside the new size, mark it as off. */
9162 mark_window_cursors_off (XWINDOW (f->root_window));
9164 /* Clear out any recollection of where the mouse highlighting was,
9165 since it might be in a place that's outside the new frame size.
9166 Actually checking whether it is outside is a pain in the neck,
9167 so don't try--just let the highlighting be done afresh with new size. */
9168 cancel_mouse_face (f);
9170 UNBLOCK_INPUT;
9173 /* Mouse warping. */
9175 void x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y);
9177 void
9178 x_set_mouse_position (f, x, y)
9179 struct frame *f;
9180 int x, y;
9182 int pix_x, pix_y;
9184 pix_x = CHAR_TO_PIXEL_COL (f, x) + FONT_WIDTH (f->output_data.w32->font) / 2;
9185 pix_y = CHAR_TO_PIXEL_ROW (f, y) + f->output_data.w32->line_height / 2;
9187 if (pix_x < 0) pix_x = 0;
9188 if (pix_x > PIXEL_WIDTH (f)) pix_x = PIXEL_WIDTH (f);
9190 if (pix_y < 0) pix_y = 0;
9191 if (pix_y > PIXEL_HEIGHT (f)) pix_y = PIXEL_HEIGHT (f);
9193 x_set_mouse_pixel_position (f, pix_x, pix_y);
9196 void
9197 x_set_mouse_pixel_position (f, pix_x, pix_y)
9198 struct frame *f;
9199 int pix_x, pix_y;
9201 RECT rect;
9202 POINT pt;
9204 BLOCK_INPUT;
9206 GetClientRect (FRAME_W32_WINDOW (f), &rect);
9207 pt.x = rect.left + pix_x;
9208 pt.y = rect.top + pix_y;
9209 ClientToScreen (FRAME_W32_WINDOW (f), &pt);
9211 SetCursorPos (pt.x, pt.y);
9213 UNBLOCK_INPUT;
9217 /* focus shifting, raising and lowering. */
9219 void
9220 x_focus_on_frame (f)
9221 struct frame *f;
9223 struct w32_display_info *dpyinfo = &one_w32_display_info;
9225 /* Give input focus to frame. */
9226 BLOCK_INPUT;
9227 #if 0
9228 /* Try not to change its Z-order if possible. */
9229 if (x_window_to_frame (dpyinfo, GetForegroundWindow ()))
9230 my_set_focus (f, FRAME_W32_WINDOW (f));
9231 else
9232 #endif
9233 my_set_foreground_window (FRAME_W32_WINDOW (f));
9234 UNBLOCK_INPUT;
9237 void
9238 x_unfocus_frame (f)
9239 struct frame *f;
9243 /* Raise frame F. */
9244 void
9245 x_raise_frame (f)
9246 struct frame *f;
9248 BLOCK_INPUT;
9250 /* Strictly speaking, raise-frame should only change the frame's Z
9251 order, leaving input focus unchanged. This is reasonable behaviour
9252 on X where the usual policy is point-to-focus. However, this
9253 behaviour would be very odd on Windows where the usual policy is
9254 click-to-focus.
9256 On X, if the mouse happens to be over the raised frame, it gets
9257 input focus anyway (so the window with focus will never be
9258 completely obscured) - if not, then just moving the mouse over it
9259 is sufficient to give it focus. On Windows, the user must actually
9260 click on the frame (preferrably the title bar so as not to move
9261 point), which is more awkward. Also, no other Windows program
9262 raises a window to the top but leaves another window (possibly now
9263 completely obscured) with input focus.
9265 Because there is a system setting on Windows that allows the user
9266 to choose the point to focus policy, we make the strict semantics
9267 optional, but by default we grab focus when raising. */
9269 if (NILP (Vw32_grab_focus_on_raise))
9271 /* The obvious call to my_set_window_pos doesn't work if Emacs is
9272 not already the foreground application: the frame is raised
9273 above all other frames belonging to us, but not above the
9274 current top window. To achieve that, we have to resort to this
9275 more cumbersome method. */
9277 HDWP handle = BeginDeferWindowPos (2);
9278 if (handle)
9280 DeferWindowPos (handle,
9281 FRAME_W32_WINDOW (f),
9282 HWND_TOP,
9283 0, 0, 0, 0,
9284 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
9286 DeferWindowPos (handle,
9287 GetForegroundWindow (),
9288 FRAME_W32_WINDOW (f),
9289 0, 0, 0, 0,
9290 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
9292 EndDeferWindowPos (handle);
9295 else
9297 my_set_foreground_window (FRAME_W32_WINDOW (f));
9300 UNBLOCK_INPUT;
9303 /* Lower frame F. */
9304 void
9305 x_lower_frame (f)
9306 struct frame *f;
9308 BLOCK_INPUT;
9309 my_set_window_pos (FRAME_W32_WINDOW (f),
9310 HWND_BOTTOM,
9311 0, 0, 0, 0,
9312 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
9313 UNBLOCK_INPUT;
9316 static void
9317 w32_frame_raise_lower (f, raise_flag)
9318 FRAME_PTR f;
9319 int raise_flag;
9321 if (raise_flag)
9322 x_raise_frame (f);
9323 else
9324 x_lower_frame (f);
9327 /* Change of visibility. */
9329 /* This tries to wait until the frame is really visible.
9330 However, if the window manager asks the user where to position
9331 the frame, this will return before the user finishes doing that.
9332 The frame will not actually be visible at that time,
9333 but it will become visible later when the window manager
9334 finishes with it. */
9336 void
9337 x_make_frame_visible (f)
9338 struct frame *f;
9340 Lisp_Object type;
9342 BLOCK_INPUT;
9344 type = x_icon_type (f);
9345 if (!NILP (type))
9346 x_bitmap_icon (f, type);
9348 if (! FRAME_VISIBLE_P (f))
9350 /* We test FRAME_GARBAGED_P here to make sure we don't
9351 call x_set_offset a second time
9352 if we get to x_make_frame_visible a second time
9353 before the window gets really visible. */
9354 if (! FRAME_ICONIFIED_P (f)
9355 && ! f->output_data.w32->asked_for_visible)
9356 x_set_offset (f, f->output_data.w32->left_pos, f->output_data.w32->top_pos, 0);
9358 f->output_data.w32->asked_for_visible = 1;
9360 // my_show_window (f, FRAME_W32_WINDOW (f), f->async_iconified ? SW_RESTORE : SW_SHOW);
9361 my_show_window (f, FRAME_W32_WINDOW (f), SW_SHOWNORMAL);
9364 /* Synchronize to ensure Emacs knows the frame is visible
9365 before we do anything else. We do this loop with input not blocked
9366 so that incoming events are handled. */
9368 Lisp_Object frame;
9369 int count;
9371 /* This must come after we set COUNT. */
9372 UNBLOCK_INPUT;
9374 XSETFRAME (frame, f);
9376 /* Wait until the frame is visible. Process X events until a
9377 MapNotify event has been seen, or until we think we won't get a
9378 MapNotify at all.. */
9379 for (count = input_signal_count + 10;
9380 input_signal_count < count && !FRAME_VISIBLE_P (f);)
9382 /* Force processing of queued events. */
9383 /* NTEMACS_TODO: x_sync equivalent? */
9385 /* Machines that do polling rather than SIGIO have been observed
9386 to go into a busy-wait here. So we'll fake an alarm signal
9387 to let the handler know that there's something to be read.
9388 We used to raise a real alarm, but it seems that the handler
9389 isn't always enabled here. This is probably a bug. */
9390 if (input_polling_used ())
9392 /* It could be confusing if a real alarm arrives while processing
9393 the fake one. Turn it off and let the handler reset it. */
9394 int old_poll_suppress_count = poll_suppress_count;
9395 poll_suppress_count = 1;
9396 poll_for_input_1 ();
9397 poll_suppress_count = old_poll_suppress_count;
9400 FRAME_SAMPLE_VISIBILITY (f);
9404 /* Change from mapped state to withdrawn state. */
9406 /* Make the frame visible (mapped and not iconified). */
9408 x_make_frame_invisible (f)
9409 struct frame *f;
9411 /* Don't keep the highlight on an invisible frame. */
9412 if (FRAME_W32_DISPLAY_INFO (f)->w32_highlight_frame == f)
9413 FRAME_W32_DISPLAY_INFO (f)->w32_highlight_frame = 0;
9415 BLOCK_INPUT;
9417 my_show_window (f, FRAME_W32_WINDOW (f), SW_HIDE);
9419 /* We can't distinguish this from iconification
9420 just by the event that we get from the server.
9421 So we can't win using the usual strategy of letting
9422 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
9423 and synchronize with the server to make sure we agree. */
9424 f->visible = 0;
9425 FRAME_ICONIFIED_P (f) = 0;
9426 f->async_visible = 0;
9427 f->async_iconified = 0;
9429 UNBLOCK_INPUT;
9432 /* Change window state from mapped to iconified. */
9434 void
9435 x_iconify_frame (f)
9436 struct frame *f;
9438 int result;
9439 Lisp_Object type;
9441 /* Don't keep the highlight on an invisible frame. */
9442 if (FRAME_W32_DISPLAY_INFO (f)->w32_highlight_frame == f)
9443 FRAME_W32_DISPLAY_INFO (f)->w32_highlight_frame = 0;
9445 if (f->async_iconified)
9446 return;
9448 BLOCK_INPUT;
9450 type = x_icon_type (f);
9451 if (!NILP (type))
9452 x_bitmap_icon (f, type);
9454 /* Simulate the user minimizing the frame. */
9455 SendMessage (FRAME_W32_WINDOW (f), WM_SYSCOMMAND, SC_MINIMIZE, 0);
9457 UNBLOCK_INPUT;
9460 /* Destroy the window of frame F. */
9462 x_destroy_window (f)
9463 struct frame *f;
9465 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
9467 BLOCK_INPUT;
9469 my_destroy_window (f, FRAME_W32_WINDOW (f));
9470 free_frame_menubar (f);
9471 free_frame_faces (f);
9473 xfree (f->output_data.w32);
9474 f->output_data.w32 = 0;
9475 if (f == dpyinfo->w32_focus_frame)
9476 dpyinfo->w32_focus_frame = 0;
9477 if (f == dpyinfo->w32_focus_event_frame)
9478 dpyinfo->w32_focus_event_frame = 0;
9479 if (f == dpyinfo->w32_highlight_frame)
9480 dpyinfo->w32_highlight_frame = 0;
9482 dpyinfo->reference_count--;
9484 if (f == dpyinfo->mouse_face_mouse_frame)
9486 dpyinfo->mouse_face_beg_row
9487 = dpyinfo->mouse_face_beg_col = -1;
9488 dpyinfo->mouse_face_end_row
9489 = dpyinfo->mouse_face_end_col = -1;
9490 dpyinfo->mouse_face_window = Qnil;
9493 UNBLOCK_INPUT;
9496 /* Setting window manager hints. */
9498 /* Set the normal size hints for the window manager, for frame F.
9499 FLAGS is the flags word to use--or 0 meaning preserve the flags
9500 that the window now has.
9501 If USER_POSITION is nonzero, we set the USPosition
9502 flag (this is useful when FLAGS is 0). */
9503 void
9504 x_wm_set_size_hint (f, flags, user_position)
9505 struct frame *f;
9506 long flags;
9507 int user_position;
9509 Window window = FRAME_W32_WINDOW (f);
9511 enter_crit ();
9513 SetWindowLong (window, WND_FONTWIDTH_INDEX, FONT_WIDTH (f->output_data.w32->font));
9514 SetWindowLong (window, WND_LINEHEIGHT_INDEX, f->output_data.w32->line_height);
9515 SetWindowLong (window, WND_BORDER_INDEX, f->output_data.w32->internal_border_width);
9516 SetWindowLong (window, WND_SCROLLBAR_INDEX, f->output_data.w32->vertical_scroll_bar_extra);
9518 leave_crit ();
9521 /* Window manager things */
9522 x_wm_set_icon_position (f, icon_x, icon_y)
9523 struct frame *f;
9524 int icon_x, icon_y;
9526 #if 0
9527 Window window = FRAME_W32_WINDOW (f);
9529 f->display.x->wm_hints.flags |= IconPositionHint;
9530 f->display.x->wm_hints.icon_x = icon_x;
9531 f->display.x->wm_hints.icon_y = icon_y;
9533 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->display.x->wm_hints);
9534 #endif
9539 /***********************************************************************
9540 Initialization
9541 ***********************************************************************/
9543 static int w32_initialized = 0;
9545 void
9546 w32_initialize_display_info (display_name)
9547 Lisp_Object display_name;
9549 struct w32_display_info *dpyinfo = &one_w32_display_info;
9551 bzero (dpyinfo, sizeof (*dpyinfo));
9553 /* Put it on w32_display_name_list. */
9554 w32_display_name_list = Fcons (Fcons (display_name, Qnil),
9555 w32_display_name_list);
9556 dpyinfo->name_list_element = XCAR (w32_display_name_list);
9558 dpyinfo->w32_id_name
9559 = (char *) xmalloc (XSTRING (Vinvocation_name)->size
9560 + XSTRING (Vsystem_name)->size
9561 + 2);
9562 sprintf (dpyinfo->w32_id_name, "%s@%s",
9563 XSTRING (Vinvocation_name)->data, XSTRING (Vsystem_name)->data);
9565 /* Default Console mode values - overridden when running in GUI mode
9566 with values obtained from system metrics. */
9567 dpyinfo->resx = 1;
9568 dpyinfo->resy = 1;
9569 dpyinfo->height_in = 1;
9570 dpyinfo->width_in = 1;
9571 dpyinfo->n_planes = 1;
9572 dpyinfo->n_cbits = 4;
9573 dpyinfo->n_fonts = 0;
9574 dpyinfo->smallest_font_height = 1;
9575 dpyinfo->smallest_char_width = 1;
9577 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
9578 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
9579 dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
9580 dpyinfo->mouse_face_window = Qnil;
9582 /* NTEMACS_TODO: dpyinfo->gray */
9586 struct w32_display_info *
9587 w32_term_init (display_name, xrm_option, resource_name)
9588 Lisp_Object display_name;
9589 char *xrm_option;
9590 char *resource_name;
9592 struct w32_display_info *dpyinfo;
9593 HDC hdc;
9595 BLOCK_INPUT;
9597 if (!w32_initialized)
9599 w32_initialize ();
9600 w32_initialized = 1;
9604 int argc = 0;
9605 char *argv[3];
9607 argv[0] = "";
9608 argc = 1;
9609 if (xrm_option)
9611 argv[argc++] = "-xrm";
9612 argv[argc++] = xrm_option;
9616 w32_initialize_display_info (display_name);
9618 dpyinfo = &one_w32_display_info;
9620 hdc = GetDC (GetDesktopWindow ());
9622 dpyinfo->height = GetDeviceCaps (hdc, VERTRES);
9623 dpyinfo->width = GetDeviceCaps (hdc, HORZRES);
9624 dpyinfo->root_window = GetDesktopWindow ();
9625 dpyinfo->n_planes = GetDeviceCaps (hdc, PLANES);
9626 dpyinfo->n_cbits = GetDeviceCaps (hdc, BITSPIXEL);
9627 dpyinfo->resx = GetDeviceCaps (hdc, LOGPIXELSX);
9628 dpyinfo->resy = GetDeviceCaps (hdc, LOGPIXELSY);
9629 dpyinfo->has_palette = GetDeviceCaps (hdc, RASTERCAPS) & RC_PALETTE;
9630 dpyinfo->image_cache = make_image_cache ();
9631 dpyinfo->height_in = dpyinfo->height / dpyinfo->resx;
9632 dpyinfo->width_in = dpyinfo->width / dpyinfo->resy;
9633 ReleaseDC (GetDesktopWindow (), hdc);
9635 /* initialise palette with white and black */
9637 COLORREF color;
9638 w32_defined_color (0, "white", &color, 1);
9639 w32_defined_color (0, "black", &color, 1);
9642 /* Create Row Bitmaps and store them for later use. */
9643 left_bmp = CreateBitmap (left_width, left_height, 1, 1, left_bits);
9644 ov_bmp = CreateBitmap (ov_width, ov_height, 1, 1, ov_bits);
9645 right_bmp = CreateBitmap (right_width, right_height, 1, 1, right_bits);
9646 continued_bmp = CreateBitmap (continued_width, continued_height, 1,
9647 1, continued_bits);
9648 continuation_bmp = CreateBitmap (continuation_width, continuation_height,
9649 1, 1, continuation_bits);
9650 zv_bmp = CreateBitmap (zv_width, zv_height, 1, 1, zv_bits);
9652 #ifndef F_SETOWN_BUG
9653 #ifdef F_SETOWN
9654 #ifdef F_SETOWN_SOCK_NEG
9655 /* stdin is a socket here */
9656 fcntl (connection, F_SETOWN, -getpid ());
9657 #else /* ! defined (F_SETOWN_SOCK_NEG) */
9658 fcntl (connection, F_SETOWN, getpid ());
9659 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
9660 #endif /* ! defined (F_SETOWN) */
9661 #endif /* F_SETOWN_BUG */
9663 #ifdef SIGIO
9664 if (interrupt_input)
9665 init_sigio (connection);
9666 #endif /* ! defined (SIGIO) */
9668 UNBLOCK_INPUT;
9670 return dpyinfo;
9673 /* Get rid of display DPYINFO, assuming all frames are already gone. */
9675 void
9676 x_delete_display (dpyinfo)
9677 struct w32_display_info *dpyinfo;
9679 /* Discard this display from w32_display_name_list and w32_display_list.
9680 We can't use Fdelq because that can quit. */
9681 if (! NILP (w32_display_name_list)
9682 && EQ (XCAR (w32_display_name_list), dpyinfo->name_list_element))
9683 w32_display_name_list = XCDR (w32_display_name_list);
9684 else
9686 Lisp_Object tail;
9688 tail = w32_display_name_list;
9689 while (CONSP (tail) && CONSP (XCDR (tail)))
9691 if (EQ (XCAR (XCDR (tail)), dpyinfo->name_list_element))
9693 XCDR (tail) = XCDR (XCDR (tail));
9694 break;
9696 tail = XCDR (tail);
9700 /* free palette table */
9702 struct w32_palette_entry * plist;
9704 plist = dpyinfo->color_list;
9705 while (plist)
9707 struct w32_palette_entry * pentry = plist;
9708 plist = plist->next;
9709 xfree (pentry);
9711 dpyinfo->color_list = NULL;
9712 if (dpyinfo->palette)
9713 DeleteObject(dpyinfo->palette);
9715 xfree (dpyinfo->font_table);
9716 xfree (dpyinfo->w32_id_name);
9718 /* Destroy row bitmaps. */
9719 DeleteObject (left_bmp);
9720 DeleteObject (ov_bmp);
9721 DeleteObject (right_bmp);
9722 DeleteObject (continued_bmp);
9723 DeleteObject (continuation_bmp);
9724 DeleteObject (zv_bmp);
9727 /* Set up use of W32. */
9729 DWORD w32_msg_worker ();
9731 void
9732 x_flush (struct frame * f)
9733 { /* Nothing to do */ }
9735 static struct redisplay_interface w32_redisplay_interface =
9737 x_produce_glyphs,
9738 x_write_glyphs,
9739 x_insert_glyphs,
9740 x_clear_end_of_line,
9741 x_scroll_run,
9742 x_after_update_window_line,
9743 x_update_window_begin,
9744 x_update_window_end,
9745 w32_cursor_to,
9746 x_flush,
9747 x_clear_mouse_face,
9748 x_get_glyph_overhangs,
9749 x_fix_overlapping_area
9752 void
9753 w32_initialize ()
9755 rif = &w32_redisplay_interface;
9757 /* MSVC does not type K&R functions with no arguments correctly, and
9758 so we must explicitly cast them. */
9759 clear_frame_hook = (void (*)(void)) x_clear_frame;
9760 ins_del_lines_hook = x_ins_del_lines;
9761 change_line_highlight_hook = x_change_line_highlight;
9762 delete_glyphs_hook = x_delete_glyphs;
9763 ring_bell_hook = (void (*)(void)) w32_ring_bell;
9764 reset_terminal_modes_hook = (void (*)(void)) w32_reset_terminal_modes;
9765 set_terminal_modes_hook = (void (*)(void)) w32_set_terminal_modes;
9766 update_begin_hook = x_update_begin;
9767 update_end_hook = x_update_end;
9768 set_terminal_window_hook = w32_set_terminal_window;
9769 read_socket_hook = w32_read_socket;
9770 frame_up_to_date_hook = w32_frame_up_to_date;
9771 reassert_line_highlight_hook = w32_reassert_line_highlight;
9772 mouse_position_hook = w32_mouse_position;
9773 frame_rehighlight_hook = w32_frame_rehighlight;
9774 frame_raise_lower_hook = w32_frame_raise_lower;
9775 set_vertical_scroll_bar_hook = w32_set_vertical_scroll_bar;
9776 condemn_scroll_bars_hook = w32_condemn_scroll_bars;
9777 redeem_scroll_bar_hook = w32_redeem_scroll_bar;
9778 judge_scroll_bars_hook = w32_judge_scroll_bars;
9779 estimate_mode_line_height_hook = x_estimate_mode_line_height;
9781 scroll_region_ok = 1; /* we'll scroll partial frames */
9782 char_ins_del_ok = 0; /* just as fast to write the line */
9783 line_ins_del_ok = 1; /* we'll just blt 'em */
9784 fast_clear_end_of_line = 1; /* X does this well */
9785 memory_below_frame = 0; /* we don't remember what scrolls
9786 off the bottom */
9787 baud_rate = 19200;
9789 last_tool_bar_item = -1;
9790 any_help_event_p = 0;
9792 /* Initialize input mode: interrupt_input off, no flow control, allow
9793 8 bit character input, standard quit char. */
9794 Fset_input_mode (Qnil, Qnil, make_number (2), Qnil);
9796 /* Create the window thread - it will terminate itself or when the app terminates */
9798 init_crit ();
9800 dwMainThreadId = GetCurrentThreadId ();
9801 DuplicateHandle (GetCurrentProcess (), GetCurrentThread (),
9802 GetCurrentProcess (), &hMainThread, 0, TRUE, DUPLICATE_SAME_ACCESS);
9804 /* Wait for thread to start */
9807 MSG msg;
9809 PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE);
9811 hWindowsThread = CreateThread (NULL, 0,
9812 (LPTHREAD_START_ROUTINE) w32_msg_worker,
9813 0, 0, &dwWindowsThreadId);
9815 GetMessage (&msg, NULL, WM_EMACS_DONE, WM_EMACS_DONE);
9818 /* It is desirable that mainThread should have the same notion of
9819 focus window and active window as windowsThread. Unfortunately, the
9820 following call to AttachThreadInput, which should do precisely what
9821 we need, causes major problems when Emacs is linked as a console
9822 program. Unfortunately, we have good reasons for doing that, so
9823 instead we need to send messages to windowsThread to make some API
9824 calls for us (ones that affect, or depend on, the active/focus
9825 window state. */
9826 #ifdef ATTACH_THREADS
9827 AttachThreadInput (dwMainThreadId, dwWindowsThreadId, TRUE);
9828 #endif
9830 /* Dynamically link to optional system components. */
9832 HANDLE user_lib = LoadLibrary ("user32.dll");
9834 #define LOAD_PROC(fn) pfn##fn = (void *) GetProcAddress (user_lib, #fn)
9836 /* New proportional scroll bar functions. */
9837 LOAD_PROC (SetScrollInfo);
9838 LOAD_PROC (GetScrollInfo);
9840 #undef LOAD_PROC
9842 FreeLibrary (user_lib);
9844 /* If using proportional scroll bars, ensure handle is at least 5 pixels;
9845 otherwise use the fixed height. */
9846 vertical_scroll_bar_min_handle = (pfnSetScrollInfo != NULL) ? 5 :
9847 GetSystemMetrics (SM_CYVTHUMB);
9849 /* For either kind of scroll bar, take account of the arrows; these
9850 effectively form the border of the main scroll bar range. */
9851 vertical_scroll_bar_top_border = vertical_scroll_bar_bottom_border
9852 = GetSystemMetrics (SM_CYVSCROLL);
9856 void
9857 syms_of_w32term ()
9859 Lisp_Object codepage;
9861 staticpro (&w32_display_name_list);
9862 w32_display_name_list = Qnil;
9864 staticpro (&last_mouse_scroll_bar);
9865 last_mouse_scroll_bar = Qnil;
9867 staticpro (&Qvendor_specific_keysyms);
9868 Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
9870 DEFVAR_INT ("w32-num-mouse-buttons",
9871 &Vw32_num_mouse_buttons,
9872 "Number of physical mouse buttons.");
9873 Vw32_num_mouse_buttons = Qnil;
9875 DEFVAR_LISP ("w32-swap-mouse-buttons",
9876 &Vw32_swap_mouse_buttons,
9877 "Swap the mapping of middle and right mouse buttons.\n\
9878 When nil, middle button is mouse-2 and right button is mouse-3.");
9879 Vw32_swap_mouse_buttons = Qnil;
9881 DEFVAR_LISP ("w32-grab-focus-on-raise",
9882 &Vw32_grab_focus_on_raise,
9883 "Raised frame grabs input focus.\n\
9884 When t, `raise-frame' grabs input focus as well. This fits well\n\
9885 with the normal Windows click-to-focus policy, but might not be\n\
9886 desirable when using a point-to-focus policy.");
9887 Vw32_grab_focus_on_raise = Qt;
9889 DEFVAR_LISP ("w32-capslock-is-shiftlock",
9890 &Vw32_capslock_is_shiftlock,
9891 "Apply CapsLock state to non character input keys.\n\
9892 When nil, CapsLock only affects normal character input keys.");
9893 Vw32_capslock_is_shiftlock = Qnil;
9895 DEFVAR_LISP ("w32-recognize-altgr",
9896 &Vw32_recognize_altgr,
9897 "Recognize right-alt and left-ctrl as AltGr.\n\
9898 When nil, the right-alt and left-ctrl key combination is\n\
9899 interpreted normally.");
9900 Vw32_recognize_altgr = Qt;
9902 DEFVAR_BOOL ("w32-enable-unicode-output",
9903 &w32_enable_unicode_output,
9904 "Enable the use of Unicode for text output if non-nil.\n\
9905 Unicode output may prevent some third party applications for displaying\n\
9906 Far-East Languages on Windows 95/98 from working properly.\n\
9907 NT uses Unicode internally anyway, so this flag will probably have no\n\
9908 affect on NT machines.");
9909 w32_enable_unicode_output = 1;
9911 help_echo = Qnil;
9912 staticpro (&help_echo);
9913 help_echo_object = Qnil;
9914 staticpro (&help_echo_object);
9915 help_echo_window = Qnil;
9916 staticpro (&help_echo_window);
9917 previous_help_echo = Qnil;
9918 staticpro (&previous_help_echo);
9919 help_echo_pos = -1;
9921 DEFVAR_BOOL ("x-stretch-cursor", &x_stretch_cursor_p,
9922 "*Non-nil means draw block cursor as wide as the glyph under it.\n\
9923 For example, if a block cursor is over a tab, it will be drawn as\n\
9924 wide as that tab on the display.");
9925 x_stretch_cursor_p = 0;
9927 DEFVAR_BOOL ("x-toolkit-scroll-bars-p", &x_toolkit_scroll_bars_p,
9928 "If not nil, Emacs uses toolkit scroll bars.");
9929 x_toolkit_scroll_bars_p = 1;
9931 staticpro (&last_mouse_motion_frame);
9932 last_mouse_motion_frame = Qnil;